Skip to content

Commit 7fb3fff

Browse files
committed
feat: Update button,form,formItem.Add Card
1 parent db763cb commit 7fb3fff

File tree

11 files changed

+220
-52
lines changed

11 files changed

+220
-52
lines changed

src/components/button/button.tsx

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import { Loader2Icon } from 'lucide-react'
2+
import './style.css'
3+
import type { ButtonProps } from './type'
4+
import { getBtnClx } from './style'
5+
6+
const Button = (props: ButtonProps) => {
7+
const { className, children, render, variant, size, loading, ...reset } =
8+
props
9+
10+
const btnCommonProps = {
11+
'data-slot': 'sl-button',
12+
className: getBtnClx({ variant, size, className }),
13+
children: (
14+
<>
15+
{loading && <Loader2Icon className="animate-spin" />}
16+
{children}
17+
</>
18+
),
19+
}
20+
21+
const btnProps = {
22+
...btnCommonProps,
23+
...reset,
24+
}
25+
26+
if (typeof render === 'function') {
27+
return render(btnProps)
28+
}
29+
30+
return <button {...btnProps} />
31+
}
32+
33+
export { Button }

src/components/button/index.tsx

Lines changed: 2 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,2 @@
1-
import { cva, type VariantProps } from '@shilong/utils'
2-
import './style.css'
3-
4-
const getBtnClx = cva({
5-
base: 'slButtonBase',
6-
variants: {
7-
variant: {
8-
default: 'slButtonVariantDefault',
9-
destructive: 'slButtonVariantDestructive',
10-
outline: 'slButtonVariantOutline',
11-
secondary: 'slButtonVariantSecondary',
12-
ghost: 'slButtonVariantGhost',
13-
link: 'slButtonVariantLink',
14-
},
15-
size: {
16-
default: 'slButtonSizeDefault',
17-
sm: 'slButtonSizeSm',
18-
lg: 'slButtonSizeLg',
19-
icon: 'slButtonSizeIcon',
20-
},
21-
},
22-
defaultVariants: {
23-
variant: 'default',
24-
size: 'default',
25-
},
26-
})
27-
28-
export type ButtonVariants = VariantProps<typeof getBtnClx>
29-
export type ButtonProps = ButtonVariants & React.ComponentProps<'button'>
30-
31-
export const Button = (props: ButtonProps) => {
32-
const { className, variant, size, ...reset } = props
33-
34-
return (
35-
<button
36-
data-slot="sl-button"
37-
className={getBtnClx({ variant, size, className })}
38-
{...reset}
39-
/>
40-
)
41-
}
1+
export * from './button'
2+
export * from './type'

src/components/button/style.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import { cva } from '@shilong/utils'
2+
3+
export const getBtnClx = cva({
4+
base: 'slButtonBase',
5+
variants: {
6+
variant: {
7+
default: 'slButtonVariantDefault',
8+
destructive: 'slButtonVariantDestructive',
9+
outline: 'slButtonVariantOutline',
10+
secondary: 'slButtonVariantSecondary',
11+
ghost: 'slButtonVariantGhost',
12+
link: 'slButtonVariantLink',
13+
},
14+
size: {
15+
default: 'slButtonSizeDefault',
16+
sm: 'slButtonSizeSm',
17+
lg: 'slButtonSizeLg',
18+
icon: 'slButtonSizeIcon',
19+
},
20+
},
21+
defaultVariants: {
22+
variant: 'default',
23+
size: 'default',
24+
},
25+
})

src/components/button/type.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import type { VariantProps } from '@shilong/utils'
2+
import type { ReactNode } from 'react'
3+
import type { getBtnClx } from './style'
4+
5+
type ButtonSelf = {
6+
children?: ReactNode
7+
loading?: boolean
8+
render?: (props: ButtonRenderProps) => ReactNode
9+
} & VariantProps<typeof getBtnClx>
10+
11+
export type ButtonRenderProps = {
12+
'data-slot': string
13+
} & Omit<ButtonSelf, 'variant' | 'size' | 'render'> &
14+
Record<string, unknown>
15+
16+
export type ButtonProps = ButtonSelf & React.ComponentProps<'button'>

src/components/card/index.tsx

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
import { clsx } from '@shilong/utils'
2+
import * as React from 'react'
3+
import './style.css'
4+
5+
function Card({ className, ...props }: React.ComponentProps<'div'>) {
6+
return (
7+
<div data-slot="sl-card" className={clsx('slCard', className)} {...props} />
8+
)
9+
}
10+
11+
function CardHeader({ className, ...props }: React.ComponentProps<'div'>) {
12+
return (
13+
<div
14+
data-slot="sl-card-header"
15+
className={clsx('slCardHeader', className)}
16+
{...props}
17+
/>
18+
)
19+
}
20+
21+
function CardTitle({ className, ...props }: React.ComponentProps<'div'>) {
22+
return (
23+
<div
24+
data-slot="sl-card-title"
25+
className={clsx('slCardTitle', className)}
26+
{...props}
27+
/>
28+
)
29+
}
30+
31+
function CardDescription({ className, ...props }: React.ComponentProps<'div'>) {
32+
return (
33+
<div
34+
data-slot="sl-card-description"
35+
className={clsx('slCardDescription', className)}
36+
{...props}
37+
/>
38+
)
39+
}
40+
41+
function CardAction({ className, ...props }: React.ComponentProps<'div'>) {
42+
return (
43+
<div
44+
data-slot="sl-card-action"
45+
className={clsx('slCardAction', className)}
46+
{...props}
47+
/>
48+
)
49+
}
50+
51+
function CardContent({ className, ...props }: React.ComponentProps<'div'>) {
52+
return (
53+
<div
54+
data-slot="sl-card-content"
55+
className={clsx('slCardContent', className)}
56+
{...props}
57+
/>
58+
)
59+
}
60+
61+
function CardFooter({ className, ...props }: React.ComponentProps<'div'>) {
62+
return (
63+
<div
64+
data-slot="sl-card-footer"
65+
className={clsx('slCardFooter', className)}
66+
{...props}
67+
/>
68+
)
69+
}
70+
71+
export {
72+
Card,
73+
CardHeader,
74+
CardFooter,
75+
CardTitle,
76+
CardAction,
77+
CardDescription,
78+
CardContent,
79+
}

src/components/card/style.css

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
@reference "../../global.css";
2+
3+
.slCard {
4+
@apply bg-card text-card-foreground flex flex-col gap-6 rounded-xl border py-6 shadow-sm;
5+
}
6+
7+
.slCardHeader {
8+
@apply @container/card-header grid auto-rows-min grid-rows-[auto_auto] items-start gap-1.5 px-6 has-data-[slot=card-action]:grid-cols-[1fr_auto] [.border-b]:pb-6;
9+
}
10+
11+
.slCardTitle {
12+
@apply leading-none font-semibold;
13+
}
14+
15+
.slCardDescription {
16+
@apply text-muted-foreground text-sm;
17+
}
18+
19+
.slCardAction {
20+
@apply col-start-2 row-span-2 row-start-1 self-start justify-self-end;
21+
}
22+
23+
.slCardContent {
24+
@apply px-6;
25+
}
26+
27+
.slCardFooter {
28+
@apply flex items-center px-6 [.border-t]:pt-6;
29+
}

src/components/form-item/index.tsx

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ export type FormItemProps = {
1313
rules?: any
1414
render: React.ReactElement
1515
controlled?: boolean
16+
vertical?: boolean
1617
}
1718

1819
export const FormItem = (props: FormItemProps) => {
@@ -24,14 +25,19 @@ export const FormItem = (props: FormItemProps) => {
2425
name,
2526
rules,
2627
controlled = false,
28+
vertical = false,
2729
} = props
2830

2931
const { register, errors, control } = useForm()
3032

3133
const id = useId()
3234

3335
return (
34-
<div className={clsx('slFormItem', className)}>
36+
<div
37+
className={clsx('slFormItem', className, {
38+
slFormItemVertical: vertical,
39+
})}
40+
>
3541
<Label
3642
className={clsx('slFormItemLabel', labelClassName)}
3743
htmlFor={controlled ? undefined : id}

src/components/form-item/style.css

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,21 @@
11
@reference "../../global.css";
22

33
.slFormItem {
4-
@apply flex justify-start gap-2;
4+
@apply flex items-center justify-start gap-2 pb-7;
5+
}
6+
7+
.slFormItemVertical {
8+
@apply flex-col items-start [&_.slFormItemLabel]:w-full [&_.slFormItemLabel]:text-left [&_.slFormItemValue]:w-full;
59
}
610

711
.slFormItemLabel {
8-
@apply w-2/7 shrink-0 break-all;
12+
@apply inline-block w-2/7 shrink-0 text-right;
913
}
1014

1115
.slFormItemValue {
12-
@apply relative w-5/7 shrink-0;
16+
@apply relative flex-1;
1317
}
1418

1519
.slFormItemError {
16-
@apply text-destructive absolute top-full left-0 mt-1 text-sm;
20+
@apply text-destructive absolute top-full left-0 mt-0.5 ml-0.5 text-sm;
1721
}

src/components/form/index.tsx

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,16 @@
11
import { clsx } from '@shilong/utils'
22
import { type PropsWithChildren } from 'react'
3-
import { useForm as useReackHookForm } from 'react-hook-form'
3+
import {
4+
useForm as useReackHookForm,
5+
type FieldValues,
6+
type SubmitHandler,
7+
} from 'react-hook-form'
48
import './style.css'
59
import { formContext } from './context'
610

711
export type FormProps = {
812
hookFormOptions?: any
9-
onSubmit: any
13+
onSubmit: SubmitHandler<FieldValues>
1014
} & React.ComponentProps<'form'>
1115

1216
export const Form = (props: PropsWithChildren<FormProps>) => {

src/components/form/style.css

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1 @@
11
@reference "../../global.css";
2-
3-
.slForm {
4-
@apply flex flex-col gap-8;
5-
}

0 commit comments

Comments
 (0)