mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-13 21:05:19 +00:00
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:
@@ -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>
|
||||
);
|
||||
|
||||
@@ -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: {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user