@birdycom/omniaui 0.12.4 → 0.12.6

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 (79) hide show
  1. package/README.md +1 -1
  2. package/bin/lib/copy-js.mjs +10 -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 +1496 -193
  8. package/dist/components.min.css +1 -1
  9. package/dist/data-table.js +135 -98
  10. package/dist/form-extras.d.ts +11 -0
  11. package/dist/form-extras.js +214 -0
  12. package/dist/lazy.d.ts +5 -0
  13. package/dist/lazy.js +37 -0
  14. package/dist/oc-theme.css +1 -1
  15. package/dist/parts/app-data-table-footer.css +38 -0
  16. package/dist/parts/app-data-table-rich.css +161 -0
  17. package/dist/parts/app-data-table.css +44 -74
  18. package/dist/parts/app-name-card.css +65 -0
  19. package/dist/parts/app-titlebar.css +16 -8
  20. package/dist/parts/data-meter-row.css +40 -0
  21. package/dist/parts/data-price.css +20 -0
  22. package/dist/parts/data-ribbon.css +76 -0
  23. package/dist/parts/data-spec-list.css +36 -0
  24. package/dist/parts/data-stock.css +41 -0
  25. package/dist/parts/forms-affix-input.css +1 -1
  26. package/dist/parts/forms-avatar-picker.css +43 -0
  27. package/dist/parts/forms-date-field.css +53 -0
  28. package/dist/parts/forms-density.css +13 -0
  29. package/dist/parts/forms-form-section.css +64 -0
  30. package/dist/parts/forms-quantity.css +55 -0
  31. package/dist/parts/forms-rating.css +81 -0
  32. package/dist/parts/media-attachment.css +1 -1
  33. package/dist/parts/media-barcode.css +23 -0
  34. package/dist/parts/media-chat-composer.css +3 -0
  35. package/dist/parts/media-emoji-picker.css +3 -1
  36. package/dist/parts/media-gallery.css +55 -0
  37. package/dist/parts/media-glass-liquid.css +99 -0
  38. package/dist/parts/media-glass-options.css +50 -0
  39. package/dist/parts/media-lazy.css +46 -0
  40. package/dist/parts/media-message-thread.css +1 -1
  41. package/dist/parts/media-message.css +1 -1
  42. package/dist/parts/nav-topbar-variants.css +96 -0
  43. package/dist/parts/site-header-variants.css +70 -0
  44. package/dist/parts/site-prose.css +1 -1
  45. package/dist/showcase.css +40 -9
  46. package/manifest.json +121 -9
  47. package/package.json +5 -2
  48. package/snippets/accordion-accent.html +1 -1
  49. package/snippets/attachment.html +4 -4
  50. package/snippets/avatar-picker.html +40 -0
  51. package/snippets/barcode.html +20 -0
  52. package/snippets/chat-composer.html +3 -3
  53. package/snippets/data-table.html +51 -76
  54. package/snippets/date-field.html +44 -0
  55. package/snippets/doc-viewer.html +1 -1
  56. package/snippets/emoji-picker.html +1 -1
  57. package/snippets/form-density.html +25 -0
  58. package/snippets/form-section.html +47 -0
  59. package/snippets/gallery.html +25 -0
  60. package/snippets/lazy.html +39 -0
  61. package/snippets/message-thread.html +12 -12
  62. package/snippets/message.html +10 -10
  63. package/snippets/meter-row.html +29 -0
  64. package/snippets/name-card.html +72 -0
  65. package/snippets/page-header.html +1 -1
  66. package/snippets/price.html +25 -0
  67. package/snippets/prose.html +3 -3
  68. package/snippets/quantity.html +12 -0
  69. package/snippets/rating.html +26 -0
  70. package/snippets/ribbon.html +48 -0
  71. package/snippets/sidebar.html +3 -3
  72. package/snippets/spec-list.html +34 -0
  73. package/snippets/stock.html +20 -0
  74. package/snippets/table-actions.html +5 -5
  75. package/snippets/table.html +2 -2
  76. package/snippets/titlebar.html +1 -1
  77. package/snippets/user.html +3 -3
  78. package/dist/parts/app-column-menu.css +0 -85
  79. package/snippets/column-menu.html +0 -38
@@ -1,21 +1,17 @@
1
- <!-- OmniaUI component: data-table - List table from Korrekt and OmniaDesk: search, sort, pages, columns, resize, drag, trash filter and bulk actions. Needs @birdycom/omniaui CSS.
2
- File: packages/ui/snippets/data-table.html | Map: shell -> toolbar (gear, search, pills, view) -> bulk bar -> table -> footer. Behaviour: src/data-table.js
1
+ <!-- OmniaUI component: data-table - List table for business apps: search, sort, pages, trash filter and bulk actions. Needs @birdycom/omniaui CSS.
2
+ Behaviour: data-table.js (npx omniaui copy-js data-table). Webicons: iconify-icon.
3
+ File: packages/ui/snippets/data-table.html | Map: toolbar (list actions, search, trash pills, view, New) -> bulk bar -> table (sort) -> footer. Behaviour: src/data-table.js
3
4
  -->
4
- <div class="oc-data-table oc-column-menu-scope" id="oc-articles" data-page-size="3" data-oc-live="true" style="--oc-data-table-max: 18rem">
5
+ <div class="oc-data-table" id="oc-articles" data-page-size="3" data-oc-live="true" style="--oc-data-table-max: 18rem">
5
6
  <div class="oc-data-table-toolbar">
6
7
  <div class="oc-data-table-heading">
7
8
  <span class="oc-data-table-title">Articles</span>
8
- <button class="oc-btn oc-btn--outline oc-btn--icon oc-btn--sm" type="button" popovertarget="oc-articles-menu" aria-label="Table actions">
9
- <svg viewBox="0 0 16 16" width="16" height="16" aria-hidden="true"><path fill="currentColor" d="M7.2 1.2h1.6l.3 1.5a4 4 0 0 1 1.1.6l1.4-.6 1.1 1.1-.6 1.4c.3.3.5.7.6 1.1l1.5.3v1.6l-1.5.3a4 4 0 0 1-.6 1.1l.6 1.4-1.1 1.1-1.4-.6a4 4 0 0 1-1.1.6l-.3 1.5H7.2l-.3-1.5a4 4 0 0 1-1.1-.6l-1.4.6-1.1-1.1.6-1.4a4 4 0 0 1-.6-1.1L1.8 8.8V7.2l1.5-.3c.1-.4.3-.8.6-1.1l-.6-1.4 1.1-1.1 1.4.6a4 4 0 0 1 1.1-.6l.3-1.5zM8 6.2a1.8 1.8 0 1 0 0 3.6 1.8 1.8 0 0 0 0-3.6z"/></svg>
10
- </button>
11
- <div class="oc-dropdown-menu" id="oc-articles-menu" popover>
12
- <button class="oc-dropdown-item" type="button" data-oc-export>Export CSV</button>
13
- <button class="oc-dropdown-item" type="button" data-oc-import>Import CSV</button>
14
- <input class="oc-data-table-file" type="file" accept=".csv,text/csv" data-oc-file>
9
+ <button class="oc-btn oc-btn--outline oc-btn--icon oc-btn--sm" type="button" popovertarget="oc-articles-menu" aria-label="List actions" title="List actions"><iconify-icon icon="mdi:tune-variant" aria-hidden="true"></iconify-icon></button>
10
+ <div class="oc-dropdown-menu" id="oc-articles-menu" popover="">
11
+ <button class="oc-dropdown-item" type="button" data-oc-export="">Export CSV</button>
15
12
  <div class="oc-dropdown-separator"></div>
16
13
  <button class="oc-dropdown-item" type="button" data-oc-density="comfortable">Comfortable rows</button>
17
14
  <button class="oc-dropdown-item" type="button" data-oc-density="compact">Compact rows</button>
18
- <button class="oc-dropdown-item" type="button" data-oc-reset-widths>Reset column widths</button>
19
15
  </div>
20
16
  </div>
21
17
  <input class="oc-input oc-data-table-search" type="search" placeholder="Search articles..." aria-label="Search articles">
@@ -26,28 +22,14 @@
26
22
  <button class="oc-filter-pill" type="button" data-oc-filter="archived">Archive only</button>
27
23
  </div>
28
24
  <div class="oc-data-table-view" role="group" aria-label="View">
29
- <button class="oc-btn oc-btn--outline oc-btn--sm" type="button" data-oc-view="table" aria-pressed="true">Table</button>
30
- <button class="oc-btn oc-btn--outline oc-btn--sm" type="button" data-oc-view="grid">Cards</button>
25
+ <button class="oc-btn oc-btn--outline oc-btn--icon oc-btn--sm" type="button" data-oc-view="table" aria-pressed="true" aria-label="Table"><iconify-icon icon="mdi:format-list-bulleted" aria-hidden="true"></iconify-icon></button>
26
+ <button class="oc-btn oc-btn--outline oc-btn--icon oc-btn--sm" type="button" data-oc-view="grid" aria-label="Cards"><iconify-icon icon="mdi:view-grid-outline" aria-hidden="true"></iconify-icon></button>
31
27
  </div>
32
- <div class="oc-data-table-actions"><button class="oc-btn oc-btn--sm" type="button">New article</button></div>
33
- <p class="oc-data-table-sort-summary" data-oc-sort-summary role="status"></p>
34
- </div>
35
- <div class="oc-table-toolbar">
36
- <span class="oc-table-toolbar-spacer"></span>
37
- <button class="oc-btn oc-btn--outline oc-btn--sm" type="button" popovertarget="oc-articles-columns">Columns</button>
38
- </div>
39
- <div class="oc-column-menu" id="oc-articles-columns" popover>
40
- <p class="oc-column-menu-title">Visible columns</p>
41
- <form class="oc-column-menu-list">
42
- <label class="oc-column-menu-item"><input type="checkbox" data-col="3" checked> Article ID</label>
43
- <label class="oc-column-menu-item"><input type="checkbox" data-col="4" checked> Name</label>
44
- <label class="oc-column-menu-item"><input type="checkbox" data-col="5" checked> Price</label>
45
- <label class="oc-column-menu-item"><input type="checkbox" data-col="6"> Supplier</label>
46
- <label class="oc-column-menu-item"><input type="checkbox" data-col="7" checked> Status</label>
47
- </form>
28
+ <div class="oc-data-table-actions"><button class="oc-btn oc-btn--sm" type="button"><iconify-icon icon="mdi:plus" aria-hidden="true"></iconify-icon>New article</button></div>
29
+ <p class="oc-data-table-sort-summary" data-oc-sort-summary="" role="status"></p>
48
30
  </div>
49
31
  <div class="oc-data-table-bulk" hidden>
50
- <span data-oc-selected-count>0 selected</span>
32
+ <span data-oc-selected-count="">0 selected</span>
51
33
  <button class="oc-btn oc-btn--outline oc-btn--sm" type="button" data-oc-bulk="export">Export selection</button>
52
34
  <button class="oc-btn oc-btn--outline oc-btn--sm" type="button" data-oc-bulk="duplicate">Duplicate</button>
53
35
  <button class="oc-btn oc-btn--outline oc-btn--sm" type="button" data-oc-bulk="archive">Move to trash</button>
@@ -60,76 +42,69 @@
60
42
  <table class="oc-table oc-data-table-table">
61
43
  <thead>
62
44
  <tr>
63
- <th data-oc-col="select" class="oc-data-table-select"><input class="oc-checkbox" type="checkbox" data-oc-select-all aria-label="Select all"></th>
64
- <th data-oc-col="order"><span class="oc-visually-hidden">Order</span></th>
65
- <th data-oc-col="sku" data-oc-sort="text"><span class="oc-data-table-th"><button class="oc-table-sort" type="button">Article ID</button><span class="oc-data-table-resize" role="separator" aria-orientation="vertical" aria-label="Resize Article ID"></span></span></th>
66
- <th data-oc-col="name" data-oc-sort="text"><span class="oc-data-table-th"><button class="oc-table-sort" type="button">Name</button><span class="oc-data-table-resize" role="separator" aria-orientation="vertical" aria-label="Resize Name"></span></span></th>
67
- <th data-oc-col="price" data-oc-sort="numeric" data-numeric><span class="oc-data-table-th"><button class="oc-table-sort" type="button">Price</button><span class="oc-data-table-resize" role="separator" aria-orientation="vertical" aria-label="Resize Price"></span></span></th>
68
- <th data-oc-col="supplier" data-oc-sort="text"><span class="oc-data-table-th"><button class="oc-table-sort" type="button">Supplier</button><span class="oc-data-table-resize" role="separator" aria-orientation="vertical" aria-label="Resize Supplier"></span></span></th>
45
+ <th data-oc-col="select" class="oc-data-table-select"><input class="oc-checkbox" type="checkbox" data-oc-select-all="" aria-label="Select all"></th>
46
+ <th data-oc-col="sku" data-oc-sort="text" aria-sort="ascending"><span class="oc-data-table-th"><button class="oc-table-sort" type="button">Article ID</button></span></th>
47
+ <th data-oc-col="name" data-oc-sort="text"><span class="oc-data-table-th"><button class="oc-table-sort" type="button">Name</button></span></th>
48
+ <th data-oc-col="price" data-oc-sort="numeric" data-numeric=""><span class="oc-data-table-th"><button class="oc-table-sort" type="button">Price</button></span></th>
49
+ <th data-oc-col="supplier" data-oc-sort="text"><span class="oc-data-table-th"><button class="oc-table-sort" type="button">Supplier</button></span></th>
69
50
  <th data-oc-col="status" data-oc-sort="text"><span class="oc-data-table-th"><button class="oc-table-sort" type="button">Status</button></span></th>
70
- <th data-oc-col="actions"><span class="oc-visually-hidden">Actions</span></th>
51
+ <th data-oc-col="actions" style="width:7.5rem"><span class="oc-data-table-th">Actions</span></th>
71
52
  </tr>
72
53
  </thead>
73
54
  <tbody>
74
- <tr data-oc-row data-oc-key="schar" data-oc-status="active">
75
- <td data-oc-col="select"><input class="oc-checkbox" type="checkbox" data-oc-select aria-label="Select Scharnier"></td>
76
- <td data-oc-col="order" class="oc-sortable-row-grip-cell"><button class="oc-sortable-row-grip" type="button" aria-label="Move Scharnier"></button></td>
55
+ <tr data-oc-row="" data-oc-key="schar" data-oc-status="active">
56
+ <td data-oc-col="select"><input class="oc-checkbox" type="checkbox" data-oc-select="" aria-label="Select Scharnier"></td>
77
57
  <td data-oc-col="sku">SET-SCHAR-1105C-ONS</td>
78
58
  <td data-oc-col="name">Scharnier 1105</td>
79
- <td data-oc-col="price" data-numeric data-oc-value="5.15">5,15</td>
80
- <td data-oc-col="supplier">Van Hoecke</td>
59
+ <td data-oc-col="price" data-numeric="" data-oc-value="5.15">5,15</td>
60
+ <td data-oc-col="supplier">Supplier 1</td>
81
61
  <td data-oc-col="status"><span class="oc-badge oc-badge--success">Active</span></td>
82
- <td data-oc-col="actions" class="oc-table-actions"><button class="oc-table-row-action" type="button">Edit</button></td>
62
+ <td data-oc-col="actions"><button class="oc-btn oc-btn--soft-primary oc-btn--icon oc-btn--sm" type="button" aria-label="Edit" title="Edit"><iconify-icon icon="mdi:pencil-outline" aria-hidden="true"></iconify-icon></button></td>
83
63
  </tr>
84
- <tr data-oc-row data-oc-key="greep" data-oc-status="active">
85
- <td data-oc-col="select"><input class="oc-checkbox" type="checkbox" data-oc-select aria-label="Select Greep"></td>
86
- <td data-oc-col="order" class="oc-sortable-row-grip-cell"><button class="oc-sortable-row-grip" type="button" aria-label="Move Greep"></button></td>
64
+ <tr data-oc-row="" data-oc-key="greep" data-oc-status="active">
65
+ <td data-oc-col="select"><input class="oc-checkbox" type="checkbox" data-oc-select="" aria-label="Select Greep"></td>
87
66
  <td data-oc-col="sku">SET-GREEP-40</td>
88
67
  <td data-oc-col="name">Greep 40</td>
89
- <td data-oc-col="price" data-numeric data-oc-value="12.4">12,40</td>
90
- <td data-oc-col="supplier">Van Hoecke</td>
68
+ <td data-oc-col="price" data-numeric="" data-oc-value="12.4">12,40</td>
69
+ <td data-oc-col="supplier">Supplier 1</td>
91
70
  <td data-oc-col="status"><span class="oc-badge oc-badge--success">Active</span></td>
92
- <td data-oc-col="actions" class="oc-table-actions"><button class="oc-table-row-action" type="button">Edit</button></td>
71
+ <td data-oc-col="actions"><button class="oc-btn oc-btn--soft-primary oc-btn--icon oc-btn--sm" type="button" aria-label="Edit" title="Edit"><iconify-icon icon="mdi:pencil-outline" aria-hidden="true"></iconify-icon></button></td>
93
72
  </tr>
94
- <tr data-oc-row data-oc-key="plaat" data-oc-status="active">
95
- <td data-oc-col="select"><input class="oc-checkbox" type="checkbox" data-oc-select aria-label="Select Plaat"></td>
96
- <td data-oc-col="order" class="oc-sortable-row-grip-cell"><button class="oc-sortable-row-grip" type="button" aria-label="Move Plaat"></button></td>
73
+ <tr data-oc-row="" data-oc-key="plaat" data-oc-status="active">
74
+ <td data-oc-col="select"><input class="oc-checkbox" type="checkbox" data-oc-select="" aria-label="Select Plaat"></td>
97
75
  <td data-oc-col="sku">PLAAT-18-WIT</td>
98
76
  <td data-oc-col="name">Plaat 18 wit</td>
99
- <td data-oc-col="price" data-numeric data-oc-value="28">28,00</td>
100
- <td data-oc-col="supplier">Egger</td>
77
+ <td data-oc-col="price" data-numeric="" data-oc-value="28">28,00</td>
78
+ <td data-oc-col="supplier">Supplier 2</td>
101
79
  <td data-oc-col="status"><span class="oc-badge oc-badge--success">Active</span></td>
102
- <td data-oc-col="actions" class="oc-table-actions"><button class="oc-table-row-action" type="button">Edit</button></td>
80
+ <td data-oc-col="actions"><button class="oc-btn oc-btn--soft-primary oc-btn--icon oc-btn--sm" type="button" aria-label="Edit" title="Edit"><iconify-icon icon="mdi:pencil-outline" aria-hidden="true"></iconify-icon></button></td>
103
81
  </tr>
104
- <tr data-oc-row data-oc-key="led" data-oc-status="active">
105
- <td data-oc-col="select"><input class="oc-checkbox" type="checkbox" data-oc-select aria-label="Select LED"></td>
106
- <td data-oc-col="order" class="oc-sortable-row-grip-cell"><button class="oc-sortable-row-grip" type="button" aria-label="Move LED"></button></td>
82
+ <tr data-oc-row="" data-oc-key="led" data-oc-status="active">
83
+ <td data-oc-col="select"><input class="oc-checkbox" type="checkbox" data-oc-select="" aria-label="Select LED"></td>
107
84
  <td data-oc-col="sku">LED-STRIP-2M</td>
108
85
  <td data-oc-col="name">LED strip</td>
109
- <td data-oc-col="price" data-numeric data-oc-value="16.9">16,90</td>
110
- <td data-oc-col="supplier">Egger</td>
86
+ <td data-oc-col="price" data-numeric="" data-oc-value="16.9">16,90</td>
87
+ <td data-oc-col="supplier">Supplier 2</td>
111
88
  <td data-oc-col="status"><span class="oc-badge oc-badge--success">Active</span></td>
112
- <td data-oc-col="actions" class="oc-table-actions"><button class="oc-table-row-action" type="button">Edit</button></td>
89
+ <td data-oc-col="actions"><button class="oc-btn oc-btn--soft-primary oc-btn--icon oc-btn--sm" type="button" aria-label="Edit" title="Edit"><iconify-icon icon="mdi:pencil-outline" aria-hidden="true"></iconify-icon></button></td>
113
90
  </tr>
114
- <tr data-oc-row data-oc-key="schroef" data-oc-status="deleted">
115
- <td data-oc-col="select"><input class="oc-checkbox" type="checkbox" data-oc-select aria-label="Select Schroef"></td>
116
- <td data-oc-col="order" class="oc-sortable-row-grip-cell"><button class="oc-sortable-row-grip" type="button" aria-label="Move Schroef"></button></td>
91
+ <tr data-oc-row="" data-oc-key="schroef" data-oc-status="deleted">
92
+ <td data-oc-col="select"><input class="oc-checkbox" type="checkbox" data-oc-select="" aria-label="Select Schroef"></td>
117
93
  <td data-oc-col="sku">SCHROEF-4X40</td>
118
94
  <td data-oc-col="name">Schroef 4x40</td>
119
- <td data-oc-col="price" data-numeric data-oc-value="0.08">0,08</td>
120
- <td data-oc-col="supplier">Van Hoecke</td>
95
+ <td data-oc-col="price" data-numeric="" data-oc-value="0.08">0,08</td>
96
+ <td data-oc-col="supplier">Supplier 1</td>
121
97
  <td data-oc-col="status"><span class="oc-badge oc-badge--secondary">Deleted</span></td>
122
- <td data-oc-col="actions" class="oc-table-actions"><button class="oc-table-row-action" type="button">Edit</button></td>
98
+ <td data-oc-col="actions"><button class="oc-btn oc-btn--soft-primary oc-btn--icon oc-btn--sm" type="button" aria-label="Edit" title="Edit"><iconify-icon icon="mdi:pencil-outline" aria-hidden="true"></iconify-icon></button></td>
123
99
  </tr>
124
- <tr data-oc-row data-oc-key="kast" data-oc-status="archived">
125
- <td data-oc-col="select"><input class="oc-checkbox" type="checkbox" data-oc-select aria-label="Select Kast"></td>
126
- <td data-oc-col="order" class="oc-sortable-row-grip-cell"><button class="oc-sortable-row-grip" type="button" aria-label="Move Kast"></button></td>
100
+ <tr data-oc-row="" data-oc-key="kast" data-oc-status="archived">
101
+ <td data-oc-col="select"><input class="oc-checkbox" type="checkbox" data-oc-select="" aria-label="Select Kast"></td>
127
102
  <td data-oc-col="sku">ARCH-KAST-60</td>
128
103
  <td data-oc-col="name">Kast 60</td>
129
- <td data-oc-col="price" data-numeric data-oc-value="240">240,00</td>
130
- <td data-oc-col="supplier">Egger</td>
104
+ <td data-oc-col="price" data-numeric="" data-oc-value="240">240,00</td>
105
+ <td data-oc-col="supplier">Supplier 2</td>
131
106
  <td data-oc-col="status"><span class="oc-badge oc-badge--secondary">Archived</span></td>
132
- <td data-oc-col="actions" class="oc-table-actions"><button class="oc-table-row-action" type="button">Edit</button></td>
107
+ <td data-oc-col="actions"><button class="oc-btn oc-btn--soft-primary oc-btn--icon oc-btn--sm" type="button" aria-label="Edit" title="Edit"><iconify-icon icon="mdi:pencil-outline" aria-hidden="true"></iconify-icon></button></td>
133
108
  </tr>
134
109
  </tbody>
135
110
  </table>
@@ -137,15 +112,15 @@
137
112
  <p class="oc-data-table-empty" hidden>No results</p>
138
113
  </div>
139
114
  <div class="oc-data-table-footer">
140
- <p class="oc-data-table-summary" data-oc-summary>Showing 1–3 of 4</p>
115
+ <p class="oc-data-table-summary" data-oc-summary="">Showing 1–3 of 4</p>
141
116
  <label class="oc-data-table-per-page">Rows per page
142
- <select class="oc-select" data-oc-page-size aria-label="Rows per page">
117
+ <select class="oc-select" data-oc-page-size="" aria-label="Rows per page">
143
118
  <option value="3" selected>3</option>
144
119
  <option value="5">5</option>
145
120
  <option value="10">10</option>
146
121
  <option value="15">15</option>
147
122
  </select>
148
123
  </label>
149
- <nav class="oc-data-table-pager" data-oc-pager aria-label="Pagination"></nav>
124
+ <nav class="oc-data-table-pager" data-oc-pager="" aria-label="Pagination"></nav>
150
125
  </div>
151
126
  </div>
@@ -0,0 +1,44 @@
1
+ <!-- OmniaUI component: date-field - Native date input with a calendar icon zone and the ISO week (Week 45) next to it. Needs @birdycom/omniaui CSS.
2
+ File: packages/ui/snippets/date-field.html | Map: date field demo markup. Behaviour: form-extras.js.
3
+ Class API (modifiers are extra classes / attributes on the same element):
4
+ .oc-date-field: The frame around icon, input and week; focus ring on the frame.
5
+ .oc-date-field__icon: The calendar icon zone with a line after it.
6
+ input.oc-date-field__input[type=date]: The native date input (value YYYY-MM-DD).
7
+ output.oc-date-field__week: With form-extras.js: the ISO week of the date, "Week 45". Template: data-oc-week="W{week} · {year}". Hidden without a date.
8
+ .oc-date-field--sm: 2rem high (also inside .oc-density-compact).
9
+ isoWeek(date): Exported from form-extras.js: { week, year } after ISO 8601 (week 1 holds the first Thursday).
10
+ -->
11
+ <div style="display:flex;flex-wrap:wrap;gap:1.5rem;align-items:end">
12
+ <div class="oc-field">
13
+ <label class="oc-field-label" for="oc-date-delivery">Delivery date</label>
14
+ <div class="oc-date-field">
15
+ <span class="oc-date-field__icon"><iconify-icon icon="mdi:calendar-blank-outline" aria-hidden="true"></iconify-icon></span>
16
+ <input class="oc-date-field__input" id="oc-date-delivery" type="date" value="2026-11-12">
17
+ <output class="oc-date-field__week" for="oc-date-delivery"></output>
18
+ </div>
19
+ </div>
20
+ <div class="oc-field">
21
+ <label class="oc-field-label" for="oc-date-start">Start of works</label>
22
+ <div class="oc-date-field">
23
+ <span class="oc-date-field__icon"><iconify-icon icon="mdi:calendar-blank-outline" aria-hidden="true"></iconify-icon></span>
24
+ <input class="oc-date-field__input" id="oc-date-start" type="date" value="2027-01-01">
25
+ <output class="oc-date-field__week" for="oc-date-start" data-oc-week="Week {week} · {year}"></output>
26
+ </div>
27
+ </div>
28
+ <div class="oc-field">
29
+ <label class="oc-field-label" for="oc-date-plain">Without week</label>
30
+ <div class="oc-date-field">
31
+ <span class="oc-date-field__icon"><iconify-icon icon="mdi:calendar-blank-outline" aria-hidden="true"></iconify-icon></span>
32
+ <input class="oc-date-field__input" id="oc-date-plain" type="date" value="2026-12-24">
33
+
34
+ </div>
35
+ </div>
36
+ <div class="oc-field">
37
+ <label class="oc-field-label" for="oc-date-small">Small</label>
38
+ <div class="oc-date-field oc-date-field--sm">
39
+ <span class="oc-date-field__icon"><iconify-icon icon="mdi:calendar-blank-outline" aria-hidden="true"></iconify-icon></span>
40
+ <input class="oc-date-field__input" id="oc-date-small" type="date" value="2026-11-03">
41
+ <output class="oc-date-field__week" for="oc-date-small"></output>
42
+ </div>
43
+ </div>
44
+ </div>
@@ -38,7 +38,7 @@
38
38
  <div class="oc-doc-viewer-dialog__bar">
39
39
  <h2 class="oc-doc-viewer-dialog__title" id="oc-doc-viewer-demo-pdf-title">Brochure 2026</h2>
40
40
  <div class="oc-doc-viewer-dialog__actions">
41
- <a class="oc-btn oc-btn--outline oc-btn--sm" href="#brochure.pdf" download>Download</a>
41
+ <a class="oc-btn oc-btn--outline oc-btn--sm" href="#brochure.pdf">Download</a>
42
42
  <button type="button" class="oc-doc-viewer-dialog__close" command="close" commandfor="oc-doc-viewer-demo-pdf" aria-label="Close">&#10005;</button>
43
43
  </div>
44
44
  </div>
@@ -7,7 +7,7 @@
7
7
  -->
8
8
  <div style="display:flex;gap:0.5rem;align-items:center">
9
9
  <input class="oc-input" id="oc-emoji-field" placeholder="Say something nice" style="inline-size:16rem">
10
- <button type="button" class="oc-emoji-picker__trigger" popovertarget="oc-emoji-demo" aria-label="Insert emoji">&#128578;</button>
10
+ <button type="button" class="oc-emoji-picker__trigger" popovertarget="oc-emoji-demo" 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>
11
11
  </div>
12
12
  <div class="oc-emoji-picker" id="oc-emoji-demo" popover data-oc-emoji-target="#oc-emoji-field" aria-label="Emoji">
13
13
  <p class="oc-emoji-picker__label">Smileys</p>
@@ -0,0 +1,25 @@
1
+ <!-- OmniaUI component: form-density - Compact forms: .oc-density-compact makes every control in it 2rem high instead of 2.5rem. Needs @birdycom/omniaui CSS.
2
+ File: packages/ui/snippets/form-density.html | Map: form density demo markup.
3
+ Class API (modifiers are extra classes / attributes on the same element):
4
+ .oc-density-compact: On a form or wrapper: controls inside are 2rem high, labels and gaps a step smaller.
5
+ -->
6
+ <div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(16rem,1fr));gap:1rem;inline-size:100%">
7
+ <form class="" style="display:grid;gap:0.75rem;padding:1rem;border:1px solid var(--oc-border);border-radius:var(--oc-radius)" onsubmit="event.preventDefault()">
8
+ <p style="margin:0;font-weight:600">Standard (2.5rem)</p>
9
+ <div class="oc-field"><label class="oc-field-label" for="d-desc">Description</label><input class="oc-input" id="d-desc" value="Article 1"></div>
10
+ <div style="display:grid;grid-template-columns:1fr 1fr;gap:0.75rem">
11
+ <div class="oc-field"><label class="oc-field-label" for="d-qty">Quantity</label><input class="oc-input" id="d-qty" value="2"></div>
12
+ <div class="oc-field"><label class="oc-field-label" for="d-vat">VAT</label><select class="oc-select" id="d-vat"><option>21%</option><option>6%</option></select></div>
13
+ </div>
14
+ <div style="display:flex;gap:0.5rem"><button class="oc-btn oc-btn--sm" type="submit"><iconify-icon icon="mdi:content-save-outline" aria-hidden="true"></iconify-icon>Save</button><button class="oc-btn oc-btn--outline oc-btn--sm" type="button">Cancel</button></div>
15
+ </form>
16
+ <form class="oc-density-compact" style="display:grid;gap:0.75rem;padding:1rem;border:1px solid var(--oc-border);border-radius:var(--oc-radius)" onsubmit="event.preventDefault()">
17
+ <p style="margin:0;font-weight:600">Compact (2rem)</p>
18
+ <div class="oc-field"><label class="oc-field-label" for="oc-density-compact-desc">Description</label><input class="oc-input" id="oc-density-compact-desc" value="Article 1"></div>
19
+ <div style="display:grid;grid-template-columns:1fr 1fr;gap:0.75rem">
20
+ <div class="oc-field"><label class="oc-field-label" for="oc-density-compact-qty">Quantity</label><input class="oc-input" id="oc-density-compact-qty" value="2"></div>
21
+ <div class="oc-field"><label class="oc-field-label" for="oc-density-compact-vat">VAT</label><select class="oc-select" id="oc-density-compact-vat"><option>21%</option><option>6%</option></select></div>
22
+ </div>
23
+ <div style="display:flex;gap:0.5rem"><button class="oc-btn oc-btn--sm" type="submit"><iconify-icon icon="mdi:content-save-outline" aria-hidden="true"></iconify-icon>Save</button><button class="oc-btn oc-btn--outline oc-btn--sm" type="button">Cancel</button></div>
24
+ </form>
25
+ </div>
@@ -0,0 +1,47 @@
1
+ <!-- OmniaUI component: form-section - Collapsible part of a long form with an icon, title, hint and status; red edge while a field inside is invalid. Needs @birdycom/omniaui CSS.
2
+ File: packages/ui/snippets/form-section.html | Map: form section demo markup.
3
+ Class API (modifiers are extra classes / attributes on the same element):
4
+ .oc-form-section: A <details>; same name on siblings = one open at a time.
5
+ .oc-form-section__summary: Icon, heading (title + hint), status and a chevron.
6
+ .oc-form-section__icon: The webicon of the section in a tinted square.
7
+ .oc-form-section__status: Free slot: a badge (Complete, 1 error), a count …
8
+ .oc-form-section__body: The fields in a responsive grid; .oc-form-section__wide spans the full row.
9
+ :user-invalid / [aria-invalid]: A field that fails validation after the user touched it colors the section red.
10
+ -->
11
+ <form style="inline-size:min(100%,44rem)" onsubmit="event.preventDefault()">
12
+ <details class="oc-form-section" name="contact" open>
13
+ <summary class="oc-form-section__summary">
14
+ <span class="oc-form-section__icon"><iconify-icon icon="mdi:card-account-details-outline" aria-hidden="true"></iconify-icon></span>
15
+ <span class="oc-form-section__heading"><span class="oc-form-section__title">General</span><span class="oc-form-section__hint">Name, VAT number and type</span></span>
16
+ <span class="oc-form-section__status"><span class="oc-badge oc-badge--success">Complete</span></span>
17
+ </summary>
18
+ <div class="oc-form-section__body">
19
+ <div class="oc-field"><label class="oc-field-label" for="fs-name">Name</label><input class="oc-input" id="fs-name" type="text" value="Company 1"></div>
20
+ <div class="oc-field"><label class="oc-field-label" for="fs-vat">VAT number</label><input class="oc-input" id="fs-vat" type="text" value="BE0000.000.001"></div>
21
+ <div class="oc-field"><label class="oc-field-label" for="fs-type">Type</label><input class="oc-input" id="fs-type" type="text" value="Company"></div>
22
+ </div>
23
+ </details>
24
+ <details class="oc-form-section" name="contact">
25
+ <summary class="oc-form-section__summary">
26
+ <span class="oc-form-section__icon"><iconify-icon icon="mdi:map-marker-outline" aria-hidden="true"></iconify-icon></span>
27
+ <span class="oc-form-section__heading"><span class="oc-form-section__title">Address</span><span class="oc-form-section__hint">Invoice and delivery address</span></span>
28
+ <span class="oc-form-section__status"></span>
29
+ </summary>
30
+ <div class="oc-form-section__body">
31
+ <div class="oc-field oc-form-section__wide"><label class="oc-field-label" for="fs-street">Street and number</label><input class="oc-input" id="fs-street" type="text" value="Company address 1"></div>
32
+ <div class="oc-field"><label class="oc-field-label" for="fs-zip">Postal code</label><input class="oc-input" id="fs-zip" type="text" value="1000"></div>
33
+ <div class="oc-field"><label class="oc-field-label" for="fs-city">City</label><input class="oc-input" id="fs-city" type="text" value="City 1"></div>
34
+ </div>
35
+ </details>
36
+ <details class="oc-form-section" name="contact">
37
+ <summary class="oc-form-section__summary">
38
+ <span class="oc-form-section__icon"><iconify-icon icon="mdi:email-outline" aria-hidden="true"></iconify-icon></span>
39
+ <span class="oc-form-section__heading"><span class="oc-form-section__title">Contact</span><span class="oc-form-section__hint">E-mail and phone</span></span>
40
+ <span class="oc-form-section__status"><span class="oc-badge oc-badge--destructive">1 error</span></span>
41
+ </summary>
42
+ <div class="oc-form-section__body">
43
+ <div class="oc-field"><label class="oc-field-label" for="fs-mail">E-mail</label><input class="oc-input" id="fs-mail" type="email" value="info@company1" required></div>
44
+ <div class="oc-field"><label class="oc-field-label" for="fs-phone">Phone</label><input class="oc-input" id="fs-phone" type="tel" value="+32 012 34 56 71"></div>
45
+ </div>
46
+ </details>
47
+ </form>
@@ -0,0 +1,25 @@
1
+ <!-- OmniaUI component: gallery - Product photos with thumbnails: one large photo and a row (or column) of thumbnails. No JavaScript. Needs @birdycom/omniaui CSS.
2
+ File: packages/ui/snippets/gallery.html | Map: gallery.
3
+ Class API (modifiers are extra classes / attributes on the same element):
4
+ .oc-gallery: The gallery (a container): __stage with one figure.oc-gallery__slide per photo, then __thumbs.
5
+ fieldset.oc-gallery__thumbs: The thumbnails: one label.oc-gallery__thumb per photo with a radio (same name) and an image with alt text. The first photo shows when none is checked.
6
+ .oc-gallery__badge: A badge on the photo ("-20%", "New").
7
+ .oc-gallery--side: Thumbnails in a column on the left once the gallery is 32rem wide or more.
8
+ --oc-gallery-ratio / --oc-gallery-fit / --oc-gallery-thumb: Photo ratio (default 4 / 3), contain or cover, thumbnail size (4rem).
9
+ -->
10
+ <div class="oc-gallery oc-gallery--side" style="inline-size:min(100%,34rem)">
11
+ <div class="oc-gallery__stage">
12
+ <span class="oc-badge oc-badge--destructive oc-gallery__badge">-20%</span>
13
+ <figure class="oc-gallery__slide"><img src="/img/shop/product-1-front.svg" alt="Product 1, front" width="800" height="600"></figure>
14
+ <figure class="oc-gallery__slide"><img src="/img/shop/product-1-angle.svg" alt="Product 1, from the side" width="800" height="600" loading="lazy"></figure>
15
+ <figure class="oc-gallery__slide"><img src="/img/shop/product-1-detail.svg" alt="Product 1, the shade from below" width="800" height="600" loading="lazy"></figure>
16
+ <figure class="oc-gallery__slide"><img src="/img/shop/product-1-box.svg" alt="Product 1, in its box" width="800" height="600" loading="lazy"></figure>
17
+ </div>
18
+ <fieldset class="oc-gallery__thumbs">
19
+ <legend>Photos of Product 1</legend>
20
+ <label class="oc-gallery__thumb"><input type="radio" name="oc-gallery-demo" checked><img src="/img/shop/product-1-front.svg" alt="Front"></label>
21
+ <label class="oc-gallery__thumb"><input type="radio" name="oc-gallery-demo"><img src="/img/shop/product-1-angle.svg" alt="Side"></label>
22
+ <label class="oc-gallery__thumb"><input type="radio" name="oc-gallery-demo"><img src="/img/shop/product-1-detail.svg" alt="Shade from below"></label>
23
+ <label class="oc-gallery__thumb"><input type="radio" name="oc-gallery-demo"><img src="/img/shop/product-1-box.svg" alt="In its box"></label>
24
+ </fieldset>
25
+ </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="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="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="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="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="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="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="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>