From fa2305b0e26054c420f51c43a89bdd39cdda6ad2 Mon Sep 17 00:00:00 2001 From: Cats Juice Date: Thu, 27 Jun 2024 17:54:30 +0800 Subject: [PATCH] feat(core): replace all radio-button-group usage (#7352) --- packages/frontend/component/package.json | 1 + .../frontend/component/src/ui/modal/modal.tsx | 9 +- .../general-setting/appearance/index.tsx | 128 +++++++++--------- .../share-menu/share-page.tsx | 34 +++-- .../edit-collection/edit-collection.css.ts | 3 - .../view/edit-collection/edit-collection.tsx | 46 +++---- .../workspace-mode-filter-tab/index.css.ts | 1 - .../pure/workspace-mode-filter-tab/index.tsx | 55 ++++---- .../view/header-switcher.css.ts | 47 ------- .../view/header-switcher.tsx | 49 ++++--- yarn.lock | 3 +- 11 files changed, 163 insertions(+), 213 deletions(-) delete mode 100644 packages/frontend/core/src/modules/multi-tab-sidebar/view/header-switcher.css.ts diff --git a/packages/frontend/component/package.json b/packages/frontend/component/package.json index 6d09edbe54..1e7c93a7f3 100644 --- a/packages/frontend/component/package.json +++ b/packages/frontend/component/package.json @@ -45,6 +45,7 @@ "@radix-ui/react-toolbar": "^1.0.4", "@radix-ui/react-tooltip": "^1.0.7", "@toeverything/theme": "^0.7.35", + "@radix-ui/react-visually-hidden": "^1.1.0", "@vanilla-extract/dynamic": "^2.1.0", "bytes": "^3.1.2", "check-password-strength": "^2.0.10", diff --git a/packages/frontend/component/src/ui/modal/modal.tsx b/packages/frontend/component/src/ui/modal/modal.tsx index 6d03d3fc42..a10a578107 100644 --- a/packages/frontend/component/src/ui/modal/modal.tsx +++ b/packages/frontend/component/src/ui/modal/modal.tsx @@ -6,6 +6,7 @@ import type { DialogProps, } from '@radix-ui/react-dialog'; import * as Dialog from '@radix-ui/react-dialog'; +import * as VisuallyHidden from '@radix-ui/react-visually-hidden'; import { assignInlineVars } from '@vanilla-extract/dynamic'; import clsx from 'clsx'; import type { CSSProperties } from 'react'; @@ -101,7 +102,13 @@ export const Modal = forwardRef( {title} - ) : null} + ) : ( + // Refer: https://www.radix-ui.com/primitives/docs/components/dialog#title + // If you want to hide the title, wrap it inside our Visually Hidden utility like this . + + + + )} {description ? ( {description} diff --git a/packages/frontend/core/src/components/affine/setting-modal/general-setting/appearance/index.tsx b/packages/frontend/core/src/components/affine/setting-modal/general-setting/appearance/index.tsx index 6344514948..8b17489a84 100644 --- a/packages/frontend/core/src/components/affine/setting-modal/general-setting/appearance/index.tsx +++ b/packages/frontend/core/src/components/affine/setting-modal/general-setting/appearance/index.tsx @@ -1,4 +1,5 @@ -import { RadioButton, RadioButtonGroup, Switch } from '@affine/component'; +import type { RadioItem } from '@affine/component'; +import { RadioGroup, Switch } from '@affine/component'; import { SettingHeader, SettingRow, @@ -8,7 +9,7 @@ import { useI18n } from '@affine/i18n'; import type { AppSetting } from '@toeverything/infra'; import { fontStyleOptions, windowFrameStyleOptions } from '@toeverything/infra'; import { useTheme } from 'next-themes'; -import { useCallback } from 'react'; +import { useCallback, useMemo } from 'react'; import { useAppSettingHelper } from '../../../../../hooks/affine/use-app-setting-helper'; import { LanguageMenu } from '../../../language-menu'; @@ -19,75 +20,79 @@ export const ThemeSettings = () => { const t = useI18n(); const { setTheme, theme } = useTheme(); + const radioItems = useMemo( + () => [ + { + value: 'system', + label: t['com.affine.themeSettings.system'](), + testId: 'system-theme-trigger', + }, + { + value: 'light', + label: t['com.affine.themeSettings.light'](), + testId: 'light-theme-trigger', + }, + { + value: 'dark', + label: t['com.affine.themeSettings.dark'](), + testId: 'dark-theme-trigger', + }, + ], + [t] + ); + return ( - { setTheme(value); }, [setTheme] )} - > - - {t['com.affine.themeSettings.system']()} - - - {t['com.affine.themeSettings.light']()} - - - {t['com.affine.themeSettings.dark']()} - - + /> ); }; const FontFamilySettings = () => { const t = useI18n(); const { appSettings, updateSettings } = useAppSettingHelper(); + + const radioItems = useMemo(() => { + return fontStyleOptions.map(({ key, value }) => { + const label = + key === 'Mono' + ? t[`com.affine.appearanceSettings.fontStyle.mono`]() + : key === 'Sans' + ? t['com.affine.appearanceSettings.fontStyle.sans']() + : key === 'Serif' + ? t['com.affine.appearanceSettings.fontStyle.serif']() + : ''; + return { + value: key, + label, + testId: 'system-font-style-trigger', + style: { fontFamily: value }, + } satisfies RadioItem; + }); + }, [t]); + return ( - { - updateSettings('fontStyle', key); + onChange={useCallback( + (value: AppSetting['fontStyle']) => { + updateSettings('fontStyle', value); }, [updateSettings] )} - > - {fontStyleOptions.map(({ key, value }) => { - let font = ''; - switch (key) { - case 'Sans': - font = t['com.affine.appearanceSettings.fontStyle.sans'](); - break; - case 'Serif': - font = t['com.affine.appearanceSettings.fontStyle.serif'](); - break; - case 'Mono': - font = t[`com.affine.appearanceSettings.fontStyle.mono`](); - break; - default: - break; - } - return ( - - {font} - - ); - })} - + /> ); }; @@ -152,22 +157,19 @@ export const AppearanceSettings = () => { name={t['com.affine.appearanceSettings.windowFrame.title']()} desc={t['com.affine.appearanceSettings.windowFrame.description']()} > - ({ + value: option, + label: + t[`com.affine.appearanceSettings.windowFrame.${option}`](), + }))} + value={appSettings.windowFrameStyle} className={settingWrapper} width={250} - defaultValue={appSettings.windowFrameStyle} - onValueChange={(value: AppSetting['windowFrameStyle']) => { + onChange={(value: AppSetting['windowFrameStyle']) => { updateSettings('windowFrameStyle', value); }} - > - {windowFrameStyleOptions.map(option => { - return ( - - {t[`com.affine.appearanceSettings.windowFrame.${option}`]()} - - ); - })} - + /> ) : null} diff --git a/packages/frontend/core/src/components/affine/share-page-modal/share-menu/share-page.tsx b/packages/frontend/core/src/components/affine/share-page-modal/share-menu/share-page.tsx index f3f0159835..c6ad587399 100644 --- a/packages/frontend/core/src/components/affine/share-page-modal/share-menu/share-page.tsx +++ b/packages/frontend/core/src/components/affine/share-page-modal/share-menu/share-page.tsx @@ -1,11 +1,4 @@ -import { - Input, - notify, - RadioButton, - RadioButtonGroup, - Skeleton, - Switch, -} from '@affine/component'; +import { Input, notify, RadioGroup, Skeleton, Switch } from '@affine/component'; import { PublicLinkDisableModal } from '@affine/component/disable-public-link'; import { Button } from '@affine/component/ui/button'; import { Menu, MenuItem, MenuTrigger } from '@affine/component/ui/menu'; @@ -97,6 +90,17 @@ export const AffineSharePage = (props: ShareMenuProps) => { const t = useI18n(); + const modeOptions = useMemo( + () => [ + { value: 'page', label: t['com.affine.pageMode.page']() }, + { + value: 'edgeless', + label: t['com.affine.pageMode.edgeless'](), + }, + ], + [t] + ); + const onClickCreateLink = useAsyncCallback(async () => { try { await shareService.share.enableShare( @@ -265,18 +269,12 @@ export const AffineSharePage = (props: ShareMenuProps) => { {t['com.affine.share-menu.ShareMode']()}
- - - {t['com.affine.pageMode.page']()} - - - {t['com.affine.pageMode.edgeless']()} - - + onChange={onShareModeChange} + items={modeOptions} + />
{isSharedPage ? ( diff --git a/packages/frontend/core/src/components/page-list/view/edit-collection/edit-collection.css.ts b/packages/frontend/core/src/components/page-list/view/edit-collection/edit-collection.css.ts index 8f61c7cb95..b438242188 100644 --- a/packages/frontend/core/src/components/page-list/view/edit-collection/edit-collection.css.ts +++ b/packages/frontend/core/src/components/page-list/view/edit-collection/edit-collection.css.ts @@ -173,9 +173,6 @@ export const rulesTitleHighlight = style({ fontStyle: 'italic', fontWeight: 800, }); -export const tabButton = style({ - height: 28, -}); export const icon = style({ color: cssVar('iconColor'), }); diff --git a/packages/frontend/core/src/components/page-list/view/edit-collection/edit-collection.tsx b/packages/frontend/core/src/components/page-list/view/edit-collection/edit-collection.tsx index edac81983a..58a70b9457 100644 --- a/packages/frontend/core/src/components/page-list/view/edit-collection/edit-collection.tsx +++ b/packages/frontend/core/src/components/page-list/view/edit-collection/edit-collection.tsx @@ -1,9 +1,4 @@ -import { - Button, - Modal, - RadioButton, - RadioButtonGroup, -} from '@affine/component'; +import { Button, Modal, RadioGroup } from '@affine/component'; import { useAllPageListConfig } from '@affine/core/hooks/affine/use-all-page-list-config'; import type { Collection } from '@affine/env/filter'; import { useI18n } from '@affine/i18n'; @@ -137,29 +132,24 @@ export const EditCollection = ({ ); const switchMode = useMemo( () => ( - { - setMode(mode); - }} - > - - {t['com.affine.editCollection.pages']()} - - - {t['com.affine.editCollection.rules']()} - - + onChange={setMode} + items={[ + { + value: 'page', + label: t['com.affine.editCollection.pages'](), + testId: 'edit-collection-pages-button', + }, + { + value: 'rule', + label: t['com.affine.editCollection.rules'](), + testId: 'edit-collection-rules-button', + }, + ]} + /> ), [mode, t] ); diff --git a/packages/frontend/core/src/components/pure/workspace-mode-filter-tab/index.css.ts b/packages/frontend/core/src/components/pure/workspace-mode-filter-tab/index.css.ts index 18adac82cb..02cd1bf88b 100644 --- a/packages/frontend/core/src/components/pure/workspace-mode-filter-tab/index.css.ts +++ b/packages/frontend/core/src/components/pure/workspace-mode-filter-tab/index.css.ts @@ -4,5 +4,4 @@ export const filterTab = style({ fontSize: cssVar('fontXs'), fontWeight: 600, textTransform: 'capitalize', - minWidth: '91px', }); diff --git a/packages/frontend/core/src/components/pure/workspace-mode-filter-tab/index.tsx b/packages/frontend/core/src/components/pure/workspace-mode-filter-tab/index.tsx index 40d4448ae8..1f990f683a 100644 --- a/packages/frontend/core/src/components/pure/workspace-mode-filter-tab/index.tsx +++ b/packages/frontend/core/src/components/pure/workspace-mode-filter-tab/index.tsx @@ -1,4 +1,4 @@ -import { RadioButton, RadioButtonGroup } from '@affine/component'; +import { RadioGroup, type RadioItem } from '@affine/component'; import type { AllPageFilterOption } from '@affine/core/atoms'; import { allPageFilterSelectAtom } from '@affine/core/atoms'; import { useNavigateHelper } from '@affine/core/hooks/use-navigate-helper'; @@ -6,7 +6,7 @@ import { WorkspaceSubPath } from '@affine/core/shared'; import { useI18n } from '@affine/i18n'; import { useService, WorkspaceService } from '@toeverything/infra'; import { useAtom } from 'jotai'; -import { useCallback, useEffect, useState } from 'react'; +import { useCallback, useEffect, useMemo, useState } from 'react'; import * as styles from './index.css'; @@ -45,28 +45,33 @@ export const WorkspaceModeFilterTab = ({ }, [activeFilter, filterMode, setFilterMode, value]); return ( - - - {t['com.affine.docs.header']()} - - - {t['com.affine.collections.header']()} - - - {t['Tags']()} - - + ( + () => [ + { + value: 'docs', + label: t['com.affine.docs.header'](), + testId: 'workspace-docs-button', + className: styles.filterTab, + }, + { + value: 'collections', + label: t['com.affine.collections.header'](), + testId: 'workspace-collections-button', + className: styles.filterTab, + }, + { + value: 'tags', + label: t['Tags'](), + testId: 'workspace-tags-button', + className: styles.filterTab, + }, + ], + [t] + )} + /> ); }; diff --git a/packages/frontend/core/src/modules/multi-tab-sidebar/view/header-switcher.css.ts b/packages/frontend/core/src/modules/multi-tab-sidebar/view/header-switcher.css.ts deleted file mode 100644 index d47271a1c4..0000000000 --- a/packages/frontend/core/src/modules/multi-tab-sidebar/view/header-switcher.css.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { cssVar } from '@toeverything/theme'; -import { createVar, style } from '@vanilla-extract/css'; -export const activeIdx = createVar(); -export const switchRootWrapper = style({ - height: '52px', - display: 'flex', - alignItems: 'center', - flexShrink: 0, -}); -export const switchRoot = style({ - vars: { - [activeIdx]: '0', - }, - display: 'flex', - alignItems: 'center', - gap: '8px', - height: '32px', - borderRadius: '12px', - padding: '4px', - position: 'relative', - background: cssVar('backgroundSecondaryColor'), - '::after': { - content: '""', - display: 'block', - width: '24px', - height: '24px', - background: cssVar('backgroundPrimaryColor'), - boxShadow: cssVar('shadow1'), - borderRadius: '8px', - position: 'absolute', - transform: `translateX(calc(${activeIdx} * 32px))`, - transition: 'all .15s', - }, -}); -export const button = style({ - width: '24px', - height: '24px', - borderRadius: '8px', - color: cssVar('iconColor'), - position: 'relative', - zIndex: 1, - selectors: { - '&[data-active=true]': { - pointerEvents: 'none', - }, - }, -}); diff --git a/packages/frontend/core/src/modules/multi-tab-sidebar/view/header-switcher.tsx b/packages/frontend/core/src/modules/multi-tab-sidebar/view/header-switcher.tsx index c9b1ac30da..4a55d127fe 100644 --- a/packages/frontend/core/src/modules/multi-tab-sidebar/view/header-switcher.tsx +++ b/packages/frontend/core/src/modules/multi-tab-sidebar/view/header-switcher.tsx @@ -1,8 +1,9 @@ -import { IconButton } from '@affine/component'; -import { assignInlineVars } from '@vanilla-extract/dynamic'; +import type { RadioItem } from '@affine/component'; +import { RadioGroup } from '@affine/component'; +import { cssVar } from '@toeverything/theme'; +import { useMemo } from 'react'; import type { SidebarTab, SidebarTabName } from '../multi-tabs/sidebar-tab'; -import * as styles from './header-switcher.css'; export interface MultiTabSidebarHeaderSwitcherProps { tabs: SidebarTab[]; @@ -17,30 +18,26 @@ export const MultiTabSidebarHeaderSwitcher = ({ activeTabName, setActiveTabName, }: MultiTabSidebarHeaderSwitcherProps) => { - const activeExtension = tabs.find(ext => ext.name === activeTabName); - - const vars = assignInlineVars({ - [styles.activeIdx]: String( - tabs.findIndex(ext => ext.name === activeExtension?.name) ?? 0 - ), - }); + const tabItems = useMemo(() => { + return tabs.map(extension => { + return { + value: extension.name, + label: extension.icon, + style: { padding: 0, fontSize: 20, width: 24 }, + } satisfies RadioItem; + }); + }, [tabs]); return ( -
-
- {tabs.map(extension => { - return ( - setActiveTabName(extension.name)} - key={extension.name} - data-active={activeExtension === extension} - className={styles.button} - > - {extension.icon} - - ); - })} -
-
+ ); }; diff --git a/yarn.lock b/yarn.lock index 0f132ae0b6..a3d9a86bf9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -307,6 +307,7 @@ __metadata: "@radix-ui/react-toast": "npm:^1.1.5" "@radix-ui/react-toolbar": "npm:^1.0.4" "@radix-ui/react-tooltip": "npm:^1.0.7" + "@radix-ui/react-visually-hidden": "npm:^1.1.0" "@storybook/addon-actions": "npm:^7.6.17" "@storybook/addon-essentials": "npm:^7.6.17" "@storybook/addon-interactions": "npm:^7.6.17" @@ -12840,7 +12841,7 @@ __metadata: languageName: node linkType: hard -"@radix-ui/react-visually-hidden@npm:1.1.0": +"@radix-ui/react-visually-hidden@npm:1.1.0, @radix-ui/react-visually-hidden@npm:^1.1.0": version: 1.1.0 resolution: "@radix-ui/react-visually-hidden@npm:1.1.0" dependencies: