@birdycom/omniaui 0.12.1 → 0.12.3
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.
- package/README.md +2 -1
- package/bin/lib/copy-js.mjs +56 -0
- package/bin/omniaui.mjs +6 -2
- package/dist/carousel.js +11 -2
- package/dist/components.css +494 -6
- package/dist/components.min.css +1 -1
- package/dist/data-table.js +11 -2
- package/dist/oc-theme.css +1 -1
- package/dist/parts/app-status-dot.css +50 -0
- package/dist/parts/app-titlebar.css +96 -0
- package/dist/parts/media-glass.css +71 -0
- package/dist/parts/media-live-frame.css +38 -0
- package/dist/parts/media-watermark.css +96 -0
- package/dist/parts/site-link-row.css +54 -0
- package/dist/parts/site-prose.css +12 -0
- package/manifest.json +48 -0
- package/package.json +2 -2
- package/snippets/glass.html +24 -0
- package/snippets/link-row.html +14 -0
- package/snippets/live-frame.html +20 -0
- package/snippets/status-dot.html +15 -0
- package/snippets/titlebar.html +29 -0
- package/snippets/watermark.html +40 -0
package/dist/components.css
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/* File: oc-theme.css — generated from tokens/semantic.json by @birdycom/omniacss 0.12.
|
|
1
|
+
/* File: oc-theme.css — generated from tokens/semantic.json by @birdycom/omniacss 0.12.3. Do not edit. */
|
|
2
2
|
/* Semantic theme tokens: every color is light-dark() of an Omnia palette token (oc-colors.css). */
|
|
3
3
|
/* Same source as the desktop export: npx omniacss tokens --format json|dtcg|python */
|
|
4
4
|
:root {
|
|
@@ -252,6 +252,10 @@
|
|
|
252
252
|
color: var(--oc-foreground);
|
|
253
253
|
}
|
|
254
254
|
|
|
255
|
+
/* The hidden attribute hides, also on components with their own display (.oc-field is flex, .oc-card is grid …).
|
|
256
|
+
hidden="until-found" keeps the browser's own behaviour, so find-in-page can still open it. */
|
|
257
|
+
[hidden]:not([hidden="until-found"]) { display: none !important; }
|
|
258
|
+
|
|
255
259
|
/* ===================================================================
|
|
256
260
|
BLOCK GRID HELPER
|
|
257
261
|
=================================================================== */
|
|
@@ -433,6 +437,20 @@ flex-direction: column;
|
|
|
433
437
|
opacity: 1;
|
|
434
438
|
}
|
|
435
439
|
|
|
440
|
+
/* Inline — a link button inside running text: no button padding or height, the size of the text around it.
|
|
441
|
+
Two classes, so it also wins over the size modifiers (--sm, --lg) further down. */
|
|
442
|
+
.oc-btn.oc-btn--inline {
|
|
443
|
+
display: inline;
|
|
444
|
+
padding: 0;
|
|
445
|
+
border: 0;
|
|
446
|
+
border-radius: 2px;
|
|
447
|
+
font-size: inherit;
|
|
448
|
+
line-height: inherit;
|
|
449
|
+
vertical-align: baseline;
|
|
450
|
+
white-space: normal;
|
|
451
|
+
}
|
|
452
|
+
.oc-btn.oc-btn--inline:active { transform: none; }
|
|
453
|
+
|
|
436
454
|
/* Destructive */
|
|
437
455
|
.oc-btn--destructive {
|
|
438
456
|
background: var(--oc-destructive);
|
|
@@ -1114,6 +1132,18 @@ textarea.oc-input {
|
|
|
1114
1132
|
background: color-mix(in srgb, var(--oc-destructive) 5%, var(--oc-background));
|
|
1115
1133
|
}
|
|
1116
1134
|
|
|
1135
|
+
/* Inline: a short message right under a field or a form (an error, a hint), tinted, without the box spacing. */
|
|
1136
|
+
.oc-alert--inline {
|
|
1137
|
+
padding: 8px 12px;
|
|
1138
|
+
border-radius: var(--oc-radius);
|
|
1139
|
+
font-size: 0.8125rem;
|
|
1140
|
+
line-height: 1.45;
|
|
1141
|
+
}
|
|
1142
|
+
.oc-alert--inline.oc-alert--danger { color: light-dark(var(--oc-destructive), oklch(from var(--oc-destructive) max(l, 0.75) c h)); }
|
|
1143
|
+
.oc-alert--inline .oc-alert-title { margin: 0; font-size: inherit; }
|
|
1144
|
+
.oc-alert--inline .oc-alert-title + .oc-alert-description { margin-block-start: 2px; }
|
|
1145
|
+
.oc-alert--inline .oc-alert-description { color: inherit; }
|
|
1146
|
+
|
|
1117
1147
|
/* ===================================================================
|
|
1118
1148
|
HERO (page intro block — used in docs index)
|
|
1119
1149
|
=================================================================== */
|
|
@@ -1718,7 +1748,7 @@ textarea.oc-input {
|
|
|
1718
1748
|
display: none;
|
|
1719
1749
|
}
|
|
1720
1750
|
|
|
1721
|
-
/* Optional Iconify/MDI chevron: put <
|
|
1751
|
+
/* Optional Iconify/MDI chevron: put <iconify-icon icon="mdi:chevron-down" class="oc-accordion-chevron size-4" height="unset" aria-hidden="true"></iconify-icon> in the trigger (the older <span class="iconify" data-icon="…"> works the same) */
|
|
1722
1752
|
.oc-accordion-trigger .oc-accordion-chevron {
|
|
1723
1753
|
flex-shrink: 0;
|
|
1724
1754
|
transition: transform var(--oc-transition-fast);
|
|
@@ -1967,15 +1997,44 @@ a.oc-breadcrumb-item:hover {
|
|
|
1967
1997
|
}
|
|
1968
1998
|
|
|
1969
1999
|
.oc-progress-bar {
|
|
2000
|
+
--oc-progress-color: var(--oc-primary);
|
|
2001
|
+
display: block;
|
|
2002
|
+
max-width: 100%;
|
|
1970
2003
|
height: 100%;
|
|
1971
|
-
background: var(--oc-
|
|
2004
|
+
background: var(--oc-progress-color);
|
|
1972
2005
|
border-radius: 999px;
|
|
1973
2006
|
transition: width 300ms ease;
|
|
1974
2007
|
}
|
|
1975
2008
|
|
|
1976
|
-
.oc-progress-bar--success {
|
|
1977
|
-
.oc-progress-bar--danger {
|
|
1978
|
-
.oc-progress-bar--warning {
|
|
2009
|
+
.oc-progress-bar--success { --oc-progress-color: var(--oc-success); }
|
|
2010
|
+
.oc-progress-bar--danger { --oc-progress-color: var(--oc-destructive); }
|
|
2011
|
+
.oc-progress-bar--warning { --oc-progress-color: var(--oc-warning); }
|
|
2012
|
+
|
|
2013
|
+
/* Sizes */
|
|
2014
|
+
.oc-progress--sm { height: 6px; }
|
|
2015
|
+
.oc-progress--xs { height: 4px; }
|
|
2016
|
+
|
|
2017
|
+
/* Glow: a light top edge and a soft glow in the bar color (meters, usage, quota). */
|
|
2018
|
+
.oc-progress--glow { overflow: visible; box-shadow: inset 0 1px 1px light-dark(oklch(0% 0 0deg / 0.06), oklch(0% 0 0deg / 0.35)); }
|
|
2019
|
+
.oc-progress--glow .oc-progress-bar {
|
|
2020
|
+
background: linear-gradient(180deg, color-mix(in oklch, var(--oc-progress-color) 78%, white), var(--oc-progress-color));
|
|
2021
|
+
box-shadow: 0 0 10px -2px color-mix(in oklch, var(--oc-progress-color) 60%, transparent);
|
|
2022
|
+
}
|
|
2023
|
+
|
|
2024
|
+
/* Marker: a short upright line at a target or schedule point, placed with style="left: 20%". Give it an aria-label
|
|
2025
|
+
on the progressbar or a text next to it; the line itself is decoration. */
|
|
2026
|
+
.oc-progress:has(> .oc-progress-marker) { position: relative; overflow: visible; }
|
|
2027
|
+
.oc-progress-marker {
|
|
2028
|
+
position: absolute;
|
|
2029
|
+
inset-block: -4px;
|
|
2030
|
+
inline-size: 2px;
|
|
2031
|
+
margin-inline-start: -1px;
|
|
2032
|
+
border-radius: 2px;
|
|
2033
|
+
background: var(--oc-foreground);
|
|
2034
|
+
box-shadow: 0 0 0 1.5px var(--oc-background);
|
|
2035
|
+
pointer-events: none;
|
|
2036
|
+
}
|
|
2037
|
+
.oc-progress-marker--muted { background: var(--oc-muted-foreground); }
|
|
1979
2038
|
|
|
1980
2039
|
/* ===================================================================
|
|
1981
2040
|
SKELETON LOADER
|
|
@@ -6202,6 +6261,58 @@ button.oc-stat-card:focus-visible { outline: 2px solid var(--oc-ring); outline-o
|
|
|
6202
6261
|
button.oc-stat-card:hover { translate: none; }
|
|
6203
6262
|
}
|
|
6204
6263
|
|
|
6264
|
+
/* parts/app-status-dot.css */
|
|
6265
|
+
/* File: packages/ui/src/parts/app-status-dot.css
|
|
6266
|
+
Map: dot (tone color + soft ring) -> tones (working pulses, waiting, done, error, idle) -> sizes -> status row (dot + text
|
|
6267
|
+
that cuts off with …) -> reduced motion
|
|
6268
|
+
Status dot: a small live state light for a job, agent, sync, server or person ("Working", "Waiting for input", "Done").
|
|
6269
|
+
Always put a text next to it or an aria-label on it: the color alone does not tell the state. */
|
|
6270
|
+
|
|
6271
|
+
.oc-status-dot {
|
|
6272
|
+
--oc-status-dot-color: var(--oc-muted-foreground);
|
|
6273
|
+
display: inline-block;
|
|
6274
|
+
flex: none;
|
|
6275
|
+
inline-size: 0.5rem;
|
|
6276
|
+
block-size: 0.5rem;
|
|
6277
|
+
border-radius: 50%;
|
|
6278
|
+
background: var(--oc-status-dot-color);
|
|
6279
|
+
box-shadow: 0 0 0 2px oklch(from var(--oc-status-dot-color) l c h / 0.2);
|
|
6280
|
+
vertical-align: middle;
|
|
6281
|
+
}
|
|
6282
|
+
|
|
6283
|
+
/* Tones. --working pulses a ring outwards. */
|
|
6284
|
+
.oc-status-dot--working {
|
|
6285
|
+
--oc-status-dot-color: var(--oc-primary);
|
|
6286
|
+
animation: oc-status-dot-pulse 1.8s ease-in-out infinite;
|
|
6287
|
+
}
|
|
6288
|
+
.oc-status-dot--waiting { --oc-status-dot-color: var(--oc-warning); }
|
|
6289
|
+
.oc-status-dot--done { --oc-status-dot-color: var(--oc-success); }
|
|
6290
|
+
.oc-status-dot--error { --oc-status-dot-color: var(--oc-destructive); }
|
|
6291
|
+
.oc-status-dot--idle { --oc-status-dot-color: var(--oc-muted-foreground); box-shadow: none; opacity: 0.7; }
|
|
6292
|
+
@keyframes oc-status-dot-pulse {
|
|
6293
|
+
50% { box-shadow: 0 0 0 5px oklch(from var(--oc-status-dot-color) l c h / 0.08); }
|
|
6294
|
+
}
|
|
6295
|
+
|
|
6296
|
+
/* Sizes */
|
|
6297
|
+
.oc-status-dot--sm { inline-size: 0.375rem; block-size: 0.375rem; }
|
|
6298
|
+
.oc-status-dot--lg { inline-size: 0.625rem; block-size: 0.625rem; }
|
|
6299
|
+
|
|
6300
|
+
/* Status row: dot + one line of text that cuts off with … in a narrow card. */
|
|
6301
|
+
.oc-status {
|
|
6302
|
+
display: flex;
|
|
6303
|
+
align-items: center;
|
|
6304
|
+
gap: 0.5rem;
|
|
6305
|
+
min-inline-size: 0;
|
|
6306
|
+
margin: 0;
|
|
6307
|
+
font-size: 0.8125rem;
|
|
6308
|
+
}
|
|
6309
|
+
.oc-status__text { min-inline-size: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
6310
|
+
.oc-status__meta { flex: none; margin-inline-start: auto; color: var(--oc-muted-foreground); font-variant-numeric: tabular-nums; }
|
|
6311
|
+
|
|
6312
|
+
@media (prefers-reduced-motion: reduce) {
|
|
6313
|
+
.oc-status-dot--working { animation: none; }
|
|
6314
|
+
}
|
|
6315
|
+
|
|
6205
6316
|
/* parts/app-table-actions.css */
|
|
6206
6317
|
/* File: packages/ui/src/parts/app-table-actions.css | Map: icon actions -> tone modifiers -> overflow trigger -> menu tweaks -> reduced motion */
|
|
6207
6318
|
/* Table actions: row actions as small icon buttons or as one overflow ("more") menu.
|
|
@@ -6331,6 +6442,104 @@ button.oc-stat-card:focus-visible { outline: 2px solid var(--oc-ring); outline-o
|
|
|
6331
6442
|
.oc-table-compact--plain > .oc-table tbody tr:nth-child(even),
|
|
6332
6443
|
.oc-table-compact--plain > .oc-table thead th { background: none; }
|
|
6333
6444
|
|
|
6445
|
+
/* parts/app-titlebar.css */
|
|
6446
|
+
/* File: packages/ui/src/parts/app-titlebar.css
|
|
6447
|
+
Map: window (column, shares the scroll timeline) -> title bar (drag area) -> title + subtitle -> actions (no drag) ->
|
|
6448
|
+
icon buttons (close turns red) -> body (scrolls) -> hairline when the body scrolls (scroll-driven, no JavaScript) -> sizes
|
|
6449
|
+
Title bar: the top bar of a frameless desktop window (Electron, Tauri) or a widget: you drag the window by it, the
|
|
6450
|
+
buttons stay clickable. Inside .oc-titlebar-window the bar gets a hairline once .oc-titlebar-body scrolls. */
|
|
6451
|
+
|
|
6452
|
+
.oc-titlebar-window {
|
|
6453
|
+
display: flex;
|
|
6454
|
+
flex-direction: column;
|
|
6455
|
+
min-block-size: 0;
|
|
6456
|
+
timeline-scope: --oc-titlebar-scroll;
|
|
6457
|
+
}
|
|
6458
|
+
|
|
6459
|
+
.oc-titlebar {
|
|
6460
|
+
display: flex;
|
|
6461
|
+
flex: none;
|
|
6462
|
+
align-items: center;
|
|
6463
|
+
gap: 2px;
|
|
6464
|
+
min-block-size: 46px;
|
|
6465
|
+
padding: 0 8px 0 14px;
|
|
6466
|
+
border-block-end: 1px solid transparent;
|
|
6467
|
+
-webkit-user-select: none;
|
|
6468
|
+
user-select: none;
|
|
6469
|
+
/* The OS moves the window when you drag here (Electron and Tauri read this). */
|
|
6470
|
+
-webkit-app-region: drag;
|
|
6471
|
+
app-region: drag;
|
|
6472
|
+
}
|
|
6473
|
+
.oc-titlebar :is(button, a, input, select, textarea, label, [role="button"], [tabindex], .oc-titlebar__actions) {
|
|
6474
|
+
-webkit-app-region: no-drag;
|
|
6475
|
+
app-region: no-drag;
|
|
6476
|
+
}
|
|
6477
|
+
.oc-titlebar--bordered { border-block-end-color: var(--oc-glass-hairline, var(--oc-border)); }
|
|
6478
|
+
|
|
6479
|
+
/* Title area: grows, cuts the subtitle off with …. */
|
|
6480
|
+
.oc-titlebar__main { display: flex; flex: 1; align-items: center; gap: 8px; min-inline-size: 0; }
|
|
6481
|
+
.oc-titlebar__icon { flex: none; inline-size: 18px; block-size: 18px; }
|
|
6482
|
+
.oc-titlebar__title { flex: none; font-size: 0.8667rem; font-weight: 650; letter-spacing: -0.01em; }
|
|
6483
|
+
.oc-titlebar__subtitle {
|
|
6484
|
+
min-inline-size: 0;
|
|
6485
|
+
overflow: hidden;
|
|
6486
|
+
color: var(--oc-muted-foreground);
|
|
6487
|
+
font-size: 0.8rem;
|
|
6488
|
+
text-overflow: ellipsis;
|
|
6489
|
+
white-space: nowrap;
|
|
6490
|
+
}
|
|
6491
|
+
.oc-titlebar__subtitle::before { content: "·"; margin-inline-end: 8px; }
|
|
6492
|
+
.oc-titlebar__actions { display: flex; flex: none; align-items: center; gap: 2px; }
|
|
6493
|
+
|
|
6494
|
+
/* Compact icon buttons: muted, a light surface on hover, the close button red. */
|
|
6495
|
+
.oc-titlebar__btn {
|
|
6496
|
+
display: inline-grid;
|
|
6497
|
+
place-items: center;
|
|
6498
|
+
inline-size: 30px;
|
|
6499
|
+
block-size: 30px;
|
|
6500
|
+
padding: 0;
|
|
6501
|
+
border: 0;
|
|
6502
|
+
border-radius: 8px;
|
|
6503
|
+
background: transparent;
|
|
6504
|
+
color: var(--oc-muted-foreground);
|
|
6505
|
+
font: inherit;
|
|
6506
|
+
cursor: pointer;
|
|
6507
|
+
transition: background-color var(--oc-transition-fast), color var(--oc-transition-fast);
|
|
6508
|
+
}
|
|
6509
|
+
.oc-titlebar__btn :where(svg, iconify-icon) { inline-size: 16px; block-size: 16px; }
|
|
6510
|
+
.oc-titlebar__btn:hover { background: var(--oc-glass-panel-strong, var(--oc-accent)); color: var(--oc-foreground); }
|
|
6511
|
+
.oc-titlebar__btn:focus-visible { outline: 2px solid var(--oc-ring); outline-offset: -2px; }
|
|
6512
|
+
.oc-titlebar__btn--close:hover { background: var(--oc-destructive); color: var(--oc-destructive-foreground); }
|
|
6513
|
+
|
|
6514
|
+
/* Body: the part that scrolls under the bar. */
|
|
6515
|
+
.oc-titlebar-body {
|
|
6516
|
+
flex: 1;
|
|
6517
|
+
min-block-size: 0;
|
|
6518
|
+
overflow: auto;
|
|
6519
|
+
scroll-timeline: --oc-titlebar-scroll block;
|
|
6520
|
+
scrollbar-width: thin;
|
|
6521
|
+
}
|
|
6522
|
+
|
|
6523
|
+
/* Hairline + light surface on the bar once the body scrolls (browsers without scroll timelines keep the plain bar). */
|
|
6524
|
+
@supports (animation-timeline: scroll()) {
|
|
6525
|
+
.oc-titlebar-window > .oc-titlebar:not(.oc-titlebar--bordered) {
|
|
6526
|
+
animation: oc-titlebar-scrolled linear both;
|
|
6527
|
+
animation-timeline: --oc-titlebar-scroll;
|
|
6528
|
+
animation-range: 0 48px;
|
|
6529
|
+
}
|
|
6530
|
+
}
|
|
6531
|
+
@keyframes oc-titlebar-scrolled {
|
|
6532
|
+
to { border-block-end-color: var(--oc-glass-hairline, var(--oc-border)); background: var(--oc-glass-panel, var(--oc-muted)); }
|
|
6533
|
+
}
|
|
6534
|
+
|
|
6535
|
+
/* Sizes */
|
|
6536
|
+
.oc-titlebar--sm { min-block-size: 36px; padding-inline-start: 10px; }
|
|
6537
|
+
.oc-titlebar--sm .oc-titlebar__btn { inline-size: 26px; block-size: 26px; border-radius: 6px; }
|
|
6538
|
+
|
|
6539
|
+
@media (prefers-reduced-motion: reduce) {
|
|
6540
|
+
.oc-titlebar-window > .oc-titlebar { animation: none; }
|
|
6541
|
+
}
|
|
6542
|
+
|
|
6334
6543
|
/* parts/app-top-progress.css */
|
|
6335
6544
|
/* File: packages/ui/src/parts/app-top-progress.css | Map: bar (fixed, native progress) -> determinate value -> indeterminate animation -> color + static modifiers -> done state -> reduced motion */
|
|
6336
6545
|
/* Top progress: thin loading bar at the very top of the page, on a native <progress> element.
|
|
@@ -8641,6 +8850,79 @@ a.oc-attachment-image:hover > :is(img, .oc-media-art) { filter: brightness(1.05)
|
|
|
8641
8850
|
.oc-flip-card--hover:is(:hover, :focus-within) .oc-flip-card__face--back { opacity: 1; visibility: visible; }
|
|
8642
8851
|
}
|
|
8643
8852
|
|
|
8853
|
+
/* parts/media-glass.css */
|
|
8854
|
+
/* File: packages/ui/src/parts/media-glass.css
|
|
8855
|
+
Map: tokens (light-dark) -> sheet (.oc-glass: see-through, blurred, light top edge, soft shadow) -> panel (.oc-glass-panel:
|
|
8856
|
+
a lighter layer inside) -> cards inside a sheet -> --flat (desktop window, the OS draws the blur) -> --strong -> reduced
|
|
8857
|
+
transparency
|
|
8858
|
+
Glass: see-through surfaces in the "liquid glass" style, over a photo, a gradient or the desktop (an Electron or Tauri
|
|
8859
|
+
window with Windows acrylic or macOS vibrancy behind a transparent page). Re-tint with the --oc-glass-* tokens. */
|
|
8860
|
+
|
|
8861
|
+
:root {
|
|
8862
|
+
--oc-glass-sheet: light-dark(oklch(from var(--oc-background) l c h / 0.72), oklch(from var(--oc-background) l c h / 0.62));
|
|
8863
|
+
--oc-glass-panel: light-dark(oklch(100% 0 0deg / 0.5), oklch(100% 0 0deg / 0.055));
|
|
8864
|
+
--oc-glass-panel-strong: light-dark(oklch(100% 0 0deg / 0.72), oklch(100% 0 0deg / 0.09));
|
|
8865
|
+
--oc-glass-edge: light-dark(oklch(100% 0 0deg / 0.85), oklch(100% 0 0deg / 0.11));
|
|
8866
|
+
--oc-glass-edge-hi: light-dark(oklch(100% 0 0deg / 1), oklch(100% 0 0deg / 0.16));
|
|
8867
|
+
--oc-glass-hairline: light-dark(oklch(from var(--oc-foreground) l c h / 0.1), oklch(100% 0 0deg / 0.08));
|
|
8868
|
+
--oc-glass-shadow: 0 24px 60px -20px light-dark(oklch(25% 0.06 255deg / 0.35), oklch(0% 0 0deg / 0.7));
|
|
8869
|
+
--oc-glass-panel-shadow: 0 8px 24px -16px light-dark(oklch(25% 0.06 255deg / 0.25), oklch(0% 0 0deg / 0.6));
|
|
8870
|
+
--oc-glass-blur: 28px;
|
|
8871
|
+
--oc-glass-radius: 18px;
|
|
8872
|
+
--oc-glass-panel-radius: 14px;
|
|
8873
|
+
}
|
|
8874
|
+
|
|
8875
|
+
/* Sheet: the outer glass surface (a widget, a floating panel, a dialog over a photo). */
|
|
8876
|
+
.oc-glass {
|
|
8877
|
+
position: relative;
|
|
8878
|
+
color: var(--oc-foreground);
|
|
8879
|
+
background: var(--oc-glass-sheet);
|
|
8880
|
+
border: 1px solid var(--oc-glass-edge);
|
|
8881
|
+
border-radius: var(--oc-glass-radius);
|
|
8882
|
+
box-shadow: var(--oc-glass-shadow), inset 0 1px 0 var(--oc-glass-edge-hi);
|
|
8883
|
+
backdrop-filter: blur(var(--oc-glass-blur)) saturate(1.5);
|
|
8884
|
+
/* OmniaUI cards inside become glass panels too. */
|
|
8885
|
+
--oc-card-background: var(--oc-glass-panel);
|
|
8886
|
+
--oc-card-border: var(--oc-glass-edge);
|
|
8887
|
+
}
|
|
8888
|
+
|
|
8889
|
+
/* Panel: a lighter layer inside a sheet (a group of settings, a meter, a list). */
|
|
8890
|
+
.oc-glass-panel {
|
|
8891
|
+
position: relative;
|
|
8892
|
+
background: var(--oc-glass-panel);
|
|
8893
|
+
border: 1px solid var(--oc-glass-edge);
|
|
8894
|
+
border-radius: var(--oc-glass-panel-radius);
|
|
8895
|
+
box-shadow: var(--oc-glass-panel-shadow), inset 0 1px 0 var(--oc-glass-edge-hi);
|
|
8896
|
+
}
|
|
8897
|
+
.oc-glass .oc-card {
|
|
8898
|
+
border-radius: var(--oc-glass-panel-radius);
|
|
8899
|
+
box-shadow: var(--oc-glass-panel-shadow), inset 0 1px 0 var(--oc-glass-edge-hi);
|
|
8900
|
+
}
|
|
8901
|
+
|
|
8902
|
+
/* Strong: more opaque, for text-heavy panels or a hovered row. */
|
|
8903
|
+
.oc-glass--strong,
|
|
8904
|
+
.oc-glass-panel--strong { background: var(--oc-glass-panel-strong); }
|
|
8905
|
+
|
|
8906
|
+
/* Flat: a frameless desktop window where the OS draws the blur (acrylic, vibrancy): no own blur, no drop shadow. */
|
|
8907
|
+
.oc-glass--flat {
|
|
8908
|
+
border-radius: 8px;
|
|
8909
|
+
box-shadow: inset 0 1px 0 var(--oc-glass-edge-hi);
|
|
8910
|
+
backdrop-filter: none;
|
|
8911
|
+
}
|
|
8912
|
+
|
|
8913
|
+
/* Hairline divider in glass (sections, header). */
|
|
8914
|
+
.oc-glass-divider { block-size: 1px; margin: 0; border: 0; background: var(--oc-glass-hairline); }
|
|
8915
|
+
|
|
8916
|
+
/* People who ask for less transparency get solid surfaces. */
|
|
8917
|
+
@media (prefers-reduced-transparency: reduce) {
|
|
8918
|
+
:root {
|
|
8919
|
+
--oc-glass-sheet: var(--oc-background);
|
|
8920
|
+
--oc-glass-panel: var(--oc-card);
|
|
8921
|
+
--oc-glass-panel-strong: var(--oc-muted);
|
|
8922
|
+
}
|
|
8923
|
+
.oc-glass { backdrop-filter: none; }
|
|
8924
|
+
}
|
|
8925
|
+
|
|
8644
8926
|
/* parts/media-image-zoom.css */
|
|
8645
8927
|
/* File: packages/ui/src/parts/media-image-zoom.css | Map: root + zoom variable -> toolbar + level chips
|
|
8646
8928
|
-> viewport (scroll = pan) -> canvas (grows with the zoom) -> zoom levels (classes + radios via :has()) -> motion
|
|
@@ -8844,6 +9126,46 @@ a.oc-attachment-image:hover > :is(img, .oc-media-art) { filter: brightness(1.05)
|
|
|
8844
9126
|
}
|
|
8845
9127
|
@keyframes oc-lightbox-in { from { opacity: 0; scale: 0.98; } }
|
|
8846
9128
|
|
|
9129
|
+
/* parts/media-live-frame.css */
|
|
9130
|
+
/* File: packages/ui/src/parts/media-live-frame.css
|
|
9131
|
+
Map: frame (virtual size -> ratio, container) -> content at the virtual size, scaled to the frame width -> static
|
|
9132
|
+
Live frame: shows a page (an <iframe>, or a <video>/<img>) at a virtual size such as 1280x720 and scales it down to
|
|
9133
|
+
the width of its box, so a live site looks like a screenshot that is still alive. Pure CSS: the scale is
|
|
9134
|
+
tan(atan2(100cqi, <virtual width>)), which is the frame width divided by the virtual width. On .oc-browser-frame__view
|
|
9135
|
+
or on its own. Set the size with --oc-live-w / --oc-live-h (unitless px, default 1280 x 720). */
|
|
9136
|
+
|
|
9137
|
+
.oc-live-frame {
|
|
9138
|
+
--oc-live-w: 1280;
|
|
9139
|
+
--oc-live-h: 720;
|
|
9140
|
+
position: relative;
|
|
9141
|
+
display: block;
|
|
9142
|
+
/* Always the full width of its column (also inside flex or grid centring), the height follows the ratio. */
|
|
9143
|
+
inline-size: 100%;
|
|
9144
|
+
overflow: hidden;
|
|
9145
|
+
aspect-ratio: var(--oc-live-w) / var(--oc-live-h);
|
|
9146
|
+
container-type: inline-size;
|
|
9147
|
+
background: var(--oc-background);
|
|
9148
|
+
}
|
|
9149
|
+
/* .oc-live-frame__content: any element (a whole demo page) at the virtual size. The class inside :is() also makes this
|
|
9150
|
+
rule as strong as the .oc-browser-frame__view rule, which comes earlier, so on the view slot this one wins. */
|
|
9151
|
+
.oc-live-frame > :is(iframe, video, img, object, .oc-live-frame__content) {
|
|
9152
|
+
position: absolute;
|
|
9153
|
+
inset-block-start: 0;
|
|
9154
|
+
inset-inline-start: 0;
|
|
9155
|
+
display: block;
|
|
9156
|
+
inline-size: calc(var(--oc-live-w) * 1px);
|
|
9157
|
+
max-inline-size: none;
|
|
9158
|
+
block-size: calc(var(--oc-live-h) * 1px);
|
|
9159
|
+
border: 0;
|
|
9160
|
+
transform-origin: 0 0;
|
|
9161
|
+
scale: tan(atan2(100cqi, calc(var(--oc-live-w) * 1px)));
|
|
9162
|
+
}
|
|
9163
|
+
/* Right-to-left pages: scale from the other corner. */
|
|
9164
|
+
.oc-live-frame:dir(rtl) > :is(iframe, video, img, object, .oc-live-frame__content) { transform-origin: 100% 0; }
|
|
9165
|
+
|
|
9166
|
+
/* A picture of a page, not a page to use: clicks and scrolling pass the frame by. */
|
|
9167
|
+
.oc-live-frame--static > :is(iframe, video, img, object, .oc-live-frame__content) { pointer-events: none; }
|
|
9168
|
+
|
|
8847
9169
|
/* parts/media-message-thread.css */
|
|
8848
9170
|
/* File: packages/ui/src/parts/media-message-thread.css | Map: frame (grid: header / messages / composer) -> header (title, meta,
|
|
8849
9171
|
people, status, actions) -> wallpaper (masked doodles in a token color) -> scroll area (starts at the bottom)
|
|
@@ -9459,6 +9781,104 @@ a.oc-message__quote:focus-visible { outline: 2px solid var(--oc-ring); outline-o
|
|
|
9459
9781
|
.oc-media-thumb:hover > :is(img, video, .oc-media-art) { transform: scale(1.04); }
|
|
9460
9782
|
}
|
|
9461
9783
|
|
|
9784
|
+
/* parts/media-watermark.css */
|
|
9785
|
+
/* File: packages/ui/src/parts/media-watermark.css
|
|
9786
|
+
Map: overlay (click-through, sized to its box) -> text -> straight -> tiled -> corner stamp -> tones -> print
|
|
9787
|
+
Watermark: a light layer with large slanted text ("CONCEPT", "DRAFT", "SAMPLE") over an image, a card or a live
|
|
9788
|
+
frame. Put .oc-watermark as the last child of a positioned box (the utility .relative, or any position) with the
|
|
9789
|
+
text in a <span>. Clicks go through to what is underneath (pointer-events: none). The text scales with the box
|
|
9790
|
+
(container query units). Tokens: --oc-watermark-color, -opacity, -angle, -size. Omnia tokens only. */
|
|
9791
|
+
|
|
9792
|
+
.oc-watermark {
|
|
9793
|
+
--oc-watermark-color: var(--oc-foreground);
|
|
9794
|
+
--oc-watermark-opacity: 0.12;
|
|
9795
|
+
--oc-watermark-angle: -18deg;
|
|
9796
|
+
--oc-watermark-size: clamp(1.75rem, 14cqi, 12rem);
|
|
9797
|
+
position: absolute;
|
|
9798
|
+
z-index: 2;
|
|
9799
|
+
inset: 0;
|
|
9800
|
+
display: grid;
|
|
9801
|
+
place-items: center;
|
|
9802
|
+
overflow: hidden;
|
|
9803
|
+
container-type: size;
|
|
9804
|
+
border-radius: inherit;
|
|
9805
|
+
pointer-events: none;
|
|
9806
|
+
user-select: none;
|
|
9807
|
+
}
|
|
9808
|
+
.oc-watermark > span {
|
|
9809
|
+
rotate: var(--oc-watermark-angle);
|
|
9810
|
+
color: oklch(from var(--oc-watermark-color) l c h / var(--oc-watermark-opacity));
|
|
9811
|
+
font-size: var(--oc-watermark-size);
|
|
9812
|
+
font-weight: 800;
|
|
9813
|
+
line-height: 1;
|
|
9814
|
+
letter-spacing: 0.25em;
|
|
9815
|
+
text-transform: uppercase;
|
|
9816
|
+
white-space: nowrap;
|
|
9817
|
+
}
|
|
9818
|
+
|
|
9819
|
+
/* A logo (<img>, or an inline <svg> logo) or an icon (inline <svg> with currentColor) instead of, or next to, text.
|
|
9820
|
+
An <img> keeps its own colors at the watermark opacity; --mono turns it into a flat gray stamp. An inline <svg>
|
|
9821
|
+
takes the watermark color, like the text. Size: --oc-watermark-mark (default 40% of the box width). */
|
|
9822
|
+
.oc-watermark > :is(img, svg) {
|
|
9823
|
+
inline-size: var(--oc-watermark-mark, 40cqi);
|
|
9824
|
+
max-block-size: 70cqb;
|
|
9825
|
+
block-size: auto;
|
|
9826
|
+
rotate: var(--oc-watermark-angle);
|
|
9827
|
+
}
|
|
9828
|
+
.oc-watermark > img { opacity: calc(var(--oc-watermark-opacity) * 1.5); }
|
|
9829
|
+
.oc-watermark > svg { color: oklch(from var(--oc-watermark-color) l c h / var(--oc-watermark-opacity)); }
|
|
9830
|
+
.oc-watermark--mono > img { filter: grayscale(1) contrast(0.6); }
|
|
9831
|
+
/* Logo or icon above a word: wrap both in one <span class="oc-watermark__stack">. */
|
|
9832
|
+
.oc-watermark__stack { display: grid; justify-items: center; gap: 0.3em; }
|
|
9833
|
+
.oc-watermark__stack > :is(img, svg) { inline-size: 0.9em; block-size: auto; }
|
|
9834
|
+
.oc-watermark__stack > img { opacity: calc(var(--oc-watermark-opacity) * 1.5); }
|
|
9835
|
+
|
|
9836
|
+
/* Horizontal text instead of slanted. */
|
|
9837
|
+
.oc-watermark--straight { --oc-watermark-angle: 0deg; }
|
|
9838
|
+
|
|
9839
|
+
/* Tiled: repeat the text in several spans; they fill the box in a slanted grid (for proofs and previews). */
|
|
9840
|
+
.oc-watermark--tile {
|
|
9841
|
+
--oc-watermark-size: clamp(0.9rem, 4.5cqi, 2.25rem);
|
|
9842
|
+
/* Columns in rem: container units here would measure the parent of the box, not the box. */
|
|
9843
|
+
grid-template-columns: repeat(auto-fill, minmax(14rem, 1fr));
|
|
9844
|
+
align-content: space-evenly;
|
|
9845
|
+
inset: -25%;
|
|
9846
|
+
rotate: var(--oc-watermark-angle);
|
|
9847
|
+
}
|
|
9848
|
+
.oc-watermark--tile > :is(span, img, svg) { rotate: none; justify-self: center; }
|
|
9849
|
+
.oc-watermark--tile > span { letter-spacing: 0.15em; }
|
|
9850
|
+
.oc-watermark--tile > :is(img, svg) { inline-size: 2.5rem; }
|
|
9851
|
+
/* Logos and icons are narrower than words: narrower columns, so the whole box fills up. */
|
|
9852
|
+
.oc-watermark--tile:has(> :is(img, svg)) { grid-template-columns: repeat(auto-fill, minmax(4.5rem, 1fr)); }
|
|
9853
|
+
|
|
9854
|
+
/* A small stamp in a corner instead of across the middle: --corner (bottom right) or --corner-top (top right).
|
|
9855
|
+
Two classes, so a tone (--primary …) changes its color but not its readable opacity. */
|
|
9856
|
+
.oc-watermark:is(.oc-watermark--corner, .oc-watermark--corner-top) {
|
|
9857
|
+
--oc-watermark-angle: 0deg;
|
|
9858
|
+
--oc-watermark-size: 0.75rem;
|
|
9859
|
+
--oc-watermark-opacity: 0.75;
|
|
9860
|
+
place-items: end;
|
|
9861
|
+
padding: 0.75rem;
|
|
9862
|
+
}
|
|
9863
|
+
.oc-watermark--corner-top { place-items: start end; }
|
|
9864
|
+
.oc-watermark:is(.oc-watermark--corner, .oc-watermark--corner-top) > span {
|
|
9865
|
+
padding: 0.25rem 0.6rem;
|
|
9866
|
+
border: 1px solid oklch(from var(--oc-watermark-color) l c h / 0.35);
|
|
9867
|
+
border-radius: var(--oc-radius, 0.375rem);
|
|
9868
|
+
background: oklch(from var(--oc-background) l c h / 0.7);
|
|
9869
|
+
letter-spacing: 0.12em;
|
|
9870
|
+
}
|
|
9871
|
+
|
|
9872
|
+
/* Tones: light text for dark images, the brand color, or red for "not for use". */
|
|
9873
|
+
.oc-watermark--light { --oc-watermark-color: var(--color-white-100); --oc-watermark-opacity: 0.22; }
|
|
9874
|
+
.oc-watermark--primary { --oc-watermark-color: var(--oc-primary); --oc-watermark-opacity: 0.16; }
|
|
9875
|
+
.oc-watermark--destructive { --oc-watermark-color: var(--oc-destructive); --oc-watermark-opacity: 0.2; }
|
|
9876
|
+
|
|
9877
|
+
/* Printed proofs keep the watermark, a little stronger so it survives the printer. */
|
|
9878
|
+
@media print {
|
|
9879
|
+
.oc-watermark { --oc-watermark-opacity: 0.2; print-color-adjust: exact; }
|
|
9880
|
+
}
|
|
9881
|
+
|
|
9462
9882
|
/* parts/site-fact-list.css */
|
|
9463
9883
|
/* File: packages/ui/src/parts/site-fact-list.css
|
|
9464
9884
|
Map: plain -> compact -> stacked -> accent values -> narrow screens
|
|
@@ -9522,6 +9942,62 @@ a.oc-message__quote:focus-visible { outline: 2px solid var(--oc-ring); outline-o
|
|
|
9522
9942
|
.oc-link-arrow::before { transition: none; }
|
|
9523
9943
|
}
|
|
9524
9944
|
|
|
9945
|
+
/* parts/site-link-row.css */
|
|
9946
|
+
/* File: packages/ui/src/parts/site-link-row.css
|
|
9947
|
+
Map: row (wraps) -> link -> external icon (http links) -> GitHub mark (github.com links) -> tones -> sizes
|
|
9948
|
+
Link row: a row of links under a feature or product card ("Marketplace", "Source", "Docs"). Links to another site get
|
|
9949
|
+
an "opens elsewhere" arrow by themselves, links to github.com the GitHub mark instead; links on your own site get
|
|
9950
|
+
no icon. The icons are CSS masks in the text color, so they follow the tone and light/dark mode. */
|
|
9951
|
+
|
|
9952
|
+
.oc-link-row {
|
|
9953
|
+
display: flex;
|
|
9954
|
+
flex-wrap: wrap;
|
|
9955
|
+
gap: 0.4rem 1rem;
|
|
9956
|
+
margin: 0.9rem 0 0;
|
|
9957
|
+
padding: 0;
|
|
9958
|
+
list-style: none;
|
|
9959
|
+
font-size: 0.9rem;
|
|
9960
|
+
}
|
|
9961
|
+
.oc-link-row a {
|
|
9962
|
+
display: inline-flex;
|
|
9963
|
+
align-items: center;
|
|
9964
|
+
gap: 0.35rem;
|
|
9965
|
+
border-radius: 4px;
|
|
9966
|
+
color: var(--oc-primary);
|
|
9967
|
+
font-weight: 600;
|
|
9968
|
+
text-decoration: none;
|
|
9969
|
+
}
|
|
9970
|
+
.oc-link-row a:hover { text-decoration: underline; text-underline-offset: 0.2em; }
|
|
9971
|
+
.oc-link-row a:focus-visible { outline: 2px solid var(--oc-ring); outline-offset: 3px; }
|
|
9972
|
+
|
|
9973
|
+
/* Icons: one mask per kind, filled with the text color. */
|
|
9974
|
+
.oc-link-row a:is([href^="http://"], [href^="https://"])::after,
|
|
9975
|
+
.oc-link-row a[href*="github.com"]::before {
|
|
9976
|
+
content: "";
|
|
9977
|
+
flex: none;
|
|
9978
|
+
inline-size: 0.9em;
|
|
9979
|
+
aspect-ratio: 1;
|
|
9980
|
+
background: currentColor;
|
|
9981
|
+
mask: var(--oc-link-row-icon) center / contain no-repeat;
|
|
9982
|
+
}
|
|
9983
|
+
.oc-link-row a:is([href^="http://"], [href^="https://"])::after {
|
|
9984
|
+
--oc-link-row-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M7 17 17 7M9 7h8v8'/%3E%3C/svg%3E");
|
|
9985
|
+
}
|
|
9986
|
+
.oc-link-row a[href*="github.com"]::before {
|
|
9987
|
+
--oc-link-row-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 .5a11.5 11.5 0 0 0-3.64 22.41c.58.1.79-.25.79-.56v-2c-3.2.7-3.88-1.37-3.88-1.37-.52-1.33-1.28-1.69-1.28-1.69-1.05-.71.08-.7.08-.7 1.16.08 1.77 1.19 1.77 1.19 1.03 1.77 2.7 1.26 3.36.96.1-.75.4-1.26.73-1.55-2.55-.29-5.24-1.28-5.24-5.69 0-1.26.45-2.28 1.19-3.09-.12-.29-.52-1.46.11-3.05 0 0 .97-.31 3.17 1.18a11 11 0 0 1 5.77 0c2.2-1.49 3.17-1.18 3.17-1.18.63 1.59.23 2.76.11 3.05.74.81 1.19 1.83 1.19 3.09 0 4.42-2.7 5.39-5.26 5.68.41.36.78 1.06.78 2.14v3.17c0 .31.21.67.8.56A11.5 11.5 0 0 0 12 .5Z'/%3E%3C/svg%3E");
|
|
9988
|
+
}
|
|
9989
|
+
/* A GitHub link shows the GitHub mark instead of the arrow. */
|
|
9990
|
+
.oc-link-row a[href*="github.com"]::after { content: none; }
|
|
9991
|
+
|
|
9992
|
+
/* Tones: the element's accent (with an .oc-accent--* class), or muted text that brightens on hover. */
|
|
9993
|
+
.oc-link-row--accent a { color: light-dark(var(--oc-accent-from, var(--oc-primary)), oklch(from var(--oc-accent-from, var(--oc-primary)) max(l, 0.72) c h)); }
|
|
9994
|
+
.oc-link-row--muted a { color: var(--oc-muted-foreground); font-weight: 500; }
|
|
9995
|
+
.oc-link-row--muted a:hover { color: var(--oc-foreground); }
|
|
9996
|
+
|
|
9997
|
+
/* Sizes */
|
|
9998
|
+
.oc-link-row--sm { font-size: 0.8rem; gap: 0.3rem 0.8rem; }
|
|
9999
|
+
.oc-link-row--lg { font-size: 1rem; }
|
|
10000
|
+
|
|
9525
10001
|
/* parts/site-marquee.css */
|
|
9526
10002
|
/* File: packages/ui/src/parts/site-marquee.css
|
|
9527
10003
|
Map: pause on focus -> direction / speed modifiers -> plain items -> no fade -> reduced motion
|
|
@@ -10033,6 +10509,18 @@ a.oc-message__quote:focus-visible { outline: 2px solid var(--oc-ring); outline-o
|
|
|
10033
10509
|
.oc-prose--lg { font-size: 1.125rem; line-height: 1.75; }
|
|
10034
10510
|
.oc-prose--full { max-inline-size: none; }
|
|
10035
10511
|
|
|
10512
|
+
/* Compact: help text and about pages in a widget, side panel or popover. Smaller text, tighter rhythm and headings,
|
|
10513
|
+
full width of the panel. */
|
|
10514
|
+
.oc-prose--compact { max-inline-size: none; font-size: 0.8125rem; line-height: 1.5; }
|
|
10515
|
+
.oc-prose--compact :where(* + *) { margin-block-start: 0.7em; }
|
|
10516
|
+
.oc-prose--compact :where(h1) { font-size: 1.45em; }
|
|
10517
|
+
.oc-prose--compact :where(h2) { margin-block-start: 1.4em; font-size: 1.15em; }
|
|
10518
|
+
.oc-prose--compact :where(h3) { margin-block-start: 1.2em; font-size: 1.05em; }
|
|
10519
|
+
.oc-prose--compact :where(h4) { margin-block-start: 1em; }
|
|
10520
|
+
.oc-prose--compact :where(h1, h2, h3, h4) + :where(*) { margin-block-start: 0.35em; }
|
|
10521
|
+
.oc-prose--compact :where(.oc-prose-lead) { font-size: 1.08em; }
|
|
10522
|
+
.oc-prose--compact > :where(:first-child) { margin-block-start: 0; }
|
|
10523
|
+
|
|
10036
10524
|
@media (prefers-reduced-motion: reduce) {
|
|
10037
10525
|
.oc-prose :where(a) { transition: none; }
|
|
10038
10526
|
}
|