🎨 style: adjust vertical tab theme

This commit is contained in:
Wahyu Kurniawan 2024-02-21 14:24:35 +07:00
parent 1ab155c638
commit e57591187c
No known key found for this signature in database
GPG Key ID: 040A1549143A8E33
4 changed files with 60 additions and 10 deletions

View File

@ -4,8 +4,9 @@ export type TabsVariants = VariantProps<typeof tabsTheme>;
export const tabsTheme = tv({
slots: {
root: ['flex', 'flex-col', 'w-full'],
root: ['flex', 'data-[orientation=horizontal]:w-full'],
triggerWrapper: [
// Horizontal default
'px-1',
'pb-5',
'text-elements-low-em',
@ -17,6 +18,24 @@ export const tabsTheme = tv({
'data-[state=active]:font-medium',
'data-[state=active]:text-elements-high-em',
'data-[state=active]:border-elements-high-em',
// Vertical
'data-[orientation=vertical]:px-3',
'data-[orientation=vertical]:py-3',
'data-[orientation=vertical]:min-w-[240px]',
'data-[orientation=vertical]:focus-ring',
'data-[orientation=vertical]:rounded-xl',
'data-[orientation=vertical]:border-transparent',
'data-[orientation=vertical]:hover:bg-base-bg-emphasized',
'data-[orientation=vertical]:hover:text-elements-mid-em',
'data-[orientation=vertical]:hover:border-transparent',
'data-[orientation=vertical]:focus-visible:border-transparent',
'data-[orientation=vertical]:focus-visible:bg-base-bg-emphasized',
'data-[orientation=vertical]:focus-visible:text-elements-mid-em',
'data-[orientation=vertical]:data-[state=active]:font-normal',
'data-[orientation=vertical]:data-[state=active]:bg-base-bg-emphasized',
'data-[orientation=vertical]:data-[state=active]:border-transparent',
'data-[orientation=vertical]:data-[state=active]:hover:text-elements-high-em',
'data-[orientation=vertical]:data-[state=active]:focus-visible:text-elements-high-em',
],
trigger: [
'flex',
@ -29,14 +48,22 @@ export const tabsTheme = tv({
'leading-none',
'tracking-[-0.006em]',
'rounded-md',
'focus-ring',
// Horizontal default
'data-[orientation=horizontal]:focus-ring',
// Vertical
'data-[orientation=vertical]:gap-2',
],
triggerList: [
'flex',
'shrink-0',
'gap-5',
'border-b',
'border-border-interactive/10',
'border-transparent',
// Horizontal default
'data-[orientation=horizontal]:border-border-interactive/10',
// Vertical
'data-[orientation=vertical]:flex-col',
'data-[orientation=vertical]:gap-0.5',
],
content: ['text-elements-high-em', 'grow', 'outline-none', 'tab-content'],
},

View File

@ -18,12 +18,21 @@ export interface TabsProps extends ComponentPropsWithoutRef<typeof TabsRoot> {
* A component that allows users to switch between different tabs.
* @returns JSX element representing the tabs component.
*/
export const Tabs = ({ config, className, ...props }: TabsProps) => {
export const Tabs = ({
config,
className,
orientation = 'horizontal',
...props
}: TabsProps) => {
const { root } = tabsTheme(config);
return (
<TabsProvider {...config}>
<TabsRoot {...props} className={root({ className })} />
<TabsProvider {...config} orientation={orientation}>
<TabsRoot
{...props}
orientation={orientation}
className={root({ className })}
/>
</TabsProvider>
);
};

View File

@ -2,10 +2,14 @@ import React, {
createContext,
useContext,
type PropsWithChildren,
ComponentPropsWithoutRef,
} from 'react';
import { TabsVariants } from './Tabs.theme';
import { Root as TabsRoot } from '@radix-ui/react-tabs';
export interface TabsProviderProps extends Partial<TabsVariants> {}
export interface TabsProviderProps
extends Partial<TabsVariants>,
ComponentPropsWithoutRef<typeof TabsRoot> {}
type TabsProviderContext = ReturnType<typeof useTabsValues>;

View File

@ -27,18 +27,28 @@ const TabsTrigger = forwardRef<
>(({ className, icon, children, ...props }, ref) => {
const config = useTabs();
const { triggerWrapper, trigger } = tabsTheme(config);
const orientation = config.orientation;
return (
<Trigger
ref={ref}
tabIndex={-1}
// Disabled focus state for horizontal tabs
tabIndex={orientation === 'horizontal' ? -1 : undefined}
className={triggerWrapper({ className })}
{...props}
>
{/* Need to add button in the trigger children because there's focus state inside the children */}
<button className={trigger()}>
<button
data-orientation={orientation}
// Disabled focus state for vertical tabs
tabIndex={orientation === 'vertical' ? -1 : undefined}
className={trigger()}
>
{/* Put the icon on the left of the text for veritcal tab */}
{orientation === 'vertical' && icon}
{children}
{icon}
{/* Put the icon on the right of the text for horizontal tab */}
{orientation === 'horizontal' && icon}
</button>
</Trigger>
);