rizzo-css 0.0.62 → 0.0.63

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 (171) hide show
  1. package/README.md +9 -5
  2. package/bin/rizzo-css.js +247 -27
  3. package/dist/rizzo.min.css +5 -3
  4. package/package.json +14 -7
  5. package/scaffold/astro/Footer.astro +8 -0
  6. package/scaffold/astro/Settings.astro +8 -2
  7. package/scaffold/astro/Tabs.astro +2 -2
  8. package/scaffold/react/Accordion.tsx +143 -0
  9. package/scaffold/react/Alert.tsx +90 -0
  10. package/scaffold/react/AlertDialog.tsx +80 -0
  11. package/scaffold/react/AspectRatio.tsx +32 -0
  12. package/scaffold/react/Avatar.tsx +53 -0
  13. package/scaffold/react/BackToTop.tsx +62 -0
  14. package/scaffold/react/Badge.tsx +39 -0
  15. package/scaffold/react/Breadcrumb.tsx +81 -0
  16. package/scaffold/react/Button.tsx +40 -0
  17. package/scaffold/react/ButtonGroup.tsx +24 -0
  18. package/scaffold/react/Card.tsx +26 -0
  19. package/scaffold/react/Checkbox.tsx +40 -0
  20. package/scaffold/react/Collapsible.tsx +58 -0
  21. package/scaffold/react/ContextMenu.tsx +67 -0
  22. package/scaffold/react/CopyToClipboard.tsx +128 -0
  23. package/scaffold/react/Dashboard.tsx +23 -0
  24. package/scaffold/react/Divider.tsx +47 -0
  25. package/scaffold/react/DocsSidebar.tsx +48 -0
  26. package/scaffold/react/Dropdown.tsx +256 -0
  27. package/scaffold/react/Empty.tsx +29 -0
  28. package/scaffold/react/FontSwitcher.tsx +68 -0
  29. package/scaffold/react/Footer.tsx +55 -0
  30. package/scaffold/react/FormGroup.tsx +57 -0
  31. package/scaffold/react/HoverCard.tsx +61 -0
  32. package/scaffold/react/Icons.tsx +22 -0
  33. package/scaffold/react/Input.tsx +69 -0
  34. package/scaffold/react/Kbd.tsx +16 -0
  35. package/scaffold/react/Label.tsx +16 -0
  36. package/scaffold/react/Modal.tsx +149 -0
  37. package/scaffold/react/Navbar.tsx +72 -0
  38. package/scaffold/react/Pagination.tsx +155 -0
  39. package/scaffold/react/Popover.tsx +66 -0
  40. package/scaffold/react/ProgressBar.tsx +66 -0
  41. package/scaffold/react/Radio.tsx +38 -0
  42. package/scaffold/react/ResizableHandle.tsx +24 -0
  43. package/scaffold/react/ResizablePane.tsx +29 -0
  44. package/scaffold/react/ResizablePaneGroup.tsx +29 -0
  45. package/scaffold/react/ScrollArea.tsx +29 -0
  46. package/scaffold/react/Search.tsx +62 -0
  47. package/scaffold/react/Select.tsx +65 -0
  48. package/scaffold/react/Separator.tsx +33 -0
  49. package/scaffold/react/Settings.tsx +60 -0
  50. package/scaffold/react/Sheet.tsx +86 -0
  51. package/scaffold/react/Skeleton.tsx +32 -0
  52. package/scaffold/react/Slider.tsx +66 -0
  53. package/scaffold/react/SoundEffects.tsx +15 -0
  54. package/scaffold/react/Spinner.tsx +36 -0
  55. package/scaffold/react/Switch.tsx +52 -0
  56. package/scaffold/react/Table.tsx +178 -0
  57. package/scaffold/react/Tabs.tsx +143 -0
  58. package/scaffold/react/Textarea.tsx +69 -0
  59. package/scaffold/react/ThemeSwitcher.tsx +89 -0
  60. package/scaffold/react/Toast.tsx +43 -0
  61. package/scaffold/react/Toggle.tsx +45 -0
  62. package/scaffold/react/ToggleGroup.tsx +34 -0
  63. package/scaffold/react/Tooltip.tsx +40 -0
  64. package/scaffold/vanilla/README-RIZZO.md +1 -1
  65. package/scaffold/vanilla/components/accordion.html +30 -0
  66. package/scaffold/vanilla/components/alert-dialog.html +30 -0
  67. package/scaffold/vanilla/components/alert.html +30 -0
  68. package/scaffold/vanilla/components/aspect-ratio.html +30 -0
  69. package/scaffold/vanilla/components/avatar.html +30 -0
  70. package/scaffold/vanilla/components/back-to-top.html +30 -0
  71. package/scaffold/vanilla/components/badge.html +30 -0
  72. package/scaffold/vanilla/components/breadcrumb.html +30 -0
  73. package/scaffold/vanilla/components/button-group.html +30 -0
  74. package/scaffold/vanilla/components/button.html +30 -0
  75. package/scaffold/vanilla/components/cards.html +30 -0
  76. package/scaffold/vanilla/components/collapsible.html +30 -0
  77. package/scaffold/vanilla/components/context-menu.html +30 -0
  78. package/scaffold/vanilla/components/copy-to-clipboard.html +30 -0
  79. package/scaffold/vanilla/components/dashboard.html +30 -0
  80. package/scaffold/vanilla/components/divider.html +30 -0
  81. package/scaffold/vanilla/components/docs-sidebar.html +30 -0
  82. package/scaffold/vanilla/components/dropdown.html +30 -0
  83. package/scaffold/vanilla/components/empty.html +30 -0
  84. package/scaffold/vanilla/components/font-switcher.html +30 -0
  85. package/scaffold/vanilla/components/footer.html +30 -0
  86. package/scaffold/vanilla/components/forms.html +30 -0
  87. package/scaffold/vanilla/components/hover-card.html +30 -0
  88. package/scaffold/vanilla/components/icons.html +30 -0
  89. package/scaffold/vanilla/components/index.html +30 -0
  90. package/scaffold/vanilla/components/kbd.html +30 -0
  91. package/scaffold/vanilla/components/label.html +30 -0
  92. package/scaffold/vanilla/components/modal.html +30 -0
  93. package/scaffold/vanilla/components/navbar.html +30 -0
  94. package/scaffold/vanilla/components/pagination.html +30 -0
  95. package/scaffold/vanilla/components/popover.html +30 -0
  96. package/scaffold/vanilla/components/progress-bar.html +30 -0
  97. package/scaffold/vanilla/components/resizable.html +30 -0
  98. package/scaffold/vanilla/components/scroll-area.html +30 -0
  99. package/scaffold/vanilla/components/search.html +30 -0
  100. package/scaffold/vanilla/components/separator.html +30 -0
  101. package/scaffold/vanilla/components/settings.html +30 -0
  102. package/scaffold/vanilla/components/sheet.html +30 -0
  103. package/scaffold/vanilla/components/skeleton.html +30 -0
  104. package/scaffold/vanilla/components/slider.html +30 -0
  105. package/scaffold/vanilla/components/sound-effects.html +30 -0
  106. package/scaffold/vanilla/components/spinner.html +30 -0
  107. package/scaffold/vanilla/components/switch.html +30 -0
  108. package/scaffold/vanilla/components/table.html +30 -0
  109. package/scaffold/vanilla/components/tabs.html +30 -0
  110. package/scaffold/vanilla/components/theme-switcher.html +30 -0
  111. package/scaffold/vanilla/components/toast.html +30 -0
  112. package/scaffold/vanilla/components/toggle-group.html +30 -0
  113. package/scaffold/vanilla/components/toggle.html +30 -0
  114. package/scaffold/vanilla/components/tooltip.html +30 -0
  115. package/scaffold/vanilla/index.html +30 -0
  116. package/scaffold/vue/Accordion.vue +9 -0
  117. package/scaffold/vue/Alert.vue +9 -0
  118. package/scaffold/vue/AlertDialog.vue +9 -0
  119. package/scaffold/vue/AspectRatio.vue +9 -0
  120. package/scaffold/vue/Avatar.vue +9 -0
  121. package/scaffold/vue/BackToTop.vue +9 -0
  122. package/scaffold/vue/Badge.vue +28 -0
  123. package/scaffold/vue/Breadcrumb.vue +9 -0
  124. package/scaffold/vue/Button.vue +23 -0
  125. package/scaffold/vue/ButtonGroup.vue +9 -0
  126. package/scaffold/vue/Card.vue +21 -0
  127. package/scaffold/vue/Checkbox.vue +31 -0
  128. package/scaffold/vue/Collapsible.vue +9 -0
  129. package/scaffold/vue/ContextMenu.vue +9 -0
  130. package/scaffold/vue/CopyToClipboard.vue +9 -0
  131. package/scaffold/vue/Dashboard.vue +9 -0
  132. package/scaffold/vue/Divider.vue +23 -0
  133. package/scaffold/vue/DocsSidebar.vue +9 -0
  134. package/scaffold/vue/Dropdown.vue +9 -0
  135. package/scaffold/vue/Empty.vue +9 -0
  136. package/scaffold/vue/FontSwitcher.vue +9 -0
  137. package/scaffold/vue/Footer.vue +9 -0
  138. package/scaffold/vue/FormGroup.vue +45 -0
  139. package/scaffold/vue/HoverCard.vue +9 -0
  140. package/scaffold/vue/Icons.vue +9 -0
  141. package/scaffold/vue/Input.vue +59 -0
  142. package/scaffold/vue/Kbd.vue +9 -0
  143. package/scaffold/vue/Label.vue +23 -0
  144. package/scaffold/vue/Modal.vue +9 -0
  145. package/scaffold/vue/Navbar.vue +9 -0
  146. package/scaffold/vue/Pagination.vue +9 -0
  147. package/scaffold/vue/Popover.vue +9 -0
  148. package/scaffold/vue/ProgressBar.vue +9 -0
  149. package/scaffold/vue/Radio.vue +29 -0
  150. package/scaffold/vue/ResizableHandle.vue +9 -0
  151. package/scaffold/vue/ResizablePane.vue +9 -0
  152. package/scaffold/vue/ResizablePaneGroup.vue +9 -0
  153. package/scaffold/vue/ScrollArea.vue +9 -0
  154. package/scaffold/vue/Search.vue +9 -0
  155. package/scaffold/vue/Select.vue +52 -0
  156. package/scaffold/vue/Separator.vue +9 -0
  157. package/scaffold/vue/Settings.vue +9 -0
  158. package/scaffold/vue/Sheet.vue +9 -0
  159. package/scaffold/vue/Skeleton.vue +9 -0
  160. package/scaffold/vue/Slider.vue +9 -0
  161. package/scaffold/vue/SoundEffects.vue +9 -0
  162. package/scaffold/vue/Spinner.vue +21 -0
  163. package/scaffold/vue/Switch.vue +9 -0
  164. package/scaffold/vue/Table.vue +9 -0
  165. package/scaffold/vue/Tabs.vue +9 -0
  166. package/scaffold/vue/Textarea.vue +60 -0
  167. package/scaffold/vue/ThemeSwitcher.vue +9 -0
  168. package/scaffold/vue/Toast.vue +9 -0
  169. package/scaffold/vue/Toggle.vue +9 -0
  170. package/scaffold/vue/ToggleGroup.vue +9 -0
  171. package/scaffold/vue/Tooltip.vue +9 -0
@@ -29,7 +29,9 @@ a.docs-layout-demo__nav-link--active{color:var(--accent-text)!important}::-moz-s
29
29
  .btn,button{background-color:var(--accent);border:var(--border-width) solid var(--border);border-radius:var(--radius-md);color:var(--accent-text);cursor:pointer;font-family:var(--font-family);font-size:inherit;padding:var(--spacing-2) var(--spacing-4);transition:background-color var(--transition-base),border-color var(--transition-base),color var(--transition-base)}
30
30
  .btn:hover,button:hover{background-color:var(--accent-hover);border-color:var(--accent-hover);color:var(--accent-text-on-hover)}
31
31
  .btn:active,button:active{opacity:var(--opacity-90)}
32
- .btn:disabled,button:disabled{cursor:not-allowed;opacity:var(--opacity-50)}.btn-primary:disabled:hover{background-color:var(--accent);color:var(--accent-text)}.btn-success:disabled:hover{background-color:var(--success);color:var(--success-text-on-solid)}.btn-warning:disabled:hover{background-color:var(--warning);color:var(--warning-text-on-solid)}.btn-error:disabled:hover{background-color:var(--error);color:var(--error-text-on-solid)}.btn-info:disabled:hover{background-color:var(--info);color:var(--info-text-on-solid)}.btn-primary{background-color:var(--accent);color:var(--accent-text)}.btn-primary:hover{background-color:var(--accent-hover);color:var(--accent-text-on-hover)}.btn-success{background-color:var(--success);color:var(--success-text-on-solid)}.btn-success:hover{background-color:var(--success-hover);color:var(--text-on-solid-hover)}.btn-warning{background-color:var(--warning);color:var(--warning-text-on-solid)}.btn-warning:hover{background-color:var(--warning-hover);color:var(--text-on-solid-hover)}.btn-error{background-color:var(--error);color:var(--error-text-on-solid)}.btn-error:hover{background-color:var(--error-hover);color:var(--text-on-solid-hover)}.btn-info{background-color:var(--info);color:var(--info-text-on-solid)}.btn-info:hover{background-color:var(--info-hover);color:var(--text-on-solid-hover)}.btn-outline{background-color:transparent;border:var(--border-width) solid var(--accent-fg);color:var(--accent-fg)}.btn-outline:hover{background-color:var(--accent);color:var(--accent-text)}
32
+ .btn:disabled,button:disabled{cursor:not-allowed;opacity:var(--opacity-50)}.btn-primary:disabled:hover{background-color:var(--accent);color:var(--accent-text)}.btn-success:disabled:hover{background-color:var(--success);color:var(--success-text-on-solid)}.btn-warning:disabled:hover{background-color:var(--warning);color:var(--warning-text-on-solid)}.btn-error:disabled:hover{background-color:var(--error);color:var(--error-text-on-solid)}.btn-info:disabled:hover{background-color:var(--info);color:var(--info-text-on-solid)}.btn-primary{background-color:var(--accent);color:var(--accent-text)}.btn-primary:hover{background-color:var(--accent-hover);color:var(--accent-text-on-hover)}a.btn-primary,
33
+ a.btn-primary:visited{color:var(--accent-text)!important}a.btn-primary:hover,
34
+ a.btn-primary:visited:hover{color:var(--accent-text-on-hover)!important}.btn-success{background-color:var(--success);color:var(--success-text-on-solid)}.btn-success:hover{background-color:var(--success-hover);color:var(--text-on-solid-hover)}.btn-warning{background-color:var(--warning);color:var(--warning-text-on-solid)}.btn-warning:hover{background-color:var(--warning-hover);color:var(--text-on-solid-hover)}.btn-error{background-color:var(--error);color:var(--error-text-on-solid)}.btn-error:hover{background-color:var(--error-hover);color:var(--text-on-solid-hover)}.btn-info{background-color:var(--info);color:var(--info-text-on-solid)}.btn-info:hover{background-color:var(--info-hover);color:var(--text-on-solid-hover)}.btn-outline{background-color:transparent;border:var(--border-width) solid var(--accent-fg);color:var(--accent-fg)}.btn-outline:hover{background-color:var(--accent);color:var(--accent-text)}
33
35
  input[type="date"],
34
36
  input[type="datetime-local"],
35
37
  input[type="email"],
@@ -121,7 +123,7 @@ div.navbar__link{background:none;border:none;color:inherit;cursor:pointer;font:i
121
123
  .reduced-motion .modal,.reduced-motion .modal__overlay{transition:none}@media (width <= 640px){.modal{bottom:auto;left:auto;margin:var(--spacing-4);max-height:95vh;max-width:95vw;right:auto;top:auto}.modal,.modal[aria-hidden="false"]{transform:none}
122
124
  .modal__body,
123
125
  .modal__footer,.modal__header{padding:var(--spacing-4)}}.copy-to-clipboard{align-items:center;background-color:var(--background-alt);border:var(--border-width) solid var(--border);border-radius:var(--radius-md);color:var(--text);cursor:pointer;display:inline-flex;font-family:var(--font-family-mono);font-size:var(--font-size-sm);gap:var(--spacing-2);padding:var(--spacing-2) var(--spacing-3);position:relative;transition:background-color var(--transition-base),border-color var(--transition-base),color var(--transition-base)}.copy-to-clipboard:hover{background-color:var(--background);border-color:var(--accent);color:var(--accent)}.copy-to-clipboard:focus-visible{outline:var(--outline-width) solid var(--accent);outline-offset:var(--outline-offset)}.copy-to-clipboard__text{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.copy-to-clipboard__icon{align-items:center;color:var(--icon);display:flex;flex-shrink:0;height:var(--spacing-4);justify-content:center;transition:opacity var(--transition-base),transform var(--transition-base);width:var(--spacing-4)}.copy-to-clipboard__icon--check{opacity:0;position:absolute;right:var(--spacing-3);transform:scale(var(--scale-80))}.copy-to-clipboard__icon--check:not(.copy-to-clipboard__icon--hidden){opacity:1;transform:scale(var(--scale-100))}.copy-to-clipboard__icon--copy.copy-to-clipboard__icon--hidden{opacity:0;transform:scale(var(--scale-80))}.copy-to-clipboard__feedback{border-width:0;clip-path:inset(50%);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;white-space:nowrap;width:1px}.copy-to-clipboard--icon-only{padding:var(--spacing-2)}.copy-to-clipboard--icon-only .copy-to-clipboard__text{border-width:0;clip-path:inset(50%);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;white-space:nowrap;width:1px}.copy-to-clipboard--icon-only .copy-to-clipboard__icon--check{right:var(--spacing-2)}.alert{align-items:flex-start;background-color:var(--alert-bg);border:var(--border-width) solid var(--border);border-radius:var(--radius-lg);box-sizing:border-box;color:var(--text);display:flex;gap:var(--spacing-3);margin-bottom:var(--spacing-3);min-width:0;padding:var(--spacing-4) var(--spacing-5);position:relative;transition:opacity var(--transition-base),transform var(--transition-base);width:100%}.alert:last-child{margin-bottom:0}.alert__content{flex:1;min-width:0}.alert__close{align-items:center;background:none;border:1px solid transparent;border-radius:var(--radius);color:inherit;cursor:pointer;display:flex;fill:none;flex-shrink:0;height:var(--spacing-6);justify-content:center;margin:calc(var(--spacing-1)*-1) calc(var(--spacing-2)*-1) calc(var(--spacing-1)*-1) 0;opacity:var(--opacity-80);padding:0;stroke:currentcolor;transition:opacity var(--transition-base),background-color var(--transition-base),border-color var(--transition-base),color var(--transition-base);width:var(--spacing-6)}.alert__close:hover{background-color:oklch(from var(--background) l c h/25%);border-color:var(--border);color:var(--text);opacity:1}.alert__close:focus-visible{opacity:1;outline:var(--outline-width) solid currentcolor;outline-offset:var(--outline-offset)}.alert--success{background-color:var(--alert-success-bg);border-color:var(--success);color:var(--success-text)}.alert--error{background-color:var(--alert-error-bg);border-color:var(--error);color:var(--error-text)}.alert--warning{background-color:var(--alert-warning-bg);border-color:var(--warning)}.alert--warning,.alert--warning .alert__content,
124
- .alert--warning .alert__content strong{color:var(--warning-text)}.alert--warning .alert__close{color:var(--warning-text);opacity:.9}.alert--warning .alert__close:hover{color:var(--text)}.alert--info{background-color:var(--alert-info-bg);border-color:var(--info);color:var(--info-text)}.alert-examples-container{align-items:stretch;display:flex;flex-direction:column;justify-content:center;min-height:8rem}.toast{max-width:var(--spacing-96);pointer-events:none;position:fixed;width:100%;z-index:var(--z-toast)}.toast .alert{box-shadow:var(--shadow-lg);margin-bottom:var(--spacing-2);pointer-events:auto}
126
+ .alert--warning .alert__content strong{color:var(--warning-text)}.alert--warning .alert__close{color:var(--warning-text);opacity:.9}.alert--warning .alert__close:hover{color:var(--text)}.alert--info{background-color:var(--alert-info-bg);border-color:var(--info);color:var(--info-text)}.alert-examples-container{align-items:stretch;display:flex;flex-direction:column;justify-content:center;min-height:8rem}.example{background:var(--background-alt);border:1px solid var(--border);border-radius:var(--radius-lg);margin:var(--spacing-6) 0;padding:var(--spacing-4)}.example-title{color:var(--text-dim);font-size:var(--font-size-sm);font-weight:var(--font-weight-medium);letter-spacing:var(--letter-spacing-wider);margin-bottom:var(--spacing-3);text-transform:uppercase}.example-demo{align-items:center;display:flex;flex-wrap:wrap;gap:var(--spacing-3)}.toast{max-width:var(--spacing-96);pointer-events:none;position:fixed;width:100%;z-index:var(--z-toast)}.toast .alert{box-shadow:var(--shadow-lg);margin-bottom:var(--spacing-2);pointer-events:auto}
125
127
  .toast--bottom-right .alert,.toast--top-right .alert{animation:toast-slide-in-right var(--transition-slow) ease-out}
126
128
  .toast--bottom-left .alert,.toast--top-left .alert{animation:toast-slide-in-left var(--transition-slow) ease-out}
127
129
  .toast--bottom-center .alert,.toast--top-center .alert{animation:toast-slide-in-down var(--transition-slow) ease-out}@keyframes toast-slide-in-right{from{opacity:0;transform:translateX(100%)}to{opacity:1;transform:translateX(0)}}@keyframes toast-slide-in-left{from{opacity:0;transform:translateX(-100%)}to{opacity:1;transform:translateX(0)}}@keyframes toast-slide-in-down{from{opacity:0;transform:translateY(-100%)}to{opacity:1;transform:translateY(0)}}.reduced-motion .toast .alert{animation:none}.toast--top-right{right:var(--spacing-4)}.toast--top-left,.toast--top-right{top:var(--toast-top-offset,var(--spacing-4))}.toast--top-left{left:var(--spacing-4)}.toast--top-center{left:50%;top:var(--toast-top-offset,var(--spacing-4));transform:translateX(-50%)}.toast--bottom-right{bottom:var(--spacing-4);right:var(--spacing-4)}.toast--bottom-left{bottom:var(--spacing-4);left:var(--spacing-4)}.toast--bottom-center{bottom:var(--spacing-4);left:50%;transform:translateX(-50%)}.toast-container{display:flex;flex-direction:column;gap:var(--spacing-2);pointer-events:none;position:fixed;z-index:var(--z-toast)}.toast-container--top-right{align-items:flex-end;right:var(--spacing-4);top:var(--toast-top-offset,var(--spacing-4))}.toast-container--top-left{align-items:flex-start;left:var(--spacing-4);top:var(--toast-top-offset,var(--spacing-4))}.toast-container--top-center{align-items:center;left:50%;top:var(--toast-top-offset,var(--spacing-4));transform:translateX(-50%)}.toast-container--bottom-right{align-items:flex-end;bottom:var(--spacing-4);right:var(--spacing-4)}.toast-container--bottom-left{align-items:flex-start;bottom:var(--spacing-4);left:var(--spacing-4)}.toast-container--bottom-center{align-items:center;bottom:var(--spacing-4);left:50%;transform:translateX(-50%)}.toast-container .alert{box-shadow:var(--shadow-lg);max-width:24rem;pointer-events:auto;width:100%}
@@ -190,7 +192,7 @@ div.navbar__link{background:none;border:none;color:inherit;cursor:pointer;font:i
190
192
  .button-group :global(button:last-child){border-radius:0 var(--radius) var(--radius) 0}.button-group--vertical :global(.btn:first-child),
191
193
  .button-group--vertical :global(button:first-child){border-radius:var(--radius) var(--radius) 0 0}.button-group--vertical :global(.btn:last-child),
192
194
  .button-group--vertical :global(button:last-child){border-radius:0 0 var(--radius) var(--radius)}.empty{padding:var(--spacing-12) var(--spacing-6);text-align:center}.empty,.empty__icon{color:var(--text-dim)}.empty__icon{margin-bottom:var(--spacing-4)}.empty__icon:empty{display:none}.empty__title{color:var(--text);font-size:var(--font-size-lg);font-weight:var(--font-weight-semibold);margin:0 0 var(--spacing-2) 0}.empty__description{font-size:var(--font-size-sm);margin:0 0 var(--spacing-5) 0}.empty__action:empty{display:none}.separator{background:var(--border);flex-shrink:0}.separator--horizontal{height:1px;width:100%}.separator--vertical{height:100%;min-height:1em;width:1px}.slider{padding:var(--spacing-3) 0;position:relative;width:100%}.slider__input{cursor:pointer;height:100%;margin:0;opacity:0;position:absolute;width:100%}.slider__track{background:var(--background-alt);height:var(--spacing-1);overflow:hidden}.slider__fill,.slider__track{border-radius:var(--radius-full)}.slider__fill{background:var(--accent);height:100%;transition:width var(--transition-fast)}.sheet__overlay{background:oklch(from var(--background) l c h/70%);inset:0;opacity:0;position:fixed;transition:opacity var(--transition-base),visibility var(--transition-base);visibility:hidden;z-index:var(--z-sheet-overlay,9998)}.sheet__overlay--open{opacity:1;visibility:visible}.sheet{background:var(--background);border:var(--border-width) solid var(--border);box-shadow:var(--shadow-lg);max-height:100%;max-width:100%;overflow:auto;position:fixed;transition:transform var(--transition-base);z-index:var(--z-sheet,9999)}.sheet--right{height:100%;right:0;top:0;transform:translateX(100%);width:min(100%,var(--spacing-150))}.sheet--right.sheet--open{transform:translateX(0)}.sheet--left{height:100%;left:0;top:0;transform:translateX(-100%);width:min(100%,var(--spacing-150))}.sheet--left.sheet--open{transform:translateX(0)}.sheet--top{left:0;max-height:90vh;right:0;top:0;transform:translateY(-100%)}.sheet--top.sheet--open{transform:translateY(0)}.sheet--bottom{bottom:0;left:0;max-height:90vh;right:0;transform:translateY(100%)}.sheet--bottom.sheet--open{transform:translateY(0)}.sheet__content{display:flex;flex-direction:column;height:100%;min-height:0}.sheet__header{align-items:center;border-bottom:var(--border-width) solid var(--border);display:flex;flex-shrink:0;justify-content:space-between;padding:var(--spacing-5)}.sheet__title{font-size:var(--font-size-lg);font-weight:var(--font-weight-semibold);margin:0}.sheet__close{background:transparent;border:none;border-radius:var(--radius);color:var(--text);cursor:pointer;padding:var(--spacing-2)}.sheet__close:hover{background:var(--background-alt)}.sheet__body{flex:1;overflow:auto;padding:var(--spacing-5)}.popover{display:inline-block;position:relative}.popover__content{background:var(--background);border:var(--border-width) solid var(--border);border-radius:var(--radius-lg);box-shadow:var(--shadow-md);margin-top:var(--spacing-1);min-width:var(--spacing-56);opacity:0;padding:var(--spacing-4);position:absolute;transition:opacity var(--transition-fast),visibility var(--transition-fast);visibility:hidden;z-index:var(--z-popover,100)}.popover__content--open{opacity:1;visibility:visible}.toggle{align-items:center;background:var(--background-alt);border:var(--border-width) solid var(--border);border-radius:var(--radius);color:var(--text);cursor:pointer;display:inline-flex;font-size:var(--font-size-sm);font-weight:var(--font-weight-medium);justify-content:center;padding:var(--spacing-2) var(--spacing-4);transition:background-color var(--transition-fast),border-color var(--transition-fast)}.toggle:hover{background:var(--background);border-color:var(--border)}.toggle--pressed,
193
- .toggle[aria-pressed="true"]{background:var(--accent);border-color:var(--accent);color:var(--accent-text)}.toggle-group{display:inline-flex;flex-direction:row;gap:0}.toggle-group--vertical{flex-direction:column}.toggle-group :global(.toggle){border-radius:0}.toggle-group :global(.toggle:first-child){border-radius:var(--radius) 0 0 var(--radius)}.toggle-group :global(.toggle:last-child){border-radius:0 var(--radius) var(--radius) 0}.toggle-group--vertical :global(.toggle:first-child){border-radius:var(--radius) var(--radius) 0 0}.toggle-group--vertical :global(.toggle:last-child){border-radius:0 0 var(--radius) var(--radius)}.tabs{width:100%}.tabs__list{border-bottom:var(--outline-width) solid var(--border);display:flex;gap:var(--spacing-1);margin-bottom:var(--spacing-6);overflow-x:auto;scrollbar-width:thin;-webkit-overflow-scrolling:touch}.tabs__list::-webkit-scrollbar{height:var(--spacing-0-125)}.tabs__list::-webkit-scrollbar-track{background:var(--background-alt)}.tabs__list::-webkit-scrollbar-thumb{background:var(--border);border-radius:var(--radius)}.tabs__tab{align-items:center;background:transparent;border:none;border-bottom:calc(var(--outline-width)*2) solid transparent;border-radius:var(--radius-md) var(--radius-md) 0 0;color:var(--text-dim);cursor:pointer;display:inline-flex;font-family:var(--font-family);font-size:var(--font-size-base);font-weight:var(--font-weight-medium);gap:var(--spacing-2);justify-content:center;margin-bottom:calc(var(--outline-width)*-1*2);min-height:var(--touch-target-min);outline:none;padding:var(--spacing-3) var(--spacing-5);position:relative;transition:color var(--transition-base),border-color var(--transition-base),background-color var(--transition-base);white-space:nowrap}.tabs__tab-icon{flex-shrink:0;vertical-align:middle}.tabs__tab:hover:not(.tabs__tab--active){background-color:var(--background-alt);color:var(--text)}.tabs__tab:focus-visible{border-radius:var(--radius-md) var(--radius-md) 0 0;outline:var(--outline-width) solid var(--accent);outline-offset:var(--outline-offset)}.tabs__tab--active{border-bottom-color:var(--accent-fg);border-bottom-width:calc(var(--outline-width)*3);font-weight:var(--font-weight-semibold)}.tabs__tab--active,.tabs__tab--active:hover{background-color:var(--background-alt);color:var(--accent-fg)}.tabs__tab--active:hover{border-bottom-color:var(--accent-fg)}.tabs__panels-wrapper{width:100%}.tabs__panel{display:none;min-height:var(--spacing-20);padding:var(--spacing-6) 0;width:100%}.tabs__panel--active{animation:fadeIn var(--transition-base);display:block}.tabs__panel-content{width:100%}@keyframes fade-in{from{opacity:0;transform:translateY(var(--spacing-1))}to{opacity:1;transform:translateY(0)}}.tabs__slot-content{display:none}.tabs--pills .tabs__list{border-bottom:none;gap:var(--spacing-2)}.tabs--pills .tabs__tab{border-bottom:none;border-radius:var(--radius-md);margin-bottom:0}.tabs--pills .tabs__tab--active{background-color:var(--accent);border-bottom-color:transparent;color:var(--accent-text)}.tabs--pills .tabs__tab--active:hover{background-color:var(--accent-hover);color:var(--accent-text)}.tabs--underline .tabs__list{border-bottom:var(--outline-width) solid var(--border)}.tabs--underline .tabs__tab{border-bottom:var(--outline-width) solid transparent;padding-bottom:var(--spacing-3)}.tabs--underline .tabs__tab--active{border-bottom-color:var(--accent-fg);border-bottom-width:calc(var(--outline-width)*2)}@media (width <= 640px){.tabs__list{gap:var(--spacing-1)}.tabs__tab{font-size:var(--font-size-sm);padding:var(--spacing-2) var(--spacing-3)}.tabs__panel{padding:var(--spacing-3) 0}}@media (prefers-reduced-motion:reduce){.tabs__tab{transition:none}.tabs__panel--active{animation:none}}.progress{display:flex;flex-direction:column;gap:var(--spacing-2);width:100%}.progress__track{background-color:var(--background-alt);border:var(--border-width) solid var(--border);overflow:hidden;width:100%}.progress__bar,.progress__track{border-radius:var(--radius-full)}.progress__bar{flex-shrink:0;height:100%;min-height:var(--spacing-2);transition:width var(--transition-slow) var(--ease-in-out-cubic)}.progress--sm .progress__track{height:var(--spacing-1)}.progress--sm .progress__bar{min-height:var(--spacing-1)}.progress--md .progress__track{height:var(--spacing-2)}.progress--md .progress__bar{min-height:var(--spacing-2)}.progress--lg .progress__track{height:var(--spacing-3)}.progress--lg .progress__bar{min-height:var(--spacing-3)}.progress--primary .progress__bar{background-color:var(--accent)}.progress--success .progress__bar{background-color:var(--success)}.progress--warning .progress__bar{background-color:var(--warning)}.progress--error .progress__bar{background-color:var(--error)}.progress--info .progress__bar{background-color:var(--info)}.progress__label{color:var(--text-dim);font-size:var(--font-size-sm);text-align:right}.progress--indeterminate .progress__bar{animation:progress-indeterminate 1.5s ease-in-out infinite;min-width:30%;width:30%!important}@keyframes progress-indeterminate{0%{transform:translateX(-100%)}100%{transform:translateX(233.333%)}}@media (prefers-reduced-motion:reduce){.progress__bar{transition:none}.progress--indeterminate .progress__bar{animation:none;opacity:.7;width:50%!important}}.spinner{align-items:center;display:inline-flex;justify-content:center;vertical-align:middle}.spinner__ring{animation:spinner-rotate .8s linear infinite;border-color:var(--border);border-radius:var(--radius-full);border-style:solid;border-top-color:currentcolor;display:block}.spinner--sm .spinner__ring{border-width:var(--border-width-2);height:var(--spacing-4);width:var(--spacing-4)}.spinner--md .spinner__ring{border-width:var(--border-width-3);height:var(--spacing-6);width:var(--spacing-6)}.spinner--lg .spinner__ring{border-width:var(--border-width-4);height:var(--spacing-8);width:var(--spacing-8)}.spinner--primary{color:var(--accent)}.spinner--success{color:var(--success)}.spinner--warning{color:var(--warning)}.spinner--error{color:var(--error)}.spinner--info{color:var(--info)}@keyframes spinner-rotate{to{transform:rotate(1turn)}}@media (prefers-reduced-motion:reduce){.spinner__ring{animation:none;border-bottom-color:transparent;border-left-color:transparent;border-right-color:transparent}}.avatar{align-items:center;background-color:var(--background-alt);border:var(--border-width) solid var(--border);color:var(--text-dim);display:inline-flex;flex-shrink:0;font-size:inherit;font-weight:var(--font-weight-semibold);justify-content:center;line-height:1;overflow:hidden}.avatar__img{display:block;height:100%;-o-object-fit:cover;object-fit:cover;width:100%}.avatar__initials{align-items:center;display:flex;height:100%;justify-content:center;width:100%}.avatar--sm{font-size:var(--font-size-xs);height:var(--spacing-8);width:var(--spacing-8)}.avatar--md{font-size:var(--font-size-sm);height:var(--spacing-10);width:var(--spacing-10)}.avatar--lg{font-size:var(--font-size-base);height:var(--spacing-12);width:var(--spacing-12)}.avatar--circle{border-radius:var(--radius-full)}.avatar--square{border-radius:var(--radius-md)}.divider{align-items:center;color:var(--text-dim);display:flex;font-size:var(--font-size-sm);gap:var(--spacing-3)}.divider__line{border:none;border-left:none;border-top:var(--border-width) solid var(--border);flex:1;min-height:0;min-width:0}.divider__label{flex-shrink:0;padding:0 var(--spacing-2);white-space:nowrap}.divider--horizontal{width:100%}.divider--horizontal .divider__line{border-left:none;border-top:var(--border-width) solid var(--border)}.divider--vertical{flex-direction:column;height:100%;min-height:var(--spacing-8);width:auto}.divider--vertical .divider__line{border-left:var(--border-width) solid var(--border);border-top:none;flex:1;min-height:var(--spacing-4);width:0}.footer{background-color:var(--background-alt);border-top:var(--border-width) solid var(--border);color:var(--text-dim);font-size:var(--font-size-sm);margin-top:auto;padding:var(--spacing-6) 0}.footer__container{box-sizing:border-box;margin-left:auto;margin-right:auto;max-width:var(--container-default);padding-left:var(--content-padding-x);padding-right:var(--content-padding-x);width:100%}.footer__inner{align-items:center;display:flex;flex-wrap:wrap;gap:var(--spacing-4);justify-content:space-between}.footer__copyright{color:var(--text-dim);margin:0}.footer__site-name{color:var(--text);font-weight:var(--font-weight-medium)}.footer__nav{margin:0}.footer__links{align-items:center;display:flex;flex-wrap:wrap;gap:var(--spacing-2) var(--spacing-4);list-style:none;margin:0;padding:0}.footer__link-item{margin:0}.footer__link{color:var(--text);text-decoration:none;transition:color var(--transition-base)}.footer__link:hover{color:var(--accent-fg)}.footer__link:focus-visible{outline:var(--outline-width) solid var(--accent);outline-offset:var(--outline-offset)}@media (width <= 1024px){.footer{padding-bottom:calc(var(--spacing-6) + var(--spacing-10) + var(--spacing-6))}}.table{display:flex;flex-direction:column;gap:var(--spacing-3);width:100%}.table__filter-wrap{align-items:center;display:flex;flex-shrink:0;position:relative}.table__filter-icon{align-items:center;color:var(--icon-dim);display:flex;justify-content:center;left:var(--spacing-3);pointer-events:none;position:absolute;top:50%;transform:translateY(-50%)}.table__filter-icon-svg{color:currentcolor;height:var(--table-filter-icon-size,1.25rem);width:var(--table-filter-icon-size,1.25rem)}.table__filter-wrap:focus-within .table__filter-icon{color:var(--accent)}.table__filter-wrap .table__filter{background-color:var(--background);border:var(--border-width) solid var(--border);border-radius:var(--radius-md);color:var(--text);font-family:var(--font-family);font-size:var(--font-size-base);max-width:var(--spacing-80);padding-bottom:var(--spacing-2);padding-left:3.5rem;padding-right:var(--spacing-3);padding-top:var(--spacing-2);width:100%}.table__filter-wrap .table__filter::-moz-placeholder{color:var(--text-dim)}.table__filter-wrap .table__filter::placeholder{color:var(--text-dim)}.table__filter-wrap .table__filter:focus{outline:var(--outline-width) solid var(--accent);outline-offset:var(--outline-offset)}.table__wrapper{min-width:0;overflow-x:auto;width:100%;-webkit-overflow-scrolling:touch}.table__table{border-collapse:collapse;border-spacing:0;font-size:var(--font-size-sm);width:100%}.table__caption{color:var(--text);font-weight:var(--font-weight-semibold);padding:var(--spacing-2) 0;text-align:left}.table__head .table__row{border-bottom:var(--border-width-2) solid var(--border)}.table__cell{border-bottom:var(--border-width) solid var(--border);color:var(--text);padding:var(--spacing-3) var(--spacing-4);text-align:left}.table__cell--head{color:var(--text);font-weight:var(--font-weight-semibold);white-space:nowrap}.table__sort-trigger{align-items:center;-webkit-appearance:none;-moz-appearance:none;appearance:none;background:none;border:none;border-radius:var(--radius-md);color:var(--text);cursor:pointer;display:inline-flex;font:inherit;font-weight:var(--font-weight-semibold);padding:0;text-align:left;transition:background-color var(--transition-fast),color var(--transition-fast);width:100%}.table__sort-trigger:hover{background-color:var(--background-alt);color:var(--text)}.table__sort-trigger:hover .table__sort-icon-svg{color:var(--accent)}.table__sort-trigger:focus-visible{outline:var(--outline-width) solid var(--accent);outline-offset:var(--outline-offset)}.table--sortable .table__cell--head{padding:0}.table--sortable .table__cell--head .table__sort-trigger{padding:var(--spacing-3) var(--spacing-4)}.table__cell-content{display:inline-block}.table__sort-icon{align-items:center;display:inline-flex;flex-shrink:0;justify-content:center;margin-left:var(--spacing-2)}.table__sort-icon-svg{color:var(--icon-dim);height:var(--table-sort-icon-size,1.25rem);transition:color var(--transition-fast);width:var(--table-sort-icon-size,1.25rem)}.table__body .table__row:hover{background-color:var(--background-alt)}.table__body .table__row:hover .table__cell{color:var(--text)}.table--striped .table__body .table__row:nth-child(even){background-color:var(--background-alt)}.table--striped .table__body .table__row:nth-child(even):hover{background-color:var(--background)}.table--striped .table__body .table__row:nth-child(even):hover .table__cell{color:var(--text)}.table__body .table__row[hidden]{display:none}@media (prefers-reduced-motion:reduce){.table__sort-icon-svg,.table__sort-trigger{transition:none}}.skeleton{background-color:var(--background-alt);border-radius:var(--radius);display:block;overflow:hidden}.skeleton::after{animation:skeleton-shimmer 1.2s ease-in-out infinite;background:linear-gradient(90deg,transparent 0,oklch(from var(--background-alt) calc(l + .08) .01 264deg) 50%,transparent 100%);background-size:200% 100%;content:"";display:block;height:100%;min-height:1rem;width:100%}@media (prefers-reduced-motion:reduce){.skeleton::after{animation:none;background:none}}@keyframes skeleton-shimmer{0%{background-position:200% 0}100%{background-position:-200% 0}}.skeleton--text{height:1em}.skeleton--circle{aspect-ratio:1;border-radius:var(--radius-full)}.skeleton--rect{aspect-ratio:16/9}.switch{align-items:center;color:var(--text);cursor:pointer;display:inline-flex;font-family:var(--font-family);font-size:var(--font-size-base);gap:var(--spacing-2)}.switch__input{border:0;clip-path:inset(50%);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;white-space:nowrap;width:1px}.switch__track{align-items:center;background-color:var(--background-alt);border:var(--border-width) solid var(--border);display:inline-flex;flex-shrink:0;height:var(--spacing-6);padding:var(--spacing-0-125);position:relative;transition:background-color var(--transition-base),border-color var(--transition-base);width:2.75rem}.switch__thumb,.switch__track{border-radius:var(--radius-full)}.switch__thumb{background-color:var(--text);height:calc(var(--spacing-6) - var(--spacing-0-375));transition:transform var(--transition-base);width:calc(var(--spacing-6) - var(--spacing-0-375))}.switch:has(.switch__input:checked) .switch__track{background-color:var(--accent);border-color:var(--accent)}.switch:has(.switch__input:checked) .switch__thumb{background-color:var(--accent-text);transform:translateX(calc(2.75rem - 100% - var(--spacing-0-375)))}.switch:focus-within .switch__track{outline:var(--outline-width) solid var(--accent-fg);outline-offset:var(--outline-offset)}.switch:has(.switch__input:disabled){cursor:not-allowed;opacity:var(--opacity-60)}.switch:has(.switch__input:disabled) .switch__track{cursor:not-allowed}.reduced-motion .switch__thumb,
195
+ .toggle[aria-pressed="true"]{background:var(--accent);border-color:var(--accent);color:var(--accent-text)}.toggle-group{display:inline-flex;flex-direction:row;gap:0}.toggle-group--vertical{flex-direction:column}.toggle-group :global(.toggle){border-radius:0}.toggle-group :global(.toggle:first-child){border-radius:var(--radius) 0 0 var(--radius)}.toggle-group :global(.toggle:last-child){border-radius:0 var(--radius) var(--radius) 0}.toggle-group--vertical :global(.toggle:first-child){border-radius:var(--radius) var(--radius) 0 0}.toggle-group--vertical :global(.toggle:last-child){border-radius:0 0 var(--radius) var(--radius)}.tabs{width:100%}.tabs__list{border-bottom:var(--outline-width) solid var(--border);display:flex;gap:var(--spacing-1);margin-bottom:var(--spacing-6);overflow-x:auto;scrollbar-width:thin;-webkit-overflow-scrolling:touch}.tabs__list::-webkit-scrollbar{height:var(--spacing-0-125)}.tabs__list::-webkit-scrollbar-track{background:var(--background-alt)}.tabs__list::-webkit-scrollbar-thumb{background:var(--border);border-radius:var(--radius)}.tabs__tab{align-items:center;background:transparent;border:none;border-bottom:calc(var(--outline-width)*2) solid transparent;border-radius:var(--radius-md) var(--radius-md) 0 0;color:var(--text-dim);cursor:pointer;display:inline-flex;font-family:var(--font-family);font-size:var(--font-size-base);font-weight:var(--font-weight-medium);gap:var(--spacing-2);justify-content:center;margin-bottom:calc(var(--outline-width)*-1*2);min-height:var(--touch-target-min);outline:none;padding:var(--spacing-3) var(--spacing-5);position:relative;transition:color var(--transition-base),border-color var(--transition-base),background-color var(--transition-base);white-space:nowrap}.tabs__tab-icon{flex-shrink:0;vertical-align:middle}.tabs__tab:hover:not(.tabs__tab--active){background-color:var(--background-alt);color:var(--text)}.tabs__tab:focus-visible{border-radius:var(--radius-md) var(--radius-md) 0 0;outline:var(--outline-width) solid var(--accent);outline-offset:var(--outline-offset)}.tabs__tab--active{border-bottom-color:var(--accent-fg);border-bottom-width:calc(var(--outline-width)*3);font-weight:var(--font-weight-semibold)}.tabs__tab--active,.tabs__tab--active:hover{background-color:var(--background-alt);color:var(--accent-fg)}.tabs__tab--active:hover{border-bottom-color:var(--accent-fg)}.tabs__panels-wrapper{width:100%}.tabs__panel{display:none;min-height:var(--spacing-20);padding:var(--spacing-6) 0;width:100%}.tabs__panel--active{animation:fadeIn var(--transition-base);display:block}.tabs__panel-content{width:100%}@keyframes fade-in{from{opacity:0;transform:translateY(var(--spacing-1))}to{opacity:1;transform:translateY(0)}}.tabs__slot-content{display:none}.tabs--pills .tabs__list{border-bottom:none;gap:var(--spacing-2)}.tabs--pills .tabs__tab{border-bottom:none;border-radius:var(--radius-md);margin-bottom:0}.tabs--pills .tabs__tab--active{background-color:var(--accent);border-bottom-color:transparent;color:var(--accent-text)}.tabs--pills .tabs__tab--active:hover{background-color:var(--accent-hover);color:var(--accent-text)}.tabs--underline .tabs__list{border-bottom:var(--outline-width) solid var(--border)}.tabs--underline .tabs__tab{border-bottom:var(--outline-width) solid transparent;padding-bottom:var(--spacing-3)}.tabs--underline .tabs__tab--active{border-bottom-color:var(--accent-fg);border-bottom-width:calc(var(--outline-width)*2)}@media (width <= 640px){.tabs__list{gap:var(--spacing-1)}.tabs__tab{font-size:var(--font-size-sm);padding:var(--spacing-2) var(--spacing-3)}.tabs__panel{padding:var(--spacing-3) 0}}@media (prefers-reduced-motion:reduce){.tabs__tab{transition:none}.tabs__panel--active{animation:none}}.progress{display:flex;flex-direction:column;gap:var(--spacing-2);width:100%}.progress__track{background-color:var(--background-alt);border:var(--border-width) solid var(--border);overflow:hidden;width:100%}.progress__bar,.progress__track{border-radius:var(--radius-full)}.progress__bar{flex-shrink:0;height:100%;min-height:var(--spacing-2);transition:width var(--transition-slow) var(--ease-in-out-cubic)}.progress--sm .progress__track{height:var(--spacing-1)}.progress--sm .progress__bar{min-height:var(--spacing-1)}.progress--md .progress__track{height:var(--spacing-2)}.progress--md .progress__bar{min-height:var(--spacing-2)}.progress--lg .progress__track{height:var(--spacing-3)}.progress--lg .progress__bar{min-height:var(--spacing-3)}.progress--primary .progress__bar{background-color:var(--accent)}.progress--success .progress__bar{background-color:var(--success)}.progress--warning .progress__bar{background-color:var(--warning)}.progress--error .progress__bar{background-color:var(--error)}.progress--info .progress__bar{background-color:var(--info)}.progress__label{color:var(--text-dim);font-size:var(--font-size-sm);text-align:right}.progress--indeterminate .progress__bar{animation:progress-indeterminate 1.5s ease-in-out infinite;min-width:30%;width:30%!important}@keyframes progress-indeterminate{0%{transform:translateX(-100%)}100%{transform:translateX(233.333%)}}@media (prefers-reduced-motion:reduce){.progress__bar{transition:none}.progress--indeterminate .progress__bar{animation:none;opacity:.7;width:50%!important}}.spinner{align-items:center;display:inline-flex;justify-content:center;vertical-align:middle}.spinner__ring{animation:spinner-rotate .8s linear infinite;border-color:var(--border);border-radius:var(--radius-full);border-style:solid;border-top-color:currentcolor;display:block}.spinner--sm .spinner__ring{border-width:var(--border-width-2);height:var(--spacing-4);width:var(--spacing-4)}.spinner--md .spinner__ring{border-width:var(--border-width-3);height:var(--spacing-6);width:var(--spacing-6)}.spinner--lg .spinner__ring{border-width:var(--border-width-4);height:var(--spacing-8);width:var(--spacing-8)}.spinner--primary{color:var(--accent)}.spinner--success{color:var(--success)}.spinner--warning{color:var(--warning)}.spinner--error{color:var(--error)}.spinner--info{color:var(--info)}@keyframes spinner-rotate{to{transform:rotate(1turn)}}@media (prefers-reduced-motion:reduce){.spinner__ring{animation:none;border-bottom-color:transparent;border-left-color:transparent;border-right-color:transparent}}.avatar{align-items:center;background-color:var(--background-alt);border:var(--border-width) solid var(--border);color:var(--text-dim);display:inline-flex;flex-shrink:0;font-size:inherit;font-weight:var(--font-weight-semibold);justify-content:center;line-height:1;overflow:hidden}.avatar__img{display:block;height:100%;-o-object-fit:cover;object-fit:cover;width:100%}.avatar__initials{align-items:center;display:flex;height:100%;justify-content:center;width:100%}.avatar--sm{font-size:var(--font-size-xs);height:var(--spacing-8);width:var(--spacing-8)}.avatar--md{font-size:var(--font-size-sm);height:var(--spacing-10);width:var(--spacing-10)}.avatar--lg{font-size:var(--font-size-base);height:var(--spacing-12);width:var(--spacing-12)}.avatar--circle{border-radius:var(--radius-full)}.avatar--square{border-radius:var(--radius-md)}.divider{align-items:center;color:var(--text-dim);display:flex;font-size:var(--font-size-sm);gap:var(--spacing-3)}.divider__line{border:none;border-left:none;border-top:var(--border-width) solid var(--border);flex:1;min-height:0;min-width:0}.divider__label{flex-shrink:0;padding:0 var(--spacing-2);white-space:nowrap}.divider--horizontal{width:100%}.divider--horizontal .divider__line{border-left:none;border-top:var(--border-width) solid var(--border)}.divider--vertical{flex-direction:column;height:100%;min-height:var(--spacing-8);width:auto}.divider--vertical .divider__line{border-left:var(--border-width) solid var(--border);border-top:none;flex:1;min-height:var(--spacing-4);width:0}.footer{background-color:var(--background-alt);border-top:var(--border-width) solid var(--border);color:var(--text-dim);font-size:var(--font-size-sm);margin-top:auto;padding:var(--spacing-6) 0}.footer__container{box-sizing:border-box;margin-left:auto;margin-right:auto;max-width:var(--container-default);padding-left:var(--content-padding-x);padding-right:var(--content-padding-x);width:100%}.footer__inner{align-items:center;display:flex;flex-wrap:wrap;gap:var(--spacing-4);justify-content:space-between}.footer__copyright{color:var(--text-dim);margin:0}.footer__site-name{color:var(--text);font-weight:var(--font-weight-medium)}.footer__nav{margin:0}.footer__links{align-items:center;display:flex;flex-wrap:wrap;gap:var(--spacing-2) var(--spacing-4);list-style:none;margin:0;padding:0}.footer__link-item{margin:0}.footer__link{color:var(--text);text-decoration:none;transition:color var(--transition-base)}.footer__link:hover{color:var(--accent-fg)}.footer__link:focus-visible{outline:var(--outline-width) solid var(--accent);outline-offset:var(--outline-offset)}.footer__version{font-size:var(--font-size-sm);margin:0}.footer__version,.footer__version .footer__link{color:var(--text-dim)}.footer__version .footer__link:hover{color:var(--accent-fg)}@media (width <= 1024px){.footer{padding-bottom:calc(var(--spacing-6) + var(--spacing-10) + var(--spacing-6))}}.table{display:flex;flex-direction:column;gap:var(--spacing-3);width:100%}.table__filter-wrap{align-items:center;display:flex;flex-shrink:0;position:relative}.table__filter-icon{align-items:center;color:var(--icon-dim);display:flex;justify-content:center;left:var(--spacing-3);pointer-events:none;position:absolute;top:50%;transform:translateY(-50%)}.table__filter-icon-svg{color:currentcolor;height:var(--table-filter-icon-size,1.25rem);width:var(--table-filter-icon-size,1.25rem)}.table__filter-wrap:focus-within .table__filter-icon{color:var(--accent)}.table__filter-wrap .table__filter{background-color:var(--background);border:var(--border-width) solid var(--border);border-radius:var(--radius-md);color:var(--text);font-family:var(--font-family);font-size:var(--font-size-base);max-width:var(--spacing-80);padding-bottom:var(--spacing-2);padding-left:3.5rem;padding-right:var(--spacing-3);padding-top:var(--spacing-2);width:100%}.table__filter-wrap .table__filter::-moz-placeholder{color:var(--text-dim)}.table__filter-wrap .table__filter::placeholder{color:var(--text-dim)}.table__filter-wrap .table__filter:focus{outline:var(--outline-width) solid var(--accent);outline-offset:var(--outline-offset)}.table__wrapper{min-width:0;overflow-x:auto;width:100%;-webkit-overflow-scrolling:touch}.table__table{border-collapse:collapse;border-spacing:0;font-size:var(--font-size-sm);width:100%}.table__caption{color:var(--text);font-weight:var(--font-weight-semibold);padding:var(--spacing-2) 0;text-align:left}.table__head .table__row{border-bottom:var(--border-width-2) solid var(--border)}.table__cell{border-bottom:var(--border-width) solid var(--border);color:var(--text);padding:var(--spacing-3) var(--spacing-4);text-align:left}.table__cell--head{color:var(--text);font-weight:var(--font-weight-semibold);white-space:nowrap}.table__sort-trigger{align-items:center;-webkit-appearance:none;-moz-appearance:none;appearance:none;background:none;border:none;border-radius:var(--radius-md);color:var(--text);cursor:pointer;display:inline-flex;font:inherit;font-weight:var(--font-weight-semibold);padding:0;text-align:left;transition:background-color var(--transition-fast),color var(--transition-fast);width:100%}.table__sort-trigger:hover{background-color:var(--background-alt);color:var(--text)}.table__sort-trigger:hover .table__sort-icon-svg{color:var(--accent)}.table__sort-trigger:focus-visible{outline:var(--outline-width) solid var(--accent);outline-offset:var(--outline-offset)}.table--sortable .table__cell--head{padding:0}.table--sortable .table__cell--head .table__sort-trigger{padding:var(--spacing-3) var(--spacing-4)}.table__cell-content{display:inline-block}.table__sort-icon{align-items:center;display:inline-flex;flex-shrink:0;justify-content:center;margin-left:var(--spacing-2)}.table__sort-icon-svg{color:var(--icon-dim);height:var(--table-sort-icon-size,1.25rem);transition:color var(--transition-fast);width:var(--table-sort-icon-size,1.25rem)}.table__body .table__row:hover{background-color:var(--background-alt)}.table__body .table__row:hover .table__cell{color:var(--text)}.table--striped .table__body .table__row:nth-child(even){background-color:var(--background-alt)}.table--striped .table__body .table__row:nth-child(even):hover{background-color:var(--background)}.table--striped .table__body .table__row:nth-child(even):hover .table__cell{color:var(--text)}.table__body .table__row[hidden]{display:none}@media (prefers-reduced-motion:reduce){.table__sort-icon-svg,.table__sort-trigger{transition:none}}.skeleton{background-color:var(--background-alt);border-radius:var(--radius);display:block;overflow:hidden}.skeleton::after{animation:skeleton-shimmer 1.2s ease-in-out infinite;background:linear-gradient(90deg,transparent 0,oklch(from var(--background-alt) calc(l + .08) .01 264deg) 50%,transparent 100%);background-size:200% 100%;content:"";display:block;height:100%;min-height:1rem;width:100%}@media (prefers-reduced-motion:reduce){.skeleton::after{animation:none;background:none}}@keyframes skeleton-shimmer{0%{background-position:200% 0}100%{background-position:-200% 0}}.skeleton--text{height:1em}.skeleton--circle{aspect-ratio:1;border-radius:var(--radius-full)}.skeleton--rect{aspect-ratio:16/9}.switch{align-items:center;color:var(--text);cursor:pointer;display:inline-flex;font-family:var(--font-family);font-size:var(--font-size-base);gap:var(--spacing-2)}.switch__input{border:0;clip-path:inset(50%);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;white-space:nowrap;width:1px}.switch__track{align-items:center;background-color:var(--background-alt);border:var(--border-width) solid var(--border);display:inline-flex;flex-shrink:0;height:var(--spacing-6);padding:var(--spacing-0-125);position:relative;transition:background-color var(--transition-base),border-color var(--transition-base);width:2.75rem}.switch__thumb,.switch__track{border-radius:var(--radius-full)}.switch__thumb{background-color:var(--text);height:calc(var(--spacing-6) - var(--spacing-0-375));transition:transform var(--transition-base);width:calc(var(--spacing-6) - var(--spacing-0-375))}.switch:has(.switch__input:checked) .switch__track{background-color:var(--accent);border-color:var(--accent)}.switch:has(.switch__input:checked) .switch__thumb{background-color:var(--accent-text);transform:translateX(calc(2.75rem - 100% - var(--spacing-0-375)))}.switch:focus-within .switch__track{outline:var(--outline-width) solid var(--accent-fg);outline-offset:var(--outline-offset)}.switch:has(.switch__input:disabled){cursor:not-allowed;opacity:var(--opacity-60)}.switch:has(.switch__input:disabled) .switch__track{cursor:not-allowed}.reduced-motion .switch__thumb,
194
196
  .reduced-motion .switch__track{transition:none}.scroll-area{overflow:hidden;position:relative}.scroll-area__viewport{height:100%;overflow:auto;scrollbar-width:thin;width:100%}.scroll-area__viewport::-webkit-scrollbar{height:var(--spacing-2);width:var(--spacing-2)}.scroll-area__viewport::-webkit-scrollbar-track{background:var(--background-alt);border-radius:var(--radius)}.scroll-area__viewport::-webkit-scrollbar-thumb{background:var(--border);border-radius:var(--radius)}.scroll-area__viewport::-webkit-scrollbar-thumb:hover{background:var(--text-dim)}.scroll-area--horizontal .scroll-area__viewport{overflow-x:auto;overflow-y:hidden}.hover-card{display:inline-block;position:relative}.hover-card__content{background:var(--background);border:var(--border-width) solid var(--border);border-radius:var(--radius-lg);box-shadow:var(--shadow-md);margin-top:var(--spacing-1);min-width:var(--spacing-56);opacity:0;padding:var(--spacing-4);pointer-events:none;position:absolute;transition:opacity var(--transition-fast),visibility var(--transition-fast);visibility:hidden;z-index:var(--z-popover,100)}.hover-card__content--open{opacity:1;pointer-events:auto;visibility:visible}.context-menu{display:inline-block;position:relative}.context-menu__content{background:var(--background);border:var(--border-width) solid var(--border);border-radius:var(--radius-lg);box-shadow:var(--shadow-md);min-width:var(--spacing-48);opacity:0;padding:var(--spacing-1);position:fixed;visibility:hidden;z-index:var(--z-context-menu,200)}.context-menu__content--open{opacity:1;visibility:visible}.context-menu__item{align-items:center;background:transparent;border:none;border-radius:var(--radius);color:var(--text);cursor:pointer;display:flex;font-family:var(--font-family);font-size:var(--font-size-sm);gap:var(--spacing-4);justify-content:space-between;padding:var(--spacing-2) var(--spacing-3);text-align:left;transition:background-color var(--transition-fast);width:100%}
195
197
  .context-menu__item:focus-visible,.context-menu__item:hover:not(:disabled){background:var(--background-alt);outline:none}.context-menu__item:disabled{cursor:not-allowed;opacity:var(--opacity-60)}.context-menu__separator{background:var(--border);height:var(--border-width);margin:var(--spacing-1) 0}.resizable__pane-group{display:flex;height:100%;width:100%}.resizable__pane-group--horizontal{flex-direction:row}.resizable__pane-group--vertical{flex-direction:column}.resizable__pane{min-height:0;min-width:0;overflow:auto}.resizable__handle{background:var(--border);cursor:col-resize;flex-shrink:0;position:relative}.resizable__pane-group--horizontal > .resizable__handle{cursor:col-resize;width:var(--spacing-1)}.resizable__pane-group--vertical > .resizable__handle{cursor:row-resize;height:var(--spacing-1)}
196
198
  .resizable__handle:active,.resizable__handle:hover{background:var(--accent)}.resizable__handle--with-handle::after{background:var(--text-dim);border-radius:var(--radius);content:"";height:var(--spacing-4);left:50%;opacity:.5;position:absolute;top:50%;transform:translate(-50%,-50%);width:var(--spacing-4)}.resizable__pane-group--vertical > .resizable__handle--with-handle::after{height:var(--spacing-1);width:var(--spacing-4)}.resizable__pane-group--horizontal > .resizable__handle--with-handle::after{height:var(--spacing-4);width:var(--spacing-1)}.home{padding:var(--content-padding-y) 0}.home__container{box-sizing:border-box;margin-left:auto;margin-right:auto;max-width:var(--container-default);min-width:0;padding-left:var(--content-padding-x);padding-right:var(--content-padding-x);width:100%}.home__announcement{align-items:center;background-color:oklch(from var(--accent-fg) l c h/8%);border:var(--border-width) solid oklch(from var(--accent-fg) l c h/14%);border-radius:var(--radius-lg);color:var(--text);display:flex;flex-wrap:wrap;font-size:var(--font-size-sm);gap:var(--spacing-2);justify-content:center;margin-bottom:var(--section-spacing);padding:var(--spacing-3) var(--spacing-4);text-decoration:none;transition:background-color var(--transition-base),border-color var(--transition-base)}.home__announcement:hover{background-color:oklch(from var(--accent-fg) l c h/12%);border-color:oklch(from var(--accent-fg) l c h/20%)}.home__announcement-label{color:var(--accent-fg);font-weight:var(--font-weight-semibold)}.home__announcement-text{color:var(--text-dim)}.home__announcement-arrow{color:var(--text-dim);transition:transform var(--transition-base)}.home__announcement:hover .home__announcement-arrow{transform:translateX(var(--spacing-0-5))}.home__hero{margin-bottom:var(--section-spacing-lg);padding:var(--spacing-14) 0 var(--spacing-16);text-align:center}.home__title{color:var(--text);font-size:var(--font-size-5xl);font-weight:var(--font-weight-extrabold);line-height:var(--line-height-tight);margin:0 0 var(--spacing-6) 0}.home__subtitle{color:var(--text-dim);font-size:var(--font-size-xl);line-height:var(--line-height-relaxed);margin:0 auto var(--spacing-8) auto;max-width:var(--spacing-175)}.home__hero-ctas{display:flex;flex-wrap:wrap;gap:var(--spacing-4);justify-content:center;margin-top:var(--spacing-6)}.home__hero-cta{text-decoration:none}.home__examples-row{display:flex;flex-wrap:wrap;gap:var(--spacing-3);justify-content:center;margin-top:var(--spacing-10)}.home__example-pill{background-color:var(--background-alt);border:var(--border-width) solid var(--border);border-radius:var(--radius-full);color:var(--text);display:inline-block;font-size:var(--font-size-sm);font-weight:var(--font-weight-medium);padding:var(--spacing-2) var(--spacing-4);text-decoration:none;transition:background-color var(--transition-base),border-color var(--transition-base),color var(--transition-base)}.home__example-pill:hover{background-color:var(--background);border-color:var(--accent);color:var(--accent-fg)}.home__example-pill:focus-visible{outline:var(--outline-width) solid var(--accent);outline-offset:var(--outline-offset)}.home__showcase{margin-bottom:var(--section-spacing-lg)}.home__showcase-grid{display:grid;gap:var(--spacing-8);grid-template-columns:1fr;margin:0 auto;max-width:var(--spacing-150)}@media (width >= 768px){.home__showcase-grid{grid-template-columns:1fr 1fr;max-width:100%}}.home__showcase .home__example{margin-bottom:0}.home__showcase .home__example:last-child{grid-column:1/-1;justify-self:center;max-width:var(--spacing-80)}@media (width >= 768px){.home__showcase .home__example:last-child{grid-column:auto;max-width:100%}}.home__section-title{color:var(--text);font-size:var(--font-size-3xl);font-weight:var(--font-weight-bold);margin-bottom:var(--page-header-margin-bottom);text-align:center}.home__install{align-items:center;display:flex;flex-direction:column;justify-content:center;margin-bottom:var(--section-spacing-lg);max-width:100%;min-width:0}.home__install-grid{display:grid;gap:0;grid-template-columns:1fr;margin:0 auto;max-width:var(--spacing-150);min-width:0;width:100%}@media (width >= 768px){.home__install-grid{grid-template-columns:1fr auto 1fr;max-width:100%}}.home__install-block{align-items:stretch;background-color:var(--background-alt);border:var(--border-width) solid var(--border);border-radius:var(--radius-lg);box-sizing:border-box;display:flex;flex-direction:column;justify-content:center;min-height:var(--spacing-24);min-width:0;overflow:hidden;padding:var(--spacing-6);width:100%}.home__install-or{align-items:center;color:var(--text-dim);display:flex;font-size:var(--font-size-sm);font-weight:var(--font-weight-semibold);gap:var(--spacing-4);justify-content:center;letter-spacing:var(--letter-spacing-wider);padding:var(--spacing-4) 0}
package/package.json CHANGED
@@ -1,11 +1,13 @@
1
1
  {
2
2
  "name": "rizzo-css",
3
- "version": "0.0.62",
4
- "engines": { "node": ">=18" },
3
+ "version": "0.0.63",
4
+ "engines": {
5
+ "node": ">=18"
6
+ },
5
7
  "scripts": {
6
8
  "prepublishOnly": "cd ../.. && pnpm run lint:css:fix && pnpm run build:css && node scripts/copy-scaffold.js && node scripts/prepare-vanilla-scaffold.js"
7
9
  },
8
- "description": "A modern CSS design system with semantic theming, 14 themes, accessible components (BEM), and pre-built blocks. Same CSS and components for Vanilla JS, Astro, and Svelte; CLI scaffolds with flat nav (Docs, Components, Blocks, Themes, Colors).",
10
+ "description": "A modern CSS design system with semantic theming, 14 themes, accessible components (BEM), and pre-built blocks. Same CSS and components for Vanilla JS, Astro, Svelte, React, and Vue; CLI scaffolds all five; blocks include Landing hero, Pricing, Dashboard, Docs layout.",
9
11
  "style": "dist/rizzo.min.css",
10
12
  "main": "dist/rizzo.min.css",
11
13
  "unpkg": "dist/rizzo.min.css",
@@ -27,12 +29,15 @@
27
29
  "bin",
28
30
  "dist",
29
31
  "scaffold/astro",
30
- "scaffold/landing","scaffold/minimal",
32
+ "scaffold/landing",
33
+ "scaffold/minimal",
31
34
  "scaffold/config",
32
35
  "scaffold/shared",
33
36
  "scaffold/svelte",
34
37
  "scaffold/utils",
35
- "scaffold/vanilla"
38
+ "scaffold/vanilla",
39
+ "scaffold/react",
40
+ "scaffold/vue"
36
41
  ],
37
42
  "keywords": [
38
43
  "css",
@@ -42,7 +47,9 @@
42
47
  "accessibility",
43
48
  "vanilla",
44
49
  "astro",
45
- "svelte"
50
+ "svelte",
51
+ "react",
52
+ "vue"
46
53
  ],
47
54
  "repository": {
48
55
  "type": "git",
@@ -51,4 +58,4 @@
51
58
  "homepage": "https://rizzo-css.vercel.app",
52
59
  "license": "MIT",
53
60
  "author": "mingleusa"
54
- }
61
+ }
@@ -13,6 +13,8 @@ interface Props {
13
13
  links?: FooterLink[];
14
14
  /** Optional class for the root element */
15
15
  class?: string;
16
+ /** Optional version string (e.g. from package.json); shown as "v0.0.63" with link to CHANGELOG */
17
+ version?: string;
16
18
  }
17
19
 
18
20
  const {
@@ -20,6 +22,7 @@ const {
20
22
  year = new Date().getFullYear(),
21
23
  links = [],
22
24
  class: className = '',
25
+ version,
23
26
  } = Astro.props;
24
27
 
25
28
  const classes = `footer ${className}`.trim();
@@ -50,6 +53,11 @@ const classes = `footer ${className}`.trim();
50
53
  </ul>
51
54
  </nav>
52
55
  ) : null}
56
+ {version ? (
57
+ <p class="footer__version" aria-label="Package version">
58
+ <a class="footer__link" href="/docs/overview" title="Documentation">v{version}</a>
59
+ </p>
60
+ ) : null}
53
61
  <slot />
54
62
  </div>
55
63
  </div>
@@ -305,10 +305,15 @@ const { open = false } = Astro.props;
305
305
 
306
306
  // Focus trapping and keyboard handlers
307
307
  const handleKeyDown = (e: KeyboardEvent) => {
308
- if (panel.getAttribute('data-open') !== 'true') return;
308
+ // Consider "open" when root aria-hidden is false (panel is visible). Don't rely only on
309
+ // data-open: in WebKit headless/CI requestAnimationFrame can be throttled, so data-open
310
+ // may not be set yet when the user presses Escape.
311
+ const isOpen = settings.getAttribute('aria-hidden') === 'false';
312
+ if (!isOpen) return;
309
313
 
310
314
  if (e.key === 'Escape') {
311
315
  e.preventDefault();
316
+ e.stopPropagation();
312
317
  closeSettings();
313
318
  return;
314
319
  }
@@ -338,7 +343,8 @@ const { open = false } = Astro.props;
338
343
  }
339
344
  };
340
345
 
341
- document.addEventListener('keydown', handleKeyDown);
346
+ // Capture phase so Escape is handled before WebKit/Safari can consume it
347
+ document.addEventListener('keydown', handleKeyDown, true);
342
348
 
343
349
  // Font size slider
344
350
  if (fontSizeSlider) {
@@ -4,8 +4,8 @@ interface Tab {
4
4
  label: string;
5
5
  /** Optional icon URL (e.g. /icons/devicons/Bun.svg) shown before the label */
6
6
  icon?: string;
7
- /** Optional Astro icon component (theme-aware); used when present instead of icon URL */
8
- iconComponent?: any;
7
+ /** Optional Astro icon component (theme-aware); used when present instead of icon URL. Rendered as <Component width={20} height={20} class="..." /> */
8
+ iconComponent?: (props: { width?: number; height?: number; class?: string }) => unknown;
9
9
  content?: string;
10
10
  }
11
11
 
@@ -0,0 +1,143 @@
1
+ import type { HTMLAttributes } from 'react';
2
+ import { useState, useCallback } from 'react';
3
+
4
+ export interface AccordionItem {
5
+ id: string;
6
+ title: string;
7
+ content?: string;
8
+ }
9
+
10
+ export interface AccordionProps extends HTMLAttributes<HTMLDivElement> {
11
+ items: AccordionItem[];
12
+ id?: string;
13
+ allowMultiple?: boolean;
14
+ defaultExpanded?: string | string[];
15
+ className?: string;
16
+ }
17
+
18
+ export function Accordion({
19
+ items,
20
+ id: idProp,
21
+ allowMultiple = false,
22
+ defaultExpanded,
23
+ className = '',
24
+ ...rest
25
+ }: AccordionProps) {
26
+ const accordionId = idProp ?? `accordion-${Math.random().toString(36).slice(2, 11)}`;
27
+
28
+ function getInitialExpanded(): Set<string> {
29
+ if (defaultExpanded === undefined) return new Set(items[0] ? [items[0].id] : []);
30
+ if (typeof defaultExpanded === 'string') return new Set([defaultExpanded]);
31
+ return new Set(defaultExpanded);
32
+ }
33
+
34
+ const [expanded, setExpanded] = useState<Set<string>>(getInitialExpanded);
35
+
36
+ const toggle = useCallback(
37
+ (itemId: string) => {
38
+ setExpanded((prev) => {
39
+ const next = new Set(prev);
40
+ if (allowMultiple) {
41
+ if (next.has(itemId)) next.delete(itemId);
42
+ else next.add(itemId);
43
+ } else {
44
+ next.clear();
45
+ if (!prev.has(itemId)) next.add(itemId);
46
+ }
47
+ return next;
48
+ });
49
+ },
50
+ [allowMultiple]
51
+ );
52
+
53
+ const handleKeydown = useCallback(
54
+ (e: React.KeyboardEvent, itemId: string, index: number) => {
55
+ const triggers = e.currentTarget?.parentElement?.querySelectorAll?.('[data-accordion-trigger]') ?? [];
56
+ const len = triggers.length;
57
+ let targetIndex = index;
58
+ switch (e.key) {
59
+ case 'ArrowDown':
60
+ e.preventDefault();
61
+ targetIndex = Math.min(index + 1, len - 1);
62
+ break;
63
+ case 'ArrowUp':
64
+ e.preventDefault();
65
+ targetIndex = Math.max(index - 1, 0);
66
+ break;
67
+ case 'Home':
68
+ e.preventDefault();
69
+ targetIndex = 0;
70
+ break;
71
+ case 'End':
72
+ e.preventDefault();
73
+ targetIndex = len - 1;
74
+ break;
75
+ case 'Enter':
76
+ case ' ':
77
+ e.preventDefault();
78
+ toggle(itemId);
79
+ return;
80
+ default:
81
+ return;
82
+ }
83
+ if (targetIndex !== index && triggers[targetIndex]) (triggers[targetIndex] as HTMLElement).focus();
84
+ },
85
+ [toggle]
86
+ );
87
+
88
+ const classes = ['accordion', className].filter(Boolean).join(' ').trim();
89
+
90
+ return (
91
+ <div
92
+ className={classes}
93
+ data-accordion={accordionId}
94
+ data-allow-multiple={allowMultiple ? 'true' : 'false'}
95
+ {...rest}
96
+ >
97
+ {items.map((item, i) => {
98
+ const triggerId = `${accordionId}-trigger-${item.id}`;
99
+ const panelId = `${accordionId}-panel-${item.id}`;
100
+ const isExpanded = expanded.has(item.id);
101
+ return (
102
+ <div key={item.id} className="accordion__item" data-accordion-item data-item-id={item.id}>
103
+ <h3 className="accordion__heading">
104
+ <button
105
+ type="button"
106
+ className={`accordion__trigger ${isExpanded ? 'accordion__trigger--expanded' : ''}`.trim()}
107
+ id={triggerId}
108
+ aria-expanded={isExpanded}
109
+ aria-controls={panelId}
110
+ data-accordion-trigger
111
+ onClick={() => toggle(item.id)}
112
+ onKeyDown={(e) => handleKeydown(e, item.id, i)}
113
+ >
114
+ <span className="accordion__title">{item.title}</span>
115
+ <span className="accordion__icon" aria-hidden="true">
116
+ <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
117
+ <path d="m6 9 6 6 6-6" />
118
+ </svg>
119
+ </span>
120
+ </button>
121
+ </h3>
122
+ <div
123
+ className={`accordion__panel ${isExpanded ? 'accordion__panel--expanded' : ''}`.trim()}
124
+ id={panelId}
125
+ role="region"
126
+ aria-labelledby={triggerId}
127
+ hidden={!isExpanded}
128
+ data-accordion-panel
129
+ >
130
+ <div className="accordion__panel-inner">
131
+ <div className="accordion__panel-content">
132
+ {item.content && <div dangerouslySetInnerHTML={{ __html: item.content }} />}
133
+ </div>
134
+ </div>
135
+ </div>
136
+ </div>
137
+ );
138
+ })}
139
+ </div>
140
+ );
141
+ }
142
+
143
+ export default Accordion;
@@ -0,0 +1,90 @@
1
+ import type { HTMLAttributes, ReactNode } from 'react';
2
+ import { useEffect, useRef, useState } from 'react';
3
+
4
+ export type AlertVariant = 'success' | 'error' | 'warning' | 'info';
5
+
6
+ export interface AlertProps extends Omit<HTMLAttributes<HTMLDivElement>, 'onDismiss'> {
7
+ variant?: AlertVariant;
8
+ dismissible?: boolean;
9
+ autoDismiss?: number;
10
+ onDismiss?: () => void;
11
+ children?: ReactNode;
12
+ className?: string;
13
+ id?: string;
14
+ }
15
+
16
+ const ARIA_LABELS: Record<AlertVariant, string> = {
17
+ success: 'Success message',
18
+ error: 'Error message',
19
+ warning: 'Warning message',
20
+ info: 'Information message',
21
+ };
22
+
23
+ export function Alert({
24
+ variant = 'info',
25
+ dismissible = false,
26
+ autoDismiss = 0,
27
+ onDismiss,
28
+ className = '',
29
+ id: idProp,
30
+ children,
31
+ ...rest
32
+ }: AlertProps) {
33
+ const [visible, setVisible] = useState(true);
34
+ const id = idProp ?? `alert-${Math.random().toString(36).slice(2, 11)}`;
35
+ const timeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);
36
+
37
+ const dismiss = () => {
38
+ setVisible(false);
39
+ if (timeoutRef.current) clearTimeout(timeoutRef.current);
40
+ onDismiss?.();
41
+ };
42
+
43
+ useEffect(() => {
44
+ if (autoDismiss > 0) {
45
+ timeoutRef.current = setTimeout(dismiss, autoDismiss);
46
+ }
47
+ return () => {
48
+ if (timeoutRef.current) clearTimeout(timeoutRef.current);
49
+ };
50
+ }, [autoDismiss]);
51
+
52
+ if (!visible) return null;
53
+
54
+ const classes = ['alert', `alert--${variant}`, className].filter(Boolean).join(' ').trim();
55
+
56
+ return (
57
+ <div
58
+ className={classes}
59
+ id={id}
60
+ role="alert"
61
+ aria-live="polite"
62
+ aria-atomic="true"
63
+ aria-label={ARIA_LABELS[variant]}
64
+ {...rest}
65
+ >
66
+ <div className="alert__content">{children}</div>
67
+ {dismissible && (
68
+ <button
69
+ type="button"
70
+ className="alert__close"
71
+ aria-label="Dismiss alert"
72
+ aria-controls={id}
73
+ onClick={dismiss}
74
+ onKeyDown={(e) => {
75
+ if (e.key === 'Enter' || e.key === ' ') {
76
+ e.preventDefault();
77
+ dismiss();
78
+ }
79
+ }}
80
+ >
81
+ <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" aria-hidden="true">
82
+ <path d="M18 6L6 18M6 6l12 12" />
83
+ </svg>
84
+ </button>
85
+ )}
86
+ </div>
87
+ );
88
+ }
89
+
90
+ export default Alert;
@@ -0,0 +1,80 @@
1
+ import type { HTMLAttributes, ReactNode } from 'react';
2
+ import { useEffect } from 'react';
3
+
4
+ export interface AlertDialogProps extends HTMLAttributes<HTMLDivElement> {
5
+ id?: string;
6
+ title?: string;
7
+ description?: string;
8
+ open?: boolean;
9
+ onOpenChange?: (open: boolean) => void;
10
+ children?: ReactNode;
11
+ actions?: ReactNode;
12
+ className?: string;
13
+ }
14
+
15
+ export function AlertDialog({
16
+ id: idProp,
17
+ title = 'Are you sure?',
18
+ description,
19
+ open = false,
20
+ onOpenChange,
21
+ children,
22
+ actions,
23
+ className = '',
24
+ ...rest
25
+ }: AlertDialogProps) {
26
+ const id = idProp ?? `alert-dialog-${Math.random().toString(36).slice(2, 9)}`;
27
+
28
+ const close = () => onOpenChange?.(false);
29
+
30
+ useEffect(() => {
31
+ if (!open) return;
32
+ const handleKey = (e: KeyboardEvent) => {
33
+ if (e.key === 'Escape') {
34
+ e.preventDefault();
35
+ close();
36
+ }
37
+ };
38
+ document.addEventListener('keydown', handleKey);
39
+ return () => document.removeEventListener('keydown', handleKey);
40
+ }, [open, onOpenChange]);
41
+
42
+ return (
43
+ <>
44
+ <div
45
+ className={`alert-dialog__overlay ${open ? 'alert-dialog__overlay--open' : ''}`.trim()}
46
+ data-alert-dialog-overlay
47
+ aria-hidden={!open}
48
+ id={`${id}-overlay`}
49
+ onClick={close}
50
+ role="presentation"
51
+ />
52
+ <div
53
+ className={`alert-dialog ${className}`.trim()}
54
+ role="alertdialog"
55
+ aria-modal="true"
56
+ aria-labelledby={`${id}-title`}
57
+ aria-describedby={description ? `${id}-desc` : undefined}
58
+ aria-hidden={!open}
59
+ id={id}
60
+ data-alert-dialog
61
+ hidden={!open}
62
+ {...rest}
63
+ >
64
+ <div className="alert-dialog__content">
65
+ <h2 id={`${id}-title`} className="alert-dialog__title">
66
+ {title}
67
+ </h2>
68
+ {description && (
69
+ <p id={`${id}-desc`} className="alert-dialog__description">
70
+ {description}
71
+ </p>
72
+ )}
73
+ <div className="alert-dialog__actions">{actions}</div>
74
+ </div>
75
+ </div>
76
+ </>
77
+ );
78
+ }
79
+
80
+ export default AlertDialog;
@@ -0,0 +1,32 @@
1
+ import type { HTMLAttributes, ReactNode } from 'react';
2
+
3
+ export interface AspectRatioProps extends HTMLAttributes<HTMLDivElement> {
4
+ ratio?: number;
5
+ children?: ReactNode;
6
+ className?: string;
7
+ }
8
+
9
+ export function AspectRatio({
10
+ ratio = 16 / 9,
11
+ className = '',
12
+ children,
13
+ style,
14
+ ...rest
15
+ }: AspectRatioProps) {
16
+ const paddingPercent = (1 / ratio) * 100;
17
+ return (
18
+ <div
19
+ className={`aspect-ratio ${className}`.trim()}
20
+ style={{
21
+ ['--aspect-ratio' as string]: ratio,
22
+ ['--aspect-ratio-padding' as string]: `${paddingPercent}%`,
23
+ ...(style as React.CSSProperties),
24
+ }}
25
+ {...rest}
26
+ >
27
+ <div className="aspect-ratio__inner">{children}</div>
28
+ </div>
29
+ );
30
+ }
31
+
32
+ export default AspectRatio;
@@ -0,0 +1,53 @@
1
+ import type { HTMLAttributes } from 'react';
2
+
3
+ function getInitials(name: string): string {
4
+ const parts = name.trim().split(/\s+/).filter(Boolean);
5
+ if (parts.length === 0) return '';
6
+ if (parts.length === 1) return parts[0].slice(0, 2).toUpperCase();
7
+ return (parts[0][0] + parts[parts.length - 1][0]).toUpperCase();
8
+ }
9
+
10
+ export type AvatarSize = 'sm' | 'md' | 'lg';
11
+ export type AvatarShape = 'circle' | 'square';
12
+
13
+ export interface AvatarProps extends HTMLAttributes<HTMLSpanElement> {
14
+ src?: string;
15
+ alt?: string;
16
+ name?: string;
17
+ initials?: string;
18
+ size?: AvatarSize;
19
+ shape?: AvatarShape;
20
+ className?: string;
21
+ }
22
+
23
+ export function Avatar({
24
+ src,
25
+ alt = '',
26
+ name = '',
27
+ initials: initialsProp = '',
28
+ size = 'md',
29
+ shape = 'circle',
30
+ className = '',
31
+ ...rest
32
+ }: AvatarProps) {
33
+ const displayInitials = name ? getInitials(name) : initialsProp;
34
+ const ariaLabel = alt || name || (displayInitials ? `Avatar: ${displayInitials}` : 'Avatar');
35
+ const classes = ['avatar', `avatar--${size}`, `avatar--${shape}`, className]
36
+ .filter(Boolean)
37
+ .join(' ')
38
+ .trim();
39
+
40
+ return (
41
+ <span className={classes} role="img" aria-label={ariaLabel} {...rest}>
42
+ {src ? (
43
+ <img src={src} alt={alt || name || ''} className="avatar__img" loading="lazy" />
44
+ ) : (
45
+ <span className="avatar__initials" aria-hidden="true">
46
+ {displayInitials || '?'}
47
+ </span>
48
+ )}
49
+ </span>
50
+ );
51
+ }
52
+
53
+ export default Avatar;