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/carousel.tsx CHANGED
@@ -1,7 +1,8 @@
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 type CarouselProps = HTMLAttributes<HTMLDivElement>
5
+ export type CarouselProps<T extends ElementType = 'div'> = PolymorphicProps<T>
5
6
 
6
7
  /**
7
8
  * Pure-CSS carousel. The element itself is the scroll container — put
@@ -14,17 +15,33 @@ export type CarouselProps = HTMLAttributes<HTMLDivElement>
14
15
  * component sets no gap on purpose (a fixed basis + gap breaks first/last
15
16
  * snapping, so the prev/next buttons wouldn't disable and end dots wouldn't
16
17
  * highlight).
18
+ *
19
+ * @example
20
+ * <Carousel>
21
+ * <CarouselItem data-name="Slide 1">…</CarouselItem>
22
+ * <CarouselItem data-name="Slide 2">…</CarouselItem>
23
+ * </Carousel>
17
24
  */
18
- export function Carousel({ className, ...props }: CarouselProps) {
19
- return <div className={cn('sheerly-carousel', className)} {...props} />
25
+ export function Carousel<T extends ElementType = 'div'>({
26
+ as,
27
+ className,
28
+ ...props
29
+ }: CarouselProps<T>) {
30
+ const Tag = as ?? 'div'
31
+ return <Tag className={cn('sheerly-carousel', className)} {...props} />
20
32
  }
21
33
 
22
- export interface CarouselItemProps extends HTMLAttributes<HTMLDivElement> {
23
- /** Accessible name for this slide's generated scroll marker (WCAG). */
24
- 'data-name'?: string
25
- }
34
+ export type CarouselItemProps<T extends ElementType = 'div'> = PolymorphicProps<
35
+ T,
36
+ { /** Accessible name for this slide's generated scroll marker (WCAG). */ 'data-name'?: string }
37
+ >
26
38
 
27
39
  /** A slide. Defaults to `width: 100%` (one per page); override via `style`/`className`. */
28
- export function CarouselItem({ className, ...props }: CarouselItemProps) {
29
- return <div className={cn('sheerly-carousel-item', className)} {...props} />
40
+ export function CarouselItem<T extends ElementType = 'div'>({
41
+ as,
42
+ className,
43
+ ...props
44
+ }: CarouselItemProps<T>) {
45
+ const Tag = as ?? 'div'
46
+ return <Tag className={cn('sheerly-carousel-item', className)} {...props} />
30
47
  }
package/src/checkbox.tsx CHANGED
@@ -1,8 +1,14 @@
1
1
  import type { InputHTMLAttributes } from 'react'
2
- import { cn } from './cn'
2
+ import { cn } from './utils/cn'
3
3
 
4
4
  export type CheckboxProps = Omit<InputHTMLAttributes<HTMLInputElement>, 'type'>
5
5
 
6
+ /**
7
+ * A checkbox `<input>`. Pair with a <Label> for a clickable target.
8
+ *
9
+ * @example
10
+ * <Checkbox id="terms" defaultChecked />
11
+ */
6
12
  export function Checkbox({ className, ...props }: CheckboxProps) {
7
13
  return (
8
14
  <input type="checkbox" className={cn('sheerly-checkbox', className)} {...props} />
package/src/dialog.tsx CHANGED
@@ -1,39 +1,78 @@
1
- import type { ButtonHTMLAttributes, DialogHTMLAttributes, HTMLAttributes } from 'react'
2
- import { cn } from './cn'
1
+ import type { ButtonHTMLAttributes, DialogHTMLAttributes, ElementType } from 'react'
2
+ import { cn } from './utils/cn'
3
+ import type { PolymorphicProps } from './utils/polymorphic'
3
4
 
4
5
  /**
5
6
  * Native <dialog>. Open via invoker command (`command="show-modal"`) or
6
7
  * `.showModal()`. Add `closedby="any"` for light-dismiss.
8
+ *
9
+ * @example
10
+ * <button commandfor="d" command="show-modal">Open</button>
11
+ * <Dialog id="d" closedby="any">
12
+ * <DialogHeader><DialogTitle>Confirm</DialogTitle></DialogHeader>
13
+ * <DialogFooter><DialogClose command="close" commandfor="d">Cancel</DialogClose></DialogFooter>
14
+ * </Dialog>
7
15
  */
8
16
  export function Dialog({ className, ...props }: DialogHTMLAttributes<HTMLDialogElement>) {
9
17
  return <dialog className={cn('sheerly-dialog', className)} {...props} />
10
18
  }
11
19
 
12
- export function DialogHeader({ className, ...props }: HTMLAttributes<HTMLDivElement>) {
13
- return <div className={cn('sheerly-dialog-header', className)} {...props} />
14
- }
20
+ export type DialogHeaderProps<T extends ElementType = 'div'> = PolymorphicProps<T>
15
21
 
16
- export function DialogTitle({ className, ...props }: HTMLAttributes<HTMLHeadingElement>) {
17
- return <h3 className={cn('sheerly-dialog-title', className)} {...props} />
22
+ export function DialogHeader<T extends ElementType = 'div'>({
23
+ as,
24
+ className,
25
+ ...props
26
+ }: DialogHeaderProps<T>) {
27
+ const Tag = as ?? 'div'
28
+ return <Tag className={cn('sheerly-dialog-header', className)} {...props} />
18
29
  }
19
30
 
20
- export function DialogDescription({
31
+ export type DialogTitleProps<T extends ElementType = 'h3'> = PolymorphicProps<T>
32
+
33
+ export function DialogTitle<T extends ElementType = 'h3'>({
34
+ as,
21
35
  className,
22
36
  ...props
23
- }: HTMLAttributes<HTMLParagraphElement>) {
24
- return <p className={cn('sheerly-dialog-description', className)} {...props} />
37
+ }: DialogTitleProps<T>) {
38
+ const Tag = as ?? 'h3'
39
+ return <Tag className={cn('sheerly-dialog-title', className)} {...props} />
25
40
  }
26
41
 
27
- export function DialogBody({ className, ...props }: HTMLAttributes<HTMLDivElement>) {
28
- return <div className={cn('sheerly-dialog-body', className)} {...props} />
42
+ export type DialogDescriptionProps<T extends ElementType = 'p'> = PolymorphicProps<T>
43
+
44
+ export function DialogDescription<T extends ElementType = 'p'>({
45
+ as,
46
+ className,
47
+ ...props
48
+ }: DialogDescriptionProps<T>) {
49
+ const Tag = as ?? 'p'
50
+ return <Tag className={cn('sheerly-dialog-description', className)} {...props} />
29
51
  }
30
52
 
31
- export interface DialogFooterProps extends HTMLAttributes<HTMLDivElement> {
32
- 'data-direction'?: 'column'
53
+ export type DialogBodyProps<T extends ElementType = 'div'> = PolymorphicProps<T>
54
+
55
+ export function DialogBody<T extends ElementType = 'div'>({
56
+ as,
57
+ className,
58
+ ...props
59
+ }: DialogBodyProps<T>) {
60
+ const Tag = as ?? 'div'
61
+ return <Tag className={cn('sheerly-dialog-body', className)} {...props} />
33
62
  }
34
63
 
35
- export function DialogFooter({ className, ...props }: DialogFooterProps) {
36
- return <div className={cn('sheerly-dialog-footer', className)} {...props} />
64
+ export type DialogFooterProps<T extends ElementType = 'div'> = PolymorphicProps<
65
+ T,
66
+ { 'data-direction'?: 'column' }
67
+ >
68
+
69
+ export function DialogFooter<T extends ElementType = 'div'>({
70
+ as,
71
+ className,
72
+ ...props
73
+ }: DialogFooterProps<T>) {
74
+ const Tag = as ?? 'div'
75
+ return <Tag className={cn('sheerly-dialog-footer', className)} {...props} />
37
76
  }
38
77
 
39
78
  export function DialogClose({
@@ -1,9 +1,28 @@
1
- import type { AnchorHTMLAttributes, ButtonHTMLAttributes, HTMLAttributes } from 'react'
2
- import { cn } from './cn'
1
+ import type { ButtonHTMLAttributes, ElementType } from 'react'
2
+ import { cn } from './utils/cn'
3
+ import type { PolymorphicProps } from './utils/polymorphic'
3
4
 
4
- /** Wrapper carrying the anchor. Nest the trigger button + content inside. */
5
- export function DropdownMenu({ className, ...props }: HTMLAttributes<HTMLSpanElement>) {
6
- return <span className={cn('sheerly-dropdown-menu', className)} {...props} />
5
+ /**
6
+ * Wrapper carrying the anchor. Nest the trigger button + content inside.
7
+ *
8
+ * @example
9
+ * <DropdownMenu>
10
+ * <Button commandfor="m" command="toggle-popover">Open</Button>
11
+ * <DropdownMenuContent id="m" popover role="menu">
12
+ * <DropdownMenuItem>Profile</DropdownMenuItem>
13
+ * <DropdownMenuItem data-variant="destructive">Sign out</DropdownMenuItem>
14
+ * </DropdownMenuContent>
15
+ * </DropdownMenu>
16
+ */
17
+ export type DropdownMenuProps<T extends ElementType = 'span'> = PolymorphicProps<T>
18
+
19
+ export function DropdownMenu<T extends ElementType = 'span'>({
20
+ as,
21
+ className,
22
+ ...props
23
+ }: DropdownMenuProps<T>) {
24
+ const Tag = as ?? 'span'
25
+ return <Tag className={cn('sheerly-dropdown-menu', className)} {...props} />
7
26
  }
8
27
 
9
28
  /**
@@ -11,24 +30,42 @@ export function DropdownMenu({ className, ...props }: HTMLAttributes<HTMLSpanEle
11
30
  * `commandfor`, and `role="menu"`. When nested inside a <DropdownMenuSub> it is
12
31
  * automatically styled as a submenu panel (no extra attribute needed).
13
32
  */
14
- export type DropdownMenuContentProps = HTMLAttributes<HTMLDivElement>
15
-
16
- export function DropdownMenuContent({ className, ...props }: DropdownMenuContentProps) {
17
- return <div className={cn('sheerly-dropdown-menu-content', className)} {...props} />
33
+ export type DropdownMenuContentProps<T extends ElementType = 'div'> = PolymorphicProps<T>
34
+
35
+ export function DropdownMenuContent<T extends ElementType = 'div'>({
36
+ as,
37
+ className,
38
+ ...props
39
+ }: DropdownMenuContentProps<T>) {
40
+ const Tag = as ?? 'div'
41
+ return <Tag className={cn('sheerly-dropdown-menu-content', className)} {...props} />
18
42
  }
19
43
 
20
44
  /** A semantic wrapper for a set of related items/labels. */
21
- export function DropdownMenuGroup({ className, ...props }: HTMLAttributes<HTMLDivElement>) {
22
- return <div className={cn('sheerly-dropdown-menu-group', className)} {...props} />
45
+ export type DropdownMenuGroupProps<T extends ElementType = 'div'> = PolymorphicProps<T>
46
+
47
+ export function DropdownMenuGroup<T extends ElementType = 'div'>({
48
+ as,
49
+ className,
50
+ ...props
51
+ }: DropdownMenuGroupProps<T>) {
52
+ const Tag = as ?? 'div'
53
+ return <Tag className={cn('sheerly-dropdown-menu-group', className)} {...props} />
23
54
  }
24
55
 
25
56
  /** A non-interactive section heading. */
26
- export interface DropdownMenuLabelProps extends HTMLAttributes<HTMLDivElement> {
27
- 'data-inset'?: boolean
28
- }
29
-
30
- export function DropdownMenuLabel({ className, ...props }: DropdownMenuLabelProps) {
31
- return <div className={cn('sheerly-dropdown-menu-label', className)} {...props} />
57
+ export type DropdownMenuLabelProps<T extends ElementType = 'div'> = PolymorphicProps<
58
+ T,
59
+ { 'data-inset'?: boolean }
60
+ >
61
+
62
+ export function DropdownMenuLabel<T extends ElementType = 'div'>({
63
+ as,
64
+ className,
65
+ ...props
66
+ }: DropdownMenuLabelProps<T>) {
67
+ const Tag = as ?? 'div'
68
+ return <Tag className={cn('sheerly-dropdown-menu-label', className)} {...props} />
32
69
  }
33
70
 
34
71
  /** An interactive menu row. Renders a <button> by default. */
@@ -41,29 +78,69 @@ export function DropdownMenuItem({ className, type = 'button', ...props }: Dropd
41
78
  return <button type={type} className={cn('sheerly-dropdown-menu-item', className)} {...props} />
42
79
  }
43
80
 
44
- /** An interactive menu row rendered as a link (<a>). */
45
- export interface DropdownMenuLinkItemProps extends AnchorHTMLAttributes<HTMLAnchorElement> {
46
- 'data-variant'?: 'destructive'
47
- 'data-inset'?: boolean
48
- }
49
-
50
- export function DropdownMenuLinkItem({ className, ...props }: DropdownMenuLinkItemProps) {
51
- return <a className={cn('sheerly-dropdown-menu-item', className)} {...props} />
81
+ /**
82
+ * An interactive menu row rendered as a link.
83
+ *
84
+ * Polymorphic: pass `as` to change the rendered tag (defaults to `a`, e.g.
85
+ * `as={Link}` for a router link).
86
+ */
87
+ export type DropdownMenuLinkItemProps<T extends ElementType = 'a'> = PolymorphicProps<
88
+ T,
89
+ {
90
+ 'data-variant'?: 'destructive'
91
+ 'data-inset'?: boolean
92
+ }
93
+ >
94
+
95
+ export function DropdownMenuLinkItem<T extends ElementType = 'a'>({
96
+ as,
97
+ className,
98
+ ...props
99
+ }: DropdownMenuLinkItemProps<T>) {
100
+ const Tag = as ?? 'a'
101
+ return <Tag className={cn('sheerly-dropdown-menu-item', className)} {...props} />
52
102
  }
53
103
 
54
104
  /** A trailing keyboard-shortcut hint inside an item. */
55
- export function DropdownMenuShortcut({ className, ...props }: HTMLAttributes<HTMLSpanElement>) {
56
- return <span className={cn('sheerly-dropdown-menu-shortcut', className)} {...props} />
105
+ export type DropdownMenuShortcutProps<T extends ElementType = 'span'> = PolymorphicProps<T>
106
+
107
+ export function DropdownMenuShortcut<T extends ElementType = 'span'>({
108
+ as,
109
+ className,
110
+ ...props
111
+ }: DropdownMenuShortcutProps<T>) {
112
+ const Tag = as ?? 'span'
113
+ return <Tag className={cn('sheerly-dropdown-menu-shortcut', className)} {...props} />
57
114
  }
58
115
 
59
116
  /** A horizontal divider between item groups. */
60
- export function DropdownMenuSeparator({ className, ...props }: HTMLAttributes<HTMLDivElement>) {
61
- return <div role="separator" className={cn('sheerly-dropdown-menu-separator', className)} {...props} />
117
+ export type DropdownMenuSeparatorProps<T extends ElementType = 'div'> = PolymorphicProps<T>
118
+
119
+ export function DropdownMenuSeparator<T extends ElementType = 'div'>({
120
+ as,
121
+ className,
122
+ ...props
123
+ }: DropdownMenuSeparatorProps<T>) {
124
+ const Tag = as ?? 'div'
125
+ return (
126
+ <Tag
127
+ role="separator"
128
+ className={cn('sheerly-dropdown-menu-separator', className)}
129
+ {...props}
130
+ />
131
+ )
62
132
  }
63
133
 
64
134
  /** Submenu wrapper (display: contents). Nest a sub-trigger + a sub-content. */
65
- export function DropdownMenuSub({ className, ...props }: HTMLAttributes<HTMLDivElement>) {
66
- return <div className={cn('sheerly-dropdown-menu-sub', className)} {...props} />
135
+ export type DropdownMenuSubProps<T extends ElementType = 'div'> = PolymorphicProps<T>
136
+
137
+ export function DropdownMenuSub<T extends ElementType = 'div'>({
138
+ as,
139
+ className,
140
+ ...props
141
+ }: DropdownMenuSubProps<T>) {
142
+ const Tag = as ?? 'div'
143
+ return <Tag className={cn('sheerly-dropdown-menu-sub', className)} {...props} />
67
144
  }
68
145
 
69
146
  /**
@@ -83,6 +160,11 @@ export function DropdownMenuSubTrigger({ className, type = 'button', ...props }:
83
160
  * The submenu panel. It's a DropdownMenuContent nested inside a DropdownMenuSub;
84
161
  * the child-combinator CSS picks it up as a submenu — no extra attribute needed.
85
162
  */
86
- export function DropdownMenuSubContent({ className, ...props }: DropdownMenuContentProps) {
87
- return <div className={cn('sheerly-dropdown-menu-content', className)} {...props} />
163
+ export function DropdownMenuSubContent<T extends ElementType = 'div'>({
164
+ as,
165
+ className,
166
+ ...props
167
+ }: DropdownMenuContentProps<T>) {
168
+ const Tag = as ?? 'div'
169
+ return <Tag className={cn('sheerly-dropdown-menu-content', className)} {...props} />
88
170
  }
@@ -1,16 +1,35 @@
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 type HoverCardProps = HTMLAttributes<HTMLSpanElement>
5
+ export type HoverCardProps<T extends ElementType = 'span'> = PolymorphicProps<T>
5
6
 
6
- /** Wrapper carrying the anchor. Nest the trigger + content inside. */
7
- export function HoverCard({ className, ...props }: HoverCardProps) {
8
- return <span className={cn('sheerly-hover-card', className)} {...props} />
7
+ /**
8
+ * Wrapper carrying the anchor. Nest the trigger + content inside.
9
+ *
10
+ * @example
11
+ * <HoverCard>
12
+ * <a href="/user/ada" interestfor="hc">@ada</a>
13
+ * <HoverCardContent id="hc" popover="hint">Ada Lovelace — 1815</HoverCardContent>
14
+ * </HoverCard>
15
+ */
16
+ export function HoverCard<T extends ElementType = 'span'>({
17
+ as,
18
+ className,
19
+ ...props
20
+ }: HoverCardProps<T>) {
21
+ const Tag = as ?? 'span'
22
+ return <Tag className={cn('sheerly-hover-card', className)} {...props} />
9
23
  }
10
24
 
11
- export type HoverCardContentProps = HTMLAttributes<HTMLDivElement>
25
+ export type HoverCardContentProps<T extends ElementType = 'div'> = PolymorphicProps<T>
12
26
 
13
27
  /** The floating card. Give it `popover="hint"` and an `id` matched by the trigger's `interestfor`. */
14
- export function HoverCardContent({ className, ...props }: HoverCardContentProps) {
15
- return <div className={cn('sheerly-hover-card-content', className)} {...props} />
28
+ export function HoverCardContent<T extends ElementType = 'div'>({
29
+ as,
30
+ className,
31
+ ...props
32
+ }: HoverCardContentProps<T>) {
33
+ const Tag = as ?? 'div'
34
+ return <Tag className={cn('sheerly-hover-card-content', className)} {...props} />
16
35
  }
package/src/index.css CHANGED
@@ -19,6 +19,7 @@
19
19
  @import "./badge.css";
20
20
  @import "./alert.css";
21
21
  @import "./separator.css";
22
+ @import "./scrollbar.css";
22
23
  @import "./skeleton.css";
23
24
  @import "./spinner.css";
24
25
  @import "./avatar.css";
package/src/index.ts CHANGED
@@ -2,7 +2,6 @@
2
2
  // The core library is CSS-only; import this entry only if you want typed JSX.
3
3
  // You still need to import the stylesheet: `import 'sheerly/index.css'`.
4
4
 
5
- export * from './cn'
6
5
  export * from './accordion'
7
6
  export * from './alert'
8
7
  export * from './avatar'
@@ -22,6 +21,7 @@ export * from './pagination'
22
21
  export * from './popover'
23
22
  export * from './progress'
24
23
  export * from './radio'
24
+ export * from './scrollbar'
25
25
  export * from './select'
26
26
  export * from './separator'
27
27
  export * from './sheet'
package/src/input.css CHANGED
@@ -4,6 +4,7 @@
4
4
  min-width: 0;
5
5
  border-radius: var(--sheerly-radius-lg);
6
6
  border: 1px solid var(--sheerly-input);
7
+ box-sizing: border-box;
7
8
  background-color: transparent;
8
9
  padding: 0 10px;
9
10
  font-family: "Geist Sans", system-ui, -apple-system, sans-serif;
package/src/input.tsx CHANGED
@@ -1,10 +1,16 @@
1
1
  import type { InputHTMLAttributes } from 'react'
2
- import { cn } from './cn'
2
+ import { cn } from './utils/cn'
3
3
 
4
4
  export interface InputProps extends InputHTMLAttributes<HTMLInputElement> {
5
5
  'data-size'?: 'xs' | 'sm' | 'default' | 'lg'
6
6
  }
7
7
 
8
+ /**
9
+ * A text input. Set `aria-invalid` for the error ring; `data-size` for height.
10
+ *
11
+ * @example
12
+ * <Input type="email" placeholder="you@example.com" />
13
+ */
8
14
  export function Input({ className, ...props }: InputProps) {
9
15
  return <input className={cn('sheerly-input', className)} {...props} />
10
16
  }
package/src/kbd.tsx CHANGED
@@ -1,14 +1,26 @@
1
- import type { HTMLAttributes } from 'react'
2
- import { cn } from './cn'
1
+ import type { ElementType, HTMLAttributes } from 'react'
2
+ import { cn } from './utils/cn'
3
+ import type { PolymorphicProps } from './utils/polymorphic'
3
4
 
4
5
  export type KbdProps = HTMLAttributes<HTMLElement>
5
6
 
7
+ /**
8
+ * A keyboard key hint. Wrap several in a <KbdGroup> for combos.
9
+ *
10
+ * @example
11
+ * <KbdGroup><Kbd>⌘</Kbd><Kbd>K</Kbd></KbdGroup>
12
+ */
6
13
  export function Kbd({ className, ...props }: KbdProps) {
7
14
  return <kbd className={cn('sheerly-kbd', className)} {...props} />
8
15
  }
9
16
 
10
- export type KbdGroupProps = HTMLAttributes<HTMLElement>
17
+ export type KbdGroupProps<T extends ElementType = 'span'> = PolymorphicProps<T>
11
18
 
12
- export function KbdGroup({ className, ...props }: KbdGroupProps) {
13
- return <span className={cn('sheerly-kbd-group', className)} {...props} />
19
+ export function KbdGroup<T extends ElementType = 'span'>({
20
+ as,
21
+ className,
22
+ ...props
23
+ }: KbdGroupProps<T>) {
24
+ const Tag = as ?? 'span'
25
+ return <Tag className={cn('sheerly-kbd-group', className)} {...props} />
14
26
  }
package/src/label.css CHANGED
@@ -9,6 +9,7 @@
9
9
  line-height: 20px;
10
10
  color: var(--sheerly-foreground);
11
11
  user-select: none;
12
+ cursor: pointer;
12
13
 
13
14
  &[data-disabled="true"] {
14
15
  color: var(--sheerly-muted-foreground);
package/src/label.tsx CHANGED
@@ -1,10 +1,16 @@
1
1
  import type { LabelHTMLAttributes } from 'react'
2
- import { cn } from './cn'
2
+ import { cn } from './utils/cn'
3
3
 
4
4
  export interface LabelProps extends LabelHTMLAttributes<HTMLLabelElement> {
5
5
  'data-disabled'?: 'true'
6
6
  }
7
7
 
8
+ /**
9
+ * A form label. Set `data-disabled="true"` to mute it.
10
+ *
11
+ * @example
12
+ * <Label htmlFor="email">Email</Label>
13
+ */
8
14
  export function Label({ className, ...props }: LabelProps) {
9
15
  return <label className={cn('sheerly-label', className)} {...props} />
10
16
  }