@birdycom/omniaui 0.11.0 → 0.11.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (214) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +21 -21
  3. package/bin/lib/add.mjs +126 -126
  4. package/bin/lib/catalog.mjs +169 -169
  5. package/bin/lib/project.mjs +90 -90
  6. package/bin/omniaui.mjs +69 -69
  7. package/dist/code-block.css +25 -25
  8. package/dist/components-extra.css +916 -914
  9. package/dist/components.css +6559 -6469
  10. package/dist/components.min.css +1 -1
  11. package/dist/data-table.d.ts +9 -9
  12. package/dist/data-table.js +505 -505
  13. package/dist/docs-ui.css +267 -265
  14. package/dist/oc-theme.css +69 -69
  15. package/dist/parts/app-accordion-accent.css +60 -60
  16. package/dist/parts/app-alpha-tabs.css +68 -68
  17. package/dist/parts/app-busy-overlay.css +25 -25
  18. package/dist/parts/app-column-menu.css +85 -85
  19. package/dist/parts/app-confirm-dialog.css +70 -70
  20. package/dist/parts/app-cookie-consent.css +63 -63
  21. package/dist/parts/app-data-table.css +174 -174
  22. package/dist/parts/app-greeting.css +47 -47
  23. package/dist/parts/app-list-toolbar.css +81 -81
  24. package/dist/parts/app-page-header.css +54 -54
  25. package/dist/parts/app-severity-card.css +91 -91
  26. package/dist/parts/app-sidebar-dark.css +15 -15
  27. package/dist/parts/app-sortable-row.css +52 -52
  28. package/dist/parts/app-stat-card.css +68 -68
  29. package/dist/parts/app-table-actions.css +71 -71
  30. package/dist/parts/app-table-compact.css +54 -54
  31. package/dist/parts/app-top-progress.css +68 -68
  32. package/dist/parts/app-tree.css +104 -104
  33. package/dist/parts/app-upgrade-banner.css +90 -90
  34. package/dist/parts/app-version-banner.css +80 -80
  35. package/dist/parts/data-chart-line.css +167 -167
  36. package/dist/parts/forms-affix-input.css +75 -75
  37. package/dist/parts/forms-barcode-input.css +75 -75
  38. package/dist/parts/forms-chip-filter.css +91 -91
  39. package/dist/parts/forms-color-select.css +97 -89
  40. package/dist/parts/forms-decimal-input.css +51 -51
  41. package/dist/parts/forms-filter-counts.css +94 -94
  42. package/dist/parts/forms-language-select.css +89 -76
  43. package/dist/parts/forms-number-input.css +98 -95
  44. package/dist/parts/forms-password-requirements.css +55 -55
  45. package/dist/parts/forms-phone-input.css +85 -85
  46. package/dist/parts/forms-time-input.css +74 -74
  47. package/dist/parts/forms-toggle-field.css +69 -69
  48. package/dist/parts/media-art.css +21 -21
  49. package/dist/parts/media-attachment.css +160 -160
  50. package/dist/parts/media-browser-frame.css +73 -73
  51. package/dist/parts/media-card.css +83 -83
  52. package/dist/parts/media-chat-composer.css +90 -90
  53. package/dist/parts/media-doc-viewer.css +151 -151
  54. package/dist/parts/media-emoji-picker.css +88 -88
  55. package/dist/parts/media-entity-card.css +52 -52
  56. package/dist/parts/media-flip-card.css +78 -78
  57. package/dist/parts/media-image-zoom.css +68 -68
  58. package/dist/parts/media-lightbox.css +131 -131
  59. package/dist/parts/media-message-thread.css +136 -136
  60. package/dist/parts/media-message.css +160 -160
  61. package/dist/parts/media-row.css +78 -78
  62. package/dist/parts/media-stack-card.css +82 -82
  63. package/dist/parts/media-terminal-log.css +76 -76
  64. package/dist/parts/media-thumb.css +71 -71
  65. package/dist/parts/site-fact-list.css +25 -25
  66. package/dist/parts/site-link-arrow.css +34 -34
  67. package/dist/parts/site-marquee.css +34 -34
  68. package/dist/parts/site-next-teaser.css +75 -75
  69. package/dist/parts/site-price-card.css +91 -75
  70. package/dist/parts/site-product-mark.css +66 -66
  71. package/dist/parts/site-project-card.css +111 -111
  72. package/dist/parts/site-prose.css +124 -124
  73. package/dist/parts/site-stack-list.css +48 -48
  74. package/dist/parts/site-timeline.css +54 -54
  75. package/dist/showcase.css +404 -404
  76. package/package.json +69 -69
  77. package/snippets/accordion-accent.html +24 -24
  78. package/snippets/accordion.html +11 -11
  79. package/snippets/affix-input.html +30 -30
  80. package/snippets/alert-dialog.html +22 -22
  81. package/snippets/alert.html +5 -5
  82. package/snippets/alpha-tabs.html +37 -37
  83. package/snippets/aspect-ratio.html +15 -15
  84. package/snippets/attachment.html +43 -43
  85. package/snippets/avatar.html +6 -6
  86. package/snippets/back-link.html +5 -5
  87. package/snippets/badge.html +5 -5
  88. package/snippets/barcode-input.html +18 -18
  89. package/snippets/breadcrumb.html +6 -6
  90. package/snippets/browser-frame.html +18 -18
  91. package/snippets/busy-overlay.html +31 -31
  92. package/snippets/button-group.html +21 -21
  93. package/snippets/button.html +8 -8
  94. package/snippets/calendar.html +43 -43
  95. package/snippets/card.html +17 -17
  96. package/snippets/carousel.html +21 -21
  97. package/snippets/chart-line.html +46 -46
  98. package/snippets/chart.html +27 -27
  99. package/snippets/chat-composer.html +21 -21
  100. package/snippets/checkbox.html +5 -5
  101. package/snippets/checklist.html +23 -23
  102. package/snippets/chip-filter.html +14 -14
  103. package/snippets/code-window.html +20 -20
  104. package/snippets/collapsible.html +19 -19
  105. package/snippets/color-field.html +13 -13
  106. package/snippets/color-select.html +18 -18
  107. package/snippets/column-menu.html +38 -38
  108. package/snippets/combobox.html +19 -19
  109. package/snippets/command.html +24 -24
  110. package/snippets/confirm-dialog.html +32 -32
  111. package/snippets/context-menu.html +25 -25
  112. package/snippets/cookie-consent.html +70 -70
  113. package/snippets/copy-field.html +19 -19
  114. package/snippets/counter.html +2 -2
  115. package/snippets/data-table.html +151 -151
  116. package/snippets/date-picker.html +32 -32
  117. package/snippets/decimal-input.html +20 -20
  118. package/snippets/definition-list.html +20 -20
  119. package/snippets/demo-panel.html +18 -18
  120. package/snippets/doc-viewer.html +58 -58
  121. package/snippets/drawer.html +30 -30
  122. package/snippets/dropdown-menu.html +27 -27
  123. package/snippets/dropdown.html +9 -9
  124. package/snippets/dropzone.html +13 -13
  125. package/snippets/emoji-picker.html +51 -51
  126. package/snippets/empty-state.html +17 -17
  127. package/snippets/entity-card.html +26 -26
  128. package/snippets/expandable-table.html +26 -26
  129. package/snippets/fact-list.html +14 -14
  130. package/snippets/filter-counts.html +30 -30
  131. package/snippets/flip-card.html +22 -22
  132. package/snippets/form-field.html +6 -6
  133. package/snippets/greeting.html +22 -22
  134. package/snippets/heading.html +14 -14
  135. package/snippets/hover-card.html +18 -18
  136. package/snippets/image-zoom.html +30 -30
  137. package/snippets/input-group.html +10 -10
  138. package/snippets/input.html +5 -5
  139. package/snippets/item.html +26 -26
  140. package/snippets/kbd.html +13 -13
  141. package/snippets/label.html +9 -9
  142. package/snippets/language-select.html +26 -26
  143. package/snippets/launcher-card.html +14 -14
  144. package/snippets/lightbox.html +50 -50
  145. package/snippets/link-arrow.html +10 -10
  146. package/snippets/list-toolbar.html +33 -33
  147. package/snippets/marquee.html +15 -15
  148. package/snippets/media-card.html +28 -28
  149. package/snippets/media-row.html +21 -21
  150. package/snippets/media-thumb.html +12 -12
  151. package/snippets/menubar.html +30 -30
  152. package/snippets/message-thread.html +123 -123
  153. package/snippets/message.html +51 -51
  154. package/snippets/modal.html +15 -15
  155. package/snippets/native-select.html +15 -15
  156. package/snippets/navmenu.html +23 -23
  157. package/snippets/next-teaser.html +15 -15
  158. package/snippets/number-input.html +27 -27
  159. package/snippets/otp-input.html +9 -9
  160. package/snippets/page-header.html +24 -24
  161. package/snippets/pagination.html +6 -6
  162. package/snippets/password-input.html +24 -24
  163. package/snippets/password-requirements.html +30 -30
  164. package/snippets/phone-input.html +22 -22
  165. package/snippets/popover.html +15 -15
  166. package/snippets/price-card.html +34 -34
  167. package/snippets/product-mark.html +13 -13
  168. package/snippets/progress.html +4 -4
  169. package/snippets/project-card.html +23 -23
  170. package/snippets/prose.html +54 -54
  171. package/snippets/radio.html +17 -17
  172. package/snippets/recovery-codes.html +20 -20
  173. package/snippets/resizable.html +16 -16
  174. package/snippets/scroll-area.html +20 -20
  175. package/snippets/search.html +8 -8
  176. package/snippets/segmented.html +11 -11
  177. package/snippets/select.html +7 -7
  178. package/snippets/separator.html +15 -15
  179. package/snippets/severity-card.html +35 -35
  180. package/snippets/sheet.html +32 -32
  181. package/snippets/sidebar-docs.html +24 -24
  182. package/snippets/sidebar.html +55 -55
  183. package/snippets/site-footer.html +6 -6
  184. package/snippets/site-header.html +26 -26
  185. package/snippets/skeleton.html +4 -4
  186. package/snippets/slider.html +17 -17
  187. package/snippets/sortable-row.html +31 -31
  188. package/snippets/spinner.html +14 -14
  189. package/snippets/stack-card.html +17 -17
  190. package/snippets/stack-list.html +16 -16
  191. package/snippets/stat-card.html +24 -24
  192. package/snippets/stepper.html +13 -13
  193. package/snippets/switch.html +6 -6
  194. package/snippets/table-actions.html +39 -39
  195. package/snippets/table-compact.html +24 -24
  196. package/snippets/table.html +29 -29
  197. package/snippets/tabs.html +9 -9
  198. package/snippets/tag-input.html +60 -17
  199. package/snippets/terminal-log.html +23 -23
  200. package/snippets/textarea.html +3 -3
  201. package/snippets/theme-switch.html +6 -6
  202. package/snippets/time-input.html +26 -26
  203. package/snippets/timeline.html +28 -28
  204. package/snippets/toast-stack.html +10 -10
  205. package/snippets/toast.html +36 -36
  206. package/snippets/toc.html +13 -13
  207. package/snippets/toggle-field.html +20 -20
  208. package/snippets/toggle.html +22 -22
  209. package/snippets/tooltip.html +4 -4
  210. package/snippets/top-progress.html +12 -12
  211. package/snippets/tree.html +38 -38
  212. package/snippets/upgrade-banner.html +28 -28
  213. package/snippets/user.html +15 -15
  214. package/snippets/version-banner.html +15 -15
@@ -1,25 +1,25 @@
1
- /* File: packages/ui/src/parts/site-fact-list.css
2
- Map: plain -> compact -> stacked -> accent values -> narrow screens
3
- Fact list component: key / value product facts (the marketing sibling of the definition list).
4
- The base .oc-fact-list (card with <div><dt><dd> rows) lives in showcase.css. This part ADDS modifiers, plus one safe fix: rows may wrap in very narrow containers. */
5
-
6
- /* Plain: no card, only lines between the rows. */
7
- .oc-fact-list--plain {
8
- border: 0;
9
- border-radius: 0;
10
- background: none;
11
- }
12
- .oc-fact-list--plain > div { padding-inline: 0; }
13
-
14
- /* Compact rows (sidebars, small cards). */
15
- .oc-fact-list--compact > div { padding-block: 0.6rem; font-size: 0.9rem; }
16
-
17
- /* Stacked: the value goes below the label (long values). */
18
- .oc-fact-list--stacked > div { flex-direction: column; gap: 0.2rem; }
19
- .oc-fact-list--stacked dd { text-align: start; }
20
-
21
- /* Values in the accent color. */
22
- .oc-fact-list--accent dd { color: var(--oc-accent-from); }
23
-
24
- /* Very narrow containers: wrap instead of squeezing label and value together. */
25
- .oc-fact-list > div { flex-wrap: wrap; }
1
+ /* File: packages/ui/src/parts/site-fact-list.css
2
+ Map: plain -> compact -> stacked -> accent values -> narrow screens
3
+ Fact list component: key / value product facts (the marketing sibling of the definition list).
4
+ The base .oc-fact-list (card with <div><dt><dd> rows) lives in showcase.css. This part ADDS modifiers, plus one safe fix: rows may wrap in very narrow containers. */
5
+
6
+ /* Plain: no card, only lines between the rows. */
7
+ .oc-fact-list--plain {
8
+ border: 0;
9
+ border-radius: 0;
10
+ background: none;
11
+ }
12
+ .oc-fact-list--plain > div { padding-inline: 0; }
13
+
14
+ /* Compact rows (sidebars, small cards). */
15
+ .oc-fact-list--compact > div { padding-block: 0.6rem; font-size: 0.9rem; }
16
+
17
+ /* Stacked: the value goes below the label (long values). */
18
+ .oc-fact-list--stacked > div { flex-direction: column; gap: 0.2rem; }
19
+ .oc-fact-list--stacked dd { text-align: start; }
20
+
21
+ /* Values in the accent color. */
22
+ .oc-fact-list--accent dd { color: var(--oc-accent-from); }
23
+
24
+ /* Very narrow containers: wrap instead of squeezing label and value together. */
25
+ .oc-fact-list > div { flex-wrap: wrap; }
@@ -1,34 +1,34 @@
1
- /* File: packages/ui/src/parts/site-link-arrow.css
2
- Map: focus ring -> back arrow -> external arrow -> color modifiers -> sizes -> reduced motion
3
- Link arrow component. The base .oc-link-arrow (text + "→" that moves on hover) lives in showcase.css.
4
- This part only ADDS modifiers. */
5
-
6
- .oc-link-arrow:focus-visible {
7
- border-radius: 4px;
8
- outline: 2px solid var(--oc-ring);
9
- outline-offset: 3px;
10
- }
11
- .oc-link-arrow:focus-visible::after { translate: 4px 0; }
12
-
13
- /* Back link: the arrow points left, sits before the text and moves left on hover. */
14
- .oc-link-arrow--back::after { content: none; }
15
- .oc-link-arrow--back::before { content: "←"; transition: translate 0.2s var(--oc-ease-out); }
16
- .oc-link-arrow--back:is(:hover, :focus-visible)::before { translate: -4px 0; }
17
-
18
- /* External link: diagonal arrow that moves up-right. */
19
- .oc-link-arrow--external::after { content: "↗"; }
20
- .oc-link-arrow--external:is(:hover, :focus-visible)::after { translate: 3px -3px; }
21
-
22
- /* Colors: accent of the element, or muted text that turns to the foreground color on hover. */
23
- .oc-link-arrow--accent { color: var(--oc-accent-from); }
24
- .oc-link-arrow--muted { color: var(--oc-muted-foreground); font-weight: 500; transition: color 0.2s; }
25
- .oc-link-arrow--muted:hover { color: var(--oc-foreground); }
26
-
27
- /* Sizes */
28
- .oc-link-arrow--sm { font-size: 0.85rem; }
29
- .oc-link-arrow--lg { font-size: 1.15rem; }
30
-
31
- @media (prefers-reduced-motion: reduce) {
32
- .oc-link-arrow::after,
33
- .oc-link-arrow::before { transition: none; }
34
- }
1
+ /* File: packages/ui/src/parts/site-link-arrow.css
2
+ Map: focus ring -> back arrow -> external arrow -> color modifiers -> sizes -> reduced motion
3
+ Link arrow component. The base .oc-link-arrow (text + "→" that moves on hover) lives in showcase.css.
4
+ This part only ADDS modifiers. */
5
+
6
+ .oc-link-arrow:focus-visible {
7
+ border-radius: 4px;
8
+ outline: 2px solid var(--oc-ring);
9
+ outline-offset: 3px;
10
+ }
11
+ .oc-link-arrow:focus-visible::after { translate: 4px 0; }
12
+
13
+ /* Back link: the arrow points left, sits before the text and moves left on hover. */
14
+ .oc-link-arrow--back::after { content: none; }
15
+ .oc-link-arrow--back::before { content: "←"; transition: translate 0.2s var(--oc-ease-out); }
16
+ .oc-link-arrow--back:is(:hover, :focus-visible)::before { translate: -4px 0; }
17
+
18
+ /* External link: diagonal arrow that moves up-right. */
19
+ .oc-link-arrow--external::after { content: "↗"; }
20
+ .oc-link-arrow--external:is(:hover, :focus-visible)::after { translate: 3px -3px; }
21
+
22
+ /* Colors: accent of the element, or muted text that turns to the foreground color on hover. */
23
+ .oc-link-arrow--accent { color: var(--oc-accent-from); }
24
+ .oc-link-arrow--muted { color: var(--oc-muted-foreground); font-weight: 500; transition: color 0.2s; }
25
+ .oc-link-arrow--muted:hover { color: var(--oc-foreground); }
26
+
27
+ /* Sizes */
28
+ .oc-link-arrow--sm { font-size: 0.85rem; }
29
+ .oc-link-arrow--lg { font-size: 1.15rem; }
30
+
31
+ @media (prefers-reduced-motion: reduce) {
32
+ .oc-link-arrow::after,
33
+ .oc-link-arrow::before { transition: none; }
34
+ }
@@ -1,34 +1,34 @@
1
- /* File: packages/ui/src/parts/site-marquee.css
2
- Map: pause on focus -> direction / speed modifiers -> plain items -> no fade -> reduced motion
3
- Marquee component. The base .oc-marquee (endless track, pause on hover) lives in showcase.css.
4
- This part only ADDS modifiers and a reduced-motion fallback that shows every item without movement. */
5
-
6
- /* Keyboard users: pause too when a link inside the strip has focus. */
7
- .oc-marquee:focus-within .oc-marquee__track { animation-play-state: paused; }
8
-
9
- /* Scroll the other way (nice for a second row). */
10
- .oc-marquee--reverse .oc-marquee__track { animation-direction: reverse; }
11
-
12
- /* Speed presets. You can also set --oc-marquee-duration yourself. */
13
- .oc-marquee--slow { --oc-marquee-duration: 70s; }
14
- .oc-marquee--fast { --oc-marquee-duration: 20s; }
15
-
16
- /* Plain items: no pill, just text (logo or name strips). */
17
- .oc-marquee--plain .oc-marquee__item {
18
- padding-inline: 0.5rem;
19
- border-color: transparent;
20
- background: none;
21
- font-family: inherit;
22
- font-size: 1.05rem;
23
- font-weight: 600;
24
- }
25
-
26
- /* No soft fade at both edges. */
27
- .oc-marquee--no-fade { mask-image: none; }
28
-
29
- /* Reduced motion: no animation (showcase.css), no fade, the items wrap and the duplicates hide. */
30
- @media (prefers-reduced-motion: reduce) {
31
- .oc-marquee { mask-image: none; }
32
- .oc-marquee__track { flex-wrap: wrap; inline-size: auto; }
33
- .oc-marquee__item[aria-hidden="true"] { display: none; }
34
- }
1
+ /* File: packages/ui/src/parts/site-marquee.css
2
+ Map: pause on focus -> direction / speed modifiers -> plain items -> no fade -> reduced motion
3
+ Marquee component. The base .oc-marquee (endless track, pause on hover) lives in showcase.css.
4
+ This part only ADDS modifiers and a reduced-motion fallback that shows every item without movement. */
5
+
6
+ /* Keyboard users: pause too when a link inside the strip has focus. */
7
+ .oc-marquee:focus-within .oc-marquee__track { animation-play-state: paused; }
8
+
9
+ /* Scroll the other way (nice for a second row). */
10
+ .oc-marquee--reverse .oc-marquee__track { animation-direction: reverse; }
11
+
12
+ /* Speed presets. You can also set --oc-marquee-duration yourself. */
13
+ .oc-marquee--slow { --oc-marquee-duration: 70s; }
14
+ .oc-marquee--fast { --oc-marquee-duration: 20s; }
15
+
16
+ /* Plain items: no pill, just text (logo or name strips). */
17
+ .oc-marquee--plain .oc-marquee__item {
18
+ padding-inline: 0.5rem;
19
+ border-color: transparent;
20
+ background: none;
21
+ font-family: inherit;
22
+ font-size: 1.05rem;
23
+ font-weight: 600;
24
+ }
25
+
26
+ /* No soft fade at both edges. */
27
+ .oc-marquee--no-fade { mask-image: none; }
28
+
29
+ /* Reduced motion: no animation (showcase.css), no fade, the items wrap and the duplicates hide. */
30
+ @media (prefers-reduced-motion: reduce) {
31
+ .oc-marquee { mask-image: none; }
32
+ .oc-marquee__track { flex-wrap: wrap; inline-size: auto; }
33
+ .oc-marquee__item[aria-hidden="true"] { display: none; }
34
+ }
@@ -1,75 +1,75 @@
1
- /* File: packages/ui/src/parts/site-next-teaser.css
2
- Map: card -> label -> name (+ mark) -> tagline with arrow -> previous variant -> hover -> reduced motion
3
- Next teaser: a "Next product / Next project" card at the end of a detail page.
4
- Accent: --oc-accent-from, or an .oc-accent--* preset on the card. */
5
-
6
- .oc-next-teaser {
7
- display: grid;
8
- gap: 0.45rem;
9
- padding: 2rem;
10
- border: 1px solid var(--oc-border);
11
- border-radius: var(--oc-radius-lg);
12
- background:
13
- radial-gradient(28rem circle at 100% 0%, color-mix(in oklch, var(--oc-accent-from) 12%, transparent), transparent 60%),
14
- var(--oc-surface);
15
- color: var(--oc-foreground);
16
- text-decoration: none;
17
- transition: transform 0.3s var(--oc-ease-out), border-color 0.3s;
18
- }
19
-
20
- /* Small uppercase label ("Next product"). */
21
- .oc-next-teaser__label {
22
- color: var(--oc-muted-foreground);
23
- font-size: 0.78rem;
24
- font-weight: 600;
25
- letter-spacing: 0.14em;
26
- text-transform: uppercase;
27
- }
28
-
29
- /* Name with an optional product mark in front. */
30
- .oc-next-teaser__name {
31
- display: flex;
32
- align-items: center;
33
- gap: 0.75rem;
34
- margin: 0;
35
- font-size: clamp(1.4rem, 3vw, 1.85rem);
36
- font-weight: 700;
37
- letter-spacing: -0.02em;
38
- }
39
-
40
- /* Tagline + arrow that moves on hover. */
41
- .oc-next-teaser__tagline {
42
- display: flex;
43
- align-items: center;
44
- gap: 0.4rem;
45
- margin: 0;
46
- color: var(--oc-muted-foreground);
47
- }
48
- .oc-next-teaser__tagline::after {
49
- content: "→";
50
- color: var(--oc-accent-from);
51
- transition: translate 0.25s var(--oc-ease-out);
52
- }
53
-
54
- /* Previous: the arrow points left and sits before the tagline. */
55
- .oc-next-teaser--prev .oc-next-teaser__tagline::after { content: none; }
56
- .oc-next-teaser--prev .oc-next-teaser__tagline::before {
57
- content: "←";
58
- color: var(--oc-accent-from);
59
- transition: translate 0.25s var(--oc-ease-out);
60
- }
61
-
62
- /* Hover / focus */
63
- .oc-next-teaser:is(a):hover {
64
- transform: translateY(-4px);
65
- border-color: color-mix(in oklch, var(--oc-accent-from) 55%, transparent);
66
- }
67
- .oc-next-teaser:hover .oc-next-teaser__tagline::after { translate: 4px 0; }
68
- .oc-next-teaser--prev:hover .oc-next-teaser__tagline::before { translate: -4px 0; }
69
- .oc-next-teaser:focus-visible { outline: 2px solid var(--oc-ring); outline-offset: 3px; }
70
-
71
- @media (prefers-reduced-motion: reduce) {
72
- .oc-next-teaser,
73
- .oc-next-teaser__tagline::after,
74
- .oc-next-teaser__tagline::before { transition: none; }
75
- }
1
+ /* File: packages/ui/src/parts/site-next-teaser.css
2
+ Map: card -> label -> name (+ mark) -> tagline with arrow -> previous variant -> hover -> reduced motion
3
+ Next teaser: a "Next product / Next project" card at the end of a detail page.
4
+ Accent: --oc-accent-from, or an .oc-accent--* preset on the card. */
5
+
6
+ .oc-next-teaser {
7
+ display: grid;
8
+ gap: 0.45rem;
9
+ padding: 2rem;
10
+ border: 1px solid var(--oc-border);
11
+ border-radius: var(--oc-radius-lg);
12
+ background:
13
+ radial-gradient(28rem circle at 100% 0%, color-mix(in oklch, var(--oc-accent-from) 12%, transparent), transparent 60%),
14
+ var(--oc-surface);
15
+ color: var(--oc-foreground);
16
+ text-decoration: none;
17
+ transition: transform 0.3s var(--oc-ease-out), border-color 0.3s;
18
+ }
19
+
20
+ /* Small uppercase label ("Next product"). */
21
+ .oc-next-teaser__label {
22
+ color: var(--oc-muted-foreground);
23
+ font-size: 0.78rem;
24
+ font-weight: 600;
25
+ letter-spacing: 0.14em;
26
+ text-transform: uppercase;
27
+ }
28
+
29
+ /* Name with an optional product mark in front. */
30
+ .oc-next-teaser__name {
31
+ display: flex;
32
+ align-items: center;
33
+ gap: 0.75rem;
34
+ margin: 0;
35
+ font-size: clamp(1.4rem, 3vw, 1.85rem);
36
+ font-weight: 700;
37
+ letter-spacing: -0.02em;
38
+ }
39
+
40
+ /* Tagline + arrow that moves on hover. */
41
+ .oc-next-teaser__tagline {
42
+ display: flex;
43
+ align-items: center;
44
+ gap: 0.4rem;
45
+ margin: 0;
46
+ color: var(--oc-muted-foreground);
47
+ }
48
+ .oc-next-teaser__tagline::after {
49
+ content: "→";
50
+ color: var(--oc-accent-from);
51
+ transition: translate 0.25s var(--oc-ease-out);
52
+ }
53
+
54
+ /* Previous: the arrow points left and sits before the tagline. */
55
+ .oc-next-teaser--prev .oc-next-teaser__tagline::after { content: none; }
56
+ .oc-next-teaser--prev .oc-next-teaser__tagline::before {
57
+ content: "←";
58
+ color: var(--oc-accent-from);
59
+ transition: translate 0.25s var(--oc-ease-out);
60
+ }
61
+
62
+ /* Hover / focus */
63
+ .oc-next-teaser:is(a):hover {
64
+ transform: translateY(-4px);
65
+ border-color: color-mix(in oklch, var(--oc-accent-from) 55%, transparent);
66
+ }
67
+ .oc-next-teaser:hover .oc-next-teaser__tagline::after { translate: 4px 0; }
68
+ .oc-next-teaser--prev:hover .oc-next-teaser__tagline::before { translate: -4px 0; }
69
+ .oc-next-teaser:focus-visible { outline: 2px solid var(--oc-ring); outline-offset: 3px; }
70
+
71
+ @media (prefers-reduced-motion: reduce) {
72
+ .oc-next-teaser,
73
+ .oc-next-teaser__tagline::after,
74
+ .oc-next-teaser__tagline::before { transition: none; }
75
+ }
@@ -1,75 +1,91 @@
1
- /* File: packages/ui/src/parts/site-price-card.css
2
- Map: card -> head + discount badge -> period toggle -> monthly / yearly price (:has) -> features -> featured
3
- Price card: one plan with a monthly / yearly switch (radio inputs + :has(), no JavaScript).
4
- The toggle is the segmented component; give every card its own radio name. */
5
-
6
- .oc-price-card {
7
- display: flex;
8
- flex-direction: column;
9
- gap: 1rem;
10
- padding: 1.75rem;
11
- border: 1px solid var(--oc-border);
12
- border-radius: var(--oc-radius-lg);
13
- background: var(--oc-card);
14
- color: var(--oc-foreground);
15
- }
16
-
17
- .oc-price-card__head { display: flex; align-items: center; justify-content: space-between; gap: 0.75rem; }
18
- .oc-price-card__name { margin: 0; font-size: 1.2rem; font-weight: 700; }
19
- .oc-price-card__desc { margin: 0; color: var(--oc-muted-foreground); font-size: 0.92rem; }
20
-
21
- /* Discount badge ("Save 20%"). It is dimmed while the monthly price shows. */
22
- .oc-price-card__discount {
23
- padding: 0.2rem 0.6rem;
24
- border-radius: 999px;
25
- background: color-mix(in oklch, var(--oc-success) 16%, transparent);
26
- color: var(--oc-success);
27
- font-size: 0.75rem;
28
- font-weight: 700;
29
- white-space: nowrap;
30
- transition: opacity 0.2s;
31
- }
32
- .oc-price-card:has(.oc-price-card__toggle input[value="monthly"]:checked) .oc-price-card__discount { opacity: 0.55; }
33
-
34
- .oc-price-card__toggle { align-self: flex-start; }
35
-
36
- /* Price rows: monthly shows by default, yearly when its radio is checked. */
37
- .oc-price-card__price {
38
- display: flex;
39
- flex-wrap: wrap;
40
- align-items: baseline;
41
- gap: 0.35rem;
42
- margin: 0;
43
- }
44
- .oc-price-card__price--yearly { display: none; }
45
- .oc-price-card:has(.oc-price-card__toggle input[value="yearly"]:checked) .oc-price-card__price--yearly { display: flex; }
46
- .oc-price-card:has(.oc-price-card__toggle input[value="yearly"]:checked) .oc-price-card__price--monthly { display: none; }
47
-
48
- .oc-price-card__amount { font-size: 2.5rem; font-weight: 700; line-height: 1; letter-spacing: -0.03em; }
49
- .oc-price-card__period { color: var(--oc-muted-foreground); font-size: 0.9rem; }
50
- /* Old price, struck through. */
51
- .oc-price-card__was { color: var(--oc-muted-foreground); font-size: 0.95rem; }
52
- .oc-price-card__note { flex-basis: 100%; color: var(--oc-muted-foreground); font-size: 0.8rem; }
53
-
54
- /* Features: a check for included, a cross + muted text for excluded. */
55
- .oc-price-card__features {
56
- display: grid;
57
- gap: 0.55rem;
58
- flex-grow: 1;
59
- margin: 0;
60
- padding: 0;
61
- list-style: none;
62
- font-size: 0.92rem;
63
- }
64
- .oc-price-card__feature { display: flex; align-items: baseline; gap: 0.55rem; }
65
- .oc-price-card__feature::before { content: "✓"; flex-shrink: 0; color: var(--oc-success); font-weight: 700; }
66
- .oc-price-card__feature--excluded { color: var(--oc-muted-foreground); }
67
- .oc-price-card__feature--excluded::before { content: "✕"; color: var(--oc-muted-foreground); font-weight: 400; }
68
-
69
- .oc-price-card__cta { inline-size: 100%; }
70
-
71
- /* Featured plan: accent border + soft glow. */
72
- .oc-price-card--featured {
73
- border-color: color-mix(in oklch, var(--oc-accent-from) 60%, transparent);
74
- box-shadow: 0 24px 60px -30px var(--oc-accent-from);
75
- }
1
+ /* File: packages/ui/src/parts/site-price-card.css
2
+ Map: card -> head + discount badge -> period toggle -> monthly / yearly price (:has) -> features -> featured
3
+ Price card: one plan with a monthly / yearly switch (radio inputs + :has(), no JavaScript).
4
+ The toggle is the segmented component; give every card its own radio name. */
5
+
6
+ .oc-price-card {
7
+ display: flex;
8
+ flex-direction: column;
9
+ gap: 1rem;
10
+ padding: 1.75rem;
11
+ border: 1px solid var(--oc-border);
12
+ border-radius: var(--oc-radius-lg);
13
+ background: var(--oc-card);
14
+ color: var(--oc-foreground);
15
+ }
16
+
17
+ .oc-price-card__head { display: flex; align-items: center; justify-content: space-between; gap: 0.75rem; }
18
+ .oc-price-card__name { margin: 0; font-size: 1.2rem; font-weight: 700; }
19
+ .oc-price-card__desc { margin: 0; color: var(--oc-muted-foreground); font-size: 0.92rem; }
20
+
21
+ /* Discount badge ("Save 20%"). It is dimmed while the monthly price shows. */
22
+ .oc-price-card__discount {
23
+ padding: 0.2rem 0.6rem;
24
+ border-radius: 999px;
25
+ background: color-mix(in oklch, var(--oc-success) 16%, transparent);
26
+ color: var(--oc-success);
27
+ font-size: 0.75rem;
28
+ font-weight: 700;
29
+ white-space: nowrap;
30
+ transition: opacity 0.2s;
31
+ }
32
+ .oc-price-card:has(.oc-price-card__toggle input[value="monthly"]:checked) .oc-price-card__discount { opacity: 0.55; }
33
+
34
+ .oc-price-card__toggle { align-self: flex-start; }
35
+
36
+ /* Price rows: monthly shows by default, yearly when its radio is checked. */
37
+ .oc-price-card__price {
38
+ display: flex;
39
+ flex-wrap: wrap;
40
+ align-items: baseline;
41
+ gap: 0.35rem;
42
+ margin: 0;
43
+ }
44
+ .oc-price-card__price--yearly { display: none; }
45
+ .oc-price-card:has(.oc-price-card__toggle input[value="yearly"]:checked) .oc-price-card__price--yearly { display: flex; }
46
+ .oc-price-card:has(.oc-price-card__toggle input[value="yearly"]:checked) .oc-price-card__price--monthly { display: none; }
47
+
48
+ .oc-price-card__amount { font-size: 2.5rem; font-weight: 700; line-height: 1; letter-spacing: -0.03em; }
49
+ .oc-price-card__period { color: var(--oc-muted-foreground); font-size: 0.9rem; }
50
+ /* Old price, struck through. */
51
+ .oc-price-card__was { color: var(--oc-muted-foreground); font-size: 0.95rem; }
52
+ .oc-price-card__note { flex-basis: 100%; color: var(--oc-muted-foreground); font-size: 0.8rem; }
53
+
54
+ /* Features: a check for included, a cross + muted text for excluded. */
55
+ .oc-price-card__features {
56
+ display: grid;
57
+ gap: 0.55rem;
58
+ flex-grow: 1;
59
+ align-content: start; /* the list grows to push the button down, its rows stay together */
60
+ margin: 0;
61
+ padding: 0;
62
+ list-style: none;
63
+ font-size: 0.92rem;
64
+ }
65
+ .oc-price-card__feature { display: flex; align-items: baseline; gap: 0.55rem; }
66
+ .oc-price-card__feature::before { content: "✓"; flex-shrink: 0; color: var(--oc-success); font-weight: 700; }
67
+ .oc-price-card__feature--excluded { color: var(--oc-muted-foreground); }
68
+ .oc-price-card__feature--excluded::before { content: "✕"; color: var(--oc-muted-foreground); font-weight: 400; }
69
+
70
+ .oc-price-card__cta { inline-size: 100%; }
71
+
72
+ /* Featured plan: accent border + soft glow. The glow follows the pointer: the card you hover or tab into gets it,
73
+ and the featured card gives it up while another card in the same row is hovered. */
74
+ .oc-price-card {
75
+ transition: border-color 0.25s var(--oc-ease-out), box-shadow 0.25s var(--oc-ease-out), translate 0.25s var(--oc-ease-out);
76
+ }
77
+ .oc-price-card--featured,
78
+ .oc-price-card:hover,
79
+ .oc-price-card:focus-within {
80
+ border-color: color-mix(in oklch, var(--oc-accent-from) 60%, transparent);
81
+ box-shadow: 0 24px 60px -30px var(--oc-accent-from);
82
+ }
83
+ .oc-price-card:hover { translate: 0 -2px; }
84
+ :has(> .oc-price-card:hover) > .oc-price-card--featured:not(:hover, :focus-within) {
85
+ border-color: var(--oc-border);
86
+ box-shadow: none;
87
+ }
88
+ @media (prefers-reduced-motion: reduce) {
89
+ .oc-price-card { transition: none; }
90
+ .oc-price-card:hover { translate: none; }
91
+ }
@@ -1,66 +1,66 @@
1
- /* File: packages/ui/src/parts/site-product-mark.css
2
- Map: base tile -> squircle (corner-shape) -> image / svg -> sizes -> soft variant -> glow
3
- Product mark: a filled app-icon tile in the accent gradient (logo, glyph or SVG).
4
- Accent: --oc-accent-from / --oc-accent-to, or an .oc-accent--* preset on the element. */
5
-
6
- .oc-product-mark {
7
- --oc-mark-size: 3rem;
8
- display: inline-grid;
9
- place-items: center;
10
- inline-size: var(--oc-mark-size);
11
- aspect-ratio: 1;
12
- flex-shrink: 0;
13
- /* Fallback shape: a rounded square close to an app icon. */
14
- border-radius: 26%;
15
- background: linear-gradient(135deg, var(--oc-accent-from), var(--oc-accent-to));
16
- color: var(--color-white-50);
17
- font-size: calc(var(--oc-mark-size) * 0.45);
18
- line-height: 1;
19
- /* Light edge on top + a soft drop shadow in the accent color. */
20
- box-shadow:
21
- inset 0 1px 0 color-mix(in oklch, var(--color-white-50) 35%, transparent),
22
- 0 10px 24px -12px var(--oc-accent-to);
23
- overflow: hidden;
24
- }
25
-
26
- /* Real squircle where the browser supports corner-shape (a larger radius looks right with it). */
27
- @supports (corner-shape: squircle) {
28
- .oc-product-mark {
29
- border-radius: 50%;
30
- corner-shape: squircle;
31
- }
32
- }
33
-
34
- /* Logo image or inline SVG inside the tile. */
35
- .oc-product-mark > :is(img, svg) {
36
- inline-size: 58%;
37
- block-size: 58%;
38
- object-fit: contain;
39
- }
40
- /* Full-bleed image (the logo already is a tile). */
41
- .oc-product-mark--cover > img {
42
- inline-size: 100%;
43
- block-size: 100%;
44
- object-fit: cover;
45
- }
46
-
47
- /* Sizes */
48
- .oc-product-mark--sm { --oc-mark-size: 2.25rem; }
49
- .oc-product-mark--lg { --oc-mark-size: 4rem; }
50
- .oc-product-mark--xl {
51
- --oc-mark-size: clamp(6rem, 18vw, 10rem);
52
- box-shadow:
53
- inset 0 2px 0 color-mix(in oklch, var(--color-white-50) 35%, transparent),
54
- 0 0 80px -20px var(--oc-accent-from);
55
- }
56
-
57
- /* Soft variant: tinted background, accent glyph (quieter, for lists). */
58
- .oc-product-mark--soft {
59
- border: 1px solid color-mix(in oklch, var(--oc-accent-from) 40%, transparent);
60
- background: color-mix(in oklch, var(--oc-accent-from) 16%, var(--oc-card));
61
- color: var(--oc-accent-from);
62
- box-shadow: none;
63
- }
64
-
65
- /* Extra glow (hero visuals). */
66
- .oc-product-mark--glow { box-shadow: 0 0 48px -8px var(--oc-accent-from); }
1
+ /* File: packages/ui/src/parts/site-product-mark.css
2
+ Map: base tile -> squircle (corner-shape) -> image / svg -> sizes -> soft variant -> glow
3
+ Product mark: a filled app-icon tile in the accent gradient (logo, glyph or SVG).
4
+ Accent: --oc-accent-from / --oc-accent-to, or an .oc-accent--* preset on the element. */
5
+
6
+ .oc-product-mark {
7
+ --oc-mark-size: 3rem;
8
+ display: inline-grid;
9
+ place-items: center;
10
+ inline-size: var(--oc-mark-size);
11
+ aspect-ratio: 1;
12
+ flex-shrink: 0;
13
+ /* Fallback shape: a rounded square close to an app icon. */
14
+ border-radius: 26%;
15
+ background: linear-gradient(135deg, var(--oc-accent-from), var(--oc-accent-to));
16
+ color: var(--color-white-50);
17
+ font-size: calc(var(--oc-mark-size) * 0.45);
18
+ line-height: 1;
19
+ /* Light edge on top + a soft drop shadow in the accent color. */
20
+ box-shadow:
21
+ inset 0 1px 0 color-mix(in oklch, var(--color-white-50) 35%, transparent),
22
+ 0 10px 24px -12px var(--oc-accent-to);
23
+ overflow: hidden;
24
+ }
25
+
26
+ /* Real squircle where the browser supports corner-shape (a larger radius looks right with it). */
27
+ @supports (corner-shape: squircle) {
28
+ .oc-product-mark {
29
+ border-radius: 50%;
30
+ corner-shape: squircle;
31
+ }
32
+ }
33
+
34
+ /* Logo image or inline SVG inside the tile. */
35
+ .oc-product-mark > :is(img, svg) {
36
+ inline-size: 58%;
37
+ block-size: 58%;
38
+ object-fit: contain;
39
+ }
40
+ /* Full-bleed image (the logo already is a tile). */
41
+ .oc-product-mark--cover > img {
42
+ inline-size: 100%;
43
+ block-size: 100%;
44
+ object-fit: cover;
45
+ }
46
+
47
+ /* Sizes */
48
+ .oc-product-mark--sm { --oc-mark-size: 2.25rem; }
49
+ .oc-product-mark--lg { --oc-mark-size: 4rem; }
50
+ .oc-product-mark--xl {
51
+ --oc-mark-size: clamp(6rem, 18vw, 10rem);
52
+ box-shadow:
53
+ inset 0 2px 0 color-mix(in oklch, var(--color-white-50) 35%, transparent),
54
+ 0 0 80px -20px var(--oc-accent-from);
55
+ }
56
+
57
+ /* Soft variant: tinted background, accent glyph (quieter, for lists). */
58
+ .oc-product-mark--soft {
59
+ border: 1px solid color-mix(in oklch, var(--oc-accent-from) 40%, transparent);
60
+ background: color-mix(in oklch, var(--oc-accent-from) 16%, var(--oc-card));
61
+ color: var(--oc-accent-from);
62
+ box-shadow: none;
63
+ }
64
+
65
+ /* Extra glow (hero visuals). */
66
+ .oc-product-mark--glow { box-shadow: 0 0 48px -8px var(--oc-accent-from); }