sheerly 0.0.1 → 0.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (90) hide show
  1. package/lib/accordion.d.ts +13 -4
  2. package/lib/alert.d.ts +22 -7
  3. package/lib/avatar.css +1 -1
  4. package/lib/avatar.d.ts +21 -8
  5. package/lib/badge.d.ts +14 -4
  6. package/lib/breadcrumb.d.ts +49 -8
  7. package/lib/button.css +1 -1
  8. package/lib/button.d.ts +13 -4
  9. package/lib/card.d.ts +32 -12
  10. package/lib/carousel.d.ts +13 -7
  11. package/lib/checkbox.d.ts +6 -0
  12. package/lib/dialog.d.ts +20 -8
  13. package/lib/dropdown-menu.d.ts +39 -17
  14. package/lib/hover-card.d.ts +15 -6
  15. package/lib/index.css +1 -1
  16. package/lib/index.d.ts +1 -1
  17. package/lib/index.js +308 -300
  18. package/lib/input.css +1 -1
  19. package/lib/input.d.ts +6 -0
  20. package/lib/kbd.d.ts +10 -3
  21. package/lib/label.css +1 -1
  22. package/lib/label.d.ts +6 -0
  23. package/lib/pagination.d.ts +52 -13
  24. package/lib/popover.d.ts +15 -6
  25. package/lib/progress.d.ts +6 -0
  26. package/lib/radio.d.ts +13 -3
  27. package/lib/scrollbar.css +1 -0
  28. package/lib/scrollbar.d.ts +17 -0
  29. package/lib/select.css +1 -1
  30. package/lib/select.d.ts +6 -0
  31. package/lib/separator.d.ts +14 -4
  32. package/lib/sheet.d.ts +19 -6
  33. package/lib/skeleton.d.ts +12 -3
  34. package/lib/slider.d.ts +6 -0
  35. package/lib/spinner.d.ts +10 -4
  36. package/lib/switch.d.ts +6 -0
  37. package/lib/table.css +1 -1
  38. package/lib/table.d.ts +14 -3
  39. package/lib/tabs.d.ts +37 -11
  40. package/lib/textarea.d.ts +6 -0
  41. package/lib/toggle.d.ts +7 -0
  42. package/lib/tooltip.d.ts +15 -6
  43. package/lib/typography.d.ts +12 -4
  44. package/lib/utils/polymorphic.d.ts +14 -0
  45. package/package.json +34 -33
  46. package/src/accordion.tsx +20 -6
  47. package/src/alert.tsx +52 -14
  48. package/src/avatar.css +0 -1
  49. package/src/avatar.tsx +44 -15
  50. package/src/badge.tsx +34 -16
  51. package/src/breadcrumb.tsx +97 -26
  52. package/src/button.css +1 -0
  53. package/src/button.tsx +44 -27
  54. package/src/card.tsx +82 -23
  55. package/src/carousel.tsx +28 -11
  56. package/src/checkbox.tsx +7 -1
  57. package/src/dialog.tsx +55 -16
  58. package/src/dropdown-menu.tsx +115 -33
  59. package/src/hover-card.tsx +28 -9
  60. package/src/index.css +1 -0
  61. package/src/index.ts +1 -1
  62. package/src/input.css +1 -0
  63. package/src/input.tsx +7 -1
  64. package/src/kbd.tsx +17 -5
  65. package/src/label.css +1 -0
  66. package/src/label.tsx +7 -1
  67. package/src/pagination.tsx +107 -35
  68. package/src/popover.tsx +28 -9
  69. package/src/progress.tsx +7 -1
  70. package/src/radio.tsx +20 -5
  71. package/src/scrollbar.css +56 -0
  72. package/src/scrollbar.tsx +28 -0
  73. package/src/select.css +24 -0
  74. package/src/select.tsx +7 -1
  75. package/src/separator.tsx +23 -7
  76. package/src/sheet.tsx +53 -13
  77. package/src/skeleton.tsx +19 -5
  78. package/src/slider.tsx +7 -1
  79. package/src/spinner.tsx +21 -8
  80. package/src/switch.tsx +7 -1
  81. package/src/table.css +0 -1
  82. package/src/table.tsx +21 -5
  83. package/src/tabs.tsx +65 -25
  84. package/src/textarea.tsx +7 -1
  85. package/src/toggle.tsx +8 -1
  86. package/src/tooltip.tsx +28 -9
  87. package/src/typography.tsx +19 -5
  88. package/src/utils/polymorphic.ts +19 -0
  89. /package/lib/{cn.d.ts → utils/cn.d.ts} +0 -0
  90. /package/src/{cn.ts → utils/cn.ts} +0 -0
package/src/accordion.tsx CHANGED
@@ -1,15 +1,29 @@
1
- import type { DetailsHTMLAttributes, HTMLAttributes } from 'react'
2
- import { cn } from './cn'
1
+ import type { DetailsHTMLAttributes, ElementType } from 'react'
2
+ import { cn } from './utils/cn'
3
+ import type { PolymorphicProps } from './utils/polymorphic'
3
4
 
4
5
  export type AccordionProps = DetailsHTMLAttributes<HTMLDetailsElement>
5
6
 
6
- /** Native <details>. Set the same `name` on siblings for exclusive open. */
7
+ /**
8
+ * Native <details>. Set the same `name` on siblings for exclusive open.
9
+ *
10
+ * @example
11
+ * <Accordion name="faq">
12
+ * <summary>Is it accessible?</summary>
13
+ * <AccordionContent>Yes.</AccordionContent>
14
+ * </Accordion>
15
+ */
7
16
  export function Accordion({ className, ...props }: AccordionProps) {
8
17
  return <details className={cn('sheerly-accordion', className)} {...props} />
9
18
  }
10
19
 
11
- export type AccordionContentProps = HTMLAttributes<HTMLDivElement>
20
+ export type AccordionContentProps<T extends ElementType = 'div'> = PolymorphicProps<T>
12
21
 
13
- export function AccordionContent({ className, ...props }: AccordionContentProps) {
14
- return <div className={cn('sheerly-accordion-content', className)} {...props} />
22
+ export function AccordionContent<T extends ElementType = 'div'>({
23
+ as,
24
+ className,
25
+ ...props
26
+ }: AccordionContentProps<T>) {
27
+ const Tag = as ?? 'div'
28
+ return <Tag className={cn('sheerly-accordion-content', className)} {...props} />
15
29
  }
package/src/alert.tsx CHANGED
@@ -1,25 +1,63 @@
1
- import type { HTMLAttributes } from 'react'
2
- import { cn } from './cn'
1
+ import type { ElementType } from 'react'
2
+ import { cn } from './utils/cn'
3
+ import type { PolymorphicProps } from './utils/polymorphic'
3
4
 
4
- export interface AlertProps extends HTMLAttributes<HTMLDivElement> {
5
- 'data-variant'?: 'default' | 'destructive' | 'success' | 'info' | 'warning'
6
- }
5
+ export type AlertProps<T extends ElementType = 'div'> = PolymorphicProps<
6
+ T,
7
+ { 'data-variant'?: 'default' | 'destructive' | 'success' | 'info' | 'warning' }
8
+ >
7
9
 
8
- export function Alert({ className, role = 'alert', ...props }: AlertProps) {
9
- return <div role={role} className={cn('sheerly-alert', className)} {...props} />
10
+ /**
11
+ * A callout. The leading icon is embedded in CSS and swaps per `data-variant`.
12
+ *
13
+ * Polymorphic: pass `as` to change the rendered tag (defaults to `div`).
14
+ *
15
+ * @example
16
+ * <Alert data-variant="warning">
17
+ * <AlertTitle>Heads up</AlertTitle>
18
+ * <AlertDescription>Your session expires soon.</AlertDescription>
19
+ * </Alert>
20
+ */
21
+ export function Alert<T extends ElementType = 'div'>({
22
+ as,
23
+ className,
24
+ ...props
25
+ }: AlertProps<T>) {
26
+ const Tag = as ?? 'div'
27
+ return (
28
+ <Tag role="alert" className={cn('sheerly-alert', className)} {...props} />
29
+ )
10
30
  }
11
31
 
12
- export function AlertTitle({ className, ...props }: HTMLAttributes<HTMLDivElement>) {
13
- return <div className={cn('sheerly-alert-title', className)} {...props} />
32
+ export type AlertTitleProps<T extends ElementType = 'div'> = PolymorphicProps<T>
33
+
34
+ export function AlertTitle<T extends ElementType = 'div'>({
35
+ as,
36
+ className,
37
+ ...props
38
+ }: AlertTitleProps<T>) {
39
+ const Tag = as ?? 'div'
40
+ return <Tag className={cn('sheerly-alert-title', className)} {...props} />
14
41
  }
15
42
 
16
- export function AlertDescription({
43
+ export type AlertDescriptionProps<T extends ElementType = 'div'> = PolymorphicProps<T>
44
+
45
+ export function AlertDescription<T extends ElementType = 'div'>({
46
+ as,
17
47
  className,
18
48
  ...props
19
- }: HTMLAttributes<HTMLDivElement>) {
20
- return <div className={cn('sheerly-alert-description', className)} {...props} />
49
+ }: AlertDescriptionProps<T>) {
50
+ const Tag = as ?? 'div'
51
+ return <Tag className={cn('sheerly-alert-description', className)} {...props} />
21
52
  }
22
53
 
23
- export function AlertAction({ className, ...props }: HTMLAttributes<HTMLDivElement>) {
24
- return <div className={cn('sheerly-alert-action', className)} {...props} />
54
+ export type AlertActionProps<T extends ElementType = 'div'> = PolymorphicProps<T>
55
+
56
+ export function AlertAction<T extends ElementType = 'div'>({
57
+ as,
58
+ className,
59
+ ...props
60
+ }: AlertActionProps<T>) {
61
+ const Tag = as ?? 'div'
62
+ return <Tag className={cn('sheerly-alert-action', className)} {...props} />
25
63
  }
package/src/avatar.css CHANGED
@@ -1,6 +1,5 @@
1
1
  /* Avatar — circular image with initials fallback */
2
2
  .sheerly-avatar {
3
- position: relative;
4
3
  display: flex;
5
4
  flex-shrink: 0;
6
5
  overflow: hidden;
package/src/avatar.tsx CHANGED
@@ -1,12 +1,31 @@
1
- import type { HTMLAttributes, ImgHTMLAttributes } from 'react'
2
- import { cn } from './cn'
3
-
4
- export interface AvatarProps extends HTMLAttributes<HTMLDivElement> {
5
- 'data-size'?: 'sm' | 'default' | 'lg' | 'xl'
6
- }
7
-
8
- export function Avatar({ className, ...props }: AvatarProps) {
9
- return <div className={cn('sheerly-avatar', className)} {...props} />
1
+ import type { ElementType, ImgHTMLAttributes } from 'react'
2
+ import { cn } from './utils/cn'
3
+ import type { PolymorphicProps } from './utils/polymorphic'
4
+
5
+ export type AvatarProps<T extends ElementType = 'div'> = PolymorphicProps<
6
+ T,
7
+ { 'data-size'?: 'sm' | 'default' | 'lg' | 'xl' }
8
+ >
9
+
10
+ /**
11
+ * A circular avatar. Nest an <AvatarImage> with an <AvatarFallback> for initials.
12
+ *
13
+ * Polymorphic: pass `as` to change the rendered tag (defaults to `div`, e.g.
14
+ * `as="a"` for a linkable avatar).
15
+ *
16
+ * @example
17
+ * <Avatar>
18
+ * <AvatarImage src="/me.jpg" alt="Ada" />
19
+ * <AvatarFallback>AL</AvatarFallback>
20
+ * </Avatar>
21
+ */
22
+ export function Avatar<T extends ElementType = 'div'>({
23
+ as,
24
+ className,
25
+ ...props
26
+ }: AvatarProps<T>) {
27
+ const Tag = as ?? 'div'
28
+ return <Tag className={cn('sheerly-avatar', className)} {...props} />
10
29
  }
11
30
 
12
31
  export interface AvatarImageProps extends ImgHTMLAttributes<HTMLImageElement> {
@@ -17,14 +36,24 @@ export function AvatarImage(props: AvatarImageProps) {
17
36
  return <img {...props} />
18
37
  }
19
38
 
20
- export type AvatarFallbackProps = HTMLAttributes<HTMLSpanElement>
39
+ export type AvatarFallbackProps<T extends ElementType = 'span'> = PolymorphicProps<T>
21
40
 
22
- export function AvatarFallback({ className, ...props }: AvatarFallbackProps) {
23
- return <span className={cn('sheerly-avatar-fallback', className)} {...props} />
41
+ export function AvatarFallback<T extends ElementType = 'span'>({
42
+ as,
43
+ className,
44
+ ...props
45
+ }: AvatarFallbackProps<T>) {
46
+ const Tag = as ?? 'span'
47
+ return <Tag className={cn('sheerly-avatar-fallback', className)} {...props} />
24
48
  }
25
49
 
26
- export type AvatarGroupProps = HTMLAttributes<HTMLDivElement>
50
+ export type AvatarGroupProps<T extends ElementType = 'div'> = PolymorphicProps<T>
27
51
 
28
- export function AvatarGroup({ className, ...props }: AvatarGroupProps) {
29
- return <div className={cn('sheerly-avatar-group', className)} {...props} />
52
+ export function AvatarGroup<T extends ElementType = 'div'>({
53
+ as,
54
+ className,
55
+ ...props
56
+ }: AvatarGroupProps<T>) {
57
+ const Tag = as ?? 'div'
58
+ return <Tag className={cn('sheerly-avatar-group', className)} {...props} />
30
59
  }
package/src/badge.tsx CHANGED
@@ -1,19 +1,37 @@
1
- import type { HTMLAttributes } from 'react'
2
- import { cn } from './cn'
1
+ import type { ElementType } from 'react'
2
+ import { cn } from './utils/cn'
3
+ import type { PolymorphicProps } from './utils/polymorphic'
3
4
 
4
- export interface BadgeProps extends HTMLAttributes<HTMLSpanElement> {
5
- 'data-variant'?:
6
- | 'default'
7
- | 'secondary'
8
- | 'destructive'
9
- | 'outline'
10
- | 'ghost'
11
- | 'success'
12
- | 'warning'
13
- | 'error'
14
- | 'blue'
15
- }
5
+ export type BadgeProps<T extends ElementType = 'span'> = PolymorphicProps<
6
+ T,
7
+ {
8
+ 'data-variant'?:
9
+ | 'default'
10
+ | 'secondary'
11
+ | 'destructive'
12
+ | 'outline'
13
+ | 'ghost'
14
+ | 'success'
15
+ | 'warning'
16
+ | 'error'
17
+ | 'blue'
18
+ }
19
+ >
16
20
 
17
- export function Badge({ className, ...props }: BadgeProps) {
18
- return <span className={cn('sheerly-badge', className)} {...props} />
21
+ /**
22
+ * A pill-shaped label. Set `data-variant` for color.
23
+ *
24
+ * Polymorphic: pass `as` to change the rendered tag (defaults to `span`, e.g.
25
+ * `as="a"` for a linkable badge).
26
+ *
27
+ * @example
28
+ * <Badge data-variant="success">Active</Badge>
29
+ */
30
+ export function Badge<T extends ElementType = 'span'>({
31
+ as,
32
+ className,
33
+ ...props
34
+ }: BadgeProps<T>) {
35
+ const Tag = as ?? 'span'
36
+ return <Tag className={cn('sheerly-badge', className)} {...props} />
19
37
  }
@@ -1,9 +1,31 @@
1
- import type { AnchorHTMLAttributes, HTMLAttributes, OlHTMLAttributes } from 'react'
2
- import { cn } from './cn'
1
+ import type { ElementType } from 'react'
2
+ import { cn } from './utils/cn'
3
+ import type { PolymorphicProps } from './utils/polymorphic'
3
4
 
4
- export function Breadcrumb({ className, ...props }: HTMLAttributes<HTMLElement>) {
5
+ export type BreadcrumbProps<T extends ElementType = 'nav'> = PolymorphicProps<T>
6
+
7
+ /**
8
+ * A path hierarchy of links.
9
+ *
10
+ * Polymorphic: pass `as` to change the rendered tag (defaults to `nav`).
11
+ *
12
+ * @example
13
+ * <Breadcrumb>
14
+ * <BreadcrumbList>
15
+ * <BreadcrumbItem><BreadcrumbLink href="/">Home</BreadcrumbLink></BreadcrumbItem>
16
+ * <BreadcrumbSeparator />
17
+ * <BreadcrumbItem><BreadcrumbPage>Docs</BreadcrumbPage></BreadcrumbItem>
18
+ * </BreadcrumbList>
19
+ * </Breadcrumb>
20
+ */
21
+ export function Breadcrumb<T extends ElementType = 'nav'>({
22
+ as,
23
+ className,
24
+ ...props
25
+ }: BreadcrumbProps<T>) {
26
+ const Tag = as ?? 'nav'
5
27
  return (
6
- <nav
28
+ <Tag
7
29
  aria-label="breadcrumb"
8
30
  className={cn('sheerly-breadcrumb', className)}
9
31
  {...props}
@@ -11,21 +33,62 @@ export function Breadcrumb({ className, ...props }: HTMLAttributes<HTMLElement>)
11
33
  )
12
34
  }
13
35
 
14
- export function BreadcrumbList({ className, ...props }: OlHTMLAttributes<HTMLOListElement>) {
15
- return <ol className={cn('sheerly-breadcrumb-list', className)} {...props} />
36
+ export type BreadcrumbListProps<T extends ElementType = 'ol'> = PolymorphicProps<T>
37
+
38
+ /**
39
+ * Polymorphic: pass `as` to change the rendered tag (defaults to `ol`).
40
+ */
41
+ export function BreadcrumbList<T extends ElementType = 'ol'>({
42
+ as,
43
+ className,
44
+ ...props
45
+ }: BreadcrumbListProps<T>) {
46
+ const Tag = as ?? 'ol'
47
+ return <Tag className={cn('sheerly-breadcrumb-list', className)} {...props} />
16
48
  }
17
49
 
18
- export function BreadcrumbItem({ className, ...props }: HTMLAttributes<HTMLLIElement>) {
19
- return <li className={cn('sheerly-breadcrumb-item', className)} {...props} />
50
+ export type BreadcrumbItemProps<T extends ElementType = 'li'> = PolymorphicProps<T>
51
+
52
+ /**
53
+ * Polymorphic: pass `as` to change the rendered tag (defaults to `li`).
54
+ */
55
+ export function BreadcrumbItem<T extends ElementType = 'li'>({
56
+ as,
57
+ className,
58
+ ...props
59
+ }: BreadcrumbItemProps<T>) {
60
+ const Tag = as ?? 'li'
61
+ return <Tag className={cn('sheerly-breadcrumb-item', className)} {...props} />
20
62
  }
21
63
 
22
- export function BreadcrumbLink({ className, ...props }: AnchorHTMLAttributes<HTMLAnchorElement>) {
23
- return <a className={cn('sheerly-breadcrumb-link', className)} {...props} />
64
+ export type BreadcrumbLinkProps<T extends ElementType = 'a'> = PolymorphicProps<T>
65
+
66
+ /**
67
+ * Polymorphic: pass `as` to change the rendered tag (defaults to `a`, e.g.
68
+ * `as={Link}` for a router link).
69
+ */
70
+ export function BreadcrumbLink<T extends ElementType = 'a'>({
71
+ as,
72
+ className,
73
+ ...props
74
+ }: BreadcrumbLinkProps<T>) {
75
+ const Tag = as ?? 'a'
76
+ return <Tag className={cn('sheerly-breadcrumb-link', className)} {...props} />
24
77
  }
25
78
 
26
- export function BreadcrumbPage({ className, ...props }: HTMLAttributes<HTMLSpanElement>) {
79
+ export type BreadcrumbPageProps<T extends ElementType = 'span'> = PolymorphicProps<T>
80
+
81
+ /**
82
+ * Polymorphic: pass `as` to change the rendered tag (defaults to `span`).
83
+ */
84
+ export function BreadcrumbPage<T extends ElementType = 'span'>({
85
+ as,
86
+ className,
87
+ ...props
88
+ }: BreadcrumbPageProps<T>) {
89
+ const Tag = as ?? 'span'
27
90
  return (
28
- <span
91
+ <Tag
29
92
  role="link"
30
93
  aria-disabled="true"
31
94
  aria-current="page"
@@ -35,37 +98,45 @@ export function BreadcrumbPage({ className, ...props }: HTMLAttributes<HTMLSpanE
35
98
  )
36
99
  }
37
100
 
38
- export function BreadcrumbSeparator({
101
+ export type BreadcrumbSeparatorProps<T extends ElementType = 'li'> = PolymorphicProps<T>
102
+
103
+ /**
104
+ * Polymorphic: pass `as` to change the rendered tag (defaults to `li`).
105
+ */
106
+ export function BreadcrumbSeparator<T extends ElementType = 'li'>({
107
+ as,
39
108
  className,
40
- children,
41
109
  ...props
42
- }: HTMLAttributes<HTMLLIElement>) {
110
+ }: BreadcrumbSeparatorProps<T>) {
111
+ const Tag = as ?? 'li'
43
112
  return (
44
- <li
113
+ <Tag
45
114
  role="presentation"
46
115
  aria-hidden="true"
47
116
  className={cn('sheerly-breadcrumb-separator', className)}
48
117
  {...props}
49
- >
50
- {children}
51
- </li>
118
+ />
52
119
  )
53
120
  }
54
121
 
55
- export function BreadcrumbEllipsis({
122
+ export type BreadcrumbEllipsisProps<T extends ElementType = 'span'> = PolymorphicProps<T>
123
+
124
+ /**
125
+ * Polymorphic: pass `as` to change the rendered tag (defaults to `span`).
126
+ */
127
+ export function BreadcrumbEllipsis<T extends ElementType = 'span'>({
128
+ as,
56
129
  className,
57
- children,
58
130
  ...props
59
- }: HTMLAttributes<HTMLSpanElement>) {
131
+ }: BreadcrumbEllipsisProps<T>) {
132
+ const Tag = as ?? 'span'
60
133
  return (
61
- <span
134
+ <Tag
62
135
  role="presentation"
63
136
  aria-hidden="true"
64
137
  aria-label="More"
65
138
  className={cn('sheerly-breadcrumb-ellipsis', className)}
66
139
  {...props}
67
- >
68
- {children}
69
- </span>
140
+ />
70
141
  )
71
142
  }
package/src/button.css CHANGED
@@ -15,6 +15,7 @@
15
15
  outline: none;
16
16
  cursor: pointer;
17
17
  border: 1px solid transparent;
18
+ box-sizing: border-box;
18
19
  text-decoration: none;
19
20
  user-select: none;
20
21
 
package/src/button.tsx CHANGED
@@ -1,30 +1,47 @@
1
- import type { ButtonHTMLAttributes } from 'react'
2
- import { cn } from './cn'
1
+ import type { ElementType } from 'react'
2
+ import { cn } from './utils/cn'
3
+ import type { PolymorphicProps } from './utils/polymorphic'
3
4
 
4
- export interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
5
- 'data-variant'?:
6
- | 'default'
7
- | 'primary'
8
- | 'secondary'
9
- | 'tertiary'
10
- | 'ghost'
11
- | 'muted'
12
- | 'destructive'
13
- | 'error'
14
- | 'outline'
15
- | 'link'
16
- 'data-size'?:
17
- | 'xs'
18
- | 'sm'
19
- | 'default'
20
- | 'lg'
21
- | 'icon'
22
- | 'icon-xs'
23
- | 'icon-sm'
24
- | 'icon-lg'
25
- 'data-rounded'?: 'full'
26
- }
5
+ export type ButtonProps<T extends ElementType = 'button'> = PolymorphicProps<
6
+ T,
7
+ {
8
+ 'data-variant'?:
9
+ | 'default'
10
+ | 'primary'
11
+ | 'secondary'
12
+ | 'tertiary'
13
+ | 'ghost'
14
+ | 'muted'
15
+ | 'destructive'
16
+ | 'error'
17
+ | 'outline'
18
+ | 'link'
19
+ 'data-size'?:
20
+ | 'xs'
21
+ | 'sm'
22
+ | 'default'
23
+ | 'lg'
24
+ | 'icon'
25
+ | 'icon-xs'
26
+ | 'icon-sm'
27
+ | 'icon-lg'
28
+ 'data-rounded'?: 'full'
29
+ }
30
+ >
27
31
 
28
- export function Button({ className, ...props }: ButtonProps) {
29
- return <button className={cn('sheerly-button', className)} {...props} />
32
+ /**
33
+ * A button. Defaults to the primary variant; set `data-variant` / `data-size`
34
+ * to change it.
35
+ *
36
+ * @example
37
+ * <Button data-variant="secondary">Save</Button>
38
+ * <Button as="a" role="button" href="/settings">Settings</Button>
39
+ */
40
+ export function Button<T extends ElementType = 'button'>({
41
+ as,
42
+ className,
43
+ ...props
44
+ }: ButtonProps<T>) {
45
+ const Tag = as ?? 'button'
46
+ return <Tag className={cn('sheerly-button', className)} {...props} />
30
47
  }
package/src/card.tsx CHANGED
@@ -1,41 +1,100 @@
1
- import type { HTMLAttributes } from 'react'
2
- import { cn } from './cn'
1
+ import type { ElementType } from 'react'
2
+ import { cn } from './utils/cn'
3
+ import type { PolymorphicProps } from './utils/polymorphic'
3
4
 
4
- export interface CardProps extends HTMLAttributes<HTMLDivElement> {
5
- 'data-size'?: 'default' | 'sm'
6
- }
5
+ export type CardProps<T extends ElementType = 'div'> = PolymorphicProps<
6
+ T,
7
+ { 'data-size'?: 'default' | 'sm' }
8
+ >
7
9
 
8
- export function Card({ className, ...props }: CardProps) {
9
- return <div className={cn('sheerly-card', className)} {...props} />
10
+ /**
11
+ * A surface container. Compose with the sub-parts below.
12
+ *
13
+ * Polymorphic: pass `as` to change the rendered tag (defaults to `div`).
14
+ *
15
+ * @example
16
+ * <Card as="article">
17
+ * <CardHeader>
18
+ * <CardTitle>Notifications</CardTitle>
19
+ * <CardDescription>You have 3 unread.</CardDescription>
20
+ * </CardHeader>
21
+ * <CardContent>…</CardContent>
22
+ * </Card>
23
+ */
24
+ export function Card<T extends ElementType = 'div'>({
25
+ as,
26
+ className,
27
+ ...props
28
+ }: CardProps<T>) {
29
+ const Tag = as ?? 'div'
30
+ return <Tag className={cn('sheerly-card', className)} {...props} />
10
31
  }
11
32
 
12
- export function CardHeader({ className, ...props }: HTMLAttributes<HTMLDivElement>) {
13
- return <div className={cn('sheerly-card-header', className)} {...props} />
14
- }
33
+ export type CardHeaderProps<T extends ElementType = 'div'> = PolymorphicProps<T>
15
34
 
16
- export function CardTitle({ className, ...props }: HTMLAttributes<HTMLHeadingElement>) {
17
- return <h3 className={cn('sheerly-card-title', className)} {...props} />
35
+ export function CardHeader<T extends ElementType = 'div'>({
36
+ as,
37
+ className,
38
+ ...props
39
+ }: CardHeaderProps<T>) {
40
+ const Tag = as ?? 'div'
41
+ return <Tag className={cn('sheerly-card-header', className)} {...props} />
18
42
  }
19
43
 
20
- export function CardDescription({
44
+ export type CardTitleProps<T extends ElementType = 'h3'> = PolymorphicProps<T>
45
+
46
+ export function CardTitle<T extends ElementType = 'h3'>({
47
+ as,
21
48
  className,
22
49
  ...props
23
- }: HTMLAttributes<HTMLParagraphElement>) {
24
- return <p className={cn('sheerly-card-description', className)} {...props} />
50
+ }: CardTitleProps<T>) {
51
+ const Tag = as ?? 'h3'
52
+ return <Tag className={cn('sheerly-card-title', className)} {...props} />
25
53
  }
26
54
 
27
- export function CardAction({ className, ...props }: HTMLAttributes<HTMLDivElement>) {
28
- return <div className={cn('sheerly-card-action', className)} {...props} />
55
+ export type CardDescriptionProps<T extends ElementType = 'p'> = PolymorphicProps<T>
56
+
57
+ export function CardDescription<T extends ElementType = 'p'>({
58
+ as,
59
+ className,
60
+ ...props
61
+ }: CardDescriptionProps<T>) {
62
+ const Tag = as ?? 'p'
63
+ return <Tag className={cn('sheerly-card-description', className)} {...props} />
29
64
  }
30
65
 
31
- export function CardContent({ className, ...props }: HTMLAttributes<HTMLDivElement>) {
32
- return <div className={cn('sheerly-card-content', className)} {...props} />
66
+ export type CardActionProps<T extends ElementType = 'div'> = PolymorphicProps<T>
67
+
68
+ export function CardAction<T extends ElementType = 'div'>({
69
+ as,
70
+ className,
71
+ ...props
72
+ }: CardActionProps<T>) {
73
+ const Tag = as ?? 'div'
74
+ return <Tag className={cn('sheerly-card-action', className)} {...props} />
33
75
  }
34
76
 
35
- export interface CardFooterProps extends HTMLAttributes<HTMLDivElement> {
36
- 'data-direction'?: 'column'
77
+ export type CardContentProps<T extends ElementType = 'div'> = PolymorphicProps<T>
78
+
79
+ export function CardContent<T extends ElementType = 'div'>({
80
+ as,
81
+ className,
82
+ ...props
83
+ }: CardContentProps<T>) {
84
+ const Tag = as ?? 'div'
85
+ return <Tag className={cn('sheerly-card-content', className)} {...props} />
37
86
  }
38
87
 
39
- export function CardFooter({ className, ...props }: CardFooterProps) {
40
- return <div className={cn('sheerly-card-footer', className)} {...props} />
88
+ export type CardFooterProps<T extends ElementType = 'div'> = PolymorphicProps<
89
+ T,
90
+ { 'data-direction'?: 'column' }
91
+ >
92
+
93
+ export function CardFooter<T extends ElementType = 'div'>({
94
+ as,
95
+ className,
96
+ ...props
97
+ }: CardFooterProps<T>) {
98
+ const Tag = as ?? 'div'
99
+ return <Tag className={cn('sheerly-card-footer', className)} {...props} />
41
100
  }