@lepid-labs/styles 1.0.0 → 1.0.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.
@@ -0,0 +1,101 @@
1
+ /* summer-cloud — stepper: a milestone rail with labelled step nodes (Retail
2
+ * Dashboard "Active Delivery"). Violet rail on a blend track; each step is
3
+ * .ld-stepper__step--complete solid violet node, white icon
4
+ * .ld-stepper__step--current white node, 2px violet border, raised shadow
5
+ * .ld-stepper__step--upcoming sunken node, faint icon
6
+ * The fill follows the state modifiers — no progress value to compute. */
7
+ :where([data-ld-style="summer-cloud"], [data-ld-style="summer-cloud"] *).ld-stepper {
8
+ display: flex;
9
+ align-items: flex-start;
10
+ list-style: none;
11
+ margin: 0;
12
+ padding: 0;
13
+ }
14
+ :where([data-ld-style="summer-cloud"], [data-ld-style="summer-cloud"] *).ld-stepper__step {
15
+ position: relative;
16
+ flex: 1 1 0;
17
+ min-width: 0;
18
+ display: flex;
19
+ flex-direction: column;
20
+ align-items: center;
21
+ gap: var(--ld-space-2);
22
+ text-align: center;
23
+ }
24
+ /* rail segment: from this node's centre to the next node's centre; the track is
25
+ * ::before, the fill ::after. Segments meet under the nodes, so the rail reads
26
+ * as one bar and the fill ends exactly at the current node. */
27
+ :where([data-ld-style="summer-cloud"], [data-ld-style="summer-cloud"] *).ld-stepper__step::before,
28
+ :where([data-ld-style="summer-cloud"], [data-ld-style="summer-cloud"] *).ld-stepper__step::after {
29
+ content: "";
30
+ position: absolute;
31
+ top: 0.75rem;
32
+ left: 50%;
33
+ width: 100%;
34
+ height: 0.5rem;
35
+ border-radius: var(--ld-radius-pill);
36
+ }
37
+ :where([data-ld-style="summer-cloud"], [data-ld-style="summer-cloud"] *).ld-stepper__step:last-child::before,
38
+ :where([data-ld-style="summer-cloud"], [data-ld-style="summer-cloud"] *).ld-stepper__step:last-child::after { display: none; }
39
+ :where([data-ld-style="summer-cloud"], [data-ld-style="summer-cloud"] *).ld-stepper__step::before { background: var(--ld-bg-blend); }
40
+ :where([data-ld-style="summer-cloud"], [data-ld-style="summer-cloud"] *).ld-stepper__step::after {
41
+ width: 0;
42
+ background: var(--ld-primary);
43
+ box-shadow: 0 0 10px rgba(69, 0, 217, 0.5);
44
+ transition: width var(--ld-transition);
45
+ }
46
+ :where([data-ld-style="summer-cloud"], [data-ld-style="summer-cloud"] *).ld-stepper__step--complete::after { width: 100%; }
47
+
48
+ :where([data-ld-style="summer-cloud"], [data-ld-style="summer-cloud"] *).ld-stepper__node {
49
+ position: relative;
50
+ z-index: 1;
51
+ display: inline-flex;
52
+ align-items: center;
53
+ justify-content: center;
54
+ width: 2rem;
55
+ height: 2rem;
56
+ border-radius: 50%;
57
+ box-sizing: border-box;
58
+ font-family: var(--ld-font-mono);
59
+ font-size: 12px;
60
+ font-weight: var(--ld-font-weight-bold);
61
+ line-height: 1;
62
+ transition: background var(--ld-transition), color var(--ld-transition), box-shadow var(--ld-transition);
63
+ }
64
+ :where([data-ld-style="summer-cloud"], [data-ld-style="summer-cloud"] *).ld-stepper__node > svg { width: 1rem; height: 1rem; }
65
+ :where([data-ld-style="summer-cloud"], [data-ld-style="summer-cloud"] *).ld-stepper__step--complete .ld-stepper__node {
66
+ background: var(--ld-primary);
67
+ color: var(--ld-on-primary);
68
+ }
69
+ :where([data-ld-style="summer-cloud"], [data-ld-style="summer-cloud"] *).ld-stepper__step--current .ld-stepper__node {
70
+ background: var(--ld-surface);
71
+ border: 2px solid var(--ld-primary);
72
+ color: var(--ld-primary);
73
+ box-shadow: var(--ld-shadow-raised);
74
+ }
75
+ :where([data-ld-style="summer-cloud"], [data-ld-style="summer-cloud"] *).ld-stepper__step--upcoming .ld-stepper__node {
76
+ background: var(--ld-surface-sunken);
77
+ color: var(--ld-faint);
78
+ }
79
+
80
+ /* label voice: mono 12px, tracked, sentence case */
81
+ :where([data-ld-style="summer-cloud"], [data-ld-style="summer-cloud"] *).ld-stepper__label {
82
+ font-family: var(--ld-font-mono);
83
+ font-size: 12px;
84
+ font-weight: 500;
85
+ letter-spacing: var(--ld-tracking-wide);
86
+ line-height: 1.3;
87
+ color: var(--ld-faint);
88
+ transition: color var(--ld-transition);
89
+ }
90
+ :where([data-ld-style="summer-cloud"], [data-ld-style="summer-cloud"] *).ld-stepper__step--complete .ld-stepper__label { color: var(--ld-on-surface); }
91
+ :where([data-ld-style="summer-cloud"], [data-ld-style="summer-cloud"] *).ld-stepper__step--current .ld-stepper__label {
92
+ color: var(--ld-primary);
93
+ font-weight: var(--ld-font-weight-bold);
94
+ }
95
+ :where([data-ld-style="summer-cloud"], [data-ld-style="summer-cloud"] *).ld-stepper__step--upcoming .ld-stepper__label { color: var(--ld-faint); }
96
+
97
+ @media (prefers-reduced-motion: reduce) {
98
+ :where([data-ld-style="summer-cloud"], [data-ld-style="summer-cloud"] *).ld-stepper__step::after,
99
+ :where([data-ld-style="summer-cloud"], [data-ld-style="summer-cloud"] *).ld-stepper__node,
100
+ :where([data-ld-style="summer-cloud"], [data-ld-style="summer-cloud"] *).ld-stepper__label { transition: none; }
101
+ }
@@ -36,3 +36,45 @@
36
36
  :where([data-ld-style="summer-cloud"], [data-ld-style="summer-cloud"] *).ld-tabpanel {
37
37
  padding: var(--ld-space-3) 0;
38
38
  }
39
+
40
+ /* Sliding indicator: one bar on the tablist, pinned to the active tab by
41
+ * anchor positioning, takes over the underline. Its inline edges transition
42
+ * separately — with data-ld-dir ("forward" | "back", set by the Tabs
43
+ * component) the edge nearer the target leads and the far edge trails, so the
44
+ * bar reaches for the tab; without it the bar just slides. Browsers without
45
+ * anchor positioning keep the static underline above. */
46
+ @supports (anchor-name: --ld-a) and (anchor-scope: --ld-a) {
47
+ :where([data-ld-style="summer-cloud"], [data-ld-style="summer-cloud"] *).ld-tabs {
48
+ position: relative;
49
+ anchor-scope: --ld-tab-active;
50
+ }
51
+ :where([data-ld-style="summer-cloud"], [data-ld-style="summer-cloud"] *).ld-tabs :is(.ld-tab--active, .ld-tab[aria-selected="true"]) {
52
+ anchor-name: --ld-tab-active;
53
+ border-bottom-color: transparent;
54
+ }
55
+ :where([data-ld-style="summer-cloud"], [data-ld-style="summer-cloud"] *).ld-tabs:where(:has(.ld-tab--active, .ld-tab[aria-selected="true"]))::after {
56
+ content: "";
57
+ position: absolute;
58
+ position-anchor: --ld-tab-active;
59
+ inset-block-end: anchor(bottom);
60
+ inset-inline: anchor(start) anchor(end);
61
+ block-size: 2px;
62
+ background: var(--ld-primary);
63
+ border-radius: 2px 2px 0 0;
64
+ pointer-events: none;
65
+ transition: inset-inline-start var(--ld-slide-lead), inset-inline-end var(--ld-slide-lead);
66
+ }
67
+ :where([data-ld-style="summer-cloud"], [data-ld-style="summer-cloud"] *).ld-tabs[data-ld-dir="forward"]::after {
68
+ transition: inset-inline-start var(--ld-slide-trail), inset-inline-end var(--ld-slide-lead);
69
+ }
70
+ :where([data-ld-style="summer-cloud"], [data-ld-style="summer-cloud"] *).ld-tabs[data-ld-dir="back"]::after {
71
+ transition: inset-inline-start var(--ld-slide-lead), inset-inline-end var(--ld-slide-trail);
72
+ }
73
+ }
74
+
75
+ @media (prefers-reduced-motion: reduce) {
76
+ :where([data-ld-style="summer-cloud"], [data-ld-style="summer-cloud"] *).ld-tabs::after,
77
+ :where([data-ld-style="summer-cloud"], [data-ld-style="summer-cloud"] *).ld-tabs[data-ld-dir]::after {
78
+ transition: none;
79
+ }
80
+ }
@@ -80,24 +80,58 @@ Class prefix `ld-` (shared across themes so `@lepid-labs/ui-react` stays
80
80
  theme-agnostic). Variants use BEM-ish modifiers (`ld-btn--primary`).
81
81
 
82
82
  - **Card** `.ld-card` — glass panel; `--floating` adds the Level 2 hover lift.
83
+ - **Status card** `.ld-status-card` — dense dashboard card on high glass, raised shadow on hover (from pulse's repo
84
+ card): 3px left edge takes a semantic `--<tone>`, `data-ld-attention="<tone>"`
85
+ adds an outline + glow ring, `data-ld-changed` replays a 30s tint flash.
86
+ Parts: `__watermark`, `__head`, `__prefix`, `__title`, `__meta`, `__note`,
87
+ `__rows`, `__row` (`-lead`/`-main`/`-trail`), `__footer`, `__empty`.
83
88
  - **NavLink** `.ld-link` — pill, sky-tint wash, `→` slides 4px on hover;
84
89
  `--active` / `[aria-current=page]` becomes the violet underline rule.
85
90
  - **Button** `.ld-btn` — glass by default; `--primary` (solid violet CTA, one
86
91
  per view), `--accent` (sky-edged glass), `--ghost`, `--danger`. `--sm` is a
87
92
  compact size scaled to `.ld-badge`, for inline/table-row actions; the pill
88
93
  shape is kept.
94
+ - **Hold button** `.ld-btn--hold` (+ `__ring`, `__body`, `__label`, `__hint`,
95
+ `__meter`) — hold-to-confirm: a 3px conic **violet** ring around the icon
96
+ well fills as `--ld-hold` goes 0→1, on the glass pill. With `--danger` the
97
+ pill stays glass with deep-red text (the ring and hint carry the state; a
98
+ violet ring on the solid red CTA would fight it). Press does not shrink
99
+ the pill — the ring is the feedback. `data-ld-hold="fired"` bounces to
100
+ 1.06 (dropped under reduced motion; the fill stays). Window:
101
+ `--ld-hold-duration` 350 ms — soft and unhurried.
102
+ - **Button group** `.ld-btn-group` (+ `--block`) — one long track with
103
+ `.ld-btn` segments lined up inside; the track owns the chrome and the
104
+ segments drop theirs. A long glass pill; segments are pills inside it.
105
+ The pressed segment (`aria-pressed="true"` / `.ld-btn--active`) floats up as
106
+ a white chip with bold violet text and a violet-tinted shadow. No hover
107
+ scale inside the pill (neighbours would overlap); the 0.97 press stays.
108
+ With one pressed segment the chrome is a single sliding chip: the edge
109
+ nearer the new segment leads, the far edge trails on the bounciest spring of the three themes
110
+ (`--ld-slide-lead` / `--ld-slide-trail`, direction from `data-ld-dir`).
111
+ Variants tint the label only; `--block` fills the row with equal-width
112
+ segments. Use `role="group"` + `aria-label`.
89
113
  - **Form** `.ld-input`, `.ld-textarea`, `.ld-select`, `.ld-label`, `.ld-field`,
90
114
  `.ld-checkbox`, `.ld-radio`, `.ld-switch`, `.ld-choice` — sunken fields, no
91
115
  resting border, sky-blue ring on focus. The switch is the oversized
92
116
  "cloud-toggle": squishy, and green when live.
93
117
  - **Badge** `.ld-badge` + semantic modifiers — solid pills, mono uppercase.
118
+ `--sm` is the 9px dashboard pill; `--pulse` the amber call to action with a
119
+ breathing glow.
94
120
  **Chip** `.ld-chip` — outlined filter chip; `--selected` fills violet.
95
121
  - **Alert** `.ld-alert` — glass card with a 4px semantic left rule.
96
122
  - **Dialog** `.ld-dialog` — native `<dialog>`, opaque white, blurred backdrop.
97
- - **Tabs** `.ld-tabs`/`.ld-tab`/`.ld-tabpanel` — violet underline when active.
123
+ - **Tabs** `.ld-tabs`/`.ld-tab`/`.ld-tabpanel` — violet underline when active; it stretches to the new tab and bounces back to width (same slide tokens).
98
124
  - **Table** `.ld-table` — mono uppercase headers, sky-tint row hover; add
99
125
  `.ld-num` to numeric cells for the mono/right-aligned treatment.
100
126
  - **Progress** `.ld-progress`, **Spinner** `.ld-spinner` — glowing violet.
127
+ - **Stepper** `.ld-stepper` (+ `__step`, `__node`, `__label`) — milestone
128
+ rail from the Retail Dashboard "Active Delivery" box: glowing violet fill on
129
+ a blend track, 2rem nodes. `__step--complete` is a solid violet node with a
130
+ white icon and an on-surface label; `--current` a white node with a 2px
131
+ violet border, violet icon, raised shadow, and violet label; `--upcoming` a
132
+ sunken node with faint icon and label. The rail is per-step
133
+ (`::before` track, `::after` fill), so the fill follows the modifiers and
134
+ `aria-current="step"` marks the active node.
101
135
  - **Muted text** `.ld-muted` — faint secondary/empty-state text;
102
136
  `color: var(--ld-faint)`, italic — a friendly, soft touch consistent with
103
137
  the theme's airy, optimistic voice.
@@ -2,8 +2,11 @@
2
2
  @import "./tokens.css";
3
3
  @import "./base.css";
4
4
  @import "./components/card.css";
5
+ @import "./components/status-card.css";
5
6
  @import "./components/link.css";
6
7
  @import "./components/button.css";
8
+ @import "./components/button-hold.css";
9
+ @import "./components/button-group.css";
7
10
  @import "./components/form.css";
8
11
  @import "./components/badge.css";
9
12
  @import "./components/alert.css";
@@ -11,5 +14,6 @@
11
14
  @import "./components/tabs.css";
12
15
  @import "./components/table.css";
13
16
  @import "./components/progress.css";
17
+ @import "./components/stepper.css";
14
18
  @import "./components/muted.css";
15
19
  @import "./components/pre.css";
@@ -76,6 +76,12 @@
76
76
  --ld-blur: 12px;
77
77
  --ld-blur-high: 20px; /* (extra) */
78
78
  --ld-transition: 0.3s;
79
+ --ld-hold-duration: 350ms; /* (extra) hold-to-confirm commitment window */
80
+ /* (extra) sliding indicator — tabs underline, button-group pill. The edge
81
+ * nearer the target leads; the far edge trails on a soft, bouncy spring that overshoots
82
+ * inward, so the indicator stretches across the gap and snaps back to shape. */
83
+ --ld-slide-lead: 0.26s cubic-bezier(0.2, 0.9, 0.3, 1);
84
+ --ld-slide-trail: 0.65s linear(0, 0.092, 0.301, 0.545, 0.767, 0.939, 1.052, 1.11, 1.126, 1.114, 1.088, 1.057, 1.029, 1.008, 0.993, 0.986, 0.984, 0.986, 0.989, 0.993, 0.996, 0.999, 1.001, 1.002, 1);
79
85
  --ld-ease-bounce: cubic-bezier(0.34, 1.56, 0.64, 1); /* (extra) */
80
86
 
81
87
  /* elevation (extra) — tinted with the primary, never grey */