feat(core): rewrite page-mode-switch with RadioGroup, bind hotkey with cmdk (#7758)

close AF-1170

- bump `@toeverything/theme`
- refactor page-mode-switch
  - use global `<RadioGroup />`
  - reuse for doc history
  - remove `styled` usage
  - bind hotkey via cmdk
- Update `<RadioGroup />` color scheme with latest design system
- Update right sidebar header tab style
- Update tooltip with shortcut for app nav button
This commit is contained in:
CatsJuice
2024-08-12 03:56:56 +00:00
parent 4ac9bd7790
commit 75e02bb088
18 changed files with 210 additions and 302 deletions

View File

@@ -1,7 +1,14 @@
import * as RadixRadioGroup from '@radix-ui/react-radio-group';
import { assignInlineVars } from '@vanilla-extract/dynamic';
import clsx from 'clsx';
import { createRef, memo, useCallback, useMemo, useRef } from 'react';
import {
createRef,
memo,
useCallback,
useEffect,
useMemo,
useRef,
} from 'react';
import { withUnit } from '../../utils/with-unit';
import * as styles from './styles.css';
@@ -71,6 +78,7 @@ export const RadioGroup = memo(function RadioGroup({
animationEasing = 'cubic-bezier(.18,.22,0,1)',
activeItemClassName,
activeItemStyle,
iconMode,
onChange,
}: RadioProps) {
const animationTImerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
@@ -128,23 +136,25 @@ export const RadioGroup = memo(function RadioGroup({
[animationDuration, animationEasing, finalItems]
);
const onValueChange = useCallback(
(newValue: string) => {
const oldValue = value;
if (oldValue !== newValue) {
onChange(newValue);
animate(oldValue, newValue);
}
},
[animate, onChange, value]
);
// animate on value change
// useEffect: in case that value is changed from outside
const prevValue = useRef(value);
useEffect(() => {
const currentValue = value;
const previousValue = prevValue.current;
if (currentValue !== previousValue) {
animate(previousValue, currentValue);
prevValue.current = currentValue;
}
}, [animate, value]);
return (
<RadixRadioGroup.Root
value={value}
onValueChange={onValueChange}
onValueChange={onChange}
className={styles.radioButtonGroup}
style={finalStyle}
data-icon-mode={iconMode}
>
{finalItems.map(({ customRender, ...item }, index) => {
const testId = item.testId ? { 'data-testid': item.testId } : {};
@@ -173,9 +183,7 @@ export const RadioGroup = memo(function RadioGroup({
ref={item.indicatorRef}
/>
<span className={styles.radioButtonContent}>
{customRender
? customRender(item, index)
: (item.label ?? item.value)}
{customRender?.(item, index) ?? item.label ?? item.value}
</span>
</RadixRadioGroup.Item>
);

View File

@@ -1,4 +1,5 @@
import { cssVar } from '@toeverything/theme';
import { cssVarV2 } from '@toeverything/theme/v2';
import { createVar, globalStyle, style } from '@vanilla-extract/css';
export const outerPadding = createVar('radio-outer-padding');
@@ -16,16 +17,22 @@ export const radioButton = style({
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
color: cssVar('textSecondaryColor'),
color: cssVarV2('switch/fontColor/tertiary'),
whiteSpace: 'nowrap',
userSelect: 'none',
fontWeight: 600,
selectors: {
'&[data-state="checked"]': {
color: cssVar('textPrimaryColor'),
color: cssVarV2('switch/fontColor/primary'),
},
'&[data-state="unchecked"]:hover': {
background: cssVar('hoverColor'),
background: cssVarV2('switch/buttonBackground/hover'),
},
'[data-icon-mode=true] &': {
color: cssVarV2('switch/iconColor/default'),
},
'[data-icon-mode=true] &[data-state="checked"]': {
color: cssVarV2('switch/iconColor/active'),
},
},
});
@@ -37,7 +44,7 @@ globalStyle(`${radioButtonContent} > svg`, { display: 'block' });
export const radioButtonGroup = style({
display: 'inline-flex',
alignItems: 'center',
background: cssVar('hoverColorFilled'),
background: cssVarV2('switch/switchBackground/background'),
borderRadius: outerRadius,
padding: outerPadding,
@@ -53,8 +60,8 @@ export const indicator = style({
height: '100%',
left: 0,
top: 0,
background: cssVar('white'),
filter: 'drop-shadow(0px 0px 4px rgba(0, 0, 0, 0.1))',
background: cssVarV2('switch/buttonBackground/active'),
boxShadow: cssVar('buttonShadow'),
opacity: 0,
transformOrigin: 'left',
selectors: {

View File

@@ -47,6 +47,10 @@ export interface RadioProps extends RadioGroupItemProps {
activeItemClassName?: string;
/** Customize active item's style */
activeItemStyle?: CSSProperties;
/**
* This prop is used to use a different color scheme
*/
iconMode?: boolean;
}
export interface RadioItem {