@junoput01/junoui 0.3.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +219 -0
- package/README.md +23 -19
- package/dist/css/juno-custom-media.css +32 -0
- package/dist/css/juno.css +1216 -60
- package/dist/icons/inline.js +22 -0
- package/docs/accessibility.md +55 -34
- package/docs/boot-shell.md +295 -0
- package/docs/components/README.md +46 -43
- package/docs/components/dock.md +167 -8
- package/docs/components/drawer.md +47 -7
- package/docs/components/fold-slot.md +31 -0
- package/docs/components/icon-loader.md +85 -18
- package/docs/components/icon.md +21 -0
- package/docs/components/load-state.md +131 -0
- package/docs/components/loader.md +13 -5
- package/docs/components/pillbar.md +157 -10
- package/docs/components/reload.md +41 -0
- package/docs/components/skeleton.md +22 -15
- package/docs/components/thumb.md +34 -14
- package/docs/design-guidelines.md +26 -0
- package/docs/getting-started.md +23 -0
- package/docs/ios-conformance.md +224 -0
- package/docs/layout.md +71 -1
- package/docs/web.md +6 -0
- package/package.json +5 -2
- package/src/css/base.css +169 -6
- package/src/css/components/dock.css +322 -0
- package/src/css/components/drawer.css +40 -3
- package/src/css/components/fold-slot.css +44 -0
- package/src/css/components/icon-loader.css +32 -18
- package/src/css/components/icon.css +6 -4
- package/src/css/components/load-state.css +136 -0
- package/src/css/components/loader.css +6 -0
- package/src/css/components/menu.css +4 -0
- package/src/css/components/modal.css +24 -3
- package/src/css/components/navbar.css +5 -1
- package/src/css/components/pillbar.css +207 -7
- package/src/css/components/reload.css +48 -0
- package/src/css/components/skeleton.css +41 -13
- package/src/css/components/tabs.css +5 -0
- package/src/css/components/thumb.css +63 -1
- package/src/css/components/toast.css +5 -1
- package/src/css/density.css +22 -0
- package/src/css/layout.css +30 -2
- package/src/css/utilities.css +4 -1
|
@@ -9,10 +9,22 @@
|
|
|
9
9
|
* <figure class="juno-thumb" style="aspect-ratio: 1">
|
|
10
10
|
* <img src="…" alt="Sunset clip" onerror="this.remove()" />
|
|
11
11
|
* </figure>
|
|
12
|
-
*
|
|
12
|
+
* \3c !-- known-missing: ship no <img>; label the figure instead -->
|
|
13
13
|
* <figure class="juno-thumb juno-thumb--video" role="img" aria-label="Preview unavailable"></figure>
|
|
14
14
|
* The onerror one-liner is the whole JS contract (optional, stateless):
|
|
15
15
|
* a broken image removes itself and the placeholder underneath shows.
|
|
16
|
+
* Aspect is locked by default (--juno-thumb-ratio, square) so a media wall's
|
|
17
|
+
* scroll height is stable before anything loads; override per instance with
|
|
18
|
+
* style="--juno-thumb-ratio: 16/9" (an inline aspect-ratio still wins too).
|
|
19
|
+
* Selection is an outline (never a border — a border would shift the frame)
|
|
20
|
+
* toggled by a class/data-attr; junoui never decides what's selected.
|
|
21
|
+
* Corner slots anchor badges/duration chips over the media with logical
|
|
22
|
+
* inset so they swap sides correctly under dir="rtl".
|
|
23
|
+
* Usage:
|
|
24
|
+
* <figure class="juno-thumb juno-thumb--selected">
|
|
25
|
+
* <img src="…" alt="Sunset clip" onerror="this.remove()" />
|
|
26
|
+
* <span class="juno-thumb__corner juno-thumb__corner--top-end badge">0:42</span>
|
|
27
|
+
* </figure>
|
|
16
28
|
* ════════════════════════════════════════════════════════════════════ */
|
|
17
29
|
|
|
18
30
|
.juno-thumb {
|
|
@@ -23,12 +35,30 @@
|
|
|
23
35
|
justify-content: center;
|
|
24
36
|
gap: var(--juno-space-4);
|
|
25
37
|
margin: 0;
|
|
38
|
+
aspect-ratio: var(--juno-thumb-ratio, 1);
|
|
26
39
|
overflow: hidden;
|
|
27
40
|
background: var(--juno-s2);
|
|
28
41
|
border: var(--juno-border-width-1) solid var(--juno-border);
|
|
29
42
|
border-radius: var(--juno-radius-3);
|
|
30
43
|
}
|
|
31
44
|
|
|
45
|
+
/* Flush — drop the border/radius for tight walls where the frame's own edge
|
|
46
|
+
would fight the grid (full-bleed tiles); the media stays edge-to-edge via
|
|
47
|
+
object-fit: cover regardless. */
|
|
48
|
+
.juno-thumb--flush {
|
|
49
|
+
border: none;
|
|
50
|
+
border-radius: 0;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/* Selected — an inset outline, not a border: it overlays the existing frame
|
|
54
|
+
edge instead of adding to the box, so nothing reflows when selection
|
|
55
|
+
toggles. Role-neutral (--juno-active), matching the checkbox/switch focus
|
|
56
|
+
ring elsewhere in the system. */
|
|
57
|
+
.juno-thumb--selected {
|
|
58
|
+
outline: var(--juno-border-width-2) solid var(--juno-active);
|
|
59
|
+
outline-offset: calc(-1 * var(--juno-border-width-2));
|
|
60
|
+
}
|
|
61
|
+
|
|
32
62
|
/* placeholder glyph (Phosphor "images", masked so it takes any color) */
|
|
33
63
|
.juno-thumb::before {
|
|
34
64
|
--juno-thumb-glyph: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 256 256'%3E%3Cpath d='M160,88a16,16,0,1,1,16,16A16,16,0,0,1,160,88Zm76-32V160a20,20,0,0,1-20,20H204v20a20,20,0,0,1-20,20H40a20,20,0,0,1-20-20V88A20,20,0,0,1,40,68H60V56A20,20,0,0,1,80,36H216A20,20,0,0,1,236,56ZM180,180H80a20,20,0,0,1-20-20V92H44V196H180Zm-21.66-24L124,121.66,89.66,156ZM212,60H84v67.72l25.86-25.86a20,20,0,0,1,28.28,0L192.28,156H212Z'/%3E%3C/svg%3E");
|
|
@@ -67,3 +97,35 @@
|
|
|
67
97
|
block-size: 100%;
|
|
68
98
|
object-fit: cover;
|
|
69
99
|
}
|
|
100
|
+
|
|
101
|
+
/* Corner overlay — anchor a badge, check, or duration chip over the media
|
|
102
|
+
without joining flow or touching the frame's aspect-ratio. Pick one
|
|
103
|
+
position modifier; the base only sets stacking + inset from the frame
|
|
104
|
+
edge. Logical inset (not top/left) so start/end swap under dir="rtl" —
|
|
105
|
+
and the modifiers are named start/end for the same reason: a `--top-right`
|
|
106
|
+
that renders top-LEFT in RTL would be a trap. */
|
|
107
|
+
.juno-thumb__corner {
|
|
108
|
+
position: absolute;
|
|
109
|
+
z-index: 1;
|
|
110
|
+
margin: var(--juno-space-4);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
.juno-thumb__corner--top-start {
|
|
114
|
+
inset-block-start: 0;
|
|
115
|
+
inset-inline-start: 0;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
.juno-thumb__corner--top-end {
|
|
119
|
+
inset-block-start: 0;
|
|
120
|
+
inset-inline-end: 0;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
.juno-thumb__corner--bottom-start {
|
|
124
|
+
inset-block-end: 0;
|
|
125
|
+
inset-inline-start: 0;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
.juno-thumb__corner--bottom-end {
|
|
129
|
+
inset-block-end: 0;
|
|
130
|
+
inset-inline-end: 0;
|
|
131
|
+
}
|
|
@@ -91,7 +91,11 @@
|
|
|
91
91
|
@media (width <= 639.98px) {
|
|
92
92
|
.juno-toast-stack {
|
|
93
93
|
inset-inline: var(--juno-space-12);
|
|
94
|
-
|
|
94
|
+
|
|
95
|
+
/* unit-bearing env() fallback: inside calc() a unitless `0` is a <number>,
|
|
96
|
+
which invalidates the sum and drops the whole declaration (the stack
|
|
97
|
+
would then sit flush at 0 on any device without a safe area). */
|
|
98
|
+
inset-block-end: calc(var(--juno-space-12) + env(safe-area-inset-bottom, 0px));
|
|
95
99
|
inline-size: auto;
|
|
96
100
|
}
|
|
97
101
|
|
package/src/css/density.css
CHANGED
|
@@ -38,3 +38,25 @@
|
|
|
38
38
|
--juno-tile-min: 108px;
|
|
39
39
|
--juno-gap-content: var(--juno-space-4);
|
|
40
40
|
}
|
|
41
|
+
|
|
42
|
+
/* auto — OPT-IN. `comfortable`/`compact` never change meaning; a consumer
|
|
43
|
+
* must explicitly write `data-juno-density="auto"` to get this behavior.
|
|
44
|
+
* Baseline (any pointer, any viewport ≥ 640px) is comfortable — no rule
|
|
45
|
+
* needed here, it inherits the :root defaults above by not matching
|
|
46
|
+
* `[data-juno-density='compact']`. Only a small-viewport COARSE pointer
|
|
47
|
+
* (phone, not a touch laptop) re-densifies, mirroring the precedent already
|
|
48
|
+
* set by base.css's own `@media (pointer: coarse)` tap-target rule — this is
|
|
49
|
+
* a viewport-level document concern (set on <html>/<body>), not a component
|
|
50
|
+
* in an unknown layout, so a viewport query is the right tool here (container
|
|
51
|
+
* queries can't see pointer type anyway).
|
|
52
|
+
*
|
|
53
|
+
* NEVER shrinks a control's min-height — --juno-size-tap-min stays governed
|
|
54
|
+
* solely by base.css's coarse-pointer rule (20260802-020 / WCAG 2.5.5).
|
|
55
|
+
* This block only shrinks padding/gap/tile sizing, same contract as compact. */
|
|
56
|
+
@media (pointer: coarse) and (width <= 639.98px) {
|
|
57
|
+
[data-juno-density='auto'] {
|
|
58
|
+
--juno-tile-min: 104px;
|
|
59
|
+
--juno-gap-content: var(--juno-space-2);
|
|
60
|
+
--juno-pad-surface-inline: var(--juno-space-12);
|
|
61
|
+
}
|
|
62
|
+
}
|
package/src/css/layout.css
CHANGED
|
@@ -82,13 +82,41 @@
|
|
|
82
82
|
flex-basis: calc((var(--juno-switcher-threshold, var(--juno-bp-sm)) - 100%) * 999);
|
|
83
83
|
}
|
|
84
84
|
|
|
85
|
-
/*
|
|
85
|
+
/* Scroller — bare scroll-container primitive underneath every scrolling
|
|
86
|
+
region in the library (.juno-reel, .juno-app-shell__main, tab strips…).
|
|
87
|
+
Three knobs, each a custom prop with the sane-default fallback: overflow
|
|
88
|
+
axis, overscroll containment, and snap type — so a consumer opts into
|
|
89
|
+
containment/snap without re-deriving them, and opts OUT (snap: none is
|
|
90
|
+
the default here) without fighting a hardcoded value. `--x`/`--y` pick a
|
|
91
|
+
single scroll axis; `--bare` hides the scrollbar cross-browser; a
|
|
92
|
+
`.juno-snap` child opts into the snap stop once the container snaps.
|
|
93
|
+
<div class="juno-scroller juno-scroller--y">…</div>
|
|
94
|
+
<div class="juno-scroller juno-scroller--x juno-scroller--bare"
|
|
95
|
+
style="--juno-scroller-snap:x proximity">
|
|
96
|
+
<div class="juno-snap">…</div>
|
|
97
|
+
</div> */
|
|
98
|
+
.juno-scroller {
|
|
99
|
+
overflow: var(--juno-scroller-overflow, auto);
|
|
100
|
+
overscroll-behavior: var(--juno-scroller-overscroll, contain);
|
|
101
|
+
scroll-snap-type: var(--juno-scroller-snap, none);
|
|
102
|
+
}
|
|
103
|
+
.juno-scroller--x { overflow: auto hidden; }
|
|
104
|
+
.juno-scroller--y { overflow: hidden auto; }
|
|
105
|
+
.juno-scroller--bare { scrollbar-width: none; }
|
|
106
|
+
.juno-scroller--bare::-webkit-scrollbar { display: none; }
|
|
107
|
+
.juno-scroller > .juno-snap { scroll-snap-align: var(--juno-snap-align, start); }
|
|
108
|
+
|
|
109
|
+
/* Reel — horizontal scroll row (overflowing chips, timelines). A
|
|
110
|
+
.juno-scroller preset: single inline axis, mandatory snap by default —
|
|
111
|
+
override the mode per instance with --juno-scroller-snap (e.g. `inline
|
|
112
|
+
proximity` for a softer magnet, or `none` to opt out and keep only the
|
|
113
|
+
containment + layout). Default output is unchanged from before. */
|
|
86
114
|
.juno-reel {
|
|
87
115
|
display: flex;
|
|
88
116
|
gap: var(--juno-reel-space, var(--juno-space-12));
|
|
89
117
|
overflow-x: auto;
|
|
90
118
|
overscroll-behavior-inline: contain;
|
|
91
|
-
scroll-snap-type: inline mandatory;
|
|
119
|
+
scroll-snap-type: var(--juno-scroller-snap, inline mandatory);
|
|
92
120
|
}
|
|
93
121
|
.juno-reel > * { scroll-snap-align: start; flex: 0 0 auto; }
|
|
94
122
|
|
package/src/css/utilities.css
CHANGED
|
@@ -40,8 +40,11 @@
|
|
|
40
40
|
font-variant-numeric: tabular-nums;
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
+
/* --juno-label-size: optional size override, set by an ancestor (e.g. a
|
|
44
|
+
* density wrapper or a "compact" section) — never declared here, so it
|
|
45
|
+
* isn't shadowed for descendants that also want to read it. */
|
|
43
46
|
.juno-label {
|
|
44
|
-
font-size: var(--juno-font-size-13);
|
|
47
|
+
font-size: var(--juno-label-size, var(--juno-font-size-13));
|
|
45
48
|
color: var(--juno-label);
|
|
46
49
|
}
|
|
47
50
|
|