@birdycom/omniaui 0.11.0 → 0.11.1

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 +6559 -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 +404 -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,18 +1,18 @@
1
- <!-- OmniaUI component: barcode-input - Code field with a barcode icon in the left column. Needs @birdycom/omniaui CSS.
2
- File: packages/ui/snippets/barcode-input.html | Map: labeled field (icon column + value) -> optional preview
3
- Class API (modifiers are extra classes / attributes on the same element):
4
- .oc-barcode-input: Wrapper when you also show a preview under the field
5
- .oc-input-group--affix + .oc-input-addon: The icon column (same chrome as the euro and percent fields)
6
- .oc-barcode-input-field: Add to .oc-input
7
- .oc-barcode-preview: Optional preview under the field. Modifier: --empty
8
- States: aria-invalid="true" on the field turns the frame and the preview red
9
- Slots: replace .oc-barcode-preview-bars with your own svg, canvas or img
10
- -->
11
- <div class="oc-field">
12
- <label class="oc-field-label" for="oc-barcode-demo">Our barcode</label>
13
- <div class="oc-input-group oc-input-group--affix">
14
- <span class="oc-input-addon" aria-hidden="true"><svg viewBox="0 0 16 16"><path fill="currentColor" d="M1 1h1.4v14H1zm2.2 0h.7v14h-.7zm1.6 0h1.5v14H4.8zm2.4 0h.7v14H7.2zm1.6 0h.7v14H8.8zm1.5 0h1.4v14h-1.4zm2.2 0H15v14h-.9z"/></svg></span>
15
- <input class="oc-input oc-barcode-input-field" id="oc-barcode-demo" name="ean" type="text" maxlength="80" placeholder="EAN-13 or internal code" autocomplete="off" spellcheck="false">
16
- </div>
17
- <p class="oc-field-description">13 digits is an EAN-13. Anything else is an internal code.</p>
18
- </div>
1
+ <!-- OmniaUI component: barcode-input - Code field with a barcode icon in the left column. Needs @birdycom/omniaui CSS.
2
+ File: packages/ui/snippets/barcode-input.html | Map: labeled field (icon column + value) -> optional preview
3
+ Class API (modifiers are extra classes / attributes on the same element):
4
+ .oc-barcode-input: Wrapper when you also show a preview under the field
5
+ .oc-input-group--affix + .oc-input-addon: The icon column (same chrome as the euro and percent fields)
6
+ .oc-barcode-input-field: Add to .oc-input
7
+ .oc-barcode-preview: Optional preview under the field. Modifier: --empty
8
+ States: aria-invalid="true" on the field turns the frame and the preview red
9
+ Slots: replace .oc-barcode-preview-bars with your own svg, canvas or img
10
+ -->
11
+ <div class="oc-field">
12
+ <label class="oc-field-label" for="oc-barcode-demo">Our barcode</label>
13
+ <div class="oc-input-group oc-input-group--affix">
14
+ <span class="oc-input-addon" aria-hidden="true"><svg viewBox="0 0 16 16"><path fill="currentColor" d="M1 1h1.4v14H1zm2.2 0h.7v14h-.7zm1.6 0h1.5v14H4.8zm2.4 0h.7v14H7.2zm1.6 0h.7v14H8.8zm1.5 0h1.4v14h-1.4zm2.2 0H15v14h-.9z"/></svg></span>
15
+ <input class="oc-input oc-barcode-input-field" id="oc-barcode-demo" name="ean" type="text" maxlength="80" placeholder="EAN-13 or internal code" autocomplete="off" spellcheck="false">
16
+ </div>
17
+ <p class="oc-field-description">13 digits is an EAN-13. Anything else is an internal code.</p>
18
+ </div>
@@ -1,6 +1,6 @@
1
- <!-- OmniaUI component: breadcrumb — Breadcrumb. Needs @birdycom/omniaui CSS. -->
2
- <nav class="oc-breadcrumb" aria-label="Breadcrumb">
3
- <a class="oc-breadcrumb-item" href="/">Home</a>
4
- <a class="oc-breadcrumb-item" href="/docs/">Docs</a>
5
- <span class="oc-breadcrumb-item" aria-current="page">Components</span>
6
- </nav>
1
+ <!-- OmniaUI component: breadcrumb — Breadcrumb. Needs @birdycom/omniaui CSS. -->
2
+ <nav class="oc-breadcrumb" aria-label="Breadcrumb">
3
+ <a class="oc-breadcrumb-item" href="/">Home</a>
4
+ <a class="oc-breadcrumb-item" href="/docs/">Docs</a>
5
+ <span class="oc-breadcrumb-item" aria-current="page">Components</span>
6
+ </nav>
@@ -1,18 +1,18 @@
1
- <!-- OmniaUI component: browser-frame — Fake browser chrome around a screenshot or live content. Needs @birdycom/omniaui CSS.
2
- File: packages/ui/snippets/browser-frame.html | Map: figure -> bar (dots, address, actions) -> view (screenshot slot) -> caption
3
- Class API: figure.oc-browser-frame > .oc-browser-frame__bar (3 × <i>, .oc-browser-frame__address, .oc-browser-frame__actions) ·
4
- .oc-browser-frame__view > img / video / iframe / any content · figcaption.oc-browser-frame__caption (optional).
5
- Modifiers: --minimal (dots only), --dark (dark chrome), --tilt (3D angle, straightens on hover), --auto (free height).
6
- Ratio: --oc-browser-frame-ratio (default 16 / 10). No JavaScript.
7
- -->
8
- <figure class="oc-browser-frame" style="max-inline-size:36rem">
9
- <div class="oc-browser-frame__bar">
10
- <i></i><i></i><i></i>
11
- <span class="oc-browser-frame__address">shop.example.com/collections/spring</span>
12
- <span class="oc-browser-frame__actions" aria-hidden="true">&#8635; &#8942;</span>
13
- </div>
14
- <div class="oc-browser-frame__view">
15
- <div class="oc-media-art oc-media-art--5" role="img" aria-label="Screenshot of the spring collection page"></div>
16
- </div>
17
- <figcaption class="oc-browser-frame__caption">Spring collection, 2026 redesign</figcaption>
18
- </figure>
1
+ <!-- OmniaUI component: browser-frame — Fake browser chrome around a screenshot or live content. Needs @birdycom/omniaui CSS.
2
+ File: packages/ui/snippets/browser-frame.html | Map: figure -> bar (dots, address, actions) -> view (screenshot slot) -> caption
3
+ Class API: figure.oc-browser-frame > .oc-browser-frame__bar (3 × <i>, .oc-browser-frame__address, .oc-browser-frame__actions) ·
4
+ .oc-browser-frame__view > img / video / iframe / any content · figcaption.oc-browser-frame__caption (optional).
5
+ Modifiers: --minimal (dots only), --dark (dark chrome), --tilt (3D angle, straightens on hover), --auto (free height).
6
+ Ratio: --oc-browser-frame-ratio (default 16 / 10). No JavaScript.
7
+ -->
8
+ <figure class="oc-browser-frame" style="max-inline-size:36rem">
9
+ <div class="oc-browser-frame__bar">
10
+ <i></i><i></i><i></i>
11
+ <span class="oc-browser-frame__address">shop.example.com/collections/spring</span>
12
+ <span class="oc-browser-frame__actions" aria-hidden="true">&#8635; &#8942;</span>
13
+ </div>
14
+ <div class="oc-browser-frame__view">
15
+ <div class="oc-media-art oc-media-art--5" role="img" aria-label="Screenshot of the spring collection page"></div>
16
+ </div>
17
+ <figcaption class="oc-browser-frame__caption">Spring collection, 2026 redesign</figcaption>
18
+ </figure>
@@ -1,31 +1,31 @@
1
- <!-- OmniaUI component: busy-overlay — Modal "please wait" overlay while a long form submit or upload runs. Needs @birdycom/omniaui CSS.
2
- File: packages/ui/snippets/busy-overlay.html | Map: form[data-oc-busy] -> dialog (spinner or progress, title, text) -> script
3
- Class API (modifiers are extra classes / attributes on the same element):
4
- dialog.oc-busy-overlay[closedby="none"]: The overlay; modal, so the page is inert and Esc does not close it
5
- .oc-spinner (or .oc-progress > .oc-progress-bar for a known percentage): Activity
6
- .oc-busy-overlay__title / __text: What is happening and how long it may take
7
- form[data-oc-busy="<dialog id>"]: Opens the overlay when the form is submitted (after the browser's own validation)
8
- The overlay appears after 300ms, so quick requests never flash. The page that loads next replaces it;
9
- after a fetch() call close it yourself with dialog.close().
10
- -->
11
- <form class="oc-form-group" data-oc-busy="oc-busy-overlay-demo" action="/photos" method="post" enctype="multipart/form-data">
12
- <label class="oc-dropzone">
13
- <input type="file" name="photos[]" accept="image/*" multiple>
14
- <span><strong>Choose photos</strong> to upload</span>
15
- <span class="oc-dropzone-hint">They are resized to 600px and 1080px after saving</span>
16
- </label>
17
- <button class="oc-btn" type="submit">Save</button>
18
- </form>
19
-
20
- <dialog class="oc-busy-overlay" id="oc-busy-overlay-demo" closedby="none" aria-labelledby="oc-busy-overlay-demo-title" aria-describedby="oc-busy-overlay-demo-text">
21
- <span class="oc-spinner" role="status" aria-label="Busy"></span>
22
- <h2 class="oc-busy-overlay__title" id="oc-busy-overlay-demo-title">Saving…</h2>
23
- <p class="oc-busy-overlay__text" id="oc-busy-overlay-demo-text">The photos are being processed. This can take a minute; please keep this page open.</p>
24
- </dialog>
25
- <script>
26
- // Open the busy overlay of a form when it is submitted (the submit event only fires when the form is valid).
27
- document.addEventListener("submit", (e) => {
28
- const id = e.target.dataset?.ocBusy;
29
- if (id) document.getElementById(id)?.showModal();
30
- });
31
- </script>
1
+ <!-- OmniaUI component: busy-overlay — Modal "please wait" overlay while a long form submit or upload runs. Needs @birdycom/omniaui CSS.
2
+ File: packages/ui/snippets/busy-overlay.html | Map: form[data-oc-busy] -> dialog (spinner or progress, title, text) -> script
3
+ Class API (modifiers are extra classes / attributes on the same element):
4
+ dialog.oc-busy-overlay[closedby="none"]: The overlay; modal, so the page is inert and Esc does not close it
5
+ .oc-spinner (or .oc-progress > .oc-progress-bar for a known percentage): Activity
6
+ .oc-busy-overlay__title / __text: What is happening and how long it may take
7
+ form[data-oc-busy="<dialog id>"]: Opens the overlay when the form is submitted (after the browser's own validation)
8
+ The overlay appears after 300ms, so quick requests never flash. The page that loads next replaces it;
9
+ after a fetch() call close it yourself with dialog.close().
10
+ -->
11
+ <form class="oc-form-group" data-oc-busy="oc-busy-overlay-demo" action="/photos" method="post" enctype="multipart/form-data">
12
+ <label class="oc-dropzone">
13
+ <input type="file" name="photos[]" accept="image/*" multiple>
14
+ <span><strong>Choose photos</strong> to upload</span>
15
+ <span class="oc-dropzone-hint">They are resized to 600px and 1080px after saving</span>
16
+ </label>
17
+ <button class="oc-btn" type="submit">Save</button>
18
+ </form>
19
+
20
+ <dialog class="oc-busy-overlay" id="oc-busy-overlay-demo" closedby="none" aria-labelledby="oc-busy-overlay-demo-title" aria-describedby="oc-busy-overlay-demo-text">
21
+ <span class="oc-spinner" role="status" aria-label="Busy"></span>
22
+ <h2 class="oc-busy-overlay__title" id="oc-busy-overlay-demo-title">Saving…</h2>
23
+ <p class="oc-busy-overlay__text" id="oc-busy-overlay-demo-text">The photos are being processed. This can take a minute; please keep this page open.</p>
24
+ </dialog>
25
+ <script>
26
+ // Open the busy overlay of a form when it is submitted (the submit event only fires when the form is valid).
27
+ document.addEventListener("submit", (e) => {
28
+ const id = e.target.dataset?.ocBusy;
29
+ if (id) document.getElementById(id)?.showModal();
30
+ });
31
+ </script>
@@ -1,21 +1,21 @@
1
- <!-- OmniaUI component: button-group - Joined buttons with shared borders: horizontal, vertical, text addon. Needs @birdycom/omniaui CSS.
2
- Class API (modifiers are extra classes / attributes on the same element):
3
- .oc-btn-group: inline-flex wrapper (role="group" + aria-label). Modifier: --vertical.
4
- .oc-btn: any button variant inside the group
5
- .oc-btn-group-text: static text cell (a count, a unit) next to a button
6
- -->
7
- <div class="oc-btn-group" role="group" aria-label="Text alignment">
8
- <button class="oc-btn oc-btn--outline" type="button">Left</button>
9
- <button class="oc-btn oc-btn--outline" type="button">Center</button>
10
- <button class="oc-btn oc-btn--outline" type="button">Right</button>
11
- </div>
12
-
13
- <div class="oc-btn-group oc-btn-group--vertical" role="group" aria-label="Zoom">
14
- <button class="oc-btn oc-btn--outline" type="button">Zoom in</button>
15
- <button class="oc-btn oc-btn--outline" type="button">Zoom out</button>
16
- </div>
17
- <div class="oc-btn-group" role="group" aria-label="Quantity">
18
- <button class="oc-btn oc-btn--outline" type="button" aria-label="Decrease">&minus;</button>
19
- <span class="oc-btn-group-text">3 items</span>
20
- <button class="oc-btn oc-btn--outline" type="button" aria-label="Increase">+</button>
21
- </div>
1
+ <!-- OmniaUI component: button-group - Joined buttons with shared borders: horizontal, vertical, text addon. Needs @birdycom/omniaui CSS.
2
+ Class API (modifiers are extra classes / attributes on the same element):
3
+ .oc-btn-group: inline-flex wrapper (role="group" + aria-label). Modifier: --vertical.
4
+ .oc-btn: any button variant inside the group
5
+ .oc-btn-group-text: static text cell (a count, a unit) next to a button
6
+ -->
7
+ <div class="oc-btn-group" role="group" aria-label="Text alignment">
8
+ <button class="oc-btn oc-btn--outline" type="button">Left</button>
9
+ <button class="oc-btn oc-btn--outline" type="button">Center</button>
10
+ <button class="oc-btn oc-btn--outline" type="button">Right</button>
11
+ </div>
12
+
13
+ <div class="oc-btn-group oc-btn-group--vertical" role="group" aria-label="Zoom">
14
+ <button class="oc-btn oc-btn--outline" type="button">Zoom in</button>
15
+ <button class="oc-btn oc-btn--outline" type="button">Zoom out</button>
16
+ </div>
17
+ <div class="oc-btn-group" role="group" aria-label="Quantity">
18
+ <button class="oc-btn oc-btn--outline" type="button" aria-label="Decrease">&minus;</button>
19
+ <span class="oc-btn-group-text">3 items</span>
20
+ <button class="oc-btn oc-btn--outline" type="button" aria-label="Increase">+</button>
21
+ </div>
@@ -1,8 +1,8 @@
1
- <!-- OmniaUI component: button — Buttons: default, secondary, outline, ghost, destructive and sizes. Needs @birdycom/omniaui CSS. -->
2
- <button class="oc-btn">Default</button>
3
- <button class="oc-btn oc-btn--secondary">Secondary</button>
4
- <button class="oc-btn oc-btn--outline">Outline</button>
5
- <button class="oc-btn oc-btn--ghost">Ghost</button>
6
- <button class="oc-btn oc-btn--destructive">Delete</button>
7
- <button class="oc-btn oc-btn--sm">Small</button>
8
- <button class="oc-btn oc-btn--lg">Large</button>
1
+ <!-- OmniaUI component: button — Buttons: default, secondary, outline, ghost, destructive and sizes. Needs @birdycom/omniaui CSS. -->
2
+ <button class="oc-btn">Default</button>
3
+ <button class="oc-btn oc-btn--secondary">Secondary</button>
4
+ <button class="oc-btn oc-btn--outline">Outline</button>
5
+ <button class="oc-btn oc-btn--ghost">Ghost</button>
6
+ <button class="oc-btn oc-btn--destructive">Delete</button>
7
+ <button class="oc-btn oc-btn--sm">Small</button>
8
+ <button class="oc-btn oc-btn--lg">Large</button>
@@ -1,43 +1,43 @@
1
- <!-- OmniaUI component: calendar - Calendar: month grid markup with selected, today, range and outside-day states. Needs @birdycom/omniaui CSS.
2
- Class API (modifiers are extra classes / attributes on the same element):
3
- .oc-calendar: container. .oc-calendar-header > .oc-calendar-nav (prev/next) + .oc-calendar-title
4
- table.oc-calendar-grid[role=grid] > th.oc-calendar-weekday + td > button.oc-calendar-day
5
- Day states: [aria-selected=true] | --today | --outside | --range-start / --range-middle / --range-end | :disabled
6
- -->
7
- <div class="oc-calendar" role="group" aria-label="October 2026">
8
- <div class="oc-calendar-header">
9
- <button class="oc-calendar-nav" type="button" aria-label="Previous month"><svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m15 6-6 6 6 6"/></svg></button>
10
- <h3 class="oc-calendar-title" aria-live="polite">October 2026</h3>
11
- <button class="oc-calendar-nav" type="button" aria-label="Next month"><svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m9 6 6 6-6 6"/></svg></button>
12
- </div>
13
- <table class="oc-calendar-grid" role="grid" aria-label="October 2026">
14
- <thead><tr><th class="oc-calendar-weekday" scope="col" abbr="Monday">Mo</th><th class="oc-calendar-weekday" scope="col" abbr="Tuesday">Tu</th><th class="oc-calendar-weekday" scope="col" abbr="Wednesday">We</th><th class="oc-calendar-weekday" scope="col" abbr="Thursday">Th</th><th class="oc-calendar-weekday" scope="col" abbr="Friday">Fr</th><th class="oc-calendar-weekday" scope="col" abbr="Saturday">Sa</th><th class="oc-calendar-weekday" scope="col" abbr="Sunday">Su</th></tr></thead>
15
- <tbody>
16
- <tr><td><button class="oc-calendar-day oc-calendar-day--outside" type="button" data-date="2026-09-28" tabindex="-1">28</button></td><td><button class="oc-calendar-day oc-calendar-day--outside" type="button" data-date="2026-09-29" tabindex="-1">29</button></td><td><button class="oc-calendar-day oc-calendar-day--outside" type="button" data-date="2026-09-30" tabindex="-1">30</button></td><td><button class="oc-calendar-day" type="button" data-date="2026-10-01">1</button></td><td><button class="oc-calendar-day" type="button" data-date="2026-10-02">2</button></td><td><button class="oc-calendar-day" type="button" data-date="2026-10-03">3</button></td><td><button class="oc-calendar-day" type="button" data-date="2026-10-04">4</button></td></tr>
17
- <tr><td><button class="oc-calendar-day" type="button" data-date="2026-10-05">5</button></td><td><button class="oc-calendar-day" type="button" data-date="2026-10-06">6</button></td><td><button class="oc-calendar-day" type="button" data-date="2026-10-07">7</button></td><td><button class="oc-calendar-day" type="button" data-date="2026-10-08">8</button></td><td><button class="oc-calendar-day" type="button" data-date="2026-10-09">9</button></td><td><button class="oc-calendar-day" type="button" data-date="2026-10-10">10</button></td><td><button class="oc-calendar-day" type="button" data-date="2026-10-11">11</button></td></tr>
18
- <tr><td><button class="oc-calendar-day" type="button" data-date="2026-10-12">12</button></td><td><button class="oc-calendar-day" type="button" data-date="2026-10-13">13</button></td><td><button class="oc-calendar-day oc-calendar-day--today" type="button" data-date="2026-10-14" aria-current="date">14</button></td><td><button class="oc-calendar-day" type="button" data-date="2026-10-15">15</button></td><td><button class="oc-calendar-day" type="button" data-date="2026-10-16" aria-selected="true">16</button></td><td><button class="oc-calendar-day" type="button" data-date="2026-10-17">17</button></td><td><button class="oc-calendar-day" type="button" data-date="2026-10-18">18</button></td></tr>
19
- <tr><td><button class="oc-calendar-day" type="button" data-date="2026-10-19">19</button></td><td><button class="oc-calendar-day" type="button" data-date="2026-10-20">20</button></td><td><button class="oc-calendar-day" type="button" data-date="2026-10-21">21</button></td><td><button class="oc-calendar-day" type="button" data-date="2026-10-22">22</button></td><td><button class="oc-calendar-day" type="button" data-date="2026-10-23">23</button></td><td><button class="oc-calendar-day" type="button" data-date="2026-10-24">24</button></td><td><button class="oc-calendar-day" type="button" data-date="2026-10-25">25</button></td></tr>
20
- <tr><td><button class="oc-calendar-day" type="button" data-date="2026-10-26">26</button></td><td><button class="oc-calendar-day" type="button" data-date="2026-10-27">27</button></td><td><button class="oc-calendar-day" type="button" data-date="2026-10-28">28</button></td><td><button class="oc-calendar-day" type="button" data-date="2026-10-29">29</button></td><td><button class="oc-calendar-day" type="button" data-date="2026-10-30">30</button></td><td><button class="oc-calendar-day" type="button" data-date="2026-10-31">31</button></td><td><button class="oc-calendar-day oc-calendar-day--outside" type="button" data-date="2026-11-01" tabindex="-1">1</button></td></tr>
21
- <tr><td><button class="oc-calendar-day oc-calendar-day--outside" type="button" data-date="2026-11-02" tabindex="-1">2</button></td><td><button class="oc-calendar-day oc-calendar-day--outside" type="button" data-date="2026-11-03" tabindex="-1">3</button></td><td><button class="oc-calendar-day oc-calendar-day--outside" type="button" data-date="2026-11-04" tabindex="-1">4</button></td><td><button class="oc-calendar-day oc-calendar-day--outside" type="button" data-date="2026-11-05" tabindex="-1">5</button></td><td><button class="oc-calendar-day oc-calendar-day--outside" type="button" data-date="2026-11-06" tabindex="-1">6</button></td><td><button class="oc-calendar-day oc-calendar-day--outside" type="button" data-date="2026-11-07" tabindex="-1">7</button></td><td><button class="oc-calendar-day oc-calendar-day--outside" type="button" data-date="2026-11-08" tabindex="-1">8</button></td></tr>
22
- </tbody>
23
- </table>
24
- </div>
25
-
26
- <div class="oc-calendar" role="group" aria-label="October 2026">
27
- <div class="oc-calendar-header">
28
- <button class="oc-calendar-nav" type="button" aria-label="Previous month"><svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m15 6-6 6 6 6"/></svg></button>
29
- <h3 class="oc-calendar-title" aria-live="polite">October 2026</h3>
30
- <button class="oc-calendar-nav" type="button" aria-label="Next month"><svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m9 6 6 6-6 6"/></svg></button>
31
- </div>
32
- <table class="oc-calendar-grid" role="grid" aria-label="October 2026">
33
- <thead><tr><th class="oc-calendar-weekday" scope="col" abbr="Monday">Mo</th><th class="oc-calendar-weekday" scope="col" abbr="Tuesday">Tu</th><th class="oc-calendar-weekday" scope="col" abbr="Wednesday">We</th><th class="oc-calendar-weekday" scope="col" abbr="Thursday">Th</th><th class="oc-calendar-weekday" scope="col" abbr="Friday">Fr</th><th class="oc-calendar-weekday" scope="col" abbr="Saturday">Sa</th><th class="oc-calendar-weekday" scope="col" abbr="Sunday">Su</th></tr></thead>
34
- <tbody>
35
- <tr><td><button class="oc-calendar-day oc-calendar-day--outside" type="button" data-date="2026-09-28" tabindex="-1">28</button></td><td><button class="oc-calendar-day oc-calendar-day--outside" type="button" data-date="2026-09-29" tabindex="-1">29</button></td><td><button class="oc-calendar-day oc-calendar-day--outside" type="button" data-date="2026-09-30" tabindex="-1">30</button></td><td><button class="oc-calendar-day" type="button" data-date="2026-10-01">1</button></td><td><button class="oc-calendar-day" type="button" data-date="2026-10-02">2</button></td><td><button class="oc-calendar-day" type="button" data-date="2026-10-03">3</button></td><td><button class="oc-calendar-day" type="button" data-date="2026-10-04">4</button></td></tr>
36
- <tr><td><button class="oc-calendar-day" type="button" data-date="2026-10-05">5</button></td><td><button class="oc-calendar-day" type="button" data-date="2026-10-06">6</button></td><td><button class="oc-calendar-day" type="button" data-date="2026-10-07">7</button></td><td><button class="oc-calendar-day" type="button" data-date="2026-10-08">8</button></td><td><button class="oc-calendar-day" type="button" data-date="2026-10-09">9</button></td><td><button class="oc-calendar-day" type="button" data-date="2026-10-10">10</button></td><td><button class="oc-calendar-day" type="button" data-date="2026-10-11">11</button></td></tr>
37
- <tr><td><button class="oc-calendar-day oc-calendar-day--range-start" type="button" data-date="2026-10-12">12</button></td><td><button class="oc-calendar-day oc-calendar-day--range-middle" type="button" data-date="2026-10-13">13</button></td><td><button class="oc-calendar-day oc-calendar-day--today oc-calendar-day--range-middle" type="button" data-date="2026-10-14" aria-current="date">14</button></td><td><button class="oc-calendar-day oc-calendar-day--range-middle" type="button" data-date="2026-10-15">15</button></td><td><button class="oc-calendar-day oc-calendar-day--range-end" type="button" data-date="2026-10-16">16</button></td><td><button class="oc-calendar-day" type="button" data-date="2026-10-17">17</button></td><td><button class="oc-calendar-day" type="button" data-date="2026-10-18">18</button></td></tr>
38
- <tr><td><button class="oc-calendar-day" type="button" data-date="2026-10-19">19</button></td><td><button class="oc-calendar-day" type="button" data-date="2026-10-20">20</button></td><td><button class="oc-calendar-day" type="button" data-date="2026-10-21">21</button></td><td><button class="oc-calendar-day" type="button" data-date="2026-10-22">22</button></td><td><button class="oc-calendar-day" type="button" data-date="2026-10-23">23</button></td><td><button class="oc-calendar-day" type="button" data-date="2026-10-24">24</button></td><td><button class="oc-calendar-day" type="button" data-date="2026-10-25">25</button></td></tr>
39
- <tr><td><button class="oc-calendar-day" type="button" data-date="2026-10-26">26</button></td><td><button class="oc-calendar-day" type="button" data-date="2026-10-27">27</button></td><td><button class="oc-calendar-day" type="button" data-date="2026-10-28">28</button></td><td><button class="oc-calendar-day" type="button" data-date="2026-10-29">29</button></td><td><button class="oc-calendar-day" type="button" data-date="2026-10-30">30</button></td><td><button class="oc-calendar-day" type="button" data-date="2026-10-31">31</button></td><td><button class="oc-calendar-day oc-calendar-day--outside" type="button" data-date="2026-11-01" tabindex="-1">1</button></td></tr>
40
- <tr><td><button class="oc-calendar-day oc-calendar-day--outside" type="button" data-date="2026-11-02" tabindex="-1">2</button></td><td><button class="oc-calendar-day oc-calendar-day--outside" type="button" data-date="2026-11-03" tabindex="-1">3</button></td><td><button class="oc-calendar-day oc-calendar-day--outside" type="button" data-date="2026-11-04" tabindex="-1">4</button></td><td><button class="oc-calendar-day oc-calendar-day--outside" type="button" data-date="2026-11-05" tabindex="-1">5</button></td><td><button class="oc-calendar-day oc-calendar-day--outside" type="button" data-date="2026-11-06" tabindex="-1">6</button></td><td><button class="oc-calendar-day oc-calendar-day--outside" type="button" data-date="2026-11-07" tabindex="-1">7</button></td><td><button class="oc-calendar-day oc-calendar-day--outside" type="button" data-date="2026-11-08" tabindex="-1">8</button></td></tr>
41
- </tbody>
42
- </table>
43
- </div>
1
+ <!-- OmniaUI component: calendar - Calendar: month grid markup with selected, today, range and outside-day states. Needs @birdycom/omniaui CSS.
2
+ Class API (modifiers are extra classes / attributes on the same element):
3
+ .oc-calendar: container. .oc-calendar-header > .oc-calendar-nav (prev/next) + .oc-calendar-title
4
+ table.oc-calendar-grid[role=grid] > th.oc-calendar-weekday + td > button.oc-calendar-day
5
+ Day states: [aria-selected=true] | --today | --outside | --range-start / --range-middle / --range-end | :disabled
6
+ -->
7
+ <div class="oc-calendar" role="group" aria-label="October 2026">
8
+ <div class="oc-calendar-header">
9
+ <button class="oc-calendar-nav" type="button" aria-label="Previous month"><svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m15 6-6 6 6 6"/></svg></button>
10
+ <h3 class="oc-calendar-title" aria-live="polite">October 2026</h3>
11
+ <button class="oc-calendar-nav" type="button" aria-label="Next month"><svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m9 6 6 6-6 6"/></svg></button>
12
+ </div>
13
+ <table class="oc-calendar-grid" role="grid" aria-label="October 2026">
14
+ <thead><tr><th class="oc-calendar-weekday" scope="col" abbr="Monday">Mo</th><th class="oc-calendar-weekday" scope="col" abbr="Tuesday">Tu</th><th class="oc-calendar-weekday" scope="col" abbr="Wednesday">We</th><th class="oc-calendar-weekday" scope="col" abbr="Thursday">Th</th><th class="oc-calendar-weekday" scope="col" abbr="Friday">Fr</th><th class="oc-calendar-weekday" scope="col" abbr="Saturday">Sa</th><th class="oc-calendar-weekday" scope="col" abbr="Sunday">Su</th></tr></thead>
15
+ <tbody>
16
+ <tr><td><button class="oc-calendar-day oc-calendar-day--outside" type="button" data-date="2026-09-28" tabindex="-1">28</button></td><td><button class="oc-calendar-day oc-calendar-day--outside" type="button" data-date="2026-09-29" tabindex="-1">29</button></td><td><button class="oc-calendar-day oc-calendar-day--outside" type="button" data-date="2026-09-30" tabindex="-1">30</button></td><td><button class="oc-calendar-day" type="button" data-date="2026-10-01">1</button></td><td><button class="oc-calendar-day" type="button" data-date="2026-10-02">2</button></td><td><button class="oc-calendar-day" type="button" data-date="2026-10-03">3</button></td><td><button class="oc-calendar-day" type="button" data-date="2026-10-04">4</button></td></tr>
17
+ <tr><td><button class="oc-calendar-day" type="button" data-date="2026-10-05">5</button></td><td><button class="oc-calendar-day" type="button" data-date="2026-10-06">6</button></td><td><button class="oc-calendar-day" type="button" data-date="2026-10-07">7</button></td><td><button class="oc-calendar-day" type="button" data-date="2026-10-08">8</button></td><td><button class="oc-calendar-day" type="button" data-date="2026-10-09">9</button></td><td><button class="oc-calendar-day" type="button" data-date="2026-10-10">10</button></td><td><button class="oc-calendar-day" type="button" data-date="2026-10-11">11</button></td></tr>
18
+ <tr><td><button class="oc-calendar-day" type="button" data-date="2026-10-12">12</button></td><td><button class="oc-calendar-day" type="button" data-date="2026-10-13">13</button></td><td><button class="oc-calendar-day oc-calendar-day--today" type="button" data-date="2026-10-14" aria-current="date">14</button></td><td><button class="oc-calendar-day" type="button" data-date="2026-10-15">15</button></td><td><button class="oc-calendar-day" type="button" data-date="2026-10-16" aria-selected="true">16</button></td><td><button class="oc-calendar-day" type="button" data-date="2026-10-17">17</button></td><td><button class="oc-calendar-day" type="button" data-date="2026-10-18">18</button></td></tr>
19
+ <tr><td><button class="oc-calendar-day" type="button" data-date="2026-10-19">19</button></td><td><button class="oc-calendar-day" type="button" data-date="2026-10-20">20</button></td><td><button class="oc-calendar-day" type="button" data-date="2026-10-21">21</button></td><td><button class="oc-calendar-day" type="button" data-date="2026-10-22">22</button></td><td><button class="oc-calendar-day" type="button" data-date="2026-10-23">23</button></td><td><button class="oc-calendar-day" type="button" data-date="2026-10-24">24</button></td><td><button class="oc-calendar-day" type="button" data-date="2026-10-25">25</button></td></tr>
20
+ <tr><td><button class="oc-calendar-day" type="button" data-date="2026-10-26">26</button></td><td><button class="oc-calendar-day" type="button" data-date="2026-10-27">27</button></td><td><button class="oc-calendar-day" type="button" data-date="2026-10-28">28</button></td><td><button class="oc-calendar-day" type="button" data-date="2026-10-29">29</button></td><td><button class="oc-calendar-day" type="button" data-date="2026-10-30">30</button></td><td><button class="oc-calendar-day" type="button" data-date="2026-10-31">31</button></td><td><button class="oc-calendar-day oc-calendar-day--outside" type="button" data-date="2026-11-01" tabindex="-1">1</button></td></tr>
21
+ <tr><td><button class="oc-calendar-day oc-calendar-day--outside" type="button" data-date="2026-11-02" tabindex="-1">2</button></td><td><button class="oc-calendar-day oc-calendar-day--outside" type="button" data-date="2026-11-03" tabindex="-1">3</button></td><td><button class="oc-calendar-day oc-calendar-day--outside" type="button" data-date="2026-11-04" tabindex="-1">4</button></td><td><button class="oc-calendar-day oc-calendar-day--outside" type="button" data-date="2026-11-05" tabindex="-1">5</button></td><td><button class="oc-calendar-day oc-calendar-day--outside" type="button" data-date="2026-11-06" tabindex="-1">6</button></td><td><button class="oc-calendar-day oc-calendar-day--outside" type="button" data-date="2026-11-07" tabindex="-1">7</button></td><td><button class="oc-calendar-day oc-calendar-day--outside" type="button" data-date="2026-11-08" tabindex="-1">8</button></td></tr>
22
+ </tbody>
23
+ </table>
24
+ </div>
25
+
26
+ <div class="oc-calendar" role="group" aria-label="October 2026">
27
+ <div class="oc-calendar-header">
28
+ <button class="oc-calendar-nav" type="button" aria-label="Previous month"><svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m15 6-6 6 6 6"/></svg></button>
29
+ <h3 class="oc-calendar-title" aria-live="polite">October 2026</h3>
30
+ <button class="oc-calendar-nav" type="button" aria-label="Next month"><svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m9 6 6 6-6 6"/></svg></button>
31
+ </div>
32
+ <table class="oc-calendar-grid" role="grid" aria-label="October 2026">
33
+ <thead><tr><th class="oc-calendar-weekday" scope="col" abbr="Monday">Mo</th><th class="oc-calendar-weekday" scope="col" abbr="Tuesday">Tu</th><th class="oc-calendar-weekday" scope="col" abbr="Wednesday">We</th><th class="oc-calendar-weekday" scope="col" abbr="Thursday">Th</th><th class="oc-calendar-weekday" scope="col" abbr="Friday">Fr</th><th class="oc-calendar-weekday" scope="col" abbr="Saturday">Sa</th><th class="oc-calendar-weekday" scope="col" abbr="Sunday">Su</th></tr></thead>
34
+ <tbody>
35
+ <tr><td><button class="oc-calendar-day oc-calendar-day--outside" type="button" data-date="2026-09-28" tabindex="-1">28</button></td><td><button class="oc-calendar-day oc-calendar-day--outside" type="button" data-date="2026-09-29" tabindex="-1">29</button></td><td><button class="oc-calendar-day oc-calendar-day--outside" type="button" data-date="2026-09-30" tabindex="-1">30</button></td><td><button class="oc-calendar-day" type="button" data-date="2026-10-01">1</button></td><td><button class="oc-calendar-day" type="button" data-date="2026-10-02">2</button></td><td><button class="oc-calendar-day" type="button" data-date="2026-10-03">3</button></td><td><button class="oc-calendar-day" type="button" data-date="2026-10-04">4</button></td></tr>
36
+ <tr><td><button class="oc-calendar-day" type="button" data-date="2026-10-05">5</button></td><td><button class="oc-calendar-day" type="button" data-date="2026-10-06">6</button></td><td><button class="oc-calendar-day" type="button" data-date="2026-10-07">7</button></td><td><button class="oc-calendar-day" type="button" data-date="2026-10-08">8</button></td><td><button class="oc-calendar-day" type="button" data-date="2026-10-09">9</button></td><td><button class="oc-calendar-day" type="button" data-date="2026-10-10">10</button></td><td><button class="oc-calendar-day" type="button" data-date="2026-10-11">11</button></td></tr>
37
+ <tr><td><button class="oc-calendar-day oc-calendar-day--range-start" type="button" data-date="2026-10-12">12</button></td><td><button class="oc-calendar-day oc-calendar-day--range-middle" type="button" data-date="2026-10-13">13</button></td><td><button class="oc-calendar-day oc-calendar-day--today oc-calendar-day--range-middle" type="button" data-date="2026-10-14" aria-current="date">14</button></td><td><button class="oc-calendar-day oc-calendar-day--range-middle" type="button" data-date="2026-10-15">15</button></td><td><button class="oc-calendar-day oc-calendar-day--range-end" type="button" data-date="2026-10-16">16</button></td><td><button class="oc-calendar-day" type="button" data-date="2026-10-17">17</button></td><td><button class="oc-calendar-day" type="button" data-date="2026-10-18">18</button></td></tr>
38
+ <tr><td><button class="oc-calendar-day" type="button" data-date="2026-10-19">19</button></td><td><button class="oc-calendar-day" type="button" data-date="2026-10-20">20</button></td><td><button class="oc-calendar-day" type="button" data-date="2026-10-21">21</button></td><td><button class="oc-calendar-day" type="button" data-date="2026-10-22">22</button></td><td><button class="oc-calendar-day" type="button" data-date="2026-10-23">23</button></td><td><button class="oc-calendar-day" type="button" data-date="2026-10-24">24</button></td><td><button class="oc-calendar-day" type="button" data-date="2026-10-25">25</button></td></tr>
39
+ <tr><td><button class="oc-calendar-day" type="button" data-date="2026-10-26">26</button></td><td><button class="oc-calendar-day" type="button" data-date="2026-10-27">27</button></td><td><button class="oc-calendar-day" type="button" data-date="2026-10-28">28</button></td><td><button class="oc-calendar-day" type="button" data-date="2026-10-29">29</button></td><td><button class="oc-calendar-day" type="button" data-date="2026-10-30">30</button></td><td><button class="oc-calendar-day" type="button" data-date="2026-10-31">31</button></td><td><button class="oc-calendar-day oc-calendar-day--outside" type="button" data-date="2026-11-01" tabindex="-1">1</button></td></tr>
40
+ <tr><td><button class="oc-calendar-day oc-calendar-day--outside" type="button" data-date="2026-11-02" tabindex="-1">2</button></td><td><button class="oc-calendar-day oc-calendar-day--outside" type="button" data-date="2026-11-03" tabindex="-1">3</button></td><td><button class="oc-calendar-day oc-calendar-day--outside" type="button" data-date="2026-11-04" tabindex="-1">4</button></td><td><button class="oc-calendar-day oc-calendar-day--outside" type="button" data-date="2026-11-05" tabindex="-1">5</button></td><td><button class="oc-calendar-day oc-calendar-day--outside" type="button" data-date="2026-11-06" tabindex="-1">6</button></td><td><button class="oc-calendar-day oc-calendar-day--outside" type="button" data-date="2026-11-07" tabindex="-1">7</button></td><td><button class="oc-calendar-day oc-calendar-day--outside" type="button" data-date="2026-11-08" tabindex="-1">8</button></td></tr>
41
+ </tbody>
42
+ </table>
43
+ </div>
@@ -1,17 +1,17 @@
1
- <!-- OmniaUI component: card — Card with header, content, footer. Needs @birdycom/omniaui CSS. -->
2
- <div class="oc-card">
3
- <div class="oc-card-header">
4
- <h3 class="oc-card-title">Create project</h3>
5
- <p class="oc-card-description">Deploy your new project in one click.</p>
6
- </div>
7
- <div class="oc-card-content">
8
- <div class="oc-field">
9
- <label class="oc-field-label" for="project-name">Name</label>
10
- <input class="oc-input" id="project-name" placeholder="My project">
11
- </div>
12
- </div>
13
- <div class="oc-card-footer">
14
- <button class="oc-btn oc-btn--outline">Cancel</button>
15
- <button class="oc-btn">Deploy</button>
16
- </div>
17
- </div>
1
+ <!-- OmniaUI component: card — Card with header, content, footer. Needs @birdycom/omniaui CSS. -->
2
+ <div class="oc-card">
3
+ <div class="oc-card-header">
4
+ <h3 class="oc-card-title">Create project</h3>
5
+ <p class="oc-card-description">Deploy your new project in one click.</p>
6
+ </div>
7
+ <div class="oc-card-content">
8
+ <div class="oc-field">
9
+ <label class="oc-field-label" for="project-name">Name</label>
10
+ <input class="oc-input" id="project-name" placeholder="My project">
11
+ </div>
12
+ </div>
13
+ <div class="oc-card-footer">
14
+ <button class="oc-btn oc-btn--outline">Cancel</button>
15
+ <button class="oc-btn">Deploy</button>
16
+ </div>
17
+ </div>
@@ -1,21 +1,21 @@
1
- <!-- OmniaUI component: carousel - Carousel: CSS scroll-snap with ::scroll-button arrows and ::scroll-marker dots, fallback links. Needs @birdycom/omniaui CSS.
2
- Class API (modifiers are extra classes / attributes on the same element):
3
- .oc-carousel: wrapper (anchor scope). Modifiers: --halves, --thirds (slides per view)
4
- .oc-carousel-viewport: the scroller (tabindex="0", role="region", aria-roledescription="carousel")
5
- .oc-carousel-item: one slide (role="group" aria-roledescription="slide")
6
- .oc-carousel-dots > a.oc-carousel-dot: fallback navigation (hidden where ::scroll-marker works)
7
- -->
8
- <div class="oc-carousel" style="max-inline-size:34rem">
9
- <div class="oc-carousel-viewport" tabindex="0" role="region" aria-roledescription="carousel" aria-label="Highlights">
10
- <div class="oc-carousel-item" id="oc-slide-1" role="group" aria-roledescription="slide" aria-label="1 of 4"><div class="oc-aspect oc-aspect--wide oc-aspect--center"><span class="oc-item-title" style="font-size:1.75rem">Slide 1</span></div></div>
11
- <div class="oc-carousel-item" id="oc-slide-2" role="group" aria-roledescription="slide" aria-label="2 of 4"><div class="oc-aspect oc-aspect--wide oc-aspect--center"><span class="oc-item-title" style="font-size:1.75rem">Slide 2</span></div></div>
12
- <div class="oc-carousel-item" id="oc-slide-3" role="group" aria-roledescription="slide" aria-label="3 of 4"><div class="oc-aspect oc-aspect--wide oc-aspect--center"><span class="oc-item-title" style="font-size:1.75rem">Slide 3</span></div></div>
13
- <div class="oc-carousel-item" id="oc-slide-4" role="group" aria-roledescription="slide" aria-label="4 of 4"><div class="oc-aspect oc-aspect--wide oc-aspect--center"><span class="oc-item-title" style="font-size:1.75rem">Slide 4</span></div></div>
14
- </div>
15
- <nav class="oc-carousel-dots" aria-label="Choose a slide">
16
- <a class="oc-carousel-dot" href="#oc-slide-1" aria-label="Slide 1"></a>
17
- <a class="oc-carousel-dot" href="#oc-slide-2" aria-label="Slide 2"></a>
18
- <a class="oc-carousel-dot" href="#oc-slide-3" aria-label="Slide 3"></a>
19
- <a class="oc-carousel-dot" href="#oc-slide-4" aria-label="Slide 4"></a>
20
- </nav>
21
- </div>
1
+ <!-- OmniaUI component: carousel - Carousel: CSS scroll-snap with ::scroll-button arrows and ::scroll-marker dots, fallback links. Needs @birdycom/omniaui CSS.
2
+ Class API (modifiers are extra classes / attributes on the same element):
3
+ .oc-carousel: wrapper (anchor scope). Modifiers: --halves, --thirds (slides per view)
4
+ .oc-carousel-viewport: the scroller (tabindex="0", role="region", aria-roledescription="carousel")
5
+ .oc-carousel-item: one slide (role="group" aria-roledescription="slide")
6
+ .oc-carousel-dots > a.oc-carousel-dot: fallback navigation (hidden where ::scroll-marker works)
7
+ -->
8
+ <div class="oc-carousel" style="max-inline-size:34rem">
9
+ <div class="oc-carousel-viewport" tabindex="0" role="region" aria-roledescription="carousel" aria-label="Highlights">
10
+ <div class="oc-carousel-item" id="oc-slide-1" role="group" aria-roledescription="slide" aria-label="1 of 4"><div class="oc-aspect oc-aspect--wide oc-aspect--center"><span class="oc-item-title" style="font-size:1.75rem">Slide 1</span></div></div>
11
+ <div class="oc-carousel-item" id="oc-slide-2" role="group" aria-roledescription="slide" aria-label="2 of 4"><div class="oc-aspect oc-aspect--wide oc-aspect--center"><span class="oc-item-title" style="font-size:1.75rem">Slide 2</span></div></div>
12
+ <div class="oc-carousel-item" id="oc-slide-3" role="group" aria-roledescription="slide" aria-label="3 of 4"><div class="oc-aspect oc-aspect--wide oc-aspect--center"><span class="oc-item-title" style="font-size:1.75rem">Slide 3</span></div></div>
13
+ <div class="oc-carousel-item" id="oc-slide-4" role="group" aria-roledescription="slide" aria-label="4 of 4"><div class="oc-aspect oc-aspect--wide oc-aspect--center"><span class="oc-item-title" style="font-size:1.75rem">Slide 4</span></div></div>
14
+ </div>
15
+ <nav class="oc-carousel-dots" aria-label="Choose a slide">
16
+ <a class="oc-carousel-dot" href="#oc-slide-1" aria-label="Slide 1"></a>
17
+ <a class="oc-carousel-dot" href="#oc-slide-2" aria-label="Slide 2"></a>
18
+ <a class="oc-carousel-dot" href="#oc-slide-3" aria-label="Slide 3"></a>
19
+ <a class="oc-carousel-dot" href="#oc-slide-4" aria-label="Slide 4"></a>
20
+ </nav>
21
+ </div>
@@ -1,46 +1,46 @@
1
- <!-- OmniaUI component: chart-line — Line and area chart in inline SVG with axes, legend and tooltips on hover and focus. Needs @birdycom/omniaui CSS.
2
- File: packages/ui/snippets/chart-line.html | Map: figure -> head (title, sub) -> body (y axis, plot: svg series + hover columns, x axis) -> legend
3
- Class API (modifiers are extra classes / attributes on the same element):
4
- figure.oc-chart-line: Chart. Height from --oc-chart-line-height (12rem). Modifiers: --area (filled areas), --dots (dots always
5
- visible), --spark (no axes or grid; 3rem high)
6
- .oc-chart-line__head > .oc-chart-line__title, .oc-chart-line__sub, .oc-chart-line__value
7
- .oc-chart-line__body > ul.oc-chart-line__y (labels top to bottom), .oc-chart-line__plot, ol.oc-chart-line__x
8
- .oc-chart-line__plot (--oc-chart-line-rows: number of gridline rows, 4) > svg.oc-chart-line__svg (viewBox="0 0 100 100"
9
- preserveAspectRatio="none") > g.oc-chart-line__series (color by position: --oc-chart-1..5) > path.oc-chart-line__area +
10
- path.oc-chart-line__path (--dashed). Coordinates: x = index / (count - 1) * 100, y = 100 - value / max * 100
11
- ul.oc-chart-line__cols (--n: number of points) > li.oc-chart-line__col (--x: index, tabindex="0", aria-label with the values)
12
- > i.oc-chart-line__dot (--y: value / max in %, one per series) + span.oc-chart-line__tip > strong + span.oc-chart-line__row > b
13
- .oc-chart-legend (chart component) below the plot: the swatch colors follow the same order
14
- No JavaScript: tooltips open on :hover and :focus-visible. Generate the paths and percentages on the server or at build time.
15
- -->
16
- <figure class="oc-chart-line oc-chart-line--dots" style="max-inline-size:40rem">
17
- <figcaption class="oc-chart-line__head">
18
- <span class="oc-chart-line__title">Visitors</span>
19
- <span class="oc-chart-line__sub">January – June 2026</span>
20
- </figcaption>
21
- <div class="oc-chart-line__body">
22
- <ul class="oc-chart-line__y" aria-hidden="true"><li>320</li><li>240</li><li>160</li><li>80</li><li>0</li></ul>
23
- <div class="oc-chart-line__plot">
24
- <svg class="oc-chart-line__svg" viewBox="0 0 100 100" preserveAspectRatio="none" aria-hidden="true">
25
- <g class="oc-chart-line__series">
26
- <path class="oc-chart-line__area" d="M0 41.87 C3.33 35.68 13.33 7.34 20 4.69 C26.67 4.69 33.33 13.85 40 25.94 C46.67 38.02 53.33 75.73 60 77.19 C66.67 77.19 73.33 42.03 80 34.69 C86.67 33.13 96.67 33.39 100 33.13 L100 100 L0 100 Z"/>
27
- <path class="oc-chart-line__path" d="M0 41.87 C3.33 35.68 13.33 7.34 20 4.69 C26.67 4.69 33.33 13.85 40 25.94 C46.67 38.02 53.33 75.73 60 77.19 C66.67 77.19 73.33 42.03 80 34.69 C86.67 33.13 96.67 33.39 100 33.13"/>
28
- </g>
29
- <g class="oc-chart-line__series">
30
- <path class="oc-chart-line__area" d="M0 75 C3.33 68.75 13.33 39.58 20 37.5 C26.67 37.5 33.33 61.98 40 62.5 C46.67 62.5 53.33 41.15 60 40.63 C66.67 40.63 73.33 56.77 80 59.38 C86.67 59.38 96.67 56.77 100 56.25 L100 100 L0 100 Z"/>
31
- <path class="oc-chart-line__path" d="M0 75 C3.33 68.75 13.33 39.58 20 37.5 C26.67 37.5 33.33 61.98 40 62.5 C46.67 62.5 53.33 41.15 60 40.63 C66.67 40.63 73.33 56.77 80 59.38 C86.67 59.38 96.67 56.77 100 56.25"/>
32
- </g>
33
- </svg>
34
- <ul class="oc-chart-line__cols" style="--n:6" aria-label="Visitors per month">
35
- <li class="oc-chart-line__col" style="--x:0" tabindex="0" aria-label="January: Desktop 186, Mobile 80"><i class="oc-chart-line__dot" style="--y:58.13%"></i><i class="oc-chart-line__dot" style="--y:25%"></i><span class="oc-chart-line__tip" aria-hidden="true"><strong>January</strong><span class="oc-chart-line__row">Desktop<b>186</b></span><span class="oc-chart-line__row">Mobile<b>80</b></span></span></li>
36
- <li class="oc-chart-line__col" style="--x:1" tabindex="0" aria-label="February: Desktop 305, Mobile 200"><i class="oc-chart-line__dot" style="--y:95.31%"></i><i class="oc-chart-line__dot" style="--y:62.5%"></i><span class="oc-chart-line__tip" aria-hidden="true"><strong>February</strong><span class="oc-chart-line__row">Desktop<b>305</b></span><span class="oc-chart-line__row">Mobile<b>200</b></span></span></li>
37
- <li class="oc-chart-line__col" style="--x:2" tabindex="0" aria-label="March: Desktop 237, Mobile 120"><i class="oc-chart-line__dot" style="--y:74.06%"></i><i class="oc-chart-line__dot" style="--y:37.5%"></i><span class="oc-chart-line__tip" aria-hidden="true"><strong>March</strong><span class="oc-chart-line__row">Desktop<b>237</b></span><span class="oc-chart-line__row">Mobile<b>120</b></span></span></li>
38
- <li class="oc-chart-line__col" style="--x:3" tabindex="0" aria-label="April: Desktop 73, Mobile 190"><i class="oc-chart-line__dot" style="--y:22.81%"></i><i class="oc-chart-line__dot" style="--y:59.38%"></i><span class="oc-chart-line__tip" aria-hidden="true"><strong>April</strong><span class="oc-chart-line__row">Desktop<b>73</b></span><span class="oc-chart-line__row">Mobile<b>190</b></span></span></li>
39
- <li class="oc-chart-line__col" style="--x:4" tabindex="0" aria-label="May: Desktop 209, Mobile 130"><i class="oc-chart-line__dot" style="--y:65.31%"></i><i class="oc-chart-line__dot" style="--y:40.63%"></i><span class="oc-chart-line__tip" aria-hidden="true"><strong>May</strong><span class="oc-chart-line__row">Desktop<b>209</b></span><span class="oc-chart-line__row">Mobile<b>130</b></span></span></li>
40
- <li class="oc-chart-line__col" style="--x:5" tabindex="0" aria-label="June: Desktop 214, Mobile 140"><i class="oc-chart-line__dot" style="--y:66.88%"></i><i class="oc-chart-line__dot" style="--y:43.75%"></i><span class="oc-chart-line__tip" aria-hidden="true"><strong>June</strong><span class="oc-chart-line__row">Desktop<b>214</b></span><span class="oc-chart-line__row">Mobile<b>140</b></span></span></li>
41
- </ul>
42
- </div>
43
- <ol class="oc-chart-line__x" aria-hidden="true"><li>Jan</li><li>Feb</li><li>Mar</li><li>Apr</li><li>May</li><li>Jun</li></ol>
44
- </div>
45
- <ul class="oc-chart-legend"><li><span class="oc-chart-swatch"></span>Desktop</li><li><span class="oc-chart-swatch"></span>Mobile</li></ul>
46
- </figure>
1
+ <!-- OmniaUI component: chart-line — Line and area chart in inline SVG with axes, legend and tooltips on hover and focus. Needs @birdycom/omniaui CSS.
2
+ File: packages/ui/snippets/chart-line.html | Map: figure -> head (title, sub) -> body (y axis, plot: svg series + hover columns, x axis) -> legend
3
+ Class API (modifiers are extra classes / attributes on the same element):
4
+ figure.oc-chart-line: Chart. Height from --oc-chart-line-height (12rem). Modifiers: --area (filled areas), --dots (dots always
5
+ visible), --spark (no axes or grid; 3rem high)
6
+ .oc-chart-line__head > .oc-chart-line__title, .oc-chart-line__sub, .oc-chart-line__value
7
+ .oc-chart-line__body > ul.oc-chart-line__y (labels top to bottom), .oc-chart-line__plot, ol.oc-chart-line__x
8
+ .oc-chart-line__plot (--oc-chart-line-rows: number of gridline rows, 4) > svg.oc-chart-line__svg (viewBox="0 0 100 100"
9
+ preserveAspectRatio="none") > g.oc-chart-line__series (color by position: --oc-chart-1..5) > path.oc-chart-line__area +
10
+ path.oc-chart-line__path (--dashed). Coordinates: x = index / (count - 1) * 100, y = 100 - value / max * 100
11
+ ul.oc-chart-line__cols (--n: number of points) > li.oc-chart-line__col (--x: index, tabindex="0", aria-label with the values)
12
+ > i.oc-chart-line__dot (--y: value / max in %, one per series) + span.oc-chart-line__tip > strong + span.oc-chart-line__row > b
13
+ .oc-chart-legend (chart component) below the plot: the swatch colors follow the same order
14
+ No JavaScript: tooltips open on :hover and :focus-visible. Generate the paths and percentages on the server or at build time.
15
+ -->
16
+ <figure class="oc-chart-line oc-chart-line--dots" style="max-inline-size:40rem">
17
+ <figcaption class="oc-chart-line__head">
18
+ <span class="oc-chart-line__title">Visitors</span>
19
+ <span class="oc-chart-line__sub">January – June 2026</span>
20
+ </figcaption>
21
+ <div class="oc-chart-line__body">
22
+ <ul class="oc-chart-line__y" aria-hidden="true"><li>320</li><li>240</li><li>160</li><li>80</li><li>0</li></ul>
23
+ <div class="oc-chart-line__plot">
24
+ <svg class="oc-chart-line__svg" viewBox="0 0 100 100" preserveAspectRatio="none" aria-hidden="true">
25
+ <g class="oc-chart-line__series">
26
+ <path class="oc-chart-line__area" d="M0 41.87 C3.33 35.68 13.33 7.34 20 4.69 C26.67 4.69 33.33 13.85 40 25.94 C46.67 38.02 53.33 75.73 60 77.19 C66.67 77.19 73.33 42.03 80 34.69 C86.67 33.13 96.67 33.39 100 33.13 L100 100 L0 100 Z"/>
27
+ <path class="oc-chart-line__path" d="M0 41.87 C3.33 35.68 13.33 7.34 20 4.69 C26.67 4.69 33.33 13.85 40 25.94 C46.67 38.02 53.33 75.73 60 77.19 C66.67 77.19 73.33 42.03 80 34.69 C86.67 33.13 96.67 33.39 100 33.13"/>
28
+ </g>
29
+ <g class="oc-chart-line__series">
30
+ <path class="oc-chart-line__area" d="M0 75 C3.33 68.75 13.33 39.58 20 37.5 C26.67 37.5 33.33 61.98 40 62.5 C46.67 62.5 53.33 41.15 60 40.63 C66.67 40.63 73.33 56.77 80 59.38 C86.67 59.38 96.67 56.77 100 56.25 L100 100 L0 100 Z"/>
31
+ <path class="oc-chart-line__path" d="M0 75 C3.33 68.75 13.33 39.58 20 37.5 C26.67 37.5 33.33 61.98 40 62.5 C46.67 62.5 53.33 41.15 60 40.63 C66.67 40.63 73.33 56.77 80 59.38 C86.67 59.38 96.67 56.77 100 56.25"/>
32
+ </g>
33
+ </svg>
34
+ <ul class="oc-chart-line__cols" style="--n:6" aria-label="Visitors per month">
35
+ <li class="oc-chart-line__col" style="--x:0" tabindex="0" aria-label="January: Desktop 186, Mobile 80"><i class="oc-chart-line__dot" style="--y:58.13%"></i><i class="oc-chart-line__dot" style="--y:25%"></i><span class="oc-chart-line__tip" aria-hidden="true"><strong>January</strong><span class="oc-chart-line__row">Desktop<b>186</b></span><span class="oc-chart-line__row">Mobile<b>80</b></span></span></li>
36
+ <li class="oc-chart-line__col" style="--x:1" tabindex="0" aria-label="February: Desktop 305, Mobile 200"><i class="oc-chart-line__dot" style="--y:95.31%"></i><i class="oc-chart-line__dot" style="--y:62.5%"></i><span class="oc-chart-line__tip" aria-hidden="true"><strong>February</strong><span class="oc-chart-line__row">Desktop<b>305</b></span><span class="oc-chart-line__row">Mobile<b>200</b></span></span></li>
37
+ <li class="oc-chart-line__col" style="--x:2" tabindex="0" aria-label="March: Desktop 237, Mobile 120"><i class="oc-chart-line__dot" style="--y:74.06%"></i><i class="oc-chart-line__dot" style="--y:37.5%"></i><span class="oc-chart-line__tip" aria-hidden="true"><strong>March</strong><span class="oc-chart-line__row">Desktop<b>237</b></span><span class="oc-chart-line__row">Mobile<b>120</b></span></span></li>
38
+ <li class="oc-chart-line__col" style="--x:3" tabindex="0" aria-label="April: Desktop 73, Mobile 190"><i class="oc-chart-line__dot" style="--y:22.81%"></i><i class="oc-chart-line__dot" style="--y:59.38%"></i><span class="oc-chart-line__tip" aria-hidden="true"><strong>April</strong><span class="oc-chart-line__row">Desktop<b>73</b></span><span class="oc-chart-line__row">Mobile<b>190</b></span></span></li>
39
+ <li class="oc-chart-line__col" style="--x:4" tabindex="0" aria-label="May: Desktop 209, Mobile 130"><i class="oc-chart-line__dot" style="--y:65.31%"></i><i class="oc-chart-line__dot" style="--y:40.63%"></i><span class="oc-chart-line__tip" aria-hidden="true"><strong>May</strong><span class="oc-chart-line__row">Desktop<b>209</b></span><span class="oc-chart-line__row">Mobile<b>130</b></span></span></li>
40
+ <li class="oc-chart-line__col" style="--x:5" tabindex="0" aria-label="June: Desktop 214, Mobile 140"><i class="oc-chart-line__dot" style="--y:66.88%"></i><i class="oc-chart-line__dot" style="--y:43.75%"></i><span class="oc-chart-line__tip" aria-hidden="true"><strong>June</strong><span class="oc-chart-line__row">Desktop<b>214</b></span><span class="oc-chart-line__row">Mobile<b>140</b></span></span></li>
41
+ </ul>
42
+ </div>
43
+ <ol class="oc-chart-line__x" aria-hidden="true"><li>Jan</li><li>Feb</li><li>Mar</li><li>Apr</li><li>May</li><li>Jun</li></ol>
44
+ </div>
45
+ <ul class="oc-chart-legend"><li><span class="oc-chart-swatch"></span>Desktop</li><li><span class="oc-chart-swatch"></span>Mobile</li></ul>
46
+ </figure>