Skip to content

Commit f00654c

Browse files
committed
feat(Dock): added Dock component to replace BottomNavigation
1 parent a4a7f07 commit f00654c

11 files changed

Lines changed: 273 additions & 1049 deletions

src/BottomNavigation/BottomNavigation.stories.tsx

Lines changed: 0 additions & 891 deletions
This file was deleted.

src/BottomNavigation/BottomNavigation.test.tsx

Lines changed: 0 additions & 79 deletions
This file was deleted.

src/BottomNavigation/BottomNavigation.tsx

Lines changed: 0 additions & 54 deletions
This file was deleted.

src/BottomNavigation/index.ts

Lines changed: 0 additions & 5 deletions
This file was deleted.

src/Dock/Dock.stories.tsx

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
import React, { ReactNode } from 'react'
2+
import clsx from 'clsx'
3+
import { StoryFn as Story, Meta } from '@storybook/react'
4+
5+
import Dock, { DockProps } from '.'
6+
7+
export default {
8+
title: 'Navigation/Dock',
9+
component: Dock,
10+
parameters: {
11+
controls: { expanded: true },
12+
},
13+
argTypes: {
14+
children: {
15+
control: false,
16+
},
17+
},
18+
args: {
19+
className: 'relative',
20+
},
21+
} as Meta
22+
23+
export const Default: Story<DockProps> = (args) => {
24+
return (
25+
<div className="bg-base-300 rounded-box w-full max-w-sm pt-32">
26+
<Dock {...args} className="relative border border-base-300">
27+
<Dock.Item>
28+
<svg
29+
className="size-[1.2em]"
30+
xmlns="http://www.w3.org/2000/svg"
31+
viewBox="0 0 24 24"
32+
>
33+
<g fill="currentColor" strokeLinejoin="miter" strokeLinecap="butt">
34+
<polyline
35+
points="1 11 12 2 23 11"
36+
fill="none"
37+
stroke="currentColor"
38+
stroke-miterlimit="10"
39+
strokeWidth="2"
40+
></polyline>
41+
<path
42+
d="m5,13v7c0,1.105.895,2,2,2h10c1.105,0,2-.895,2-2v-7"
43+
fill="none"
44+
stroke="currentColor"
45+
strokeLinecap="square"
46+
stroke-miterlimit="10"
47+
strokeWidth="2"
48+
></path>
49+
<line
50+
x1="12"
51+
y1="22"
52+
x2="12"
53+
y2="18"
54+
fill="none"
55+
stroke="currentColor"
56+
strokeLinecap="square"
57+
stroke-miterlimit="10"
58+
strokeWidth="2"
59+
></line>
60+
</g>
61+
</svg>
62+
<Dock.Label>Home</Dock.Label>
63+
</Dock.Item>
64+
<Dock.Item active>
65+
<svg
66+
className="size-[1.2em]"
67+
xmlns="http://www.w3.org/2000/svg"
68+
viewBox="0 0 24 24"
69+
>
70+
<g fill="currentColor" strokeLinejoin="miter" strokeLinecap="butt">
71+
<polyline
72+
points="3 14 9 14 9 17 15 17 15 14 21 14"
73+
fill="none"
74+
stroke="currentColor"
75+
stroke-miterlimit="10"
76+
strokeWidth="2"
77+
></polyline>
78+
<rect
79+
x="3"
80+
y="3"
81+
width="18"
82+
height="18"
83+
rx="2"
84+
ry="2"
85+
fill="none"
86+
stroke="currentColor"
87+
strokeLinecap="square"
88+
stroke-miterlimit="10"
89+
strokeWidth="2"
90+
></rect>
91+
</g>
92+
</svg>
93+
<Dock.Label>Inbox</Dock.Label>
94+
</Dock.Item>
95+
<Dock.Item>
96+
<svg
97+
className="size-[1.2em]"
98+
xmlns="http://www.w3.org/2000/svg"
99+
viewBox="0 0 24 24"
100+
>
101+
<g fill="currentColor" strokeLinejoin="miter" strokeLinecap="butt">
102+
<circle
103+
cx="12"
104+
cy="12"
105+
r="3"
106+
fill="none"
107+
stroke="currentColor"
108+
strokeLinecap="square"
109+
stroke-miterlimit="10"
110+
strokeWidth="2"
111+
></circle>
112+
<path
113+
d="m22,13.25v-2.5l-2.318-.966c-.167-.581-.395-1.135-.682-1.654l.954-2.318-1.768-1.768-2.318.954c-.518-.287-1.073-.515-1.654-.682l-.966-2.318h-2.5l-.966,2.318c-.581.167-1.135.395-1.654.682l-2.318-.954-1.768,1.768.954,2.318c-.287.518-.515,1.073-.682,1.654l-2.318.966v2.5l2.318.966c.167.581.395,1.135.682,1.654l-.954,2.318,1.768,1.768,2.318-.954c.518.287,1.073.515,1.654.682l.966,2.318h2.5l.966-2.318c.581-.167,1.135-.395,1.654-.682l2.318.954,1.768-1.768-.954-2.318c.287-.518.515-1.073.682-1.654l2.318-.966Z"
114+
fill="none"
115+
stroke="currentColor"
116+
strokeLinecap="square"
117+
stroke-miterlimit="10"
118+
strokeWidth="2"
119+
></path>
120+
</g>
121+
</svg>
122+
<Dock.Label>Settings</Dock.Label>
123+
</Dock.Item>
124+
</Dock>
125+
</div>
126+
)
127+
}

src/Dock/Dock.test.tsx

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
import { render, screen } from '@testing-library/react'
2+
import Dock from './'
3+
4+
describe('Dock', () => {
5+
it('Should render Dock', () => {
6+
render(<Dock />)
7+
expect(screen.getByRole('navigation')).toBeInTheDocument()
8+
})
9+
10+
it('Should render with custom size', () => {
11+
render(<Dock size="lg" />)
12+
expect(screen.getByRole('navigation')).toHaveClass('dock-lg')
13+
})
14+
15+
it('Should apply additional class names', () => {
16+
render(<Dock className="my-class" />)
17+
expect(screen.getByRole('navigation')).toHaveClass('dock', 'my-class')
18+
})
19+
20+
it('Should render children', () => {
21+
render(
22+
<Dock>
23+
<Dock.Item>Item 1</Dock.Item>
24+
<Dock.Item>Item 2</Dock.Item>
25+
<Dock.Item>Item 3</Dock.Item>
26+
</Dock>
27+
)
28+
expect(screen.getByText('Item 1')).toBeInTheDocument()
29+
expect(screen.getByText('Item 2')).toBeInTheDocument()
30+
expect(screen.getByText('Item 3')).toBeInTheDocument()
31+
})
32+
33+
it('Should apply active styles to child element with active class', () => {
34+
render(
35+
<Dock>
36+
<Dock.Item active>Tab 1</Dock.Item>
37+
<Dock.Item>Tab 2</Dock.Item>
38+
<Dock.Item>Tab 3</Dock.Item>
39+
</Dock>
40+
)
41+
const tab1 = screen.getByText('Tab 1')
42+
const tab2 = screen.getByText('Tab 2')
43+
const tab3 = screen.getByText('Tab 3')
44+
45+
expect(tab1).toHaveClass('active')
46+
expect(tab2).not.toHaveClass('active')
47+
expect(tab3).not.toHaveClass('active')
48+
})
49+
50+
it('Should apply disabled styles to child element with disabled class', () => {
51+
render(
52+
<Dock>
53+
<Dock.Item disabled>Tab 1</Dock.Item>
54+
<Dock.Item>Tab 2</Dock.Item>
55+
<Dock.Item>Tab 3</Dock.Item>
56+
</Dock>
57+
)
58+
const tab1 = screen.getByText('Tab 1')
59+
const tab2 = screen.getByText('Tab 2')
60+
const tab3 = screen.getByText('Tab 3')
61+
62+
expect(tab1).toHaveClass('disabled')
63+
expect(tab2).not.toHaveClass('disabled')
64+
expect(tab3).not.toHaveClass('disabled')
65+
})
66+
67+
it('Should render Label with correct class name', () => {
68+
render(
69+
<Dock>
70+
<Dock.Item>
71+
<Dock.Label className="my-class">Tab 1</Dock.Label>
72+
</Dock.Item>
73+
</Dock>
74+
)
75+
expect(screen.getByText('Tab 1')).toHaveClass('dock-label', 'my-class')
76+
})
77+
})

src/Dock/Dock.tsx

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import React, { forwardRef } from 'react'
2+
import clsx from 'clsx'
3+
import { twMerge } from 'tailwind-merge'
4+
5+
import { IComponentBaseProps, ComponentSize } from '../types'
6+
7+
import DockItem, { DockItemProps as ItemProps } from './DockItem'
8+
import DockLabel, { DockLabelProps as LabelProps } from './DockLabel'
9+
10+
export type DockItemProps = ItemProps
11+
export type DockLabelProps = LabelProps
12+
13+
export type DockProps = React.HTMLAttributes<HTMLDivElement> &
14+
IComponentBaseProps & {
15+
size?: ComponentSize
16+
}
17+
18+
const Dock = forwardRef<HTMLDivElement, DockProps>(
19+
({ size, dataTheme, className, children, ...props }, ref): JSX.Element => {
20+
const classes = twMerge(
21+
'dock',
22+
clsx({
23+
'dock-lg': size === 'lg',
24+
'dock-md': size === 'md',
25+
'dock-sm': size === 'sm',
26+
'dock-xs': size === 'xs',
27+
}),
28+
className
29+
)
30+
31+
return (
32+
<div
33+
{...props}
34+
role="navigation"
35+
data-theme={dataTheme}
36+
className={classes}
37+
ref={ref}
38+
>
39+
{children}
40+
</div>
41+
)
42+
}
43+
)
44+
45+
Dock.displayName = 'Dock'
46+
47+
export default Object.assign(Dock, {
48+
Item: DockItem,
49+
Label: DockLabel,
50+
})

0 commit comments

Comments
 (0)