feat(core): replace all radio-button-group usage (#7352)
This commit is contained in:
@@ -45,6 +45,7 @@
|
|||||||
"@radix-ui/react-toolbar": "^1.0.4",
|
"@radix-ui/react-toolbar": "^1.0.4",
|
||||||
"@radix-ui/react-tooltip": "^1.0.7",
|
"@radix-ui/react-tooltip": "^1.0.7",
|
||||||
"@toeverything/theme": "^0.7.35",
|
"@toeverything/theme": "^0.7.35",
|
||||||
|
"@radix-ui/react-visually-hidden": "^1.1.0",
|
||||||
"@vanilla-extract/dynamic": "^2.1.0",
|
"@vanilla-extract/dynamic": "^2.1.0",
|
||||||
"bytes": "^3.1.2",
|
"bytes": "^3.1.2",
|
||||||
"check-password-strength": "^2.0.10",
|
"check-password-strength": "^2.0.10",
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import type {
|
|||||||
DialogProps,
|
DialogProps,
|
||||||
} from '@radix-ui/react-dialog';
|
} from '@radix-ui/react-dialog';
|
||||||
import * as Dialog 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 { assignInlineVars } from '@vanilla-extract/dynamic';
|
||||||
import clsx from 'clsx';
|
import clsx from 'clsx';
|
||||||
import type { CSSProperties } from 'react';
|
import type { CSSProperties } from 'react';
|
||||||
@@ -101,7 +102,13 @@ export const Modal = forwardRef<HTMLDivElement, ModalProps>(
|
|||||||
<Dialog.Title className={styles.modalHeader}>
|
<Dialog.Title className={styles.modalHeader}>
|
||||||
{title}
|
{title}
|
||||||
</Dialog.Title>
|
</Dialog.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 <VisuallyHidden asChild>.
|
||||||
|
<VisuallyHidden.Root asChild>
|
||||||
|
<Dialog.Title></Dialog.Title>
|
||||||
|
</VisuallyHidden.Root>
|
||||||
|
)}
|
||||||
{description ? (
|
{description ? (
|
||||||
<Dialog.Description className={styles.modalDescription}>
|
<Dialog.Description className={styles.modalDescription}>
|
||||||
{description}
|
{description}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { RadioButton, RadioButtonGroup, Switch } from '@affine/component';
|
import type { RadioItem } from '@affine/component';
|
||||||
|
import { RadioGroup, Switch } from '@affine/component';
|
||||||
import {
|
import {
|
||||||
SettingHeader,
|
SettingHeader,
|
||||||
SettingRow,
|
SettingRow,
|
||||||
@@ -8,7 +9,7 @@ import { useI18n } from '@affine/i18n';
|
|||||||
import type { AppSetting } from '@toeverything/infra';
|
import type { AppSetting } from '@toeverything/infra';
|
||||||
import { fontStyleOptions, windowFrameStyleOptions } from '@toeverything/infra';
|
import { fontStyleOptions, windowFrameStyleOptions } from '@toeverything/infra';
|
||||||
import { useTheme } from 'next-themes';
|
import { useTheme } from 'next-themes';
|
||||||
import { useCallback } from 'react';
|
import { useCallback, useMemo } from 'react';
|
||||||
|
|
||||||
import { useAppSettingHelper } from '../../../../../hooks/affine/use-app-setting-helper';
|
import { useAppSettingHelper } from '../../../../../hooks/affine/use-app-setting-helper';
|
||||||
import { LanguageMenu } from '../../../language-menu';
|
import { LanguageMenu } from '../../../language-menu';
|
||||||
@@ -19,75 +20,79 @@ export const ThemeSettings = () => {
|
|||||||
const t = useI18n();
|
const t = useI18n();
|
||||||
const { setTheme, theme } = useTheme();
|
const { setTheme, theme } = useTheme();
|
||||||
|
|
||||||
|
const radioItems = useMemo<RadioItem[]>(
|
||||||
|
() => [
|
||||||
|
{
|
||||||
|
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 (
|
return (
|
||||||
<RadioButtonGroup
|
<RadioGroup
|
||||||
|
items={radioItems}
|
||||||
|
value={theme}
|
||||||
width={250}
|
width={250}
|
||||||
className={settingWrapper}
|
className={settingWrapper}
|
||||||
value={theme}
|
onChange={useCallback(
|
||||||
onValueChange={useCallback(
|
|
||||||
(value: string) => {
|
(value: string) => {
|
||||||
setTheme(value);
|
setTheme(value);
|
||||||
},
|
},
|
||||||
[setTheme]
|
[setTheme]
|
||||||
)}
|
)}
|
||||||
>
|
/>
|
||||||
<RadioButton value="system" data-testid="system-theme-trigger">
|
|
||||||
{t['com.affine.themeSettings.system']()}
|
|
||||||
</RadioButton>
|
|
||||||
<RadioButton value="light" data-testid="light-theme-trigger">
|
|
||||||
{t['com.affine.themeSettings.light']()}
|
|
||||||
</RadioButton>
|
|
||||||
<RadioButton value="dark" data-testid="dark-theme-trigger">
|
|
||||||
{t['com.affine.themeSettings.dark']()}
|
|
||||||
</RadioButton>
|
|
||||||
</RadioButtonGroup>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const FontFamilySettings = () => {
|
const FontFamilySettings = () => {
|
||||||
const t = useI18n();
|
const t = useI18n();
|
||||||
const { appSettings, updateSettings } = useAppSettingHelper();
|
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 (
|
return (
|
||||||
<RadioButtonGroup
|
<RadioGroup
|
||||||
|
items={radioItems}
|
||||||
|
value={appSettings.fontStyle}
|
||||||
width={250}
|
width={250}
|
||||||
className={settingWrapper}
|
className={settingWrapper}
|
||||||
value={appSettings.fontStyle}
|
onChange={useCallback(
|
||||||
onValueChange={useCallback(
|
(value: AppSetting['fontStyle']) => {
|
||||||
(key: AppSetting['fontStyle']) => {
|
updateSettings('fontStyle', value);
|
||||||
updateSettings('fontStyle', key);
|
|
||||||
},
|
},
|
||||||
[updateSettings]
|
[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 (
|
|
||||||
<RadioButton
|
|
||||||
key={key}
|
|
||||||
value={key}
|
|
||||||
data-testid="system-font-style-trigger"
|
|
||||||
style={{
|
|
||||||
fontFamily: value,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{font}
|
|
||||||
</RadioButton>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</RadioButtonGroup>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -152,22 +157,19 @@ export const AppearanceSettings = () => {
|
|||||||
name={t['com.affine.appearanceSettings.windowFrame.title']()}
|
name={t['com.affine.appearanceSettings.windowFrame.title']()}
|
||||||
desc={t['com.affine.appearanceSettings.windowFrame.description']()}
|
desc={t['com.affine.appearanceSettings.windowFrame.description']()}
|
||||||
>
|
>
|
||||||
<RadioButtonGroup
|
<RadioGroup
|
||||||
|
items={windowFrameStyleOptions.map(option => ({
|
||||||
|
value: option,
|
||||||
|
label:
|
||||||
|
t[`com.affine.appearanceSettings.windowFrame.${option}`](),
|
||||||
|
}))}
|
||||||
|
value={appSettings.windowFrameStyle}
|
||||||
className={settingWrapper}
|
className={settingWrapper}
|
||||||
width={250}
|
width={250}
|
||||||
defaultValue={appSettings.windowFrameStyle}
|
onChange={(value: AppSetting['windowFrameStyle']) => {
|
||||||
onValueChange={(value: AppSetting['windowFrameStyle']) => {
|
|
||||||
updateSettings('windowFrameStyle', value);
|
updateSettings('windowFrameStyle', value);
|
||||||
}}
|
}}
|
||||||
>
|
/>
|
||||||
{windowFrameStyleOptions.map(option => {
|
|
||||||
return (
|
|
||||||
<RadioButton value={option} key={option}>
|
|
||||||
{t[`com.affine.appearanceSettings.windowFrame.${option}`]()}
|
|
||||||
</RadioButton>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</RadioButtonGroup>
|
|
||||||
</SettingRow>
|
</SettingRow>
|
||||||
) : null}
|
) : null}
|
||||||
</SettingWrapper>
|
</SettingWrapper>
|
||||||
|
|||||||
@@ -1,11 +1,4 @@
|
|||||||
import {
|
import { Input, notify, RadioGroup, Skeleton, Switch } from '@affine/component';
|
||||||
Input,
|
|
||||||
notify,
|
|
||||||
RadioButton,
|
|
||||||
RadioButtonGroup,
|
|
||||||
Skeleton,
|
|
||||||
Switch,
|
|
||||||
} from '@affine/component';
|
|
||||||
import { PublicLinkDisableModal } from '@affine/component/disable-public-link';
|
import { PublicLinkDisableModal } from '@affine/component/disable-public-link';
|
||||||
import { Button } from '@affine/component/ui/button';
|
import { Button } from '@affine/component/ui/button';
|
||||||
import { Menu, MenuItem, MenuTrigger } from '@affine/component/ui/menu';
|
import { Menu, MenuItem, MenuTrigger } from '@affine/component/ui/menu';
|
||||||
@@ -97,6 +90,17 @@ export const AffineSharePage = (props: ShareMenuProps) => {
|
|||||||
|
|
||||||
const t = useI18n();
|
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 () => {
|
const onClickCreateLink = useAsyncCallback(async () => {
|
||||||
try {
|
try {
|
||||||
await shareService.share.enableShare(
|
await shareService.share.enableShare(
|
||||||
@@ -265,18 +269,12 @@ export const AffineSharePage = (props: ShareMenuProps) => {
|
|||||||
{t['com.affine.share-menu.ShareMode']()}
|
{t['com.affine.share-menu.ShareMode']()}
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<RadioButtonGroup
|
<RadioGroup
|
||||||
className={styles.radioButtonGroup}
|
className={styles.radioButtonGroup}
|
||||||
value={mode}
|
value={mode}
|
||||||
onValueChange={onShareModeChange}
|
onChange={onShareModeChange}
|
||||||
>
|
items={modeOptions}
|
||||||
<RadioButton className={styles.radioButton} value={'page'}>
|
/>
|
||||||
{t['com.affine.pageMode.page']()}
|
|
||||||
</RadioButton>
|
|
||||||
<RadioButton className={styles.radioButton} value={'edgeless'}>
|
|
||||||
{t['com.affine.pageMode.edgeless']()}
|
|
||||||
</RadioButton>
|
|
||||||
</RadioButtonGroup>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{isSharedPage ? (
|
{isSharedPage ? (
|
||||||
|
|||||||
@@ -173,9 +173,6 @@ export const rulesTitleHighlight = style({
|
|||||||
fontStyle: 'italic',
|
fontStyle: 'italic',
|
||||||
fontWeight: 800,
|
fontWeight: 800,
|
||||||
});
|
});
|
||||||
export const tabButton = style({
|
|
||||||
height: 28,
|
|
||||||
});
|
|
||||||
export const icon = style({
|
export const icon = style({
|
||||||
color: cssVar('iconColor'),
|
color: cssVar('iconColor'),
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,9 +1,4 @@
|
|||||||
import {
|
import { Button, Modal, RadioGroup } from '@affine/component';
|
||||||
Button,
|
|
||||||
Modal,
|
|
||||||
RadioButton,
|
|
||||||
RadioButtonGroup,
|
|
||||||
} from '@affine/component';
|
|
||||||
import { useAllPageListConfig } from '@affine/core/hooks/affine/use-all-page-list-config';
|
import { useAllPageListConfig } from '@affine/core/hooks/affine/use-all-page-list-config';
|
||||||
import type { Collection } from '@affine/env/filter';
|
import type { Collection } from '@affine/env/filter';
|
||||||
import { useI18n } from '@affine/i18n';
|
import { useI18n } from '@affine/i18n';
|
||||||
@@ -137,29 +132,24 @@ export const EditCollection = ({
|
|||||||
);
|
);
|
||||||
const switchMode = useMemo(
|
const switchMode = useMemo(
|
||||||
() => (
|
() => (
|
||||||
<RadioButtonGroup
|
<RadioGroup
|
||||||
width={158}
|
key="mode-switcher"
|
||||||
style={{ height: 32 }}
|
style={{ minWidth: 158 }}
|
||||||
value={mode}
|
value={mode}
|
||||||
onValueChange={(mode: 'page' | 'rule') => {
|
onChange={setMode}
|
||||||
setMode(mode);
|
items={[
|
||||||
}}
|
{
|
||||||
>
|
value: 'page',
|
||||||
<RadioButton
|
label: t['com.affine.editCollection.pages'](),
|
||||||
spanStyle={styles.tabButton}
|
testId: 'edit-collection-pages-button',
|
||||||
value="page"
|
},
|
||||||
data-testid="edit-collection-pages-button"
|
{
|
||||||
>
|
value: 'rule',
|
||||||
{t['com.affine.editCollection.pages']()}
|
label: t['com.affine.editCollection.rules'](),
|
||||||
</RadioButton>
|
testId: 'edit-collection-rules-button',
|
||||||
<RadioButton
|
},
|
||||||
spanStyle={styles.tabButton}
|
]}
|
||||||
value="rule"
|
/>
|
||||||
data-testid="edit-collection-rules-button"
|
|
||||||
>
|
|
||||||
{t['com.affine.editCollection.rules']()}
|
|
||||||
</RadioButton>
|
|
||||||
</RadioButtonGroup>
|
|
||||||
),
|
),
|
||||||
[mode, t]
|
[mode, t]
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -4,5 +4,4 @@ export const filterTab = style({
|
|||||||
fontSize: cssVar('fontXs'),
|
fontSize: cssVar('fontXs'),
|
||||||
fontWeight: 600,
|
fontWeight: 600,
|
||||||
textTransform: 'capitalize',
|
textTransform: 'capitalize',
|
||||||
minWidth: '91px',
|
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -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 type { AllPageFilterOption } from '@affine/core/atoms';
|
||||||
import { allPageFilterSelectAtom } from '@affine/core/atoms';
|
import { allPageFilterSelectAtom } from '@affine/core/atoms';
|
||||||
import { useNavigateHelper } from '@affine/core/hooks/use-navigate-helper';
|
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 { useI18n } from '@affine/i18n';
|
||||||
import { useService, WorkspaceService } from '@toeverything/infra';
|
import { useService, WorkspaceService } from '@toeverything/infra';
|
||||||
import { useAtom } from 'jotai';
|
import { useAtom } from 'jotai';
|
||||||
import { useCallback, useEffect, useState } from 'react';
|
import { useCallback, useEffect, useMemo, useState } from 'react';
|
||||||
|
|
||||||
import * as styles from './index.css';
|
import * as styles from './index.css';
|
||||||
|
|
||||||
@@ -45,28 +45,33 @@ export const WorkspaceModeFilterTab = ({
|
|||||||
}, [activeFilter, filterMode, setFilterMode, value]);
|
}, [activeFilter, filterMode, setFilterMode, value]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<RadioButtonGroup value={value} onValueChange={handleValueChange}>
|
<RadioGroup
|
||||||
<RadioButton
|
style={{ maxWidth: '100%', width: 273 }}
|
||||||
spanStyle={styles.filterTab}
|
value={value}
|
||||||
value="docs"
|
onChange={handleValueChange}
|
||||||
data-testid="workspace-docs-button"
|
items={useMemo<RadioItem[]>(
|
||||||
>
|
() => [
|
||||||
{t['com.affine.docs.header']()}
|
{
|
||||||
</RadioButton>
|
value: 'docs',
|
||||||
<RadioButton
|
label: t['com.affine.docs.header'](),
|
||||||
spanStyle={styles.filterTab}
|
testId: 'workspace-docs-button',
|
||||||
value="collections"
|
className: styles.filterTab,
|
||||||
data-testid="workspace-collections-button"
|
},
|
||||||
>
|
{
|
||||||
{t['com.affine.collections.header']()}
|
value: 'collections',
|
||||||
</RadioButton>
|
label: t['com.affine.collections.header'](),
|
||||||
<RadioButton
|
testId: 'workspace-collections-button',
|
||||||
spanStyle={styles.filterTab}
|
className: styles.filterTab,
|
||||||
value="tags"
|
},
|
||||||
data-testid="workspace-tags-button"
|
{
|
||||||
>
|
value: 'tags',
|
||||||
{t['Tags']()}
|
label: t['Tags'](),
|
||||||
</RadioButton>
|
testId: 'workspace-tags-button',
|
||||||
</RadioButtonGroup>
|
className: styles.filterTab,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
[t]
|
||||||
|
)}
|
||||||
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -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',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
@@ -1,8 +1,9 @@
|
|||||||
import { IconButton } from '@affine/component';
|
import type { RadioItem } from '@affine/component';
|
||||||
import { assignInlineVars } from '@vanilla-extract/dynamic';
|
import { RadioGroup } from '@affine/component';
|
||||||
|
import { cssVar } from '@toeverything/theme';
|
||||||
|
import { useMemo } from 'react';
|
||||||
|
|
||||||
import type { SidebarTab, SidebarTabName } from '../multi-tabs/sidebar-tab';
|
import type { SidebarTab, SidebarTabName } from '../multi-tabs/sidebar-tab';
|
||||||
import * as styles from './header-switcher.css';
|
|
||||||
|
|
||||||
export interface MultiTabSidebarHeaderSwitcherProps {
|
export interface MultiTabSidebarHeaderSwitcherProps {
|
||||||
tabs: SidebarTab[];
|
tabs: SidebarTab[];
|
||||||
@@ -17,30 +18,26 @@ export const MultiTabSidebarHeaderSwitcher = ({
|
|||||||
activeTabName,
|
activeTabName,
|
||||||
setActiveTabName,
|
setActiveTabName,
|
||||||
}: MultiTabSidebarHeaderSwitcherProps) => {
|
}: MultiTabSidebarHeaderSwitcherProps) => {
|
||||||
const activeExtension = tabs.find(ext => ext.name === activeTabName);
|
const tabItems = useMemo(() => {
|
||||||
|
return tabs.map(extension => {
|
||||||
const vars = assignInlineVars({
|
return {
|
||||||
[styles.activeIdx]: String(
|
value: extension.name,
|
||||||
tabs.findIndex(ext => ext.name === activeExtension?.name) ?? 0
|
label: extension.icon,
|
||||||
),
|
style: { padding: 0, fontSize: 20, width: 24 },
|
||||||
|
} satisfies RadioItem;
|
||||||
});
|
});
|
||||||
|
}, [tabs]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.switchRootWrapper}>
|
<RadioGroup
|
||||||
<div className={styles.switchRoot} style={vars}>
|
borderRadius={8}
|
||||||
{tabs.map(extension => {
|
itemHeight={24}
|
||||||
return (
|
padding={4}
|
||||||
<IconButton
|
gap={8}
|
||||||
onClick={() => setActiveTabName(extension.name)}
|
items={tabItems}
|
||||||
key={extension.name}
|
value={activeTabName}
|
||||||
data-active={activeExtension === extension}
|
onChange={setActiveTabName}
|
||||||
className={styles.button}
|
activeItemStyle={{ color: cssVar('primaryColor') }}
|
||||||
>
|
/>
|
||||||
{extension.icon}
|
|
||||||
</IconButton>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -307,6 +307,7 @@ __metadata:
|
|||||||
"@radix-ui/react-toast": "npm:^1.1.5"
|
"@radix-ui/react-toast": "npm:^1.1.5"
|
||||||
"@radix-ui/react-toolbar": "npm:^1.0.4"
|
"@radix-ui/react-toolbar": "npm:^1.0.4"
|
||||||
"@radix-ui/react-tooltip": "npm:^1.0.7"
|
"@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-actions": "npm:^7.6.17"
|
||||||
"@storybook/addon-essentials": "npm:^7.6.17"
|
"@storybook/addon-essentials": "npm:^7.6.17"
|
||||||
"@storybook/addon-interactions": "npm:^7.6.17"
|
"@storybook/addon-interactions": "npm:^7.6.17"
|
||||||
@@ -12840,7 +12841,7 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
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
|
version: 1.1.0
|
||||||
resolution: "@radix-ui/react-visually-hidden@npm:1.1.0"
|
resolution: "@radix-ui/react-visually-hidden@npm:1.1.0"
|
||||||
dependencies:
|
dependencies:
|
||||||
|
|||||||
Reference in New Issue
Block a user