@birdycom/omniaui 0.11.0 → 0.11.2

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 (214) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +21 -21
  3. package/bin/lib/add.mjs +126 -126
  4. package/bin/lib/catalog.mjs +169 -169
  5. package/bin/lib/project.mjs +90 -90
  6. package/bin/omniaui.mjs +69 -69
  7. package/dist/code-block.css +25 -25
  8. package/dist/components-extra.css +916 -914
  9. package/dist/components.css +6565 -6469
  10. package/dist/components.min.css +1 -1
  11. package/dist/data-table.d.ts +9 -9
  12. package/dist/data-table.js +505 -505
  13. package/dist/docs-ui.css +267 -265
  14. package/dist/oc-theme.css +69 -69
  15. package/dist/parts/app-accordion-accent.css +60 -60
  16. package/dist/parts/app-alpha-tabs.css +68 -68
  17. package/dist/parts/app-busy-overlay.css +25 -25
  18. package/dist/parts/app-column-menu.css +85 -85
  19. package/dist/parts/app-confirm-dialog.css +70 -70
  20. package/dist/parts/app-cookie-consent.css +63 -63
  21. package/dist/parts/app-data-table.css +174 -174
  22. package/dist/parts/app-greeting.css +47 -47
  23. package/dist/parts/app-list-toolbar.css +81 -81
  24. package/dist/parts/app-page-header.css +54 -54
  25. package/dist/parts/app-severity-card.css +91 -91
  26. package/dist/parts/app-sidebar-dark.css +15 -15
  27. package/dist/parts/app-sortable-row.css +52 -52
  28. package/dist/parts/app-stat-card.css +68 -68
  29. package/dist/parts/app-table-actions.css +71 -71
  30. package/dist/parts/app-table-compact.css +54 -54
  31. package/dist/parts/app-top-progress.css +68 -68
  32. package/dist/parts/app-tree.css +104 -104
  33. package/dist/parts/app-upgrade-banner.css +90 -90
  34. package/dist/parts/app-version-banner.css +80 -80
  35. package/dist/parts/data-chart-line.css +167 -167
  36. package/dist/parts/forms-affix-input.css +75 -75
  37. package/dist/parts/forms-barcode-input.css +75 -75
  38. package/dist/parts/forms-chip-filter.css +91 -91
  39. package/dist/parts/forms-color-select.css +97 -89
  40. package/dist/parts/forms-decimal-input.css +51 -51
  41. package/dist/parts/forms-filter-counts.css +94 -94
  42. package/dist/parts/forms-language-select.css +89 -76
  43. package/dist/parts/forms-number-input.css +98 -95
  44. package/dist/parts/forms-password-requirements.css +55 -55
  45. package/dist/parts/forms-phone-input.css +85 -85
  46. package/dist/parts/forms-time-input.css +74 -74
  47. package/dist/parts/forms-toggle-field.css +69 -69
  48. package/dist/parts/media-art.css +21 -21
  49. package/dist/parts/media-attachment.css +160 -160
  50. package/dist/parts/media-browser-frame.css +73 -73
  51. package/dist/parts/media-card.css +83 -83
  52. package/dist/parts/media-chat-composer.css +90 -90
  53. package/dist/parts/media-doc-viewer.css +151 -151
  54. package/dist/parts/media-emoji-picker.css +88 -88
  55. package/dist/parts/media-entity-card.css +52 -52
  56. package/dist/parts/media-flip-card.css +78 -78
  57. package/dist/parts/media-image-zoom.css +68 -68
  58. package/dist/parts/media-lightbox.css +131 -131
  59. package/dist/parts/media-message-thread.css +136 -136
  60. package/dist/parts/media-message.css +160 -160
  61. package/dist/parts/media-row.css +78 -78
  62. package/dist/parts/media-stack-card.css +82 -82
  63. package/dist/parts/media-terminal-log.css +76 -76
  64. package/dist/parts/media-thumb.css +71 -71
  65. package/dist/parts/site-fact-list.css +25 -25
  66. package/dist/parts/site-link-arrow.css +34 -34
  67. package/dist/parts/site-marquee.css +34 -34
  68. package/dist/parts/site-next-teaser.css +75 -75
  69. package/dist/parts/site-price-card.css +91 -75
  70. package/dist/parts/site-product-mark.css +66 -66
  71. package/dist/parts/site-project-card.css +111 -111
  72. package/dist/parts/site-prose.css +124 -124
  73. package/dist/parts/site-stack-list.css +48 -48
  74. package/dist/parts/site-timeline.css +54 -54
  75. package/dist/showcase.css +410 -404
  76. package/package.json +69 -69
  77. package/snippets/accordion-accent.html +24 -24
  78. package/snippets/accordion.html +11 -11
  79. package/snippets/affix-input.html +30 -30
  80. package/snippets/alert-dialog.html +22 -22
  81. package/snippets/alert.html +5 -5
  82. package/snippets/alpha-tabs.html +37 -37
  83. package/snippets/aspect-ratio.html +15 -15
  84. package/snippets/attachment.html +43 -43
  85. package/snippets/avatar.html +6 -6
  86. package/snippets/back-link.html +5 -5
  87. package/snippets/badge.html +5 -5
  88. package/snippets/barcode-input.html +18 -18
  89. package/snippets/breadcrumb.html +6 -6
  90. package/snippets/browser-frame.html +18 -18
  91. package/snippets/busy-overlay.html +31 -31
  92. package/snippets/button-group.html +21 -21
  93. package/snippets/button.html +8 -8
  94. package/snippets/calendar.html +43 -43
  95. package/snippets/card.html +17 -17
  96. package/snippets/carousel.html +21 -21
  97. package/snippets/chart-line.html +46 -46
  98. package/snippets/chart.html +27 -27
  99. package/snippets/chat-composer.html +21 -21
  100. package/snippets/checkbox.html +5 -5
  101. package/snippets/checklist.html +23 -23
  102. package/snippets/chip-filter.html +14 -14
  103. package/snippets/code-window.html +20 -20
  104. package/snippets/collapsible.html +19 -19
  105. package/snippets/color-field.html +13 -13
  106. package/snippets/color-select.html +18 -18
  107. package/snippets/column-menu.html +38 -38
  108. package/snippets/combobox.html +19 -19
  109. package/snippets/command.html +24 -24
  110. package/snippets/confirm-dialog.html +32 -32
  111. package/snippets/context-menu.html +25 -25
  112. package/snippets/cookie-consent.html +70 -70
  113. package/snippets/copy-field.html +19 -19
  114. package/snippets/counter.html +2 -2
  115. package/snippets/data-table.html +151 -151
  116. package/snippets/date-picker.html +32 -32
  117. package/snippets/decimal-input.html +20 -20
  118. package/snippets/definition-list.html +20 -20
  119. package/snippets/demo-panel.html +18 -18
  120. package/snippets/doc-viewer.html +58 -58
  121. package/snippets/drawer.html +30 -30
  122. package/snippets/dropdown-menu.html +27 -27
  123. package/snippets/dropdown.html +9 -9
  124. package/snippets/dropzone.html +13 -13
  125. package/snippets/emoji-picker.html +51 -51
  126. package/snippets/empty-state.html +17 -17
  127. package/snippets/entity-card.html +26 -26
  128. package/snippets/expandable-table.html +26 -26
  129. package/snippets/fact-list.html +14 -14
  130. package/snippets/filter-counts.html +30 -30
  131. package/snippets/flip-card.html +22 -22
  132. package/snippets/form-field.html +6 -6
  133. package/snippets/greeting.html +22 -22
  134. package/snippets/heading.html +14 -14
  135. package/snippets/hover-card.html +18 -18
  136. package/snippets/image-zoom.html +30 -30
  137. package/snippets/input-group.html +10 -10
  138. package/snippets/input.html +5 -5
  139. package/snippets/item.html +26 -26
  140. package/snippets/kbd.html +13 -13
  141. package/snippets/label.html +9 -9
  142. package/snippets/language-select.html +26 -26
  143. package/snippets/launcher-card.html +14 -14
  144. package/snippets/lightbox.html +50 -50
  145. package/snippets/link-arrow.html +10 -10
  146. package/snippets/list-toolbar.html +33 -33
  147. package/snippets/marquee.html +15 -15
  148. package/snippets/media-card.html +28 -28
  149. package/snippets/media-row.html +21 -21
  150. package/snippets/media-thumb.html +12 -12
  151. package/snippets/menubar.html +30 -30
  152. package/snippets/message-thread.html +123 -123
  153. package/snippets/message.html +51 -51
  154. package/snippets/modal.html +15 -15
  155. package/snippets/native-select.html +15 -15
  156. package/snippets/navmenu.html +23 -23
  157. package/snippets/next-teaser.html +15 -15
  158. package/snippets/number-input.html +27 -27
  159. package/snippets/otp-input.html +9 -9
  160. package/snippets/page-header.html +24 -24
  161. package/snippets/pagination.html +6 -6
  162. package/snippets/password-input.html +24 -24
  163. package/snippets/password-requirements.html +30 -30
  164. package/snippets/phone-input.html +22 -22
  165. package/snippets/popover.html +15 -15
  166. package/snippets/price-card.html +34 -34
  167. package/snippets/product-mark.html +13 -13
  168. package/snippets/progress.html +4 -4
  169. package/snippets/project-card.html +23 -23
  170. package/snippets/prose.html +54 -54
  171. package/snippets/radio.html +17 -17
  172. package/snippets/recovery-codes.html +20 -20
  173. package/snippets/resizable.html +16 -16
  174. package/snippets/scroll-area.html +20 -20
  175. package/snippets/search.html +8 -8
  176. package/snippets/segmented.html +11 -11
  177. package/snippets/select.html +7 -7
  178. package/snippets/separator.html +15 -15
  179. package/snippets/severity-card.html +35 -35
  180. package/snippets/sheet.html +32 -32
  181. package/snippets/sidebar-docs.html +24 -24
  182. package/snippets/sidebar.html +55 -55
  183. package/snippets/site-footer.html +6 -6
  184. package/snippets/site-header.html +26 -26
  185. package/snippets/skeleton.html +4 -4
  186. package/snippets/slider.html +17 -17
  187. package/snippets/sortable-row.html +31 -31
  188. package/snippets/spinner.html +14 -14
  189. package/snippets/stack-card.html +17 -17
  190. package/snippets/stack-list.html +16 -16
  191. package/snippets/stat-card.html +24 -24
  192. package/snippets/stepper.html +13 -13
  193. package/snippets/switch.html +6 -6
  194. package/snippets/table-actions.html +39 -39
  195. package/snippets/table-compact.html +24 -24
  196. package/snippets/table.html +29 -29
  197. package/snippets/tabs.html +9 -9
  198. package/snippets/tag-input.html +60 -17
  199. package/snippets/terminal-log.html +23 -23
  200. package/snippets/textarea.html +3 -3
  201. package/snippets/theme-switch.html +6 -6
  202. package/snippets/time-input.html +26 -26
  203. package/snippets/timeline.html +28 -28
  204. package/snippets/toast-stack.html +10 -10
  205. package/snippets/toast.html +36 -36
  206. package/snippets/toc.html +13 -13
  207. package/snippets/toggle-field.html +20 -20
  208. package/snippets/toggle.html +22 -22
  209. package/snippets/tooltip.html +4 -4
  210. package/snippets/top-progress.html +12 -12
  211. package/snippets/tree.html +38 -38
  212. package/snippets/upgrade-banner.html +28 -28
  213. package/snippets/user.html +15 -15
  214. package/snippets/version-banner.html +15 -15
@@ -1,15 +1,15 @@
1
- <!-- OmniaUI component: next-teaser - "Next product" teaser card with label, name, mark and an arrow tagline. Needs @birdycom/omniaui CSS.
2
- File: packages/ui/snippets/next-teaser.html | Map: a.oc-next-teaser -> __label -> __name (mark + text) -> __tagline
3
- Class API (modifiers are extra classes / attributes on the same element):
4
- .oc-next-teaser: The card (an <a>). Modifier: --prev ("Previous" link, arrow left before the tagline)
5
- .oc-next-teaser__label: Small uppercase label
6
- .oc-next-teaser__name: Name; may start with an .oc-product-mark
7
- .oc-next-teaser__tagline: Short line with a moving arrow
8
- .oc-accent--*: Accent preset
9
- Slots: label, name, mark, tagline
10
- -->
11
- <a class="oc-next-teaser oc-accent--violet" href="#next">
12
- <span class="oc-next-teaser__label">Next product</span>
13
- <span class="oc-next-teaser__name"><span class="oc-product-mark oc-product-mark--sm oc-accent--violet" aria-hidden="true">&#9673;</span>Acme Design</span>
14
- <span class="oc-next-teaser__tagline">The design system behind our apps</span>
15
- </a>
1
+ <!-- OmniaUI component: next-teaser - "Next product" teaser card with label, name, mark and an arrow tagline. Needs @birdycom/omniaui CSS.
2
+ File: packages/ui/snippets/next-teaser.html | Map: a.oc-next-teaser -> __label -> __name (mark + text) -> __tagline
3
+ Class API (modifiers are extra classes / attributes on the same element):
4
+ .oc-next-teaser: The card (an <a>). Modifier: --prev ("Previous" link, arrow left before the tagline)
5
+ .oc-next-teaser__label: Small uppercase label
6
+ .oc-next-teaser__name: Name; may start with an .oc-product-mark
7
+ .oc-next-teaser__tagline: Short line with a moving arrow
8
+ .oc-accent--*: Accent preset
9
+ Slots: label, name, mark, tagline
10
+ -->
11
+ <a class="oc-next-teaser oc-accent--violet" href="#next">
12
+ <span class="oc-next-teaser__label">Next product</span>
13
+ <span class="oc-next-teaser__name"><span class="oc-product-mark oc-product-mark--sm oc-accent--violet" aria-hidden="true">&#9673;</span>Acme Design</span>
14
+ <span class="oc-next-teaser__tagline">The design system behind our apps</span>
15
+ </a>
@@ -1,27 +1,27 @@
1
- <!-- OmniaUI component: number-input - Number field with minus and plus step buttons. Needs @birdycom/omniaui CSS.
2
- File: packages/ui/snippets/number-input.html | Map: wrapper -> minus button -> number field -> plus button -> optional script
3
- Class API (modifiers are extra classes / attributes on the same element):
4
- .oc-number-input: Frame around buttons and field. Modifiers: --sm, --block (full width), --error.
5
- .oc-number-input-step: Minus / plus button (data-oc-step="-1" or "1")
6
- .oc-number-input-field: input type="number" (min, max, step work natively; spinners hidden)
7
- States: :focus-within (ring), :user-invalid outside min/max (red), disabled field (dimmed)
8
- The field works without JavaScript (arrow keys). The script below makes the buttons call stepDown()/stepUp().
9
- -->
10
- <div class="oc-number-input">
11
- <button class="oc-number-input-step" type="button" data-oc-step="-1" aria-label="Decrease">&minus;</button>
12
- <input class="oc-number-input-field" type="number" name="quantity" value="2" min="0" max="99" step="1" aria-label="Quantity">
13
- <button class="oc-number-input-step" type="button" data-oc-step="1" aria-label="Increase">+</button>
14
- </div>
15
- <script>
16
- // One listener for every number input on the page. stepUp/stepDown respect min, max and step.
17
- document.addEventListener('click', (e) => {
18
- const btn = e.target.closest('.oc-number-input-step');
19
- if (!btn) return;
20
- const input = btn.parentElement.querySelector('.oc-number-input-field');
21
- if (!input || input.disabled) return;
22
- btn.dataset.ocStep === '-1' ? input.stepDown() : input.stepUp();
23
- // Let forms and frameworks know the value changed.
24
- input.dispatchEvent(new Event('input', { bubbles: true }));
25
- input.dispatchEvent(new Event('change', { bubbles: true }));
26
- });
27
- </script>
1
+ <!-- OmniaUI component: number-input - Number field with minus and plus step buttons. Needs @birdycom/omniaui CSS.
2
+ File: packages/ui/snippets/number-input.html | Map: wrapper -> minus button -> number field -> plus button -> optional script
3
+ Class API (modifiers are extra classes / attributes on the same element):
4
+ .oc-number-input: Frame around buttons and field. Modifiers: --sm, --block (full width), --error.
5
+ .oc-number-input-step: Minus / plus button (data-oc-step="-1" or "1")
6
+ .oc-number-input-field: input type="number" (min, max, step work natively; spinners hidden)
7
+ States: :focus-within (ring), :user-invalid outside min/max (red), disabled field (dimmed)
8
+ The field works without JavaScript (arrow keys). The script below makes the buttons call stepDown()/stepUp().
9
+ -->
10
+ <div class="oc-number-input">
11
+ <button class="oc-number-input-step" type="button" data-oc-step="-1" aria-label="Decrease">&minus;</button>
12
+ <input class="oc-number-input-field" type="number" name="quantity" value="2" min="0" max="99" step="1" aria-label="Quantity">
13
+ <button class="oc-number-input-step" type="button" data-oc-step="1" aria-label="Increase">+</button>
14
+ </div>
15
+ <script>
16
+ // One listener for every number input on the page. stepUp/stepDown respect min, max and step.
17
+ document.addEventListener('click', (e) => {
18
+ const btn = e.target.closest('.oc-number-input-step');
19
+ if (!btn) return;
20
+ const input = btn.parentElement.querySelector('.oc-number-input-field');
21
+ if (!input || input.disabled) return;
22
+ btn.dataset.ocStep === '-1' ? input.stepDown() : input.stepUp();
23
+ // Let forms and frameworks know the value changed.
24
+ input.dispatchEvent(new Event('input', { bubbles: true }));
25
+ input.dispatchEvent(new Event('change', { bubbles: true }));
26
+ });
27
+ </script>
@@ -1,9 +1,9 @@
1
- <!-- OmniaUI component: otp-input - One-time code field drawn as separate cells on a single real input. Needs @birdycom/omniaui CSS.
2
- Class API (modifiers are extra classes / attributes on the same element):
3
- .oc-otp: The input. Set style="--oc-otp-length: 6" and maxlength to the code length. aria-invalid="true" shows the error state.
4
- -->
5
- <div class="oc-field">
6
- <label class="oc-field-label" for="oc-otp-demo">Authentication code</label>
7
- <input class="oc-otp" id="oc-otp-demo" name="code" type="text" inputmode="numeric" autocomplete="one-time-code" maxlength="6" pattern="[0-9]*" style="--oc-otp-length: 6" value="123">
8
- <p class="oc-field-description">Enter the 6-digit code from your authenticator app.</p>
9
- </div>
1
+ <!-- OmniaUI component: otp-input - One-time code field drawn as separate cells on a single real input. Needs @birdycom/omniaui CSS.
2
+ Class API (modifiers are extra classes / attributes on the same element):
3
+ .oc-otp: The input. Set style="--oc-otp-length: 6" and maxlength to the code length. aria-invalid="true" shows the error state.
4
+ -->
5
+ <div class="oc-field">
6
+ <label class="oc-field-label" for="oc-otp-demo">Authentication code</label>
7
+ <input class="oc-otp" id="oc-otp-demo" name="code" type="text" inputmode="numeric" autocomplete="one-time-code" maxlength="6" pattern="[0-9]*" style="--oc-otp-length: 6" value="123">
8
+ <p class="oc-field-description">Enter the 6-digit code from your authenticator app.</p>
9
+ </div>
@@ -1,24 +1,24 @@
1
- <!-- OmniaUI component: page-header - Page title row with back link, subtitle, meta and actions; actions move under the title in narrow containers. Needs @birdycom/omniaui CSS.
2
- File: packages/ui/snippets/page-header.html | Map: header -> back row -> main (text: title + badge, subtitle, meta | actions)
3
- Class API (modifiers are extra classes / attributes on the same element):
4
- .oc-page-header: Header (size container). Modifiers: --bordered (line under it), --sticky, --sm.
5
- .oc-page-header-back: Optional row for an .oc-back-link
6
- .oc-page-header-main: Text block + actions (side by side from a 36rem container width)
7
- .oc-page-header-text / -title / -subtitle / -meta: Text column, h1 (may hold a badge), sub line, meta row
8
- .oc-page-header-actions: Buttons
9
- Slots: back, title, subtitle, meta, actions
10
- -->
11
- <header class="oc-page-header oc-page-header--bordered">
12
- <div class="oc-page-header-back"><a class="oc-back-link" href="#">Projects</a></div>
13
- <div class="oc-page-header-main">
14
- <div class="oc-page-header-text">
15
- <h1 class="oc-page-header-title">Kitchen renovation <span class="oc-badge oc-badge--success">Active</span></h1>
16
- <p class="oc-page-header-subtitle">Main street 12, Ghent - started 2 September 2026.</p>
17
- <div class="oc-page-header-meta"><span>Owner: Ada Lovelace</span><span>Updated 2 hours ago</span></div>
18
- </div>
19
- <div class="oc-page-header-actions">
20
- <button class="oc-btn oc-btn--outline" type="button">Share</button>
21
- <button class="oc-btn" type="button">New quote</button>
22
- </div>
23
- </div>
24
- </header>
1
+ <!-- OmniaUI component: page-header - Page title row with back link, subtitle, meta and actions; actions move under the title in narrow containers. Needs @birdycom/omniaui CSS.
2
+ File: packages/ui/snippets/page-header.html | Map: header -> back row -> main (text: title + badge, subtitle, meta | actions)
3
+ Class API (modifiers are extra classes / attributes on the same element):
4
+ .oc-page-header: Header (size container). Modifiers: --bordered (line under it), --sticky, --sm.
5
+ .oc-page-header-back: Optional row for an .oc-back-link
6
+ .oc-page-header-main: Text block + actions (side by side from a 36rem container width)
7
+ .oc-page-header-text / -title / -subtitle / -meta: Text column, h1 (may hold a badge), sub line, meta row
8
+ .oc-page-header-actions: Buttons
9
+ Slots: back, title, subtitle, meta, actions
10
+ -->
11
+ <header class="oc-page-header oc-page-header--bordered">
12
+ <div class="oc-page-header-back"><a class="oc-back-link" href="#">Projects</a></div>
13
+ <div class="oc-page-header-main">
14
+ <div class="oc-page-header-text">
15
+ <h1 class="oc-page-header-title">Kitchen renovation <span class="oc-badge oc-badge--success">Active</span></h1>
16
+ <p class="oc-page-header-subtitle">Main street 12, Ghent - started 2 September 2026.</p>
17
+ <div class="oc-page-header-meta"><span>Owner: Ada Lovelace</span><span>Updated 2 hours ago</span></div>
18
+ </div>
19
+ <div class="oc-page-header-actions">
20
+ <button class="oc-btn oc-btn--outline" type="button">Share</button>
21
+ <button class="oc-btn" type="button">New quote</button>
22
+ </div>
23
+ </div>
24
+ </header>
@@ -1,6 +1,6 @@
1
- <!-- OmniaUI component: pagination — Pagination. Needs @birdycom/omniaui CSS. -->
2
- <nav class="oc-pagination" aria-label="Pagination">
3
- <a class="oc-pagination-item" href="?page=1">1</a>
4
- <a class="oc-pagination-item" href="?page=2" aria-current="page">2</a>
5
- <a class="oc-pagination-item" href="?page=3">3</a>
6
- </nav>
1
+ <!-- OmniaUI component: pagination — Pagination. Needs @birdycom/omniaui CSS. -->
2
+ <nav class="oc-pagination" aria-label="Pagination">
3
+ <a class="oc-pagination-item" href="?page=1">1</a>
4
+ <a class="oc-pagination-item" href="?page=2" aria-current="page">2</a>
5
+ <a class="oc-pagination-item" href="?page=3">3</a>
6
+ </nav>
@@ -1,24 +1,24 @@
1
- <!-- OmniaUI component: password-input - Password field with show/hide button. Needs @birdycom/omniaui CSS.
2
- Class API (modifiers are extra classes / attributes on the same element):
3
- .oc-input-reveal: Wrapper (relative)
4
- .oc-input: The password input
5
- .oc-input-reveal-button: Toggle button (aria-pressed reflects the state)
6
- -->
7
- <div class="oc-field">
8
- <label class="oc-field-label" for="oc-password-demo">Password</label>
9
- <div class="oc-input-reveal">
10
- <input class="oc-input" id="oc-password-demo" type="password" autocomplete="current-password" value="secret-value">
11
- <button class="oc-input-reveal-button" type="button" aria-pressed="false" aria-label="Toggle password visibility">Show</button>
12
- </div>
13
- </div>
14
- <script>
15
- document.addEventListener('click', (e) => {
16
- const btn = e.target.closest('.oc-input-reveal-button');
17
- if (!btn) return;
18
- const input = btn.parentElement.querySelector('input');
19
- const show = input.type === 'password';
20
- input.type = show ? 'text' : 'password';
21
- btn.setAttribute('aria-pressed', String(show));
22
- btn.textContent = show ? 'Hide' : 'Show';
23
- });
24
- </script>
1
+ <!-- OmniaUI component: password-input - Password field with show/hide button. Needs @birdycom/omniaui CSS.
2
+ Class API (modifiers are extra classes / attributes on the same element):
3
+ .oc-input-reveal: Wrapper (relative)
4
+ .oc-input: The password input
5
+ .oc-input-reveal-button: Toggle button (aria-pressed reflects the state)
6
+ -->
7
+ <div class="oc-field">
8
+ <label class="oc-field-label" for="oc-password-demo">Password</label>
9
+ <div class="oc-input-reveal">
10
+ <input class="oc-input" id="oc-password-demo" type="password" autocomplete="current-password" value="secret-value">
11
+ <button class="oc-input-reveal-button" type="button" aria-pressed="false" aria-label="Toggle password visibility">Show</button>
12
+ </div>
13
+ </div>
14
+ <script>
15
+ document.addEventListener('click', (e) => {
16
+ const btn = e.target.closest('.oc-input-reveal-button');
17
+ if (!btn) return;
18
+ const input = btn.parentElement.querySelector('input');
19
+ const show = input.type === 'password';
20
+ input.type = show ? 'text' : 'password';
21
+ btn.setAttribute('aria-pressed', String(show));
22
+ btn.textContent = show ? 'Hide' : 'Show';
23
+ });
24
+ </script>
@@ -1,30 +1,30 @@
1
- <!-- OmniaUI component: password-requirements - Live checklist of password rules under a password field. Needs @birdycom/omniaui CSS.
2
- File: packages/ui/snippets/password-requirements.html | Map: field (label + password input) -> rule list -> optional script
3
- Class API (modifiers are extra classes / attributes on the same element):
4
- .oc-password-requirements: The list (aria-live="polite"). Modifier: --inline (rules side by side).
5
- .oc-password-requirement: One rule. Modifier: --met (green with a check mark).
6
- Optional script attributes: data-oc-password-for="<input id>" on the list; per rule data-min="8" or data-pattern="[A-Z]".
7
- Without JavaScript the list is a static hint; the script (or a React/Vue wrapper) toggles --met while typing.
8
- -->
9
- <div class="oc-field">
10
- <label class="oc-field-label" for="oc-password-rules-demo">New password</label>
11
- <input class="oc-input" id="oc-password-rules-demo" type="password" autocomplete="new-password" aria-describedby="oc-password-rules-demo-list" value="Secret1">
12
- <ul class="oc-password-requirements" id="oc-password-rules-demo-list" aria-live="polite" data-oc-password-for="oc-password-rules-demo">
13
- <li class="oc-password-requirement" data-min="8">At least 8 characters</li>
14
- <li class="oc-password-requirement oc-password-requirement--met" data-pattern="[A-Z]">One uppercase letter</li>
15
- <li class="oc-password-requirement oc-password-requirement--met" data-pattern="[0-9]">One number</li>
16
- <li class="oc-password-requirement" data-pattern="[^A-Za-z0-9]">One symbol</li>
17
- </ul>
18
- </div>
19
- <script>
20
- // Re-check every rule of a linked list when its password field changes.
21
- document.addEventListener('input', (e) => {
22
- const list = e.target.id && document.querySelector(`[data-oc-password-for="${e.target.id}"]`);
23
- if (!list) return;
24
- for (const rule of list.querySelectorAll('.oc-password-requirement')) {
25
- const value = e.target.value;
26
- const met = rule.dataset.min ? value.length >= Number(rule.dataset.min) : new RegExp(rule.dataset.pattern).test(value);
27
- rule.classList.toggle('oc-password-requirement--met', met);
28
- }
29
- });
30
- </script>
1
+ <!-- OmniaUI component: password-requirements - Live checklist of password rules under a password field. Needs @birdycom/omniaui CSS.
2
+ File: packages/ui/snippets/password-requirements.html | Map: field (label + password input) -> rule list -> optional script
3
+ Class API (modifiers are extra classes / attributes on the same element):
4
+ .oc-password-requirements: The list (aria-live="polite"). Modifier: --inline (rules side by side).
5
+ .oc-password-requirement: One rule. Modifier: --met (green with a check mark).
6
+ Optional script attributes: data-oc-password-for="<input id>" on the list; per rule data-min="8" or data-pattern="[A-Z]".
7
+ Without JavaScript the list is a static hint; the script (or a React/Vue wrapper) toggles --met while typing.
8
+ -->
9
+ <div class="oc-field">
10
+ <label class="oc-field-label" for="oc-password-rules-demo">New password</label>
11
+ <input class="oc-input" id="oc-password-rules-demo" type="password" autocomplete="new-password" aria-describedby="oc-password-rules-demo-list" value="Secret1">
12
+ <ul class="oc-password-requirements" id="oc-password-rules-demo-list" aria-live="polite" data-oc-password-for="oc-password-rules-demo">
13
+ <li class="oc-password-requirement" data-min="8">At least 8 characters</li>
14
+ <li class="oc-password-requirement oc-password-requirement--met" data-pattern="[A-Z]">One uppercase letter</li>
15
+ <li class="oc-password-requirement oc-password-requirement--met" data-pattern="[0-9]">One number</li>
16
+ <li class="oc-password-requirement" data-pattern="[^A-Za-z0-9]">One symbol</li>
17
+ </ul>
18
+ </div>
19
+ <script>
20
+ // Re-check every rule of a linked list when its password field changes.
21
+ document.addEventListener('input', (e) => {
22
+ const list = e.target.id && document.querySelector(`[data-oc-password-for="${e.target.id}"]`);
23
+ if (!list) return;
24
+ for (const rule of list.querySelectorAll('.oc-password-requirement')) {
25
+ const value = e.target.value;
26
+ const met = rule.dataset.min ? value.length >= Number(rule.dataset.min) : new RegExp(rule.dataset.pattern).test(value);
27
+ rule.classList.toggle('oc-password-requirement--met', met);
28
+ }
29
+ });
30
+ </script>
@@ -1,22 +1,22 @@
1
- <!-- OmniaUI component: phone-input - Phone field with a country dial code select and the national number. Needs @birdycom/omniaui CSS.
2
- File: packages/ui/snippets/phone-input.html | Map: field wrapper -> label -> phone frame (dial select + tel input) -> hint
3
- Class API (modifiers are extra classes / attributes on the same element):
4
- .oc-phone-input: Frame around both parts. Modifiers: --sm, --error.
5
- .oc-phone-input-dial: Native select with the dial codes (+32, +31...)
6
- .oc-phone-input-number: The national number (type="tel", autocomplete="tel-national")
7
- States: :focus-within (ring), aria-invalid="true" or :user-invalid on the number (red), disabled number (dimmed)
8
- Slots: one <option> per country; the value of the form is dial code + number (join them on the server)
9
- -->
10
- <div class="oc-field">
11
- <label class="oc-field-label" for="oc-phone-demo">Mobile number</label>
12
- <div class="oc-phone-input">
13
- <select class="oc-phone-input-dial" name="phone_dial" aria-label="Country code">
14
- <option value="+32" selected>BE +32</option>
15
- <option value="+31">NL +31</option>
16
- <option value="+33">FR +33</option>
17
- <option value="+49">DE +49</option>
18
- </select>
19
- <input class="oc-phone-input-number" id="oc-phone-demo" name="phone" type="tel" inputmode="tel" autocomplete="tel-national" placeholder="470 12 34 56" pattern="[0-9 ]{8,14}">
20
- </div>
21
- <p class="oc-field-description">Digits only; spaces are fine.</p>
22
- </div>
1
+ <!-- OmniaUI component: phone-input - Phone field with a country dial code select and the national number. Needs @birdycom/omniaui CSS.
2
+ File: packages/ui/snippets/phone-input.html | Map: field wrapper -> label -> phone frame (dial select + tel input) -> hint
3
+ Class API (modifiers are extra classes / attributes on the same element):
4
+ .oc-phone-input: Frame around both parts. Modifiers: --sm, --error.
5
+ .oc-phone-input-dial: Native select with the dial codes (+32, +31...)
6
+ .oc-phone-input-number: The national number (type="tel", autocomplete="tel-national")
7
+ States: :focus-within (ring), aria-invalid="true" or :user-invalid on the number (red), disabled number (dimmed)
8
+ Slots: one <option> per country; the value of the form is dial code + number (join them on the server)
9
+ -->
10
+ <div class="oc-field">
11
+ <label class="oc-field-label" for="oc-phone-demo">Mobile number</label>
12
+ <div class="oc-phone-input">
13
+ <select class="oc-phone-input-dial" name="phone_dial" aria-label="Country code">
14
+ <option value="+32" selected>BE +32</option>
15
+ <option value="+31">NL +31</option>
16
+ <option value="+33">FR +33</option>
17
+ <option value="+49">DE +49</option>
18
+ </select>
19
+ <input class="oc-phone-input-number" id="oc-phone-demo" name="phone" type="tel" inputmode="tel" autocomplete="tel-national" placeholder="470 12 34 56" pattern="[0-9 ]{8,14}">
20
+ </div>
21
+ <p class="oc-field-description">Digits only; spaces are fine.</p>
22
+ </div>
@@ -1,15 +1,15 @@
1
- <!-- OmniaUI component: popover - Floating panel on popover + anchor positioning - no JavaScript. Needs @birdycom/omniaui CSS.
2
- Class API (modifiers are extra classes / attributes on the same element):
3
- .oc-popover[popover]: The panel. Sizes: --sm, --lg.
4
- .oc-popover-title / -text: Optional heading and body text
5
- button[popovertarget]: Trigger
6
- -->
7
- <button class="oc-btn oc-btn--outline" type="button" popovertarget="oc-popover-demo">Dimensions</button>
8
- <div class="oc-popover" id="oc-popover-demo" popover>
9
- <h3 class="oc-popover-title">Dimensions</h3>
10
- <p class="oc-popover-text">Set the width and height of the layer.</p>
11
- <div class="oc-field" style="margin-top:.75rem">
12
- <label class="oc-field-label" for="oc-popover-width">Width</label>
13
- <input class="oc-input" id="oc-popover-width" value="100%">
14
- </div>
15
- </div>
1
+ <!-- OmniaUI component: popover - Floating panel on popover + anchor positioning - no JavaScript. Needs @birdycom/omniaui CSS.
2
+ Class API (modifiers are extra classes / attributes on the same element):
3
+ .oc-popover[popover]: The panel. Sizes: --sm, --lg.
4
+ .oc-popover-title / -text: Optional heading and body text
5
+ button[popovertarget]: Trigger
6
+ -->
7
+ <button class="oc-btn oc-btn--outline" type="button" popovertarget="oc-popover-demo">Dimensions</button>
8
+ <div class="oc-popover" id="oc-popover-demo" popover>
9
+ <h3 class="oc-popover-title">Dimensions</h3>
10
+ <p class="oc-popover-text">Set the width and height of the layer.</p>
11
+ <div class="oc-field" style="margin-top:.75rem">
12
+ <label class="oc-field-label" for="oc-popover-width">Width</label>
13
+ <input class="oc-input" id="oc-popover-width" value="100%">
14
+ </div>
15
+ </div>
@@ -1,34 +1,34 @@
1
- <!-- OmniaUI component: price-card - Plan card with a monthly / yearly toggle (radio + :has), discount badge and included / excluded features. Needs @birdycom/omniaui CSS.
2
- File: packages/ui/snippets/price-card.html | Map: article.oc-price-card -> head (name + discount) -> toggle -> prices -> features -> cta
3
- Class API (modifiers are extra classes / attributes on the same element):
4
- .oc-price-card: The card. Modifier: --featured (accent border + glow; use with .oc-accent--*)
5
- .oc-price-card__head / __name / __desc: Title row, plan name, short description
6
- .oc-price-card__discount: Badge ("Save 20%"), dimmed while monthly is selected
7
- .oc-price-card__toggle: Put on an .oc-segmented with radios value="monthly" and value="yearly" (unique name per card)
8
- .oc-price-card__price--monthly / --yearly: Price rows; the checked radio decides which one shows
9
- .oc-price-card__amount / __period / __was / __note: Big number, "/month", old price (<s>), small note
10
- .oc-price-card__features: List. .oc-price-card__feature (✓), modifier --excluded (✕ + muted)
11
- .oc-price-card__cta: Full-width button
12
- Slots: name, discount, description, prices, features, cta
13
- -->
14
- <article class="oc-price-card">
15
- <div class="oc-price-card__head">
16
- <h3 class="oc-price-card__name">Pro</h3>
17
- <span class="oc-price-card__discount">Save 20%</span>
18
- </div>
19
- <p class="oc-price-card__desc">For small teams that send invoices every week.</p>
20
- <div class="oc-segmented oc-price-card__toggle" role="radiogroup" aria-label="Billing period">
21
- <label class="oc-segmented-item"><input type="radio" name="oc-price-pro" value="monthly" checked> Monthly</label>
22
- <label class="oc-segmented-item"><input type="radio" name="oc-price-pro" value="yearly"> Yearly</label>
23
- </div>
24
- <p class="oc-price-card__price oc-price-card__price--monthly"><span class="oc-price-card__amount">&euro;12</span><span class="oc-price-card__period">/month</span></p>
25
- <p class="oc-price-card__price oc-price-card__price--yearly"><span class="oc-price-card__amount">&euro;115</span><span class="oc-price-card__period">/year</span><s class="oc-price-card__was">&euro;144</s><span class="oc-price-card__note">Billed once a year</span></p>
26
- <ul class="oc-price-card__features">
27
- <li class="oc-price-card__feature">Unlimited invoices</li>
28
- <li class="oc-price-card__feature">5 team members</li>
29
- <li class="oc-price-card__feature">Bank import</li>
30
- <li class="oc-price-card__feature oc-price-card__feature--excluded">Custom domain</li>
31
- <li class="oc-price-card__feature oc-price-card__feature--excluded">Priority support</li>
32
- </ul>
33
- <a class="oc-btn oc-price-card__cta" href="#signup">Choose Pro</a>
34
- </article>
1
+ <!-- OmniaUI component: price-card - Plan card with a monthly / yearly toggle (radio + :has), discount badge and included / excluded features. Needs @birdycom/omniaui CSS.
2
+ File: packages/ui/snippets/price-card.html | Map: article.oc-price-card -> head (name + discount) -> toggle -> prices -> features -> cta
3
+ Class API (modifiers are extra classes / attributes on the same element):
4
+ .oc-price-card: The card. Modifier: --featured (accent border + glow; use with .oc-accent--*)
5
+ .oc-price-card__head / __name / __desc: Title row, plan name, short description
6
+ .oc-price-card__discount: Badge ("Save 20%"), dimmed while monthly is selected
7
+ .oc-price-card__toggle: Put on an .oc-segmented with radios value="monthly" and value="yearly" (unique name per card)
8
+ .oc-price-card__price--monthly / --yearly: Price rows; the checked radio decides which one shows
9
+ .oc-price-card__amount / __period / __was / __note: Big number, "/month", old price (<s>), small note
10
+ .oc-price-card__features: List. .oc-price-card__feature (✓), modifier --excluded (✕ + muted)
11
+ .oc-price-card__cta: Full-width button
12
+ Slots: name, discount, description, prices, features, cta
13
+ -->
14
+ <article class="oc-price-card">
15
+ <div class="oc-price-card__head">
16
+ <h3 class="oc-price-card__name">Pro</h3>
17
+ <span class="oc-price-card__discount">Save 20%</span>
18
+ </div>
19
+ <p class="oc-price-card__desc">For small teams that send invoices every week.</p>
20
+ <div class="oc-segmented oc-price-card__toggle" role="radiogroup" aria-label="Billing period">
21
+ <label class="oc-segmented-item"><input type="radio" name="oc-price-pro" value="monthly" checked> Monthly</label>
22
+ <label class="oc-segmented-item"><input type="radio" name="oc-price-pro" value="yearly"> Yearly</label>
23
+ </div>
24
+ <p class="oc-price-card__price oc-price-card__price--monthly"><span class="oc-price-card__amount">&euro;12</span><span class="oc-price-card__period">/month</span></p>
25
+ <p class="oc-price-card__price oc-price-card__price--yearly"><span class="oc-price-card__amount">&euro;115</span><span class="oc-price-card__period">/year</span><s class="oc-price-card__was">&euro;144</s><span class="oc-price-card__note">Billed once a year</span></p>
26
+ <ul class="oc-price-card__features">
27
+ <li class="oc-price-card__feature">Unlimited invoices</li>
28
+ <li class="oc-price-card__feature">5 team members</li>
29
+ <li class="oc-price-card__feature">Bank import</li>
30
+ <li class="oc-price-card__feature oc-price-card__feature--excluded">Custom domain</li>
31
+ <li class="oc-price-card__feature oc-price-card__feature--excluded">Priority support</li>
32
+ </ul>
33
+ <a class="oc-btn oc-price-card__cta" href="#signup">Choose Pro</a>
34
+ </article>
@@ -1,13 +1,13 @@
1
- <!-- OmniaUI component: product-mark - Squircle app icon tile in the accent gradient (sm / lg / xl). Needs @birdycom/omniaui CSS.
2
- File: packages/ui/snippets/product-mark.html | Map: span.oc-product-mark (glyph, img or svg) per size
3
- Class API (modifiers are extra classes / attributes on the same element):
4
- .oc-product-mark: The tile. Uses corner-shape: squircle where supported, a rounded square otherwise.
5
- Sizes: --sm, (default), --lg, --xl. Styles: --soft (tinted), --glow, --cover (full-bleed img)
6
- .oc-accent--*: Accent preset (green, violet, orange, cyan, red, yellow, blue)
7
- --oc-mark-size: Custom size
8
- Slots: content (glyph, emoji, <img alt=""> or inline SVG)
9
- -->
10
- <span class="oc-product-mark oc-product-mark--sm oc-accent--green" aria-hidden="true">&#9670;</span>
11
- <span class="oc-product-mark oc-accent--violet" aria-hidden="true">&#9673;</span>
12
- <span class="oc-product-mark oc-product-mark--lg oc-accent--orange" aria-hidden="true">&#9650;</span>
13
- <span class="oc-product-mark oc-product-mark--xl oc-accent--cyan" aria-hidden="true">&#9733;</span>
1
+ <!-- OmniaUI component: product-mark - Squircle app icon tile in the accent gradient (sm / lg / xl). Needs @birdycom/omniaui CSS.
2
+ File: packages/ui/snippets/product-mark.html | Map: span.oc-product-mark (glyph, img or svg) per size
3
+ Class API (modifiers are extra classes / attributes on the same element):
4
+ .oc-product-mark: The tile. Uses corner-shape: squircle where supported, a rounded square otherwise.
5
+ Sizes: --sm, (default), --lg, --xl. Styles: --soft (tinted), --glow, --cover (full-bleed img)
6
+ .oc-accent--*: Accent preset (green, violet, orange, cyan, red, yellow, blue)
7
+ --oc-mark-size: Custom size
8
+ Slots: content (glyph, emoji, <img alt=""> or inline SVG)
9
+ -->
10
+ <span class="oc-product-mark oc-product-mark--sm oc-accent--green" aria-hidden="true">&#9670;</span>
11
+ <span class="oc-product-mark oc-accent--violet" aria-hidden="true">&#9673;</span>
12
+ <span class="oc-product-mark oc-product-mark--lg oc-accent--orange" aria-hidden="true">&#9650;</span>
13
+ <span class="oc-product-mark oc-product-mark--xl oc-accent--cyan" aria-hidden="true">&#9733;</span>
@@ -1,4 +1,4 @@
1
- <!-- OmniaUI component: progress — Progress bar. Needs @birdycom/omniaui CSS. -->
2
- <div class="oc-progress" role="progressbar" aria-valuenow="60" aria-valuemin="0" aria-valuemax="100">
3
- <div class="oc-progress-bar" style="width: 60%"></div>
4
- </div>
1
+ <!-- OmniaUI component: progress — Progress bar. Needs @birdycom/omniaui CSS. -->
2
+ <div class="oc-progress" role="progressbar" aria-valuenow="60" aria-valuemin="0" aria-valuemax="100">
3
+ <div class="oc-progress-bar" style="width: 60%"></div>
4
+ </div>
@@ -1,23 +1,23 @@
1
- <!-- OmniaUI component: project-card - Portfolio card with a browser-like preview, type badge, name, meta and an arrow link. Needs @birdycom/omniaui CSS.
2
- File: packages/ui/snippets/project-card.html | Map: a.oc-project-card -> __frame (__bar + __shot) -> __body (type, name, meta, more)
3
- Class API (modifiers are extra classes / attributes on the same element):
4
- .oc-project-card: The card (usually an <a>, the whole card is clickable). Modifier: --flat (edge-to-edge preview)
5
- .oc-project-card__frame: Preview window. .oc-project-card__bar: title bar with three <i> dots
6
- .oc-project-card__shot: Screenshot <img>, or an empty <span> for a gradient placeholder
7
- .oc-project-card__body: Text column
8
- .oc-project-card__type / __name / __meta / __more: Badge, title, sector line, "View" link with arrow
9
- .oc-accent--*: Accent preset for the badge, dot, border and placeholder
10
- Slots: shot (image), type, name, meta, more
11
- -->
12
- <a class="oc-project-card oc-accent--green" href="#project">
13
- <span class="oc-project-card__frame">
14
- <span class="oc-project-card__bar" aria-hidden="true"><i></i><i></i><i></i></span>
15
- <span class="oc-project-card__shot" role="img" aria-label="Northwind Bakery website, screenshot"></span>
16
- </span>
17
- <span class="oc-project-card__body">
18
- <span class="oc-project-card__type">Website</span>
19
- <span class="oc-project-card__name">Northwind Bakery</span>
20
- <span class="oc-project-card__meta">Food &amp; retail &middot; Antwerp</span>
21
- <span class="oc-project-card__more">View project</span>
22
- </span>
23
- </a>
1
+ <!-- OmniaUI component: project-card - Portfolio card with a browser-like preview, type badge, name, meta and an arrow link. Needs @birdycom/omniaui CSS.
2
+ File: packages/ui/snippets/project-card.html | Map: a.oc-project-card -> __frame (__bar + __shot) -> __body (type, name, meta, more)
3
+ Class API (modifiers are extra classes / attributes on the same element):
4
+ .oc-project-card: The card (usually an <a>, the whole card is clickable). Modifier: --flat (edge-to-edge preview)
5
+ .oc-project-card__frame: Preview window. .oc-project-card__bar: title bar with three <i> dots
6
+ .oc-project-card__shot: Screenshot <img>, or an empty <span> for a gradient placeholder
7
+ .oc-project-card__body: Text column
8
+ .oc-project-card__type / __name / __meta / __more: Badge, title, sector line, "View" link with arrow
9
+ .oc-accent--*: Accent preset for the badge, dot, border and placeholder
10
+ Slots: shot (image), type, name, meta, more
11
+ -->
12
+ <a class="oc-project-card oc-accent--green" href="#project">
13
+ <span class="oc-project-card__frame">
14
+ <span class="oc-project-card__bar" aria-hidden="true"><i></i><i></i><i></i></span>
15
+ <span class="oc-project-card__shot" role="img" aria-label="Northwind Bakery website, screenshot"></span>
16
+ </span>
17
+ <span class="oc-project-card__body">
18
+ <span class="oc-project-card__type">Website</span>
19
+ <span class="oc-project-card__name">Northwind Bakery</span>
20
+ <span class="oc-project-card__meta">Food &amp; retail &middot; Antwerp</span>
21
+ <span class="oc-project-card__more">View project</span>
22
+ </span>
23
+ </a>