Skip to content

Commit c9c3054

Browse files
committed
feat: add component divider
1 parent e83e6a3 commit c9c3054

File tree

12 files changed

+401
-0
lines changed

12 files changed

+401
-0
lines changed

packages/ui-variants/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,6 @@ export * from './types';
55
export * from './variants/button';
66
export * from './variants/button-group';
77
export * from './variants/card';
8+
export * from './variants/divider';
89
export * from './variants/scroll-area';
910
export * from './variants/tabs';
Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
import { tv } from 'tailwind-variants';
2+
import type { VariantProps } from 'tailwind-variants';
3+
4+
export const dividerVariants = tv({
5+
slots: {
6+
root: `relative shrink-0 border-border`,
7+
label: `absolute top-1/2 -translate-x-1/2 -translate-y-1/2 flex justify-center items-center text-muted-foreground bg-background`
8+
},
9+
variants: {
10+
size: {
11+
xs: {
12+
label: 'text-2xs'
13+
},
14+
sm: {
15+
label: 'text-xs'
16+
},
17+
md: {
18+
label: 'text-sm'
19+
},
20+
lg: {
21+
label: 'text-base'
22+
},
23+
xl: {
24+
label: 'text-lg'
25+
},
26+
'2xl': {
27+
label: 'text-2xl'
28+
}
29+
},
30+
orientation: {
31+
vertical: {
32+
root: 'h-full border-l',
33+
label: 'w-[1px]'
34+
},
35+
horizontal: {
36+
root: 'w-full border-t',
37+
label: 'h-[1px]'
38+
}
39+
},
40+
align: {
41+
start: {
42+
label: 'left-1/16 sm:left-1/8 md:left-1/10 lg:left-1/12'
43+
},
44+
center: {
45+
label: 'left-1/2'
46+
},
47+
end: {
48+
label: 'left-15/16 sm:left-7/8 md:left-9/10 lg:left-11/12'
49+
}
50+
},
51+
border: {
52+
solid: {
53+
root: 'border-solid'
54+
},
55+
dashed: {
56+
root: 'border-dashed'
57+
},
58+
dotted: {
59+
root: 'border-dotted'
60+
}
61+
}
62+
},
63+
compoundVariants: [
64+
{
65+
size: 'xs',
66+
orientation: 'vertical',
67+
class: {
68+
label: 'px-0.75 py-1.5'
69+
}
70+
},
71+
{
72+
size: 'xs',
73+
orientation: 'horizontal',
74+
class: {
75+
label: 'px-1.5 py-0.75'
76+
}
77+
},
78+
{
79+
size: 'sm',
80+
orientation: 'vertical',
81+
class: {
82+
label: 'px-0.875 py-1.75'
83+
}
84+
},
85+
{
86+
size: 'sm',
87+
orientation: 'horizontal',
88+
class: {
89+
label: 'px-1.75 py-0.875'
90+
}
91+
},
92+
{
93+
size: 'md',
94+
orientation: 'vertical',
95+
class: {
96+
label: 'px-1 py-2'
97+
}
98+
},
99+
{
100+
size: 'md',
101+
orientation: 'horizontal',
102+
class: {
103+
label: 'px-2 py-1'
104+
}
105+
},
106+
{
107+
size: 'lg',
108+
orientation: 'vertical',
109+
class: {
110+
label: 'px-1.125 py-2.25'
111+
}
112+
},
113+
{
114+
size: 'lg',
115+
orientation: 'horizontal',
116+
class: {
117+
label: 'px-2.25 py-1.125'
118+
}
119+
},
120+
{
121+
size: 'xl',
122+
orientation: 'vertical',
123+
class: {
124+
label: 'px-1.25 py-2.5'
125+
}
126+
},
127+
{
128+
size: 'xl',
129+
orientation: 'horizontal',
130+
class: {
131+
label: 'px-2.5 py-1.25'
132+
}
133+
},
134+
{
135+
size: '2xl',
136+
orientation: 'vertical',
137+
class: {
138+
label: 'px-1.5 py-3'
139+
}
140+
},
141+
{
142+
size: '2xl',
143+
orientation: 'horizontal',
144+
class: {
145+
label: 'px-3 py-1.5'
146+
}
147+
}
148+
],
149+
defaultVariants: {
150+
size: 'md',
151+
orientation: 'horizontal',
152+
align: 'center',
153+
border: 'solid'
154+
}
155+
});
156+
157+
type DividerVariants = VariantProps<typeof dividerVariants>;
158+
159+
export type DividerBorder = NonNullable<DividerVariants['border']>;
160+
161+
export type DividerSlots = keyof typeof dividerVariants.slots;

packages/ui/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
"dependencies": {
1414
"@radix-ui/react-compose-refs": "1.1.2",
1515
"@radix-ui/react-scroll-area": "^1.2.9",
16+
"@radix-ui/react-separator": "^1.1.7",
1617
"@radix-ui/react-slot": "1.2.3",
1718
"@radix-ui/react-tabs": "1.1.12",
1819
"@soybean-react-ui/variants": "workspace:*",
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
export { default as Divider } from './source/Divider';
2+
export { default as DividerLabel } from './source/DividerLabel';
3+
export { default as DividerRoot } from './source/DividerRoot';
4+
5+
export * from './types';
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import React from 'react';
2+
3+
import type { DividerProps } from '../types';
4+
5+
import DividerLabel from './DividerLabel';
6+
import DividerRoot from './DividerRoot';
7+
8+
const Divider = React.forwardRef<HTMLDivElement, DividerProps>((props, ref) => {
9+
const { align, children, className, classNames, leading, orientation, size, trailing, ...rest } = props;
10+
11+
return (
12+
<DividerRoot
13+
className={className || classNames?.root}
14+
orientation={orientation}
15+
{...rest}
16+
ref={ref}
17+
>
18+
{leading}
19+
20+
{Boolean(children) && (
21+
<DividerLabel
22+
align={align}
23+
className={classNames?.label}
24+
orientation={orientation}
25+
size={size}
26+
{...rest}
27+
>
28+
{children}
29+
</DividerLabel>
30+
)}
31+
32+
{trailing}
33+
</DividerRoot>
34+
);
35+
});
36+
37+
Divider.displayName = 'Divider';
38+
39+
export default Divider;
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import { cn, dividerVariants } from '@soybean-react-ui/variants';
2+
import React from 'react';
3+
4+
import type { DividerLabelProps } from '../types';
5+
6+
const DividerLabel = React.forwardRef<HTMLSpanElement, DividerLabelProps>((props, ref) => {
7+
const { align, className, orientation, size, ...rest } = props;
8+
9+
const { label } = dividerVariants({ align, orientation, size });
10+
11+
const mergedCls = cn(label(), className);
12+
13+
return (
14+
<span
15+
className={mergedCls}
16+
{...rest}
17+
ref={ref}
18+
/>
19+
);
20+
});
21+
22+
DividerLabel.displayName = 'DividerLabel';
23+
24+
export default DividerLabel;
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import { Root } from '@radix-ui/react-separator';
2+
import { cn, dividerVariants } from '@soybean-react-ui/variants';
3+
import React from 'react';
4+
5+
import type { DividerRootProps } from '../types';
6+
7+
const DividerRoot = React.forwardRef<HTMLDivElement, DividerRootProps>((props, ref) => {
8+
const { border, className, orientation, ...rest } = props;
9+
10+
const { root } = dividerVariants({ border, orientation });
11+
12+
const mergedCls = cn(root(), className);
13+
14+
return (
15+
<Root
16+
className={mergedCls}
17+
{...rest}
18+
ref={ref}
19+
/>
20+
);
21+
});
22+
23+
DividerRoot.displayName = 'DividerRoot';
24+
25+
export default DividerRoot;
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import type { SeparatorProps as _SeparatorProps } from '@radix-ui/react-separator';
2+
import type { DividerBorder, DividerSlots } from '@soybean-react-ui/variants';
3+
4+
import type { ThemeAlign, ThemeOrientation } from '../../types';
5+
import type { BaseNodeProps, ClassValue, PropsSlot } from '../../types/other';
6+
7+
export interface DividerRootProps extends BaseNodeProps<_SeparatorProps> {
8+
border?: DividerBorder;
9+
}
10+
11+
export interface DividerLabelProps extends BaseNodeProps<React.ComponentProps<'span'>> {
12+
align?: ThemeAlign;
13+
orientation?: ThemeOrientation;
14+
}
15+
16+
export type DividerUi = Partial<Record<DividerSlots, ClassValue>>;
17+
18+
export interface DividerProps
19+
extends DividerRootProps,
20+
Pick<DividerLabelProps, 'align' | 'orientation' | 'size'>,
21+
PropsSlot {
22+
classNames?: DividerUi;
23+
}

packages/ui/src/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ export * from './components/button';
22

33
export * from './components/card';
44

5+
export * from './components/divider';
6+
57
export * from './components/scroll-area';
68

79
export * from './components/tabs';

packages/ui/src/types/other.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ export interface PrimitiveProps {
3636
asChild?: boolean;
3737
}
3838

39+
export type { ClassValue };
40+
3941
export type BaseNodeProps<T> = Omit<T, 'className'> & {
4042
className?: ClassValue;
4143
size?: ThemeSize;
@@ -45,3 +47,8 @@ export type BaseProps<T> = T & {
4547
className?: ClassValue;
4648
size?: ThemeSize;
4749
};
50+
51+
export type PropsSlot = {
52+
leading?: ReactNode;
53+
trailing?: ReactNode;
54+
};

0 commit comments

Comments
 (0)