rizzo-css 0.0.11 → 0.0.13

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 (233) hide show
  1. package/.env.example +12 -0
  2. package/LICENSE +21 -0
  3. package/README.md +17 -3
  4. package/bin/rizzo-css.js +98 -42
  5. package/dist/rizzo.min.css +3 -2
  6. package/package.json +5 -3
  7. package/scaffold/astro-app/README.md +13 -2
  8. package/scaffold/astro-app/src/components/Accordion.astro +178 -0
  9. package/scaffold/astro-app/src/components/Alert.astro +131 -0
  10. package/scaffold/astro-app/src/components/Avatar.astro +59 -0
  11. package/scaffold/astro-app/src/components/Badge.astro +24 -0
  12. package/scaffold/astro-app/src/components/Breadcrumb.astro +61 -0
  13. package/scaffold/astro-app/src/components/Button.astro +3 -0
  14. package/scaffold/astro-app/src/components/Card.astro +18 -0
  15. package/scaffold/astro-app/src/components/Checkbox.astro +38 -0
  16. package/scaffold/astro-app/src/components/CodeBlock.astro +393 -0
  17. package/scaffold/astro-app/src/components/CopyToClipboard.astro +219 -0
  18. package/scaffold/astro-app/src/components/Divider.astro +37 -0
  19. package/scaffold/astro-app/src/components/Dropdown.astro +807 -0
  20. package/scaffold/astro-app/src/components/FormGroup.astro +59 -0
  21. package/scaffold/astro-app/src/components/FrameworkSwitcher.astro +72 -0
  22. package/scaffold/astro-app/src/components/Input.astro +59 -0
  23. package/scaffold/astro-app/src/components/Modal.astro +212 -0
  24. package/scaffold/astro-app/src/components/Navbar.astro +701 -0
  25. package/scaffold/astro-app/src/components/Pagination.astro +240 -0
  26. package/scaffold/astro-app/src/components/ProgressBar.astro +65 -0
  27. package/scaffold/astro-app/src/components/Radio.astro +38 -0
  28. package/scaffold/astro-app/src/components/Search.astro +1259 -0
  29. package/scaffold/astro-app/src/components/Select.astro +49 -0
  30. package/scaffold/astro-app/src/components/Settings.astro +382 -0
  31. package/scaffold/astro-app/src/components/Spinner.astro +30 -0
  32. package/scaffold/astro-app/src/components/Table.astro +181 -0
  33. package/scaffold/astro-app/src/components/Tabs.astro +223 -0
  34. package/scaffold/astro-app/src/components/Textarea.astro +58 -0
  35. package/scaffold/astro-app/src/components/ThemeSwitcher.astro +504 -0
  36. package/scaffold/astro-app/src/components/Toast.astro +30 -0
  37. package/scaffold/astro-app/src/components/Tooltip.astro +32 -0
  38. package/scaffold/astro-app/src/components/icons/Brush.astro +10 -0
  39. package/scaffold/astro-app/src/components/icons/Cake.astro +11 -0
  40. package/scaffold/astro-app/src/components/icons/Check.astro +29 -0
  41. package/scaffold/astro-app/src/components/icons/Cherry.astro +11 -0
  42. package/scaffold/astro-app/src/components/icons/ChevronDown.astro +29 -0
  43. package/scaffold/astro-app/src/components/icons/Circle.astro +29 -0
  44. package/scaffold/astro-app/src/components/icons/Close.astro +30 -0
  45. package/scaffold/astro-app/src/components/icons/Cmd.astro +26 -0
  46. package/scaffold/astro-app/src/components/icons/Copy.astro +30 -0
  47. package/scaffold/astro-app/src/components/icons/Eye.astro +30 -0
  48. package/scaffold/astro-app/src/components/icons/Filter.astro +29 -0
  49. package/scaffold/astro-app/src/components/icons/Flame.astro +28 -0
  50. package/scaffold/astro-app/src/components/icons/Flower.astro +11 -0
  51. package/scaffold/astro-app/src/components/icons/Gear.astro +30 -0
  52. package/scaffold/astro-app/src/components/icons/Heart.astro +28 -0
  53. package/scaffold/astro-app/src/components/icons/IceCream.astro +31 -0
  54. package/scaffold/astro-app/src/components/icons/Leaf.astro +29 -0
  55. package/scaffold/astro-app/src/components/icons/Lemon.astro +11 -0
  56. package/scaffold/astro-app/src/components/icons/Moon.astro +29 -0
  57. package/scaffold/astro-app/src/components/icons/Owl.astro +34 -0
  58. package/scaffold/astro-app/src/components/icons/Palette.astro +33 -0
  59. package/scaffold/astro-app/src/components/icons/Rainbow.astro +31 -0
  60. package/scaffold/astro-app/src/components/icons/Search.astro +30 -0
  61. package/scaffold/astro-app/src/components/icons/Shield.astro +28 -0
  62. package/scaffold/astro-app/src/components/icons/Snowflake.astro +34 -0
  63. package/scaffold/astro-app/src/components/icons/Sort.astro +30 -0
  64. package/scaffold/astro-app/src/components/icons/Sun.astro +29 -0
  65. package/scaffold/astro-app/src/components/icons/Sunset.astro +10 -0
  66. package/scaffold/astro-app/src/components/icons/Zap.astro +9 -0
  67. package/scaffold/astro-app/src/components/icons/devicons/Astro.astro +53 -0
  68. package/scaffold/astro-app/src/components/icons/devicons/Bash.astro +34 -0
  69. package/scaffold/astro-app/src/components/icons/devicons/Css3.astro +29 -0
  70. package/scaffold/astro-app/src/components/icons/devicons/Git.astro +24 -0
  71. package/scaffold/astro-app/src/components/icons/devicons/Html5.astro +27 -0
  72. package/scaffold/astro-app/src/components/icons/devicons/Javascript.astro +25 -0
  73. package/scaffold/astro-app/src/components/icons/devicons/Nodejs.astro +47 -0
  74. package/scaffold/astro-app/src/components/icons/devicons/Plaintext.astro +33 -0
  75. package/scaffold/astro-app/src/components/icons/devicons/React.astro +27 -0
  76. package/scaffold/astro-app/src/components/icons/devicons/Svelte.astro +25 -0
  77. package/scaffold/astro-app/src/components/icons/devicons/Vue.astro +26 -0
  78. package/scaffold/astro-app/src/config/frameworks.ts +26 -0
  79. package/scaffold/astro-app/src/config/themes.ts +54 -0
  80. package/scaffold/astro-app/src/layouts/DocsLayout.astro +204 -0
  81. package/scaffold/astro-app/src/layouts/Layout.astro +11 -2
  82. package/scaffold/astro-app/src/pages/components/accordion.astro +172 -0
  83. package/scaffold/astro-app/src/pages/components/alert.astro +250 -0
  84. package/scaffold/astro-app/src/pages/components/avatar.astro +102 -0
  85. package/scaffold/astro-app/src/pages/components/badge.astro +119 -0
  86. package/scaffold/astro-app/src/pages/components/breadcrumb.astro +124 -0
  87. package/scaffold/astro-app/src/pages/components/button.astro +74 -0
  88. package/scaffold/astro-app/src/pages/components/cards.astro +247 -0
  89. package/scaffold/astro-app/src/pages/components/copy-to-clipboard.astro +49 -0
  90. package/scaffold/astro-app/src/pages/components/divider.astro +74 -0
  91. package/scaffold/astro-app/src/pages/components/dropdown.astro +394 -0
  92. package/scaffold/astro-app/src/pages/components/forms.astro +367 -0
  93. package/scaffold/astro-app/src/pages/components/icons.astro +246 -0
  94. package/scaffold/astro-app/src/pages/components/modal.astro +152 -0
  95. package/scaffold/astro-app/src/pages/components/navbar.astro +80 -0
  96. package/scaffold/astro-app/src/pages/components/pagination.astro +126 -0
  97. package/scaffold/astro-app/src/pages/components/progress-bar.astro +94 -0
  98. package/scaffold/astro-app/src/pages/components/search.astro +155 -0
  99. package/scaffold/astro-app/src/pages/components/settings.astro +78 -0
  100. package/scaffold/astro-app/src/pages/components/spinner.astro +81 -0
  101. package/scaffold/astro-app/src/pages/components/table.astro +144 -0
  102. package/scaffold/astro-app/src/pages/components/tabs.astro +220 -0
  103. package/scaffold/astro-app/src/pages/components/theme-switcher.astro +67 -0
  104. package/scaffold/astro-app/src/pages/components/toast.astro +157 -0
  105. package/scaffold/astro-app/src/pages/components/tooltip.astro +209 -0
  106. package/scaffold/astro-app/src/pages/components.astro +290 -0
  107. package/scaffold/astro-app/src/pages/docs/accessibility.astro +9 -0
  108. package/scaffold/astro-app/src/pages/docs/colors.astro +9 -0
  109. package/scaffold/astro-app/src/pages/docs/design-system.astro +9 -0
  110. package/scaffold/astro-app/src/pages/docs/getting-started.astro +9 -0
  111. package/scaffold/astro-app/src/pages/docs/index.astro +15 -0
  112. package/scaffold/astro-app/src/pages/docs/themes/[theme].astro +14 -0
  113. package/scaffold/astro-app/src/pages/docs/theming.astro +10 -0
  114. package/scaffold/astro-app/src/pages/index.astro +5 -11
  115. package/scaffold/svelte/Table.svelte +6 -5
  116. package/scaffold/svelte/Tabs.svelte +3 -1
  117. package/scaffold/svelte-app/README.md +9 -2
  118. package/scaffold/svelte-app/src/app.html +1 -1
  119. package/scaffold/svelte-app/src/lib/rizzo/Accordion.svelte +128 -0
  120. package/scaffold/svelte-app/src/lib/rizzo/Alert.svelte +85 -0
  121. package/scaffold/svelte-app/src/lib/rizzo/Avatar.svelte +39 -0
  122. package/scaffold/svelte-app/src/lib/rizzo/Badge.svelte +31 -0
  123. package/scaffold/svelte-app/src/lib/rizzo/Breadcrumb.svelte +49 -0
  124. package/scaffold/svelte-app/src/lib/rizzo/Button.svelte +27 -0
  125. package/scaffold/svelte-app/src/lib/rizzo/Card.svelte +17 -0
  126. package/scaffold/svelte-app/src/lib/rizzo/Checkbox.svelte +37 -0
  127. package/scaffold/svelte-app/src/lib/rizzo/CopyToClipboard.svelte +79 -0
  128. package/scaffold/svelte-app/src/lib/rizzo/Divider.svelte +28 -0
  129. package/scaffold/svelte-app/src/lib/rizzo/Dropdown.svelte +254 -0
  130. package/scaffold/svelte-app/src/lib/rizzo/FormGroup.svelte +51 -0
  131. package/scaffold/svelte-app/src/lib/rizzo/Input.svelte +59 -0
  132. package/scaffold/svelte-app/src/lib/rizzo/Modal.svelte +157 -0
  133. package/scaffold/svelte-app/src/lib/rizzo/Pagination.svelte +93 -0
  134. package/scaffold/svelte-app/src/lib/rizzo/ProgressBar.svelte +58 -0
  135. package/scaffold/svelte-app/src/lib/rizzo/Radio.svelte +38 -0
  136. package/scaffold/svelte-app/src/lib/rizzo/Select.svelte +51 -0
  137. package/scaffold/svelte-app/src/lib/rizzo/Spinner.svelte +14 -0
  138. package/scaffold/svelte-app/src/lib/rizzo/Table.svelte +158 -0
  139. package/scaffold/svelte-app/src/lib/rizzo/Tabs.svelte +117 -0
  140. package/scaffold/svelte-app/src/lib/rizzo/Textarea.svelte +59 -0
  141. package/scaffold/svelte-app/src/lib/rizzo/ThemeSwitcher.svelte +315 -0
  142. package/scaffold/svelte-app/src/lib/rizzo/Toast.svelte +33 -0
  143. package/scaffold/svelte-app/src/lib/rizzo/Tooltip.svelte +19 -0
  144. package/scaffold/svelte-app/src/lib/rizzo/icons/Check.svelte +29 -0
  145. package/scaffold/svelte-app/src/lib/rizzo/icons/ChevronDown.svelte +29 -0
  146. package/scaffold/svelte-app/src/lib/rizzo/icons/Circle.svelte +29 -0
  147. package/scaffold/svelte-app/src/lib/rizzo/icons/Close.svelte +30 -0
  148. package/scaffold/svelte-app/src/lib/rizzo/icons/Cmd.svelte +27 -0
  149. package/scaffold/svelte-app/src/lib/rizzo/icons/Copy.svelte +30 -0
  150. package/scaffold/svelte-app/src/lib/rizzo/icons/Eye.svelte +30 -0
  151. package/scaffold/svelte-app/src/lib/rizzo/icons/Filter.svelte +29 -0
  152. package/scaffold/svelte-app/src/lib/rizzo/icons/Gear.svelte +30 -0
  153. package/scaffold/svelte-app/src/lib/rizzo/icons/IceCream.svelte +31 -0
  154. package/scaffold/svelte-app/src/lib/rizzo/icons/Moon.svelte +29 -0
  155. package/scaffold/svelte-app/src/lib/rizzo/icons/Owl.svelte +34 -0
  156. package/scaffold/svelte-app/src/lib/rizzo/icons/Palette.svelte +33 -0
  157. package/scaffold/svelte-app/src/lib/rizzo/icons/Rainbow.svelte +31 -0
  158. package/scaffold/svelte-app/src/lib/rizzo/icons/Search.svelte +30 -0
  159. package/scaffold/svelte-app/src/lib/rizzo/icons/Snowflake.svelte +34 -0
  160. package/scaffold/svelte-app/src/lib/rizzo/icons/Sort.svelte +30 -0
  161. package/scaffold/svelte-app/src/lib/rizzo/icons/devicons/Astro.svelte +45 -0
  162. package/scaffold/svelte-app/src/lib/rizzo/icons/devicons/Bash.svelte +28 -0
  163. package/scaffold/svelte-app/src/lib/rizzo/icons/devicons/Css3.svelte +23 -0
  164. package/scaffold/svelte-app/src/lib/rizzo/icons/devicons/Git.svelte +18 -0
  165. package/scaffold/svelte-app/src/lib/rizzo/icons/devicons/Html5.svelte +21 -0
  166. package/scaffold/svelte-app/src/lib/rizzo/icons/devicons/Javascript.svelte +19 -0
  167. package/scaffold/svelte-app/src/lib/rizzo/icons/devicons/Nodejs.svelte +44 -0
  168. package/scaffold/svelte-app/src/lib/rizzo/icons/devicons/Plaintext.svelte +24 -0
  169. package/scaffold/svelte-app/src/lib/rizzo/icons/devicons/React.svelte +21 -0
  170. package/scaffold/svelte-app/src/lib/rizzo/icons/devicons/SvelteIcon.svelte +19 -0
  171. package/scaffold/svelte-app/src/lib/rizzo/icons/devicons/Vue.svelte +20 -0
  172. package/scaffold/svelte-app/src/lib/rizzo/index.ts +33 -0
  173. package/scaffold/svelte-app/src/lib/rizzo-docs/CodeBlock.svelte +239 -0
  174. package/scaffold/svelte-app/src/lib/rizzo-docs/SvelteDocPage.svelte +99 -0
  175. package/scaffold/svelte-app/src/lib/rizzo-docs/pages/AccordionDoc.svelte +53 -0
  176. package/scaffold/svelte-app/src/lib/rizzo-docs/pages/AlertDoc.svelte +114 -0
  177. package/scaffold/svelte-app/src/lib/rizzo-docs/pages/AvatarDoc.svelte +92 -0
  178. package/scaffold/svelte-app/src/lib/rizzo-docs/pages/BadgeDoc.svelte +60 -0
  179. package/scaffold/svelte-app/src/lib/rizzo-docs/pages/BreadcrumbDoc.svelte +55 -0
  180. package/scaffold/svelte-app/src/lib/rizzo-docs/pages/ButtonDoc.svelte +55 -0
  181. package/scaffold/svelte-app/src/lib/rizzo-docs/pages/CardsDoc.svelte +173 -0
  182. package/scaffold/svelte-app/src/lib/rizzo-docs/pages/ComingSoon.svelte +12 -0
  183. package/scaffold/svelte-app/src/lib/rizzo-docs/pages/ComponentsOverview.svelte +92 -0
  184. package/scaffold/svelte-app/src/lib/rizzo-docs/pages/CopyToClipboardDoc.svelte +26 -0
  185. package/scaffold/svelte-app/src/lib/rizzo-docs/pages/DividerDoc.svelte +105 -0
  186. package/scaffold/svelte-app/src/lib/rizzo-docs/pages/DropdownDoc.svelte +161 -0
  187. package/scaffold/svelte-app/src/lib/rizzo-docs/pages/FormsDoc.svelte +375 -0
  188. package/scaffold/svelte-app/src/lib/rizzo-docs/pages/IconsDoc.svelte +246 -0
  189. package/scaffold/svelte-app/src/lib/rizzo-docs/pages/Index.svelte +8 -0
  190. package/scaffold/svelte-app/src/lib/rizzo-docs/pages/ModalDoc.svelte +50 -0
  191. package/scaffold/svelte-app/src/lib/rizzo-docs/pages/NavbarDoc.svelte +79 -0
  192. package/scaffold/svelte-app/src/lib/rizzo-docs/pages/PaginationDoc.svelte +44 -0
  193. package/scaffold/svelte-app/src/lib/rizzo-docs/pages/ProgressBarDoc.svelte +95 -0
  194. package/scaffold/svelte-app/src/lib/rizzo-docs/pages/SearchDoc.svelte +147 -0
  195. package/scaffold/svelte-app/src/lib/rizzo-docs/pages/SettingsDoc.svelte +158 -0
  196. package/scaffold/svelte-app/src/lib/rizzo-docs/pages/SpinnerDoc.svelte +41 -0
  197. package/scaffold/svelte-app/src/lib/rizzo-docs/pages/TableDoc.svelte +116 -0
  198. package/scaffold/svelte-app/src/lib/rizzo-docs/pages/TabsDoc.svelte +152 -0
  199. package/scaffold/svelte-app/src/lib/rizzo-docs/pages/ThemeSwitcherDoc.svelte +181 -0
  200. package/scaffold/svelte-app/src/lib/rizzo-docs/pages/Theming.svelte +6 -0
  201. package/scaffold/svelte-app/src/lib/rizzo-docs/pages/ToastDoc.svelte +136 -0
  202. package/scaffold/svelte-app/src/lib/rizzo-docs/pages/TooltipDoc.svelte +57 -0
  203. package/scaffold/svelte-app/src/routes/+page.svelte +2 -2
  204. package/scaffold/svelte-app/src/routes/components/+page.svelte +4 -0
  205. package/scaffold/svelte-app/src/routes/components/[slug]/+page.svelte +7 -0
  206. package/scaffold/vanilla/README.md +20 -8
  207. package/scaffold/vanilla/components/accordion.html +187 -0
  208. package/scaffold/vanilla/components/alert.html +187 -0
  209. package/scaffold/vanilla/components/avatar.html +187 -0
  210. package/scaffold/vanilla/components/badge.html +187 -0
  211. package/scaffold/vanilla/components/breadcrumb.html +187 -0
  212. package/scaffold/vanilla/components/button.html +187 -0
  213. package/scaffold/vanilla/components/cards.html +187 -0
  214. package/scaffold/vanilla/components/copy-to-clipboard.html +187 -0
  215. package/scaffold/vanilla/components/divider.html +187 -0
  216. package/scaffold/vanilla/components/dropdown.html +187 -0
  217. package/scaffold/vanilla/components/forms.html +187 -0
  218. package/scaffold/vanilla/components/icons.html +187 -0
  219. package/scaffold/vanilla/components/index.html +212 -0
  220. package/scaffold/vanilla/components/modal.html +187 -0
  221. package/scaffold/vanilla/components/navbar.html +187 -0
  222. package/scaffold/vanilla/components/pagination.html +187 -0
  223. package/scaffold/vanilla/components/progress-bar.html +187 -0
  224. package/scaffold/vanilla/components/search.html +187 -0
  225. package/scaffold/vanilla/components/settings.html +187 -0
  226. package/scaffold/vanilla/components/spinner.html +187 -0
  227. package/scaffold/vanilla/components/table.html +187 -0
  228. package/scaffold/vanilla/components/tabs.html +187 -0
  229. package/scaffold/vanilla/components/theme-switcher.html +187 -0
  230. package/scaffold/vanilla/components/toast.html +187 -0
  231. package/scaffold/vanilla/components/tooltip.html +187 -0
  232. package/scaffold/vanilla/index.html +17 -283
  233. package/scaffold/vanilla/js/main.js +748 -0
@@ -0,0 +1,178 @@
1
+ ---
2
+ import ChevronDown from './icons/ChevronDown.astro';
3
+
4
+ interface AccordionItem {
5
+ id: string;
6
+ title: string;
7
+ content?: string;
8
+ }
9
+
10
+ interface Props {
11
+ items: AccordionItem[];
12
+ id?: string;
13
+ allowMultiple?: boolean;
14
+ defaultExpanded?: string | string[];
15
+ class?: string;
16
+ }
17
+
18
+ const {
19
+ items,
20
+ id,
21
+ allowMultiple = false,
22
+ defaultExpanded,
23
+ class: className = '',
24
+ } = Astro.props;
25
+
26
+ const accordionId = id || `accordion-${Math.random().toString(36).substr(2, 9)}`;
27
+
28
+ const getDefaultExpanded = (): 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 defaultOpenIds = getDefaultExpanded();
35
+ const classes = `accordion ${className}`.trim();
36
+ let slotIndex = 0;
37
+ ---
38
+
39
+ <div class={classes} data-accordion={accordionId} data-allow-multiple={allowMultiple ? 'true' : 'false'}>
40
+ {items.map((item) => {
41
+ const triggerId = `${accordionId}-trigger-${item.id}`;
42
+ const panelId = `${accordionId}-panel-${item.id}`;
43
+ const isExpanded = defaultOpenIds.has(item.id);
44
+ const useSlot = !item.content;
45
+ const currentSlotIndex = useSlot ? slotIndex++ : -1;
46
+
47
+ return (
48
+ <div class="accordion__item" data-accordion-item data-item-id={item.id}>
49
+ <h3 class="accordion__heading">
50
+ <button
51
+ type="button"
52
+ class={`accordion__trigger ${isExpanded ? 'accordion__trigger--expanded' : ''}`}
53
+ id={triggerId}
54
+ aria-expanded={isExpanded}
55
+ aria-controls={panelId}
56
+ data-accordion-trigger
57
+ >
58
+ <span class="accordion__title">{item.title}</span>
59
+ <ChevronDown class="accordion__icon" width={16} height={16} aria-hidden="true" />
60
+ </button>
61
+ </h3>
62
+ <div
63
+ class={`accordion__panel ${isExpanded ? 'accordion__panel--expanded' : ''}`}
64
+ id={panelId}
65
+ role="region"
66
+ aria-labelledby={triggerId}
67
+ hidden={!isExpanded}
68
+ data-accordion-panel
69
+ >
70
+ <div class="accordion__panel-inner">
71
+ {item.content ? (
72
+ <div class="accordion__panel-content" set:html={item.content} />
73
+ ) : (
74
+ <div class="accordion__panel-content accordion__panel-slot" data-accordion-slot-index={currentSlotIndex}>
75
+ <!-- Slot content distributed by script -->
76
+ </div>
77
+ )}
78
+ </div>
79
+ </div>
80
+ </div>
81
+ );
82
+ })}
83
+ <!-- Slot content for distribution (same order as items) -->
84
+ <div class="accordion__slot-content" style="display: none;">
85
+ <slot />
86
+ </div>
87
+ </div>
88
+
89
+ <script is:inline>
90
+ (function initAccordions() {
91
+ function initOne(accordion) {
92
+ if (accordion.dataset.accordionInit === 'true') return;
93
+ accordion.dataset.accordionInit = 'true';
94
+
95
+ const isMultiple = accordion.getAttribute('data-allow-multiple') === 'true';
96
+ const triggers = accordion.querySelectorAll('[data-accordion-trigger]');
97
+
98
+ const setExpanded = (trigger, expanded) => {
99
+ const panelId = trigger.getAttribute('aria-controls');
100
+ const panel = panelId ? accordion.querySelector('#' + CSS.escape(panelId)) : null;
101
+ trigger.setAttribute('aria-expanded', String(expanded));
102
+ trigger.classList.toggle('accordion__trigger--expanded', expanded);
103
+ if (panel) {
104
+ panel.classList.toggle('accordion__panel--expanded', expanded);
105
+ panel.hidden = !expanded;
106
+ }
107
+ };
108
+
109
+ const toggle = (trigger) => {
110
+ const expanded = trigger.getAttribute('aria-expanded') === 'true';
111
+ if (!isMultiple) {
112
+ triggers.forEach((t) => setExpanded(t, false));
113
+ }
114
+ setExpanded(trigger, !expanded);
115
+ };
116
+
117
+ triggers.forEach((trigger) => {
118
+ trigger.addEventListener('click', () => toggle(trigger));
119
+ });
120
+
121
+ triggers.forEach((trigger, index) => {
122
+ trigger.addEventListener('keydown', (e) => {
123
+ let targetIndex = index;
124
+ switch (e.key) {
125
+ case 'ArrowDown':
126
+ e.preventDefault();
127
+ targetIndex = Math.min(index + 1, triggers.length - 1);
128
+ break;
129
+ case 'ArrowUp':
130
+ e.preventDefault();
131
+ targetIndex = Math.max(index - 1, 0);
132
+ break;
133
+ case 'Home':
134
+ e.preventDefault();
135
+ targetIndex = 0;
136
+ break;
137
+ case 'End':
138
+ e.preventDefault();
139
+ targetIndex = triggers.length - 1;
140
+ break;
141
+ case 'Enter':
142
+ case ' ':
143
+ e.preventDefault();
144
+ toggle(trigger);
145
+ return;
146
+ default:
147
+ return;
148
+ }
149
+ if (targetIndex !== index) {
150
+ triggers[targetIndex].focus();
151
+ }
152
+ });
153
+ });
154
+
155
+ const slotContent = accordion.querySelector('.accordion__slot-content');
156
+ if (slotContent) {
157
+ const slotChildren = Array.from(slotContent.children);
158
+ slotChildren.forEach((child, index) => {
159
+ const slotPlaceholder = accordion.querySelector('[data-accordion-slot-index="' + index + '"]');
160
+ if (slotPlaceholder) {
161
+ slotPlaceholder.appendChild(child);
162
+ }
163
+ });
164
+ slotContent.remove();
165
+ }
166
+ }
167
+
168
+ function init() {
169
+ document.querySelectorAll('[data-accordion]').forEach(initOne);
170
+ }
171
+
172
+ if (document.readyState === 'loading') {
173
+ document.addEventListener('DOMContentLoaded', init);
174
+ } else {
175
+ init();
176
+ }
177
+ })();
178
+ </script>
@@ -0,0 +1,131 @@
1
+ ---
2
+ import Close from './icons/Close.astro';
3
+
4
+ interface Props {
5
+ variant?: 'success' | 'error' | 'warning' | 'info';
6
+ dismissible?: boolean;
7
+ autoDismiss?: number; // Duration in milliseconds (0 = disabled)
8
+ class?: string;
9
+ id?: string;
10
+ }
11
+
12
+ const {
13
+ variant = 'info',
14
+ dismissible = false,
15
+ autoDismiss = 0, // 0 means disabled
16
+ class: className = '',
17
+ id,
18
+ } = Astro.props;
19
+
20
+ const alertId = id || `alert-${Math.random().toString(36).substr(2, 9)}`;
21
+ const variantClass = `alert--${variant}`;
22
+ const classes = `alert ${variantClass} ${className}`.trim();
23
+
24
+ // ARIA labels based on variant
25
+ const ariaLabels = {
26
+ success: 'Success message',
27
+ error: 'Error message',
28
+ warning: 'Warning message',
29
+ info: 'Information message',
30
+ };
31
+ ---
32
+
33
+ <div
34
+ class={classes}
35
+ id={alertId}
36
+ role="alert"
37
+ aria-live="polite"
38
+ aria-atomic="true"
39
+ aria-label={ariaLabels[variant]}
40
+ >
41
+ <div class="alert__content">
42
+ <slot />
43
+ </div>
44
+ {dismissible && (
45
+ <button
46
+ type="button"
47
+ class="alert__close"
48
+ aria-label="Dismiss alert"
49
+ data-alert-close
50
+ aria-controls={alertId}
51
+ >
52
+ <Close width={16} height={16} />
53
+ </button>
54
+ )}
55
+ </div>
56
+
57
+ <script define:vars={{ alertId, autoDismiss }}>
58
+ (function initAlert() {
59
+ const init = () => {
60
+ const alert = document.querySelector(`#${alertId}`);
61
+ if (!alert) {
62
+ if (document.readyState === 'loading') {
63
+ document.addEventListener('DOMContentLoaded', init);
64
+ return;
65
+ }
66
+ return;
67
+ }
68
+
69
+ // Skip if already initialized
70
+ if (alert.hasAttribute('data-alert-initialized')) return;
71
+ alert.setAttribute('data-alert-initialized', 'true');
72
+
73
+ const closeBtn = alert.querySelector('[data-alert-close]');
74
+
75
+ let closeAlert = () => {
76
+ // Announce dismissal to screen readers
77
+ const announcement = document.createElement('div');
78
+ announcement.setAttribute('role', 'status');
79
+ announcement.setAttribute('aria-live', 'polite');
80
+ announcement.className = 'sr-only';
81
+ announcement.textContent = 'Alert dismissed';
82
+ document.body.appendChild(announcement);
83
+
84
+ // Remove alert with animation
85
+ alert.style.opacity = '0';
86
+ alert.style.transform = 'translateY(-10px)';
87
+
88
+ setTimeout(() => {
89
+ alert.remove();
90
+ if (document.body.contains(announcement)) {
91
+ document.body.removeChild(announcement);
92
+ }
93
+ }, 200);
94
+ };
95
+
96
+ // Auto-dismiss functionality
97
+ if (autoDismiss > 0) {
98
+ const timeoutId = setTimeout(() => {
99
+ closeAlert();
100
+ }, autoDismiss);
101
+
102
+ // Clear timeout if user manually dismisses
103
+ if (closeBtn) {
104
+ const originalClose = closeAlert;
105
+ closeAlert = () => {
106
+ clearTimeout(timeoutId);
107
+ originalClose();
108
+ };
109
+ }
110
+ }
111
+
112
+ if (closeBtn) {
113
+ closeBtn.addEventListener('click', closeAlert);
114
+
115
+ // Keyboard support
116
+ closeBtn.addEventListener('keydown', (e) => {
117
+ if (e.key === 'Enter' || e.key === ' ') {
118
+ e.preventDefault();
119
+ closeAlert();
120
+ }
121
+ });
122
+ }
123
+ };
124
+
125
+ if (document.readyState === 'loading') {
126
+ document.addEventListener('DOMContentLoaded', init);
127
+ } else {
128
+ init();
129
+ }
130
+ })();
131
+ </script>
@@ -0,0 +1,59 @@
1
+ ---
2
+ import { Image } from 'astro:assets';
3
+
4
+ interface Props {
5
+ /** Image URL (when provided, shows image; otherwise shows initials or placeholder). For remote URLs, add the domain to image.domains in astro.config. */
6
+ src?: string;
7
+ /** Alt text for the image */
8
+ alt?: string;
9
+ /** Full name used to derive initials when no image (e.g. "Jane Doe" → "JD") */
10
+ name?: string;
11
+ /** Override initials when no image (e.g. "JD"); ignored if name is provided */
12
+ initials?: string;
13
+ /** Size */
14
+ size?: 'sm' | 'md' | 'lg';
15
+ /** Shape */
16
+ shape?: 'circle' | 'square';
17
+ class?: string;
18
+ }
19
+
20
+ const {
21
+ src,
22
+ alt = '',
23
+ name = '',
24
+ initials: initialsProp = '',
25
+ size = 'md',
26
+ shape = 'circle',
27
+ class: className = '',
28
+ } = Astro.props;
29
+
30
+ function getInitials(name: string): string {
31
+ const parts = name.trim().split(/\s+/).filter(Boolean);
32
+ if (parts.length === 0) return '';
33
+ if (parts.length === 1) return parts[0].slice(0, 2).toUpperCase();
34
+ return (parts[0][0] + parts[parts.length - 1][0]).toUpperCase();
35
+ }
36
+
37
+ const displayInitials = name ? getInitials(name) : initialsProp;
38
+ const sizeClass = `avatar--${size}`;
39
+ const shapeClass = `avatar--${shape}`;
40
+ const classes = `avatar ${sizeClass} ${shapeClass} ${className}`.trim();
41
+
42
+ const sizePixels = size === 'sm' ? 32 : size === 'lg' ? 48 : 40;
43
+ ---
44
+
45
+ <span class={classes} role="img" aria-label={alt || name || (displayInitials ? `Avatar: ${displayInitials}` : 'Avatar')}>
46
+ {src ? (
47
+ <Image
48
+ src={src}
49
+ alt={alt || name || ''}
50
+ width={sizePixels}
51
+ height={sizePixels}
52
+ class="avatar__img"
53
+ />
54
+ ) : (
55
+ <span class="avatar__initials" aria-hidden="true">
56
+ {displayInitials || '?'}
57
+ </span>
58
+ )}
59
+ </span>
@@ -0,0 +1,24 @@
1
+ ---
2
+ interface Props {
3
+ variant?: 'primary' | 'success' | 'warning' | 'error' | 'info';
4
+ size?: 'sm' | 'md' | 'lg';
5
+ pill?: boolean;
6
+ class?: string;
7
+ }
8
+
9
+ const {
10
+ variant = 'primary',
11
+ size = 'md',
12
+ pill = false,
13
+ class: className = '',
14
+ } = Astro.props;
15
+
16
+ const variantClass = `badge--${variant}`;
17
+ const sizeClass = `badge--${size}`;
18
+ const pillClass = pill ? 'badge--pill' : '';
19
+ const classes = `badge ${variantClass} ${sizeClass} ${pillClass} ${className}`.trim();
20
+ ---
21
+
22
+ <span class={classes}>
23
+ <slot />
24
+ </span>
@@ -0,0 +1,61 @@
1
+ ---
2
+ import ChevronDown from './icons/ChevronDown.astro';
3
+
4
+ interface BreadcrumbItem {
5
+ label: string;
6
+ href?: string;
7
+ }
8
+
9
+ interface Props {
10
+ items: BreadcrumbItem[];
11
+ separator?: 'chevron' | 'slash' | 'arrow' | string;
12
+ class?: string;
13
+ }
14
+
15
+ const {
16
+ items,
17
+ separator = 'chevron',
18
+ class: className = '',
19
+ } = Astro.props;
20
+
21
+ const separatorVariant =
22
+ separator === 'slash' ? 'breadcrumb--slash' :
23
+ separator === 'arrow' ? 'breadcrumb--arrow' :
24
+ 'breadcrumb--chevron';
25
+ const classes = `breadcrumb ${separatorVariant} ${className}`.trim();
26
+
27
+ const separatorChar = separator === 'slash' ? '/' : separator === 'arrow' ? '›' : typeof separator === 'string' ? separator : null;
28
+ const useIcon = separator === 'chevron';
29
+ ---
30
+
31
+ <nav class={classes} aria-label="Breadcrumb">
32
+ <ol class="breadcrumb__list">
33
+ {items.map((item, index) => {
34
+ const isLast = index === items.length - 1;
35
+ const isCurrent = isLast || !item.href;
36
+
37
+ return (
38
+ <li class={`breadcrumb__item ${isCurrent ? 'breadcrumb__item--current' : ''}`}>
39
+ {isCurrent ? (
40
+ <span class="breadcrumb__current" aria-current="page">
41
+ {item.label}
42
+ </span>
43
+ ) : (
44
+ <a class="breadcrumb__link" href={item.href}>
45
+ {item.label}
46
+ </a>
47
+ )}
48
+ {!isLast && (
49
+ <span class="breadcrumb__separator" aria-hidden="true">
50
+ {useIcon ? (
51
+ <ChevronDown class="breadcrumb__separator-icon" width={14} height={14} />
52
+ ) : (
53
+ separatorChar ?? '›'
54
+ )}
55
+ </span>
56
+ )}
57
+ </li>
58
+ );
59
+ })}
60
+ </ol>
61
+ </nav>
@@ -0,0 +1,3 @@
1
+ <button>
2
+ Click me
3
+ </button>
@@ -0,0 +1,18 @@
1
+ ---
2
+ interface Props {
3
+ variant?: 'default' | 'elevated' | 'outlined' | 'filled';
4
+ class?: string;
5
+ }
6
+
7
+ const {
8
+ variant = 'default',
9
+ class: className = '',
10
+ } = Astro.props;
11
+
12
+ const variantClass = variant !== 'default' ? `card--${variant}` : '';
13
+ const classes = `card ${variantClass} ${className}`.trim();
14
+ ---
15
+
16
+ <div class={classes}>
17
+ <slot />
18
+ </div>
@@ -0,0 +1,38 @@
1
+ ---
2
+ interface Props {
3
+ id?: string;
4
+ name?: string;
5
+ value?: string;
6
+ checked?: boolean;
7
+ required?: boolean;
8
+ disabled?: boolean;
9
+ class?: string;
10
+ ariaDescribedby?: string;
11
+ ariaLabel?: string;
12
+ }
13
+
14
+ const {
15
+ id,
16
+ name,
17
+ value,
18
+ checked = false,
19
+ required = false,
20
+ disabled = false,
21
+ class: className = '',
22
+ ariaDescribedby,
23
+ ariaLabel,
24
+ } = Astro.props;
25
+ ---
26
+
27
+ <input
28
+ type="checkbox"
29
+ id={id}
30
+ name={name}
31
+ value={value}
32
+ checked={checked}
33
+ required={required}
34
+ disabled={disabled}
35
+ class={className}
36
+ aria-describedby={ariaDescribedby}
37
+ aria-label={ariaLabel}
38
+ />