@birdycom/omniaui 0.12.5 → 0.13.0

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 (102) hide show
  1. package/README.md +1 -1
  2. package/bin/lib/copy-js.mjs +12 -1
  3. package/bin/omniaui.mjs +2 -2
  4. package/dist/barcode.d.ts +15 -0
  5. package/dist/barcode.js +164 -0
  6. package/dist/components-extra.css +15 -1
  7. package/dist/components.css +2237 -256
  8. package/dist/components.min.css +1 -1
  9. package/dist/contact-form.d.ts +5 -0
  10. package/dist/contact-form.js +138 -0
  11. package/dist/data-table.js +135 -98
  12. package/dist/fly.d.ts +4 -0
  13. package/dist/fly.js +80 -0
  14. package/dist/form-extras.d.ts +11 -0
  15. package/dist/form-extras.js +214 -0
  16. package/dist/lazy.d.ts +5 -0
  17. package/dist/lazy.js +37 -0
  18. package/dist/oc-theme.css +3 -1
  19. package/dist/parts/app-data-table-footer.css +38 -0
  20. package/dist/parts/app-data-table-rich.css +161 -0
  21. package/dist/parts/app-data-table.css +44 -74
  22. package/dist/parts/app-name-card.css +65 -0
  23. package/dist/parts/app-result.css +39 -0
  24. package/dist/parts/app-titlebar.css +16 -8
  25. package/dist/parts/data-meter-row.css +40 -0
  26. package/dist/parts/data-price.css +20 -0
  27. package/dist/parts/data-ribbon.css +76 -0
  28. package/dist/parts/data-spec-list.css +36 -0
  29. package/dist/parts/data-stock.css +41 -0
  30. package/dist/parts/forms-affix-input.css +1 -1
  31. package/dist/parts/forms-avatar-picker.css +43 -0
  32. package/dist/parts/forms-date-field.css +53 -0
  33. package/dist/parts/forms-density.css +13 -0
  34. package/dist/parts/forms-form-section.css +64 -0
  35. package/dist/parts/forms-form.css +76 -0
  36. package/dist/parts/forms-quantity.css +55 -0
  37. package/dist/parts/forms-rating.css +81 -0
  38. package/dist/parts/media-attachment.css +1 -1
  39. package/dist/parts/media-barcode.css +23 -0
  40. package/dist/parts/media-chat-composer.css +3 -0
  41. package/dist/parts/media-emoji-picker.css +3 -1
  42. package/dist/parts/media-gallery.css +55 -0
  43. package/dist/parts/media-glass-liquid.css +99 -0
  44. package/dist/parts/media-glass-options.css +50 -0
  45. package/dist/parts/media-lazy.css +46 -0
  46. package/dist/parts/media-lightbox.css +4 -0
  47. package/dist/parts/media-message-thread.css +1 -1
  48. package/dist/parts/media-message.css +1 -1
  49. package/dist/parts/nav-topbar-variants.css +96 -0
  50. package/dist/parts/site-base.css +33 -0
  51. package/dist/parts/site-brand-mark.css +56 -0
  52. package/dist/parts/site-cards.css +183 -0
  53. package/dist/parts/site-fly.css +40 -0
  54. package/dist/parts/site-header-variants.css +70 -0
  55. package/dist/parts/site-layout.css +69 -0
  56. package/dist/parts/site-panel.css +29 -0
  57. package/dist/parts/site-prose.css +13 -1
  58. package/dist/parts/utility-hover.css +44 -0
  59. package/dist/showcase.css +114 -22
  60. package/manifest.json +193 -9
  61. package/package.json +7 -2
  62. package/snippets/accordion-accent.html +1 -1
  63. package/snippets/attachment.html +4 -4
  64. package/snippets/avatar-picker.html +40 -0
  65. package/snippets/barcode.html +20 -0
  66. package/snippets/brand-mark.html +41 -0
  67. package/snippets/chat-composer.html +3 -3
  68. package/snippets/data-table.html +51 -76
  69. package/snippets/date-field.html +44 -0
  70. package/snippets/doc-viewer.html +1 -1
  71. package/snippets/emoji-picker.html +1 -1
  72. package/snippets/feature-card.html +52 -0
  73. package/snippets/fly-in.html +30 -0
  74. package/snippets/form-density.html +25 -0
  75. package/snippets/form-section.html +47 -0
  76. package/snippets/gallery.html +25 -0
  77. package/snippets/hover-effects.html +19 -0
  78. package/snippets/icon-list.html +28 -0
  79. package/snippets/lazy.html +39 -0
  80. package/snippets/message-thread.html +12 -12
  81. package/snippets/message.html +10 -10
  82. package/snippets/meter-row.html +29 -0
  83. package/snippets/name-card.html +72 -0
  84. package/snippets/page-header.html +1 -1
  85. package/snippets/page-sections.html +50 -0
  86. package/snippets/panel.html +18 -0
  87. package/snippets/price.html +25 -0
  88. package/snippets/prose.html +3 -3
  89. package/snippets/quantity.html +12 -0
  90. package/snippets/rating.html +26 -0
  91. package/snippets/result.html +31 -0
  92. package/snippets/ribbon.html +48 -0
  93. package/snippets/shot-grid.html +27 -0
  94. package/snippets/sidebar.html +3 -3
  95. package/snippets/spec-list.html +34 -0
  96. package/snippets/stock.html +20 -0
  97. package/snippets/table-actions.html +5 -5
  98. package/snippets/table.html +2 -2
  99. package/snippets/titlebar.html +1 -1
  100. package/snippets/user.html +3 -3
  101. package/dist/parts/app-column-menu.css +0 -85
  102. package/snippets/column-menu.html +0 -38
@@ -0,0 +1,28 @@
1
+ <!-- OmniaUI component: icon-list - Lists for a company site: rows with an icon in a frame, points with an icon tile, a title and a text, and a list with markers in the accent color. Needs @birdycom/omniaui CSS.
2
+ File: packages/ui/snippets/icon-list.html | Map: icon rows -> points -> accent list, badges and tagline.
3
+ Class API (modifiers are extra classes / attributes on the same element):
4
+ .oc-icon-list: Rows with an icon (svg, iconify-icon) in the primary color, each in a frame.
5
+ .oc-icon-list--points: Points: an icon tile next to .oc-icon-list__title and .oc-icon-list__text, no frames.
6
+ .oc-list--accent: Disc list in muted text with markers in --oc-accent-from.
7
+ .oc-note: Small muted note under a block (0.85rem).
8
+ .oc-badge-row: Row of badges or pills above a title.
9
+ .oc-tagline--accent: Tagline in the accent color, lighter in dark mode.
10
+ -->
11
+ <ul class="oc-icon-list" style="inline-size:min(100%, 26rem)">
12
+ <li><iconify-icon icon="mdi:shield-lock-outline" aria-hidden="true"></iconify-icon>Internal tools behind a login</li>
13
+ <li><iconify-icon icon="mdi:database-sync-outline" aria-hidden="true"></iconify-icon>Links between existing systems</li>
14
+ <li><iconify-icon icon="mdi:file-document-outline" aria-hidden="true"></iconify-icon>Reports and exports</li>
15
+ </ul>
16
+ <ul class="oc-icon-list oc-icon-list--points" style="inline-size:min(100%, 30rem)">
17
+ <li><span class="oc-icon-tile oc-icon-tile--sm oc-accent--violet" aria-hidden="true"><iconify-icon icon="mdi:server-security"></iconify-icon></span><span class="oc-icon-list__title">Runs on your own server</span><span class="oc-icon-list__text">Your data does not leave the building.</span></li>
18
+ <li><span class="oc-icon-tile oc-icon-tile--sm oc-accent--violet" aria-hidden="true"><iconify-icon icon="mdi:account-key-outline"></iconify-icon></span><span class="oc-icon-list__title">Only for your team</span><span class="oc-icon-list__text">Sign in with the accounts you already have.</span></li>
19
+ </ul>
20
+ <div class="oc-accent--green" style="inline-size:min(100%, 34rem)">
21
+ <div class="oc-badge-row"><span class="oc-pill">Web app</span><span class="oc-pill">Since 2020</span></div>
22
+ <p class="oc-tagline--accent">Plan every shift in one view</p>
23
+ <ul class="oc-list--accent">
24
+ <li>Drag a shift to another day.</li>
25
+ <li>Everyone sees their own schedule on the phone.</li>
26
+ </ul>
27
+ <p class="oc-note">The demo resets every hour.</p>
28
+ </div>
@@ -0,0 +1,39 @@
1
+ <!-- OmniaUI component: lazy - Images that load when they come near the screen, with a shimmer or a blurred preview until they are there, and sections drawn only when needed. Needs @birdycom/omniaui CSS.
2
+ File: packages/ui/snippets/lazy.html | Map: lazy images -> lazy table -> placeholder while loading.
3
+ Class API (modifiers are extra classes / attributes on the same element):
4
+ figure.oc-lazy > img[loading=lazy]: The image box: keeps its aspect ratio (--oc-lazy-ratio, 16 / 10), a shimmer until the photo is there. Give the image width and height.
5
+ --oc-lazy-preview: A tiny copy of the photo (a few hundred bytes) shown blurred instead of the shimmer: style="--oc-lazy-preview: url(photo-24px.webp)".
6
+ .is-loaded / .is-error: Added by lazy.js: the photo fades in / the placeholder stays. Without the script the photo shows when it is there.
7
+ figcaption: Optional caption over the bottom of the image.
8
+ .oc-lazy--thumb: A small square thumbnail (2.5rem) for a table row or a list item.
9
+ tr.oc-lazy-row / .oc-lazy-bar: Placeholder rows while the next page of a table loads: bars that pulse, --oc-lazy-bar sets their width. Give the rows aria-hidden="true" and say what is loading in a role="status".
10
+ .oc-lazy-section: A section the browser lays out and draws only when it comes near the screen (content-visibility: auto); --oc-lazy-size is its estimated height (600px).
11
+ watchLazy(img) / initLazy(scope): Exported from @birdycom/omniaui/lazy.js; npx omniaui copy-js lazy gives /js/oc-lazy.js that starts on its own.
12
+ -->
13
+ <div style="display:grid;grid-template-columns:repeat(auto-fill,minmax(min(100%,13rem),1fr));gap:1rem;inline-size:100%">
14
+ <figure class="oc-lazy"><img src="/img/blocks/dashboard-01.jpg" alt="Dashboard" loading="lazy" decoding="async" width="640" height="400"></figure>
15
+ <figure class="oc-lazy"><img src="/img/blocks/shop-catalog.jpg" alt="Shop catalog" loading="lazy" decoding="async" width="640" height="400"></figure>
16
+ <figure class="oc-lazy"><img src="/img/blocks/product-detail.jpg" alt="Product detail" loading="lazy" decoding="async" width="640" height="400"></figure>
17
+ <figure class="oc-lazy" style="--oc-lazy-ratio: 2 / 3"><img src="/img/blocks/auth-split-photo.webp" alt="Hieroglyphs in the Valley of the Kings, photo by Serge Cools" loading="lazy" decoding="async" width="640" height="400"><figcaption>Photo: Serge Cools</figcaption></figure>
18
+ <figure class="oc-lazy"><img src="/img/blocks/chat-inbox.jpg" alt="Chat inbox" loading="lazy" decoding="async" width="640" height="400"></figure>
19
+ <figure class="oc-lazy"><img src="/img/blocks/quote-lines.jpg" alt="Quote lines" loading="lazy" decoding="async" width="640" height="400"></figure>
20
+ </div>
21
+ <table class="oc-table" style="inline-size:100%">
22
+ <thead><tr><th>Product</th><th>Category</th><th data-numeric>Price</th></tr></thead>
23
+ <tbody>
24
+ <tr><td><div style="display:flex;align-items:center;gap:0.75rem"><figure class="oc-lazy oc-lazy--thumb"><img src="/img/shop/product-1-front.svg" alt="" loading="lazy" decoding="async" width="40" height="40"></figure><span><strong>Product 1</strong><br><small class="oc-text-muted">PRD-0001</small></span></div></td><td>Lighting</td><td data-numeric>€ 179,00</td></tr>
25
+ <tr><td><div style="display:flex;align-items:center;gap:0.75rem"><figure class="oc-lazy oc-lazy--thumb"><img src="/img/shop/product-2.svg" alt="" loading="lazy" decoding="async" width="40" height="40"></figure><span><strong>Product 2</strong><br><small class="oc-text-muted">PRD-0002</small></span></div></td><td>Furniture</td><td data-numeric>€ 265,00</td></tr>
26
+ <tr><td><div style="display:flex;align-items:center;gap:0.75rem"><figure class="oc-lazy oc-lazy--thumb"><img src="/img/shop/product-3.svg" alt="" loading="lazy" decoding="async" width="40" height="40"></figure><span><strong>Product 3</strong><br><small class="oc-text-muted">PRD-0003</small></span></div></td><td>Furniture</td><td data-numeric>€ 589,00</td></tr>
27
+ <tr><td><div style="display:flex;align-items:center;gap:0.75rem"><figure class="oc-lazy oc-lazy--thumb"><img src="/img/shop/product-4.svg" alt="" loading="lazy" decoding="async" width="40" height="40"></figure><span><strong>Product 4</strong><br><small class="oc-text-muted">PRD-0004</small></span></div></td><td>Garden</td><td data-numeric>€ 22,40</td></tr>
28
+ <tr><td><div style="display:flex;align-items:center;gap:0.75rem"><figure class="oc-lazy oc-lazy--thumb"><img src="/img/shop/product-5.svg" alt="" loading="lazy" decoding="async" width="40" height="40"></figure><span><strong>Product 5</strong><br><small class="oc-text-muted">PRD-0005</small></span></div></td><td>Electronics</td><td data-numeric>€ 129,00</td></tr>
29
+ <tr><td><div style="display:flex;align-items:center;gap:0.75rem"><figure class="oc-lazy oc-lazy--thumb"><img src="/img/shop/product-6.svg" alt="" loading="lazy" decoding="async" width="40" height="40"></figure><span><strong>Product 6</strong><br><small class="oc-text-muted">PRD-0006</small></span></div></td><td>Kitchen</td><td data-numeric>€ 11,95</td></tr>
30
+ <tr class="oc-lazy-row" aria-hidden="true"><td><div style="display:flex;align-items:center;gap:0.75rem"><span class="oc-lazy oc-lazy--thumb"></span><span class="oc-lazy-bar" style="--oc-lazy-bar: 8rem"></span></div></td><td><span class="oc-lazy-bar" style="--oc-lazy-bar: 5rem"></span></td><td><span class="oc-lazy-bar" style="--oc-lazy-bar: 4rem;margin-inline-start:auto"></span></td></tr>
31
+ <tr class="oc-lazy-row" aria-hidden="true"><td><div style="display:flex;align-items:center;gap:0.75rem"><span class="oc-lazy oc-lazy--thumb"></span><span class="oc-lazy-bar" style="--oc-lazy-bar: 8rem"></span></div></td><td><span class="oc-lazy-bar" style="--oc-lazy-bar: 5rem"></span></td><td><span class="oc-lazy-bar" style="--oc-lazy-bar: 4rem;margin-inline-start:auto"></span></td></tr>
32
+ <tr class="oc-lazy-row" aria-hidden="true"><td><div style="display:flex;align-items:center;gap:0.75rem"><span class="oc-lazy oc-lazy--thumb"></span><span class="oc-lazy-bar" style="--oc-lazy-bar: 8rem"></span></div></td><td><span class="oc-lazy-bar" style="--oc-lazy-bar: 5rem"></span></td><td><span class="oc-lazy-bar" style="--oc-lazy-bar: 4rem;margin-inline-start:auto"></span></td></tr>
33
+ </tbody>
34
+ <caption class="oc-text-muted" style="caption-side:bottom;padding-block-start:0.5rem;font-size:0.8125rem" role="status">Loading 20 more products…</caption>
35
+ </table>
36
+ <div style="display:grid;grid-template-columns:repeat(auto-fill,minmax(min(100%,13rem),1fr));gap:1rem;inline-size:100%">
37
+ <figure class="oc-lazy" role="img" aria-label="Loading"></figure>
38
+ <figure class="oc-lazy" style="--oc-lazy-preview: url(/img/blocks/shop-cart.jpg)" role="img" aria-label="Loading"></figure>
39
+ </div>
@@ -16,9 +16,9 @@
16
16
  <header class="oc-message-thread__header">
17
17
  <div class="oc-message-thread__heading">
18
18
  <h3 class="oc-message-thread__title" id="oc-thread-demo-title">Kitchen worktop: which finish?</h3>
19
- <p class="oc-message-thread__meta"><strong>Villa Dewitte</strong> · Lisa Verbeke → Tom Peeters · 14 Oct 2026</p>
19
+ <p class="oc-message-thread__meta"><strong>Project 1</strong> · Customer 1 → Customer 6 · 14 Oct 2026</p>
20
20
  </div>
21
- <div class="oc-avatar-group oc-message-thread__people" aria-label="2 participants"><span class="oc-avatar" title="Lisa Verbeke">LV</span><span class="oc-avatar" title="Tom Peeters">TP</span></div>
21
+ <div class="oc-avatar-group oc-message-thread__people" aria-label="2 participants"><span class="oc-avatar" title="Customer 1">C1</span><span class="oc-avatar" title="Customer 6">C6</span></div>
22
22
  <div class="oc-message-thread__actions">
23
23
  <span class="oc-badge oc-badge--destructive">Urgent</span>
24
24
  <button type="button" class="oc-message-thread__icon-btn" popovertarget="oc-thread-demo-menu" aria-label="Conversation actions"><svg viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><circle cx="12" cy="5" r="1.8"/><circle cx="12" cy="12" r="1.8"/><circle cx="12" cy="19" r="1.8"/></svg></button>
@@ -35,35 +35,35 @@
35
35
  <div class="oc-message-list">
36
36
  <div class="oc-message-divider"><span>Tuesday 14 October</span></div>
37
37
  <article class="oc-message">
38
- <span class="oc-avatar oc-message__avatar">LV</span>
38
+ <span class="oc-avatar oc-message__avatar">C1</span>
39
39
  <div class="oc-message__bubble">
40
- <p class="oc-message__sender">Lisa Verbeke</p>
40
+ <p class="oc-message__sender">Customer 1</p>
41
41
  <div class="oc-message__text"><p>The supplier dropped off two worktop samples at the workshop. Photo attached.</p></div>
42
42
  <div class="oc-message__attachments"><a class="oc-attachment-image" href="#samples.jpg"><span class="oc-media-art oc-media-art--6" role="img" aria-label="Two worktop samples on the workbench"></span><span class="oc-attachment-image__caption">samples.jpg · 2.1 MB</span></a></div>
43
43
  <p class="oc-message__meta"><time datetime="2026-10-14T09:12">09:12</time></p>
44
44
  </div>
45
45
  </article>
46
46
  <article class="oc-message oc-message--continued">
47
- <span class="oc-avatar oc-message__avatar">LV</span>
47
+ <span class="oc-avatar oc-message__avatar">C1</span>
48
48
  <div class="oc-message__bubble">
49
49
  <div class="oc-message__text"><p>Which one should we order: <strong>Calacatta matt</strong> or <strong>Nero Marquina polished</strong>? The cutting slot is Friday.</p></div>
50
50
  <p class="oc-message__meta"><time datetime="2026-10-14T09:13">09:13</time></p>
51
51
  </div>
52
52
  </article>
53
53
  <article class="oc-message oc-message--out">
54
- <span class="oc-avatar oc-message__avatar">TP</span>
54
+ <span class="oc-avatar oc-message__avatar">C6</span>
55
55
  <div class="oc-message__bubble">
56
56
  <div class="oc-message__text"><p>Calacatta matt, 20 mm. I'll send the updated quote to the client today.</p></div>
57
- <div class="oc-message__attachments"><a class="oc-attachment oc-attachment--pdf" href="#quote.pdf" download><span class="oc-attachment__icon" aria-hidden="true">PDF</span><span class="oc-attachment__body"><span class="oc-attachment__name">Quote kitchen Dewitte v2.pdf</span><span class="oc-attachment__size">1.2 MB</span></span></a></div>
57
+ <div class="oc-message__attachments"><a class="oc-attachment oc-attachment--pdf" href="#quote.pdf"><span class="oc-attachment__icon" aria-hidden="true">PDF</span><span class="oc-attachment__body"><span class="oc-attachment__name">Quote kitchen Project 1 v2.pdf</span><span class="oc-attachment__size">1.2 MB</span></span></a></div>
58
58
  <p class="oc-message__meta"><time datetime="2026-10-14T09:20">09:20</time><span class="oc-message__status oc-message__status--read">Read</span></p>
59
59
  </div>
60
60
  <div class="oc-message__actions"><button type="button" class="oc-message__action oc-message__action--destructive" aria-label="Delete this message"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M3 6h18M8 6V4h8v2M19 6l-1 14H6L5 6M10 11v6M14 11v6"/></svg></button></div>
61
61
  </article>
62
62
  <div class="oc-message-divider"><span>Today</span></div>
63
63
  <article class="oc-message">
64
- <span class="oc-avatar oc-message__avatar">LV</span>
64
+ <span class="oc-avatar oc-message__avatar">C1</span>
65
65
  <div class="oc-message__bubble">
66
- <p class="oc-message__sender">Lisa Verbeke</p>
66
+ <p class="oc-message__sender">Customer 1</p>
67
67
  <div class="oc-message__text"><p>Client signed. Can you confirm the edge profile before 16:00?</p></div>
68
68
  <p class="oc-message__meta"><time datetime="2026-10-24T10:02">10:02</time></p>
69
69
  </div>
@@ -77,11 +77,11 @@
77
77
  <textarea class="oc-chat-composer__input" id="oc-thread-demo-input" name="message" rows="1" placeholder="Type your reply…" required></textarea>
78
78
  <div class="oc-chat-composer__bar">
79
79
  <div class="oc-chat-composer__tools">
80
- <button type="button" class="oc-chat-composer__tool" aria-label="Attach a file">&#128206;</button>
81
- <button type="button" class="oc-chat-composer__tool" aria-label="Insert emoji">&#128578;</button>
80
+ <button type="button" class="oc-chat-composer__tool" aria-label="Attach a file"><svg viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><path d="M16.5 6v11.5a4 4 0 0 1-4 4a4 4 0 0 1-4-4V5a2.5 2.5 0 0 1 2.5-2.5A2.5 2.5 0 0 1 13.5 5v10.5a1 1 0 0 1-1 1a1 1 0 0 1-1-1V6H10v9.5a2.5 2.5 0 0 0 2.5 2.5a2.5 2.5 0 0 0 2.5-2.5V5a4 4 0 0 0-4-4a4 4 0 0 0-4 4v12.5a5.5 5.5 0 0 0 5.5 5.5a5.5 5.5 0 0 0 5.5-5.5V6z"/></svg></button>
81
+ <button type="button" class="oc-chat-composer__tool" aria-label="Insert emoji"><svg viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><path d="M20 12a8 8 0 0 0-8-8a8 8 0 0 0-8 8a8 8 0 0 0 8 8a8 8 0 0 0 8-8m2 0a10 10 0 0 1-10 10A10 10 0 0 1 2 12A10 10 0 0 1 12 2a10 10 0 0 1 10 10m-12-3.5c0 .8-.7 1.5-1.5 1.5S7 9.3 7 8.5S7.7 7 8.5 7s1.5.7 1.5 1.5m7 0c0 .8-.7 1.5-1.5 1.5S14 9.3 14 8.5S14.7 7 15.5 7s1.5.7 1.5 1.5m-5 9.73c-1.75 0-3.29-.73-4.19-1.81L9.23 14c.45.72 1.52 1.23 2.77 1.23s2.32-.51 2.77-1.23l1.42 1.42c-.9 1.08-2.44 1.81-4.19 1.81"/></svg></button>
82
82
  </div>
83
83
  <span class="oc-chat-composer__hint">Ctrl + Enter to send</span>
84
- <button type="submit" class="oc-chat-composer__send" aria-label="Send">&#10148;</button>
84
+ <button type="submit" class="oc-chat-composer__send" aria-label="Send"><svg viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><path d="M2 21l21-9L2 3v7l15 2l-15 2z"/></svg></button>
85
85
  </div>
86
86
  </form>
87
87
  </div>
@@ -11,19 +11,19 @@
11
11
  .oc-message-divider > span: Date divider. Modifier: --system (a centred notice without lines)
12
12
  No JavaScript. Escape user text on the server; the markup only expects paragraphs, lists and links.
13
13
  -->
14
- <div class="oc-message-list" role="log" aria-label="Conversation with Lisa Verbeke" style="max-inline-size:36rem">
14
+ <div class="oc-message-list" role="log" aria-label="Conversation with Customer 1" style="max-inline-size:36rem">
15
15
  <div class="oc-message-divider"><span>Tuesday 14 October</span></div>
16
16
 
17
- <article class="oc-message" aria-label="Lisa Verbeke, 09:12">
18
- <span class="oc-avatar oc-message__avatar">LV</span>
17
+ <article class="oc-message" aria-label="Customer 1, 09:12">
18
+ <span class="oc-avatar oc-message__avatar">C1</span>
19
19
  <div class="oc-message__bubble">
20
- <p class="oc-message__sender">Lisa Verbeke</p>
21
- <div class="oc-message__text"><p>Morning Tom! The worktop supplier sent two samples for Villa Dewitte.</p></div>
20
+ <p class="oc-message__sender">Customer 1</p>
21
+ <div class="oc-message__text"><p>Morning Tom! The worktop supplier sent two samples for Project 1.</p></div>
22
22
  <p class="oc-message__meta"><time datetime="2026-10-14T09:12">09:12</time></p>
23
23
  </div>
24
24
  </article>
25
- <article class="oc-message oc-message--continued" id="oc-message-demo-question" aria-label="Lisa Verbeke, 09:13">
26
- <span class="oc-avatar oc-message__avatar">LV</span>
25
+ <article class="oc-message oc-message--continued" id="oc-message-demo-question" aria-label="Customer 1, 09:13">
26
+ <span class="oc-avatar oc-message__avatar">C1</span>
27
27
  <div class="oc-message__bubble">
28
28
  <div class="oc-message__text">
29
29
  <p>Which finish should we order?</p>
@@ -35,9 +35,9 @@
35
35
  </article>
36
36
 
37
37
  <article class="oc-message oc-message--out" aria-label="You, 09:20">
38
- <span class="oc-avatar oc-message__avatar">TP</span>
38
+ <span class="oc-avatar oc-message__avatar">C6</span>
39
39
  <div class="oc-message__bubble">
40
- <a class="oc-message__quote" href="#oc-message-demo-question"><strong>Lisa Verbeke</strong><span>Which finish should we order? Calacatta matt, 20 mm or Nero Marquina polished, 12 mm</span></a>
40
+ <a class="oc-message__quote" href="#oc-message-demo-question"><strong>Customer 1</strong><span>Which finish should we order? Calacatta matt, 20 mm or Nero Marquina polished, 12 mm</span></a>
41
41
  <div class="oc-message__text"><p>Calacatta matt. The client wants the lighter look next to the oak fronts.</p></div>
42
42
  <p class="oc-message__meta"><time datetime="2026-10-14T09:20">09:20</time><span class="oc-message__status oc-message__status--read"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M2 12.5 7 17.5 18 6.5M13 16.5l1 1L22.5 9"/></svg>Read</span></p>
43
43
  </div>
@@ -47,5 +47,5 @@
47
47
  </div>
48
48
  </article>
49
49
 
50
- <div class="oc-message-divider oc-message-divider--system" role="note"><span>Lisa Verbeke marked this question as answered</span></div>
50
+ <div class="oc-message-divider oc-message-divider--system" role="note"><span>Customer 1 marked this question as answered</span></div>
51
51
  </div>
@@ -0,0 +1,29 @@
1
+ <!-- OmniaUI component: meter-row - Usage line with a label, the amount as text, a colored bar and when it resets. Needs @birdycom/omniaui CSS.
2
+ File: packages/ui/snippets/meter-row.html | Map: meter row demo markup.
3
+ Class API (modifiers are extra classes / attributes on the same element):
4
+ .oc-meter-row: Grid: label and value on the first line, the bar and the reset line below.
5
+ --oc-meter: The fill, 0–100% (inline style or your code).
6
+ data-level="warn" / "critical": Orange / red bar (and a red value at critical). Without it the bar is green.
7
+ .oc-meter-row__bar[role=meter]: The bar; give it aria-valuenow and a label for screen readers.
8
+ .oc-meter-list (--compact): A stack of rows; --compact for a small widget.
9
+ -->
10
+ <div class="oc-meter-list" style="inline-size:min(100%,28rem)">
11
+ <div class="oc-meter-row" style="--oc-meter: 62%">
12
+ <span class="oc-meter-row__label">Session (5 hours)</span>
13
+ <span class="oc-meter-row__value"><strong>62%</strong> · 31k / 50k tokens</span>
14
+ <span class="oc-meter-row__bar" role="meter" aria-label="Session (5 hours)" aria-valuemin="0" aria-valuemax="100" aria-valuenow="62"></span>
15
+ <span class="oc-meter-row__reset"><iconify-icon icon="mdi:timer-sand" aria-hidden="true"></iconify-icon>Resets in 2 h 14 min</span>
16
+ </div>
17
+ <div class="oc-meter-row" data-level="warn" style="--oc-meter: 81%">
18
+ <span class="oc-meter-row__label">Week</span>
19
+ <span class="oc-meter-row__value"><strong>81%</strong> · 1.6M / 2M tokens</span>
20
+ <span class="oc-meter-row__bar" role="meter" aria-label="Week" aria-valuemin="0" aria-valuemax="100" aria-valuenow="81"></span>
21
+ <span class="oc-meter-row__reset"><iconify-icon icon="mdi:timer-sand" aria-hidden="true"></iconify-icon>Resets Monday 09:00</span>
22
+ </div>
23
+ <div class="oc-meter-row" data-level="critical" style="--oc-meter: 96%">
24
+ <span class="oc-meter-row__label">Storage</span>
25
+ <span class="oc-meter-row__value"><strong>96%</strong> · 9.6 / 10 GB</span>
26
+ <span class="oc-meter-row__bar" role="meter" aria-label="Storage" aria-valuemin="0" aria-valuemax="100" aria-valuenow="96"></span>
27
+ <span class="oc-meter-row__reset"><iconify-icon icon="mdi:timer-sand" aria-hidden="true"></iconify-icon>Upgrade or clean up to keep syncing</span>
28
+ </div>
29
+ </div>
@@ -0,0 +1,72 @@
1
+ <!-- OmniaUI component: name-card - Collapsible card with a name, rename pencil, amount and delete button; nests for titles and parts. Needs @birdycom/omniaui CSS.
2
+ File: packages/ui/snippets/name-card.html | Map: name card demo markup. Behaviour: form-extras.js.
3
+ Class API (modifiers are extra classes / attributes on the same element):
4
+ .oc-name-card: The card: a <details>; open shows the content.
5
+ .oc-name-card__head: The <summary>: chevron, name, rename, meta, amount and actions on one line.
6
+ .oc-name-card__title / __meta / __amount: Name (cut with an ellipsis), a quiet extra ("6 articles") and the amount (tabular numbers, pushed right).
7
+ .oc-name-card__actions: Buttons on the right, e.g. a soft destructive delete.
8
+ [data-oc-rename]: With form-extras.js: the pencil turns the name into an input; Enter or leaving the field saves (oc-namecard-rename event with the name), Escape cancels.
9
+ .oc-name-card__body: The content. Name cards inside it are the parts of a title (quieter surface).
10
+ .oc-name-card--total: The amount of this card in the primary color (a total).
11
+ -->
12
+ <div style="display:grid;gap:0.5rem;inline-size:min(100%,40rem)">
13
+ <details class="oc-name-card oc-name-card--total" open>
14
+ <summary class="oc-name-card__head">
15
+ <span class="oc-name-card__title">Kitchen – ground floor</span>
16
+ <button type="button" class="oc-btn oc-btn--plain" data-oc-rename aria-label="Rename Kitchen – ground floor" title="Rename"><iconify-icon icon="mdi:pencil-outline" aria-hidden="true"></iconify-icon></button>
17
+
18
+ <span class="oc-name-card__amount">€ 8.480,00</span>
19
+ <span class="oc-name-card__actions"><button type="button" class="oc-btn oc-btn--soft-destructive oc-btn--icon oc-btn--sm" aria-label="Delete Kitchen – ground floor" title="Delete"><iconify-icon icon="mdi:trash-can-outline" aria-hidden="true"></iconify-icon></button></span>
20
+ </summary>
21
+ <div class="oc-name-card__body">
22
+ <details class="oc-name-card">
23
+ <summary class="oc-name-card__head">
24
+ <span class="oc-name-card__title">Base cabinets</span>
25
+ <button type="button" class="oc-btn oc-btn--plain" data-oc-rename aria-label="Rename Base cabinets" title="Rename"><iconify-icon icon="mdi:pencil-outline" aria-hidden="true"></iconify-icon></button>
26
+ <span class="oc-name-card__meta">6 articles</span>
27
+ <span class="oc-name-card__amount">€ 4.180,00</span>
28
+ <span class="oc-name-card__actions"><button type="button" class="oc-btn oc-btn--soft-destructive oc-btn--icon oc-btn--sm" aria-label="Delete Base cabinets" title="Delete"><iconify-icon icon="mdi:trash-can-outline" aria-hidden="true"></iconify-icon></button></span>
29
+ </summary>
30
+ <div class="oc-name-card__body">
31
+ <p class="m-0 oc-text-muted">6 articles · 2 options</p>
32
+ </div>
33
+ </details>
34
+ <details class="oc-name-card">
35
+ <summary class="oc-name-card__head">
36
+ <span class="oc-name-card__title">Wall cabinets</span>
37
+ <button type="button" class="oc-btn oc-btn--plain" data-oc-rename aria-label="Rename Wall cabinets" title="Rename"><iconify-icon icon="mdi:pencil-outline" aria-hidden="true"></iconify-icon></button>
38
+ <span class="oc-name-card__meta">4 articles</span>
39
+ <span class="oc-name-card__amount">€ 2.360,00</span>
40
+ <span class="oc-name-card__actions"><button type="button" class="oc-btn oc-btn--soft-destructive oc-btn--icon oc-btn--sm" aria-label="Delete Wall cabinets" title="Delete"><iconify-icon icon="mdi:trash-can-outline" aria-hidden="true"></iconify-icon></button></span>
41
+ </summary>
42
+ <div class="oc-name-card__body">
43
+ <p class="m-0 oc-text-muted">4 articles</p>
44
+ </div>
45
+ </details>
46
+ <details class="oc-name-card">
47
+ <summary class="oc-name-card__head">
48
+ <span class="oc-name-card__title">Worktop</span>
49
+ <button type="button" class="oc-btn oc-btn--plain" data-oc-rename aria-label="Rename Worktop" title="Rename"><iconify-icon icon="mdi:pencil-outline" aria-hidden="true"></iconify-icon></button>
50
+ <span class="oc-name-card__meta">1 article</span>
51
+ <span class="oc-name-card__amount">€ 1.940,00</span>
52
+ <span class="oc-name-card__actions"><button type="button" class="oc-btn oc-btn--soft-destructive oc-btn--icon oc-btn--sm" aria-label="Delete Worktop" title="Delete"><iconify-icon icon="mdi:trash-can-outline" aria-hidden="true"></iconify-icon></button></span>
53
+ </summary>
54
+ <div class="oc-name-card__body">
55
+ <p class="m-0 oc-text-muted">1 article · cut to size</p>
56
+ </div>
57
+ </details>
58
+ </div>
59
+ </details>
60
+ <details class="oc-name-card">
61
+ <summary class="oc-name-card__head">
62
+ <span class="oc-name-card__title">Bathroom – first floor</span>
63
+ <button type="button" class="oc-btn oc-btn--plain" data-oc-rename aria-label="Rename Bathroom – first floor" title="Rename"><iconify-icon icon="mdi:pencil-outline" aria-hidden="true"></iconify-icon></button>
64
+
65
+ <span class="oc-name-card__amount">€ 3.215,50</span>
66
+ <span class="oc-name-card__actions"><button type="button" class="oc-btn oc-btn--soft-destructive oc-btn--icon oc-btn--sm" aria-label="Delete Bathroom – first floor" title="Delete"><iconify-icon icon="mdi:trash-can-outline" aria-hidden="true"></iconify-icon></button></span>
67
+ </summary>
68
+ <div class="oc-name-card__body">
69
+ <p class="m-0 oc-text-muted">Add a part with the button below.</p>
70
+ </div>
71
+ </details>
72
+ </div>
@@ -14,7 +14,7 @@
14
14
  <div class="oc-page-header-text">
15
15
  <h1 class="oc-page-header-title">Kitchen renovation <span class="oc-badge oc-badge--success">Active</span></h1>
16
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>
17
+ <div class="oc-page-header-meta"><span>Owner: Contact 1</span><span>Updated 2 hours ago</span></div>
18
18
  </div>
19
19
  <div class="oc-page-header-actions">
20
20
  <button class="oc-btn oc-btn--outline" type="button">Share</button>
@@ -0,0 +1,50 @@
1
+ <!-- OmniaUI component: page-sections - Building blocks for the pages of a company site: the header of an inner page, a section head, a row of buttons, a group title with a count, a full-width band and a meta line. Needs @birdycom/omniaui CSS.
2
+ File: packages/ui/snippets/page-sections.html | Map: inner page header -> section head, group title and more row -> centered head and buttons.
3
+ Class API (modifiers are extra classes / attributes on the same element):
4
+ .oc-section-pad--page: Header of an inner page: padding clamp(4rem, 10vw, 7rem) on top, clamp(2rem, 5vw, 3rem) below.
5
+ .oc-display--page: Larger display title for that header: clamp(2.5rem, 6.5vw, 4.75rem).
6
+ .oc-section-head: Head of a section (eyebrow, title, lead): max 46rem, 3rem below. --center centers it.
7
+ .oc-section-more: Row under a section (a <em>see all</em> link): 2.5rem above.
8
+ .oc-actions: Row of buttons that wraps: gap .75rem, 2rem above. --center, --end, --tight (1rem above).
9
+ .oc-group-title: Title of a group of cards; .oc-group-title__count is the number in a pill.
10
+ .oc-band: Band over the full width with a line above and below (--oc-band-bg, surface); the content stays in its .oc-container.
11
+ .oc-meta: Meta line under a title: version · date. Subtle text (--oc-subtle-foreground), 0.9rem.
12
+ -->
13
+ <section class="oc-section-pad--page" style="inline-size:100%">
14
+ <div class="oc-container">
15
+ <p class="oc-eyebrow">Contact</p>
16
+ <h1 class="oc-display oc-display--page">Let's <span class="oc-text-gradient">talk</span></h1>
17
+ <p class="oc-lead">A new project, a question about one of our apps or help with your IT? We would like to hear from you.</p>
18
+ <p class="oc-meta">Version 2 · 30 October 2026</p>
19
+ <div class="oc-actions">
20
+ <a class="oc-btn oc-btn--lg" href="#form">Send a message</a>
21
+ <a class="oc-btn oc-btn--outline oc-btn--lg" href="tel:+3230000000">Call us</a>
22
+ </div>
23
+ </div>
24
+ </section>
25
+ <section style="inline-size:100%">
26
+ <div class="oc-section-head">
27
+ <p class="oc-eyebrow">Software</p>
28
+ <h2 class="oc-display oc-display--md">Our own products</h2>
29
+ <p class="oc-lead">Apps we build, sell and maintain ourselves.</p>
30
+ </div>
31
+ <h3 class="oc-group-title">Business apps <span class="oc-group-title__count">3</span></h3>
32
+ <div class="oc-card-grid">
33
+ <div class="oc-card" style="padding:1.25rem">Product 1</div>
34
+ <div class="oc-card" style="padding:1.25rem">Product 2</div>
35
+ <div class="oc-card" style="padding:1.25rem">Product 3</div>
36
+ </div>
37
+ <div class="oc-section-more">
38
+ <a class="oc-link-arrow" href="#products">See all products</a>
39
+ </div>
40
+ </section>
41
+ <section style="inline-size:100%">
42
+ <div class="oc-section-head oc-section-head--center">
43
+ <h2 class="oc-display oc-display--md">Ready for the next step?</h2>
44
+ <p class="oc-lead" style="margin-inline:auto">Tell us what you need; we answer within one working day.</p>
45
+ <div class="oc-actions oc-actions--center">
46
+ <a class="oc-btn oc-btn--lg" href="#contact">Start a project</a>
47
+ <a class="oc-btn oc-btn--ghost oc-btn--lg" href="#work">See our work</a>
48
+ </div>
49
+ </div>
50
+ </section>
@@ -0,0 +1,18 @@
1
+ <!-- OmniaUI component: panel - A framed panel on the page for a form, a call to action or a feature: card background, strong border, large radius and an optional soft glow in a corner. Needs @birdycom/omniaui CSS.
2
+ File: packages/ui/snippets/panel.html | Map: panel with a glow -> glow positions.
3
+ Class API (modifiers are extra classes / attributes on the same element):
4
+ .oc-panel: The panel: padding clamp(1.5rem, 4vw, 2.5rem) (--oc-panel-padding), --oc-border-strong, radius 1.2 × --oc-radius-lg, scroll-margin-top from --oc-scroll-offset (6rem).
5
+ .oc-panel--glow: A soft light in the top start corner in --oc-panel-glow-color (brand 1); --oc-panel-glow-at moves it.
6
+ .oc-panel--glow-end: The light in the top end corner.
7
+ .oc-panel--glow-both: Two lights: brand 1 top start and brand 3 bottom end (call to action).
8
+ -->
9
+ <div class="oc-panel oc-panel--glow" style="inline-size:min(100%, 34rem)">
10
+ <h2 style="margin:0 0 0.5rem;font-size:1.35rem">Send us a message</h2>
11
+ <p class="oc-text-muted" style="margin:0">We usually answer within one working day.</p>
12
+ </div>
13
+ <div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,14rem),1fr));gap:1rem;inline-size:100%">
14
+ <div class="oc-panel"><strong>.oc-panel</strong><p class="oc-text-muted" style="margin:0.35rem 0 0">No light.</p></div>
15
+ <div class="oc-panel oc-panel--glow"><strong>--glow</strong><p class="oc-text-muted" style="margin:0.35rem 0 0">Top start.</p></div>
16
+ <div class="oc-panel oc-panel--glow oc-panel--glow-end"><strong>--glow-end</strong><p class="oc-text-muted" style="margin:0.35rem 0 0">Top end.</p></div>
17
+ <div class="oc-panel oc-panel--glow-both"><strong>--glow-both</strong><p class="oc-text-muted" style="margin:0.35rem 0 0">Two lights.</p></div>
18
+ </div>
@@ -0,0 +1,25 @@
1
+ <!-- OmniaUI component: price - A price with old price, discount, VAT note and the amount incl. or excl. VAT. Needs @birdycom/omniaui CSS.
2
+ File: packages/ui/snippets/price.html | Map: prices.
3
+ Class API (modifiers are extra classes / attributes on the same element):
4
+ .oc-price: The block: __main line, then __note and __alt below.
5
+ .oc-price__amount: The price (bold, tabular digits, never wraps).
6
+ .oc-price__old: The old price, struck through. Add an .oc-badge in __main for the discount.
7
+ .oc-price__note / __alt: A quiet note ("excl. VAT") and the other amount ("€ 121,00 incl. VAT").
8
+ .oc-price--sm / --lg / --sale: Smaller or larger amount; --sale colors the amount red.
9
+ .oc-price--inline / --end: Amount and note on one line (lists); right aligned (also automatic in a td[data-numeric]).
10
+ -->
11
+ <div class="flex flex-wrap gap-2 align-items-start">
12
+ <div class="oc-price oc-price--lg">
13
+ <div class="oc-price__main"><span class="oc-price__amount">€ 149,00</span></div>
14
+ <span class="oc-price__note">excl. VAT</span>
15
+ <span class="oc-price__alt">€ 180,29 incl. VAT</span>
16
+ </div>
17
+ <div class="oc-price oc-price--lg oc-price--sale">
18
+ <div class="oc-price__main"><span class="oc-price__amount">€ 119,00</span><s class="oc-price__old">€ 149,00</s><span class="oc-badge oc-badge--destructive">-20%</span></div>
19
+ <span class="oc-price__note">incl. VAT · free delivery</span>
20
+ </div>
21
+ <div class="oc-price oc-price--sm">
22
+ <div class="oc-price__main"><span class="oc-price__amount">€ 6,40</span></div>
23
+ <span class="oc-price__note">per piece · from 10 pieces € 5,90</span>
24
+ </div>
25
+ </div>
@@ -20,7 +20,7 @@
20
20
  </ul>
21
21
  <figure>
22
22
  <div class="oc-media-art oc-media-art--6" role="img" aria-label="Kitchen with oak fronts and a light stone worktop"></div>
23
- <figcaption>Villa Dewitte: oak fronts with a Calacatta matt worktop, finished in October 2026.</figcaption>
23
+ <figcaption>Project 1: oak fronts with a Calacatta matt worktop, finished in October 2026.</figcaption>
24
24
  </figure>
25
25
  <h3>From design to installation</h3>
26
26
  <ol>
@@ -31,7 +31,7 @@
31
31
  </ol>
32
32
  <blockquote>
33
33
  <p>The planning was clear from day one. We always knew who was coming and when, and the kitchen was ready a week early.</p>
34
- <footer>— Ann Dewitte, client in Ghent</footer>
34
+ <footer>— Customer 8, client in Ghent</footer>
35
35
  </blockquote>
36
36
  <h2>Worktop materials compared</h2>
37
37
  <table>
@@ -45,7 +45,7 @@
45
45
  </table>
46
46
  <h3>Sharing your floor plan</h3>
47
47
  <p>Upload a PDF or a photo in the client portal, or send it by e-mail. Press <kbd>Ctrl</kbd> + <kbd>V</kbd> in the chat to paste a screenshot. Files are stored as <code>project-id/plans/</code> and only your project team can see them.</p>
48
- <pre><code>Project: 2026-114 Villa Dewitte
48
+ <pre><code>Project: 2026-114 Project 1
49
49
  Room: Kitchen, ground floor
50
50
  Wall A: 412 cm (window at 160 cm)
51
51
  Wall B: 298 cm (door at the left)</code></pre>
@@ -0,0 +1,12 @@
1
+ <!-- OmniaUI component: quantity - Number field with minus and plus buttons for amounts in carts, orders and stock. Needs @birdycom/omniaui CSS.
2
+ File: packages/ui/snippets/quantity.html | Map: quantity.
3
+ Behaviour: form-extras.js (npx omniaui copy-js form-extras); works without it.
4
+ Class API (modifiers are extra classes / attributes on the same element):
5
+ .oc-quantity: The frame. --sm for a 2rem field in tables and carts.
6
+ .oc-quantity__input: A native type="number" with min, max, step and name; the spinners are hidden.
7
+ [data-oc-step="-1"] / [data-oc-step="1"]: The minus and plus buttons (.oc-quantity__step); with form-extras.js they change the value and fire input and change.
8
+ -->
9
+ <div class="flex flex-wrap gap-2 align-items-center">
10
+ <div class="oc-quantity"><button class="oc-quantity__step" type="button" data-oc-step="-1" aria-label="Decrease quantity"><svg viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><path d="M19 13H5v-2h14z"/></svg></button><input class="oc-quantity__input" id="oc-qty-demo-1" type="number" inputmode="numeric" name="quantity" value="1" min="1" max="10" step="1" aria-label="Quantity"><button class="oc-quantity__step" type="button" data-oc-step="1" aria-label="Increase quantity"><svg viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><path d="M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6z"/></svg></button></div>
11
+ <div class="oc-quantity oc-quantity--sm"><button class="oc-quantity__step" type="button" data-oc-step="-1" aria-label="Decrease pieces"><svg viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><path d="M19 13H5v-2h14z"/></svg></button><input class="oc-quantity__input" id="oc-qty-demo-2" type="number" inputmode="numeric" name="quantity" value="12" min="0" max="500" step="1" aria-label="Pieces"><button class="oc-quantity__step" type="button" data-oc-step="1" aria-label="Increase pieces"><svg viewBox="0 0 24 24" fill="currentColor" aria-hidden="true"><path d="M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6z"/></svg></button></div>
12
+ </div>
@@ -0,0 +1,26 @@
1
+ <!-- OmniaUI component: rating - Star rating: show a score with halves, or let people pick 1 to 5 stars. No JavaScript. Needs @birdycom/omniaui CSS.
2
+ File: packages/ui/snippets/rating.html | Map: score and summary -> pick a rating.
3
+ Class API (modifiers are extra classes / attributes on the same element):
4
+ .oc-rating: The stars of a score. --oc-rating is the score (decimals work), --oc-rating-max the number of stars (default 5). Give it role="img" and an aria-label ("4.5 out of 5").
5
+ .oc-rating--sm / --lg: Smaller or larger stars (--oc-rating-size sets any size).
6
+ .oc-rating-summary: Stars, the score (__score) and the number of reviews (__count, a link or text) on one line.
7
+ fieldset.oc-rating-input: Five <label>s with a radio inside (value 1–5) and a hidden text ("3 stars"). The checked or hovered star fills the stars before it. --sm / --lg sizes.
8
+ --oc-rating-color / --oc-rating-empty: Colors of the filled and empty stars (default: the warning token and a light muted tone).
9
+ -->
10
+ <div class="flex flex-column gap-1">
11
+ <span class="oc-rating" style="--oc-rating: 4.5" role="img" aria-label="4.5 out of 5"></span>
12
+ <div class="oc-rating-summary">
13
+ <span class="oc-rating oc-rating--sm" style="--oc-rating: 4.2" role="img" aria-label="4.2 out of 5"></span>
14
+ <span class="oc-rating-summary__score">4.2</span>
15
+ <a class="oc-rating-summary__count" href="#reviews">128 reviews</a>
16
+ </div>
17
+ <span class="oc-rating oc-rating--lg" style="--oc-rating: 3" role="img" aria-label="3 out of 5"></span>
18
+ </div>
19
+ <fieldset class="oc-rating-input oc-rating-input--lg">
20
+ <legend>Your rating</legend>
21
+ <label><input type="radio" name="oc-rating-demo" value="1"><span>1 star</span></label>
22
+ <label><input type="radio" name="oc-rating-demo" value="2"><span>2 stars</span></label>
23
+ <label><input type="radio" name="oc-rating-demo" value="3"><span>3 stars</span></label>
24
+ <label><input type="radio" name="oc-rating-demo" value="4" checked><span>4 stars</span></label>
25
+ <label><input type="radio" name="oc-rating-demo" value="5"><span>5 stars</span></label>
26
+ </fieldset>
@@ -0,0 +1,31 @@
1
+ <!-- OmniaUI component: result - The outcome of an action in the place where the form was: an icon tile, a title, a short text and a button such as Send another message. Needs @birdycom/omniaui CSS.
2
+ File: packages/ui/snippets/result.html | Map: message sent -> centered.
3
+ Class API (modifiers are extra classes / attributes on the same element):
4
+ .oc-result: The result: tile, title, text and actions stacked, aligned at the start.
5
+ .oc-result__title: The title (1.2rem).
6
+ .oc-result__text: Muted text; links in the primary color, underlined.
7
+ .oc-result__actions: Row of buttons under the text.
8
+ .oc-result--center: Centers everything (an empty state or a full page).
9
+ role="status" tabindex="-1": Announces the result and lets the script move the focus to it.
10
+ -->
11
+ <div class="oc-panel" style="inline-size:min(100%, 34rem)">
12
+ <div class="oc-result" role="status" tabindex="-1">
13
+ <span class="oc-icon-tile oc-icon-tile--sm oc-accent--green" aria-hidden="true"><iconify-icon icon="mdi:check"></iconify-icon></span>
14
+ <h2 class="oc-result__title">Thank you, your message was sent</h2>
15
+ <p class="oc-result__text">You will get a confirmation by e-mail.<br>Urgent? Call us on <a href="tel:+3230000000">+32 3 000 00 00</a>.</p>
16
+ <div class="oc-result__actions">
17
+ <a class="oc-btn oc-btn--outline" href="#contact-form">Send another message</a>
18
+ </div>
19
+ </div>
20
+ </div>
21
+ <div class="oc-panel" style="inline-size:min(100%, 34rem)">
22
+ <div class="oc-result oc-result--center" role="status" tabindex="-1">
23
+ <span class="oc-icon-tile oc-icon-tile--sm oc-accent--orange" aria-hidden="true"><iconify-icon icon="mdi:clock-outline"></iconify-icon></span>
24
+ <h2 class="oc-result__title">Your request is waiting for approval</h2>
25
+ <p class="oc-result__text">Customer 1 gets an e-mail as soon as it is approved.</p>
26
+ <div class="oc-result__actions">
27
+ <a class="oc-btn" href="#orders">Back to the orders</a>
28
+ <a class="oc-btn oc-btn--ghost" href="#request">View the request</a>
29
+ </div>
30
+ </div>
31
+ </div>
@@ -0,0 +1,48 @@
1
+ <!-- OmniaUI component: ribbon - A diagonal band across a corner of a card, image or document: Paid, New, Sale. Pick the corner and the tone. Needs @birdycom/omniaui CSS.
2
+ File: packages/ui/snippets/ribbon.html | Map: pick a corner -> on a document -> tones and sizes.
3
+ Class API (modifiers are extra classes / attributes on the same element):
4
+ .oc-ribbon: The band, a child of the card or image box. That box gets position: relative and clips the band automatically (:has(), zero specificity).
5
+ .oc-ribbon--top-start / --bottom-start / --bottom-end: The corner; without a modifier it sits top end (top right in a left-to-right page). Start and end follow the writing direction.
6
+ .oc-ribbon--success / --warning / --destructive / --muted: Tone; the default is the primary color.
7
+ .oc-ribbon--sm / --lg: A smaller band (product card) or a larger one (document, hero image).
8
+ --oc-ribbon-inset: Distance from the corner to the middle of the band (2.25rem); the band length follows it.
9
+ --oc-ribbon-bg / --oc-ribbon-fg: Your own colors, for example a brand color or a gradient.
10
+ -->
11
+ <div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(12rem,1fr));gap:1rem;inline-size:100%">
12
+ <div class="oc-card" style="min-block-size:9rem;display:grid;place-items:center;text-align:center">
13
+ <span class="oc-ribbon oc-ribbon--top-start">New</span>
14
+ <div><strong>Top start</strong><br><small class="oc-text-muted">--top-start</small></div>
15
+ </div>
16
+ <div class="oc-card" style="min-block-size:9rem;display:grid;place-items:center;text-align:center">
17
+ <span class="oc-ribbon oc-ribbon--success">Paid</span>
18
+ <div><strong>Top end</strong><br><small class="oc-text-muted">default</small></div>
19
+ </div>
20
+ <div class="oc-card" style="min-block-size:9rem;display:grid;place-items:center;text-align:center">
21
+ <span class="oc-ribbon oc-ribbon--bottom-start oc-ribbon--warning">Due soon</span>
22
+ <div><strong>Bottom start</strong><br><small class="oc-text-muted">--bottom-start</small></div>
23
+ </div>
24
+ <div class="oc-card" style="min-block-size:9rem;display:grid;place-items:center;text-align:center">
25
+ <span class="oc-ribbon oc-ribbon--bottom-end oc-ribbon--destructive">Overdue</span>
26
+ <div><strong>Bottom end</strong><br><small class="oc-text-muted">--bottom-end</small></div>
27
+ </div>
28
+ </div>
29
+ <article class="oc-card" style="max-inline-size:30rem;inline-size:100%;padding:1.5rem;display:grid;gap:1rem">
30
+ <span class="oc-ribbon oc-ribbon--success oc-ribbon--lg">Paid</span>
31
+ <header style="display:grid;gap:0.25rem">
32
+ <span class="oc-text-muted" style="font-size:0.8125rem">Invoice</span>
33
+ <strong style="font-size:1.25rem">2026-0042</strong>
34
+ <span style="font-size:0.875rem">Customer 1 · info@company1.example</span>
35
+ </header>
36
+ <dl style="display:grid;grid-template-columns:auto 1fr;gap:0.25rem 1rem;margin:0;font-size:0.875rem">
37
+ <dt class="oc-text-muted">Invoice date</dt><dd style="margin:0">2 November 2026</dd>
38
+ <dt class="oc-text-muted">Paid on</dt><dd style="margin:0">9 November 2026</dd>
39
+ <dt class="oc-text-muted">Total</dt><dd style="margin:0"><strong>€ 1.210,00</strong></dd>
40
+ </dl>
41
+ </article>
42
+ <div style="display:flex;flex-wrap:wrap;gap:1rem">
43
+ <div class="oc-card" style="inline-size:9rem;block-size:7rem"><span class="oc-ribbon oc-ribbon--sm">New</span></div>
44
+ <div class="oc-card" style="inline-size:9rem;block-size:7rem"><span class="oc-ribbon oc-ribbon--sm oc-ribbon--destructive">Sale</span></div>
45
+ <div class="oc-card" style="inline-size:9rem;block-size:7rem"><span class="oc-ribbon oc-ribbon--sm oc-ribbon--muted">Draft</span></div>
46
+ <div class="oc-card" style="inline-size:11rem;block-size:7rem"><span class="oc-ribbon oc-ribbon--warning">Beta</span></div>
47
+ <div class="oc-card" style="inline-size:13rem;block-size:7rem"><span class="oc-ribbon oc-ribbon--lg" style="--oc-ribbon-bg:linear-gradient(90deg,var(--oc-accent-from,var(--oc-primary)),var(--oc-accent-to,var(--oc-primary)))">Pro</span></div>
48
+ </div>