Skip to content

Commit d59d0d9

Browse files
committed
feat(tabs): rewrite Tabs component and add new TabsContent, TabsNext, and TabsPrev components
1 parent 49e8bac commit d59d0d9

41 files changed

Lines changed: 1056 additions & 621 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

apps/showcase/demo/styled/tabs/basic-demo.tsx

Lines changed: 22 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2,26 +2,27 @@ import { Tabs } from '@primereact/ui/tabs';
22

33
export default function BasicDemo() {
44
return (
5-
<div>
6-
<Tabs.Root value="tab1">
7-
<Tabs.List>
8-
<Tabs.Tab value="tab1">Account Info</Tabs.Tab>
9-
<Tabs.Tab value="tab2">Payment</Tabs.Tab>
10-
<Tabs.Tab value="tab3">Preferences</Tabs.Tab>
11-
<Tabs.Indicator />
12-
</Tabs.List>
13-
<Tabs.Panels>
14-
<Tabs.Panel value="tab1">
15-
<p className="text-sm">Update your personal information such as name, email address, and profile picture.</p>
16-
</Tabs.Panel>
17-
<Tabs.Panel value="tab2">
18-
<p className="text-sm">Manage your subscription plan, view invoices, and update your payment method.</p>
19-
</Tabs.Panel>
20-
<Tabs.Panel value="tab3">
21-
<p className="text-sm">Customize how the application looks and behaves to match your personal preferences.</p>
22-
</Tabs.Panel>
23-
</Tabs.Panels>
24-
</Tabs.Root>
25-
</div>
5+
<Tabs.Root defaultValue="tab1">
6+
<Tabs.List>
7+
<Tabs.Tab value="tab1">Account Info</Tabs.Tab>
8+
<Tabs.Tab value="tab2">Payment</Tabs.Tab>
9+
<Tabs.Tab value="tab3">Preferences</Tabs.Tab>
10+
<Tabs.Indicator />
11+
</Tabs.List>
12+
<Tabs.Panels>
13+
<Tabs.Panel value="tab1">
14+
<h2 className="text-lg font-bold">Account Info</h2>
15+
<p className="text-surface-500 mt-1">Update your personal information such as name, email address, and profile picture.</p>
16+
</Tabs.Panel>
17+
<Tabs.Panel value="tab2">
18+
<h2 className="text-lg font-bold">Payment</h2>
19+
<p className="text-surface-500 mt-1">Manage your subscription plan, view invoices, and update your payment method.</p>
20+
</Tabs.Panel>
21+
<Tabs.Panel value="tab3">
22+
<h2 className="text-lg font-bold">Preferences</h2>
23+
<p className="text-surface-500 mt-1">Customize how the application looks and behaves to match your personal preferences.</p>
24+
</Tabs.Panel>
25+
</Tabs.Panels>
26+
</Tabs.Root>
2627
);
2728
}

apps/showcase/demo/styled/tabs/controlled-demo.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@ export default function ControlledDemo() {
2828
<Tabs.Panels>
2929
{tabs.map((tab) => (
3030
<Tabs.Panel key={tab.id} value={tab.id}>
31-
<p className="text-sm">{tab.content}</p>
31+
<h2 className="text-lg font-bold">{tab.title}</h2>
32+
<p className="text-surface-500 mt-1">{tab.content}</p>
3233
</Tabs.Panel>
3334
))}
3435
</Tabs.Panels>

apps/showcase/demo/styled/tabs/custom-indicator-demo.tsx

Lines changed: 21 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -8,24 +8,26 @@ const tabs = [
88

99
export default function CustomIndicatorDemo() {
1010
return (
11-
<div>
12-
<Tabs.Root value="tab1">
13-
<Tabs.List>
14-
{tabs.map((tab) => (
15-
<Tabs.Tab key={tab.id} value={tab.id} className="border-none z-10">
16-
{tab.title}
17-
</Tabs.Tab>
18-
))}
19-
<Tabs.Indicator className="w-[var(--width)] h-[calc(var(--height)-12px)] bottom-none top-1/2 -translate-y-1/2 bg-surface-100 dark:bg-surface-800 rounded-md" />
20-
</Tabs.List>
21-
<Tabs.Panels>
22-
{tabs.map((tab) => (
23-
<Tabs.Panel key={tab.id} value={tab.id}>
24-
<p className="text-sm">{tab.content}</p>
25-
</Tabs.Panel>
26-
))}
27-
</Tabs.Panels>
28-
</Tabs.Root>
29-
</div>
11+
<Tabs.Root defaultValue="tab1">
12+
<Tabs.List>
13+
{tabs.map((tab) => (
14+
<Tabs.Tab key={tab.id} value={tab.id} className="border-none z-10">
15+
{tab.title}
16+
</Tabs.Tab>
17+
))}
18+
<Tabs.Indicator
19+
unstyled
20+
className="w-[calc(var(--active-bar-width)-10px)] h-[calc(var(--active-bar-height)-16px)] left-[calc(var(--active-bar-left)+5px)] top-[calc(var(--active-bar-top)+8px)] bg-surface-100 dark:bg-surface-800 rounded-md translate-[left,width] duration-200"
21+
/>
22+
</Tabs.List>
23+
<Tabs.Panels>
24+
{tabs.map((tab) => (
25+
<Tabs.Panel key={tab.id} value={tab.id}>
26+
<h2 className="text-lg font-bold">{tab.title}</h2>
27+
<p className="text-surface-500 mt-1">{tab.content}</p>
28+
</Tabs.Panel>
29+
))}
30+
</Tabs.Panels>
31+
</Tabs.Root>
3032
);
3133
}

apps/showcase/demo/styled/tabs/disabled-demo.tsx

Lines changed: 24 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -2,28 +2,29 @@ import { Tabs } from '@primereact/ui/tabs';
22

33
export default function DisabledDemo() {
44
return (
5-
<div>
6-
<Tabs.Root value="tab1">
7-
<Tabs.List>
8-
<Tabs.Tab value="tab1">Account Info</Tabs.Tab>
9-
<Tabs.Tab value="tab2" disabled>
10-
Payment
11-
</Tabs.Tab>
12-
<Tabs.Tab value="tab3">Preferences</Tabs.Tab>
13-
<Tabs.Indicator />
14-
</Tabs.List>
15-
<Tabs.Panels>
16-
<Tabs.Panel value="tab1">
17-
<p className="text-sm">Update your personal information such as name, email address, and profile picture.</p>
18-
</Tabs.Panel>
19-
<Tabs.Panel value="tab2">
20-
<p className="text-sm">Manage your subscription plan, view invoices, and update your payment method.</p>
21-
</Tabs.Panel>
22-
<Tabs.Panel value="tab3">
23-
<p className="text-sm">Customize how the application looks and behaves to match your personal preferences.</p>
24-
</Tabs.Panel>
25-
</Tabs.Panels>
26-
</Tabs.Root>
27-
</div>
5+
<Tabs.Root defaultValue="tab1">
6+
<Tabs.List>
7+
<Tabs.Tab value="tab1">Account Info</Tabs.Tab>
8+
<Tabs.Tab value="tab2" disabled>
9+
Payment
10+
</Tabs.Tab>
11+
<Tabs.Tab value="tab3">Preferences</Tabs.Tab>
12+
<Tabs.Indicator />
13+
</Tabs.List>
14+
<Tabs.Panels>
15+
<Tabs.Panel value="tab1">
16+
<h2 className="text-lg font-bold">Account Info</h2>
17+
<p className="text-surface-500 mt-1">Update your personal information such as name, email address, and profile picture.</p>
18+
</Tabs.Panel>
19+
<Tabs.Panel value="tab2">
20+
<h2 className="text-lg font-bold">Payment</h2>
21+
<p className="text-surface-500 mt-1">Manage your subscription plan, view invoices, and update your payment method.</p>
22+
</Tabs.Panel>
23+
<Tabs.Panel value="tab3">
24+
<h2 className="text-lg font-bold">Preferences</h2>
25+
<p className="text-surface-500 mt-1">Customize how the application looks and behaves to match your personal preferences.</p>
26+
</Tabs.Panel>
27+
</Tabs.Panels>
28+
</Tabs.Root>
2829
);
2930
}

apps/showcase/demo/styled/tabs/dynamic-demo.tsx

Lines changed: 18 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -8,24 +8,23 @@ const tabs = [
88

99
export default function DynamicDemo() {
1010
return (
11-
<div>
12-
<Tabs.Root value="tab1">
13-
<Tabs.List>
14-
{tabs.map((tab) => (
15-
<Tabs.Tab key={tab.id} value={tab.id}>
16-
{tab.title}
17-
</Tabs.Tab>
18-
))}
19-
<Tabs.Indicator />
20-
</Tabs.List>
21-
<Tabs.Panels>
22-
{tabs.map((tab) => (
23-
<Tabs.Panel key={tab.id} value={tab.id}>
24-
<p className="text-sm">{tab.content}</p>
25-
</Tabs.Panel>
26-
))}
27-
</Tabs.Panels>
28-
</Tabs.Root>
29-
</div>
11+
<Tabs.Root defaultValue="tab1">
12+
<Tabs.List>
13+
{tabs.map((tab) => (
14+
<Tabs.Tab key={tab.id} value={tab.id}>
15+
{tab.title}
16+
</Tabs.Tab>
17+
))}
18+
<Tabs.Indicator />
19+
</Tabs.List>
20+
<Tabs.Panels>
21+
{tabs.map((tab) => (
22+
<Tabs.Panel key={tab.id} value={tab.id}>
23+
<h2 className="text-lg font-bold">{tab.title}</h2>
24+
<p className="text-surface-500 mt-1">{tab.content}</p>
25+
</Tabs.Panel>
26+
))}
27+
</Tabs.Panels>
28+
</Tabs.Root>
3029
);
3130
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import { Tabs } from '@primereact/ui/tabs';
2+
3+
const tabs = [
4+
{ id: 'tab1', title: 'Account Info', content: 'Update your personal information such as name, email address, and profile picture.' },
5+
{ id: 'tab2', title: 'Payment', content: 'Manage your subscription plan, view invoices, and update your payment method.' },
6+
{ id: 'tab3', title: 'Preferences', content: 'Customize how the application looks and behaves to match your personal preferences.' }
7+
];
8+
9+
export default function FocusSelectionDemo() {
10+
return (
11+
<Tabs.Root defaultValue="tab1" selectOnFocus>
12+
<Tabs.List>
13+
{tabs.map((tab) => (
14+
<Tabs.Tab key={tab.id} value={tab.id}>
15+
{tab.title}
16+
</Tabs.Tab>
17+
))}
18+
<Tabs.Indicator />
19+
</Tabs.List>
20+
<Tabs.Panels>
21+
{tabs.map((tab) => (
22+
<Tabs.Panel key={tab.id} value={tab.id}>
23+
<h2 className="text-lg font-bold">{tab.title}</h2>
24+
<p className="text-surface-500 mt-1">{tab.content}</p>
25+
</Tabs.Panel>
26+
))}
27+
</Tabs.Panels>
28+
</Tabs.Root>
29+
);
30+
}
Lines changed: 42 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,54 @@
1+
import { ChevronLeft, ChevronRight } from '@primeicons/react';
12
import { Tabs } from '@primereact/ui/tabs';
23

3-
const scrollableTabs = Array.from({ length: 50 }, (_, i) => ({ title: `Tab ${i + 1}`, content: `Tab ${i + 1} Content`, value: `${i}` }));
4-
54
export default function ScrollableDemo() {
65
return (
7-
<div>
8-
<Tabs.Root value="0" scrollable>
9-
<Tabs.List>
6+
<Tabs.Root defaultValue={'0'}>
7+
<Tabs.List>
8+
<Tabs.Prev>
9+
<ChevronLeft />
10+
</Tabs.Prev>
11+
<Tabs.Content>
1012
{scrollableTabs.map((tab) => (
1113
<Tabs.Tab key={tab.value} value={tab.value}>
1214
{tab.title}
1315
</Tabs.Tab>
1416
))}
17+
1518
<Tabs.Indicator />
16-
</Tabs.List>
17-
<Tabs.Panels>
18-
{scrollableTabs.map((tab) => (
19-
<Tabs.Panel key={tab.value} value={tab.value}>
20-
<p className="text-sm">{tab.content}</p>
21-
</Tabs.Panel>
22-
))}
23-
</Tabs.Panels>
24-
</Tabs.Root>
25-
</div>
19+
</Tabs.Content>
20+
<Tabs.Next>
21+
<ChevronRight />
22+
</Tabs.Next>
23+
</Tabs.List>
24+
<Tabs.Panels>
25+
{scrollableTabs.map((tab) => (
26+
<Tabs.Panel key={tab.value} value={tab.value}>
27+
<h2 className="text-lg font-bold">{tab.title}</h2>
28+
<p className="text-surface-500 mt-1">{tab.content}</p>
29+
</Tabs.Panel>
30+
))}
31+
</Tabs.Panels>
32+
</Tabs.Root>
2633
);
2734
}
35+
36+
const sentences = [
37+
'Lorem ipsum dolor sit amet, consectetur adipiscing elit.',
38+
'Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',
39+
'Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris.',
40+
'Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore.',
41+
'Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia.',
42+
'Curabitur pretium tincidunt lacus, nec viverra velit semper at.',
43+
'Fusce condimentum nunc ac nisi vulputate fringilla.',
44+
'Donec fermentum porttitor nunc, vitae pellentesque tortor.',
45+
'Pellentesque habitant morbi tristique senectus et netus et malesuada fames.',
46+
'Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia.'
47+
];
48+
49+
const scrollableTabs = Array.from({ length: 50 }, (_, i) => {
50+
const start = i % sentences.length;
51+
const content = Array.from({ length: 4 }, (_, j) => sentences[(start + j) % sentences.length]).join(' ');
52+
53+
return { title: `Tab ${i + 1}`, value: `${i}`, content };
54+
});

apps/showcase/demo/styled/tabs/tabs-pt.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { Tabs } from '@primereact/ui/tabs';
22

33
export default function TabsPT() {
44
return (
5-
<Tabs.Root value="tab1">
5+
<Tabs.Root defaultValue="tab1">
66
<Tabs.List>
77
<Tabs.Tab value="tab1">Overview</Tabs.Tab>
88
<Tabs.Tab value="tab2">Details</Tabs.Tab>

0 commit comments

Comments
 (0)