Skip to content

Commit c1a8cb1

Browse files
committed
feat(tabs): enhance Tabs component and add new PageLayout story
- Introduced a new 'underline' variant for the Tabs component to improve styling options. - Updated TabsTrigger and TabsContent classes for better visual consistency. - Added a new PageLayout story 'WithTabs' showcasing tabbed navigation with empty states for expenses and reimbursements. - Updated .gitignore to include .playwright-mcp for better project management.
1 parent ff1f33c commit c1a8cb1

3 files changed

Lines changed: 58 additions & 4 deletions

File tree

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,3 +37,5 @@ yarn-error.log*
3737
# Misc
3838
.DS_Store
3939
*.pem
40+
41+
.playwright-mcp

apps/storybook/stories/PageLayout.stories.tsx

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,20 @@ import {
66
Card,
77
CardContent,
88
CardHeader,
9+
Empty,
10+
EmptyDescription,
11+
EmptyHeader,
12+
EmptyTitle,
913
Grid,
1014
Heading,
1115
HStack,
16+
PageHeader,
1217
PageLayout,
1318
Stack,
19+
Tabs,
20+
TabsContent,
21+
TabsList,
22+
TabsTrigger,
1423
Text,
1524
} from '@trycompai/design-system';
1625

@@ -207,3 +216,45 @@ export const CustomMaxWidth: Story = {
207216
</PageLayout>
208217
),
209218
};
219+
220+
export const WithTabs: Story = {
221+
args: {
222+
variant: 'default',
223+
padding: 'default',
224+
container: true,
225+
},
226+
render: (args) => (
227+
<PageLayout {...args}>
228+
<Stack gap="6">
229+
<PageHeader title="My expenses" />
230+
<Tabs defaultValue="all">
231+
<TabsList variant="underline">
232+
<TabsTrigger value="all">All</TabsTrigger>
233+
<TabsTrigger value="reimbursements">Reimbursements</TabsTrigger>
234+
</TabsList>
235+
<TabsContent value="all">
236+
<Empty>
237+
<EmptyHeader>
238+
<EmptyTitle>There are no expenses</EmptyTitle>
239+
<EmptyDescription>
240+
Your expenses will appear here once you add them.
241+
</EmptyDescription>
242+
</EmptyHeader>
243+
<Button>Add expense</Button>
244+
</Empty>
245+
</TabsContent>
246+
<TabsContent value="reimbursements">
247+
<Empty>
248+
<EmptyHeader>
249+
<EmptyTitle>No reimbursements</EmptyTitle>
250+
<EmptyDescription>
251+
Submitted reimbursement requests will appear here.
252+
</EmptyDescription>
253+
</EmptyHeader>
254+
</Empty>
255+
</TabsContent>
256+
</Tabs>
257+
</Stack>
258+
</PageLayout>
259+
),
260+
};

packages/design-system/src/components/molecules/tabs.tsx

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,19 +11,20 @@ function Tabs({
1111
<TabsPrimitive.Root
1212
data-slot="tabs"
1313
data-orientation={orientation}
14-
className="gap-2 group/tabs flex data-[orientation=horizontal]:flex-col"
14+
className="group/tabs flex data-[orientation=horizontal]:flex-col"
1515
{...props}
1616
/>
1717
);
1818
}
1919

2020
const tabsListVariants = cva(
21-
'rounded-lg p-[3px] group-data-horizontal/tabs:h-8 data-[variant=line]:rounded-none group/tabs-list text-muted-foreground inline-flex w-fit items-center justify-center group-data-[orientation=vertical]/tabs:h-fit group-data-[orientation=vertical]/tabs:flex-col',
21+
'rounded-lg p-[3px] group-data-horizontal/tabs:h-8 data-[variant=line]:rounded-none data-[variant=underline]:rounded-none group/tabs-list text-muted-foreground inline-flex w-fit items-center justify-center group-data-[orientation=vertical]/tabs:h-fit group-data-[orientation=vertical]/tabs:flex-col',
2222
{
2323
variants: {
2424
variant: {
2525
default: 'bg-muted',
2626
line: 'gap-1 bg-transparent',
27+
underline: 'p-0 pb-px bg-transparent w-full justify-start items-stretch shadow-[inset_0_-1px_0_0_var(--color-border)]',
2728
},
2829
},
2930
defaultVariants: {
@@ -50,7 +51,7 @@ function TabsTrigger({ ...props }: Omit<TabsPrimitive.Tab.Props, 'className'>) {
5051
return (
5152
<TabsPrimitive.Tab
5253
data-slot="tabs-trigger"
53-
className="gap-1.5 rounded-md border border-transparent px-1.5 py-0.5 text-sm font-medium group-data-[variant=default]/tabs-list:data-active:shadow-sm group-data-[variant=line]/tabs-list:data-active:shadow-none [&_svg:not([class*='size-'])]:size-4 focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:outline-ring text-foreground/60 hover:text-foreground dark:text-muted-foreground dark:hover:text-foreground relative inline-flex h-[calc(100%-1px)] flex-1 items-center justify-center whitespace-nowrap transition-all group-data-[orientation=vertical]/tabs:w-full group-data-[orientation=vertical]/tabs:justify-start focus-visible:ring-[3px] focus-visible:outline-1 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 group-data-[variant=line]/tabs-list:bg-transparent group-data-[variant=line]/tabs-list:data-active:bg-transparent dark:group-data-[variant=line]/tabs-list:data-active:border-transparent dark:group-data-[variant=line]/tabs-list:data-active:bg-transparent data-active:bg-background dark:data-active:text-foreground dark:data-active:border-input dark:data-active:bg-input/30 data-active:text-foreground after:bg-foreground after:absolute after:opacity-0 after:transition-opacity group-data-[orientation=horizontal]/tabs:after:inset-x-0 group-data-[orientation=horizontal]/tabs:after:bottom-[-5px] group-data-[orientation=horizontal]/tabs:after:h-0.5 group-data-[orientation=vertical]/tabs:after:inset-y-0 group-data-[orientation=vertical]/tabs:after:-right-1 group-data-[orientation=vertical]/tabs:after:w-0.5 group-data-[variant=line]/tabs-list:data-active:after:opacity-100"
54+
className="gap-1.5 rounded-md border border-transparent px-1.5 py-0.5 text-sm font-medium group-data-[variant=default]/tabs-list:data-active:shadow-sm group-data-[variant=line]/tabs-list:data-active:shadow-none group-data-[variant=underline]/tabs-list:data-active:shadow-none [&_svg:not([class*='size-'])]:size-4 focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:outline-ring text-foreground/60 hover:text-foreground dark:text-muted-foreground dark:hover:text-foreground relative inline-flex h-[calc(100%-1px)] flex-1 items-center justify-center whitespace-nowrap transition-all group-data-[orientation=vertical]/tabs:w-full group-data-[orientation=vertical]/tabs:justify-start focus-visible:ring-[3px] focus-visible:outline-1 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 group-data-[variant=line]/tabs-list:bg-transparent group-data-[variant=line]/tabs-list:data-active:bg-transparent group-data-[variant=underline]/tabs-list:bg-transparent group-data-[variant=underline]/tabs-list:data-active:bg-transparent group-data-[variant=underline]/tabs-list:px-3 group-data-[variant=underline]/tabs-list:py-2 group-data-[variant=underline]/tabs-list:mb-0 group-data-[variant=underline]/tabs-list:hover:bg-muted group-data-[variant=underline]/tabs-list:rounded-t-md group-data-[variant=underline]/tabs-list:flex-none dark:group-data-[variant=line]/tabs-list:data-active:border-transparent dark:group-data-[variant=line]/tabs-list:data-active:bg-transparent dark:group-data-[variant=underline]/tabs-list:data-active:border-transparent dark:group-data-[variant=underline]/tabs-list:data-active:bg-transparent data-active:bg-background dark:data-active:text-foreground dark:data-active:border-input dark:data-active:bg-input/30 data-active:text-foreground after:absolute after:opacity-0 after:transition-opacity group-data-[orientation=horizontal]/tabs:after:inset-x-0 group-data-[orientation=horizontal]/tabs:after:bottom-[-5px] group-data-[orientation=horizontal]/tabs:after:h-0.5 group-data-[orientation=vertical]/tabs:after:inset-y-0 group-data-[orientation=vertical]/tabs:after:-right-1 group-data-[orientation=vertical]/tabs:after:w-0.5 group-data-[variant=line]/tabs-list:after:bg-foreground group-data-[variant=underline]/tabs-list:after:bg-primary group-data-[variant=line]/tabs-list:data-active:after:opacity-100 group-data-[variant=underline]/tabs-list:after:h-[3px] group-data-[variant=underline]/tabs-list:after:bottom-0 group-data-[variant=underline]/tabs-list:after:rounded-t-sm group-data-[variant=underline]/tabs-list:h-auto group-data-[variant=underline]/tabs-list:data-active:after:opacity-100"
5455
{...props}
5556
/>
5657
);
@@ -60,7 +61,7 @@ function TabsContent({ ...props }: Omit<TabsPrimitive.Panel.Props, 'className'>)
6061
return (
6162
<TabsPrimitive.Panel
6263
data-slot="tabs-content"
63-
className="text-sm flex-1 outline-none"
64+
className="text-sm flex-1 outline-none animate-in fade-in-0 duration-200"
6465
{...props}
6566
/>
6667
);

0 commit comments

Comments
 (0)