@breathe-ds/ui 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/README.md +50 -7
- package/components/AnchorNav.tsx +12 -4
- package/components/Button.tsx +11 -4
- package/components/Byline.tsx +3 -1
- package/components/CareSteps.tsx +86 -0
- package/components/ChatPreview.tsx +138 -0
- package/components/FeaturedPosts.tsx +80 -0
- package/components/Footer.tsx +47 -10
- package/components/Header.tsx +4 -2
- package/components/PageVideoHero.tsx +65 -23
- package/components/PauseButton.tsx +41 -0
- package/components/PhotoSequence.tsx +99 -0
- package/components/PlanTimeline.tsx +66 -0
- package/components/PostArticle.tsx +102 -0
- package/components/PostCard.tsx +69 -0
- package/components/ProfessionalCard.tsx +155 -50
- package/components/Rail.tsx +94 -0
- package/components/Rows.tsx +9 -3
- package/components/StoryPanel.tsx +107 -0
- package/components/useOnAppear.ts +39 -0
- package/package.json +13 -2
- package/theme.css +140 -0
- package/tokens/creeta.css +2 -0
- package/tokens/neutral.css +2 -0
- package/tokens/ttcab.css +13 -5
package/theme.css
CHANGED
|
@@ -25,6 +25,8 @@
|
|
|
25
25
|
--color-action: var(--cg-action); /* CTA/highlight — never plain text */
|
|
26
26
|
--color-action-text: var(--cg-action-text); /* text in the action color (AA) */
|
|
27
27
|
--color-on-action: var(--cg-on-action); /* text ON the action color (button) */
|
|
28
|
+
--color-action-tint: var(--cg-action-tint, var(--cg-surface)); /* highlighted panel/card: a 6% wash of the action color */
|
|
29
|
+
--color-action-line: var(--cg-action-line, var(--cg-action)); /* border of a highlighted card (3:1 on surface) */
|
|
28
30
|
--color-line: var(--cg-line); /* hairlines/borders */
|
|
29
31
|
|
|
30
32
|
/* ── Typography (roles; actual family comes from --cg-font-*) ── */
|
|
@@ -57,6 +59,20 @@
|
|
|
57
59
|
scroll-behavior: auto;
|
|
58
60
|
}
|
|
59
61
|
}
|
|
62
|
+
/* Tailwind v4's reset leaves buttons with the default cursor; in the family
|
|
63
|
+
everything that can be tapped shows the hand: buttons, links, the summary
|
|
64
|
+
of a collapse, labels of controls, selects. Disabled ones keep the arrow. */
|
|
65
|
+
button:not(:disabled),
|
|
66
|
+
[role="button"]:not([aria-disabled="true"]),
|
|
67
|
+
a[href],
|
|
68
|
+
summary,
|
|
69
|
+
label[for],
|
|
70
|
+
select:not(:disabled),
|
|
71
|
+
input[type="checkbox"]:not(:disabled),
|
|
72
|
+
input[type="radio"]:not(:disabled),
|
|
73
|
+
input[type="file"]:not(:disabled) {
|
|
74
|
+
cursor: pointer;
|
|
75
|
+
}
|
|
60
76
|
}
|
|
61
77
|
|
|
62
78
|
/* Outbound/anchor arrow on links: takes a small step toward where the link
|
|
@@ -104,3 +120,127 @@
|
|
|
104
120
|
.cg-lockup--entrance .cg-lockup__mark, .cg-lockup--entrance .cg-lockup__name, .cg-lockup--entrance .cg-lockup__tag{ animation: cg-lockup-fade 240ms ease var(--cg-entrance-delay,0ms) both; }
|
|
105
121
|
@keyframes cg-lockup-fade{ from{ opacity:0; } }
|
|
106
122
|
}
|
|
123
|
+
|
|
124
|
+
/* Rail: the horizontal list hides its scrollbar (the progress bar under it says how much is left). */
|
|
125
|
+
.cg-no-scrollbar {
|
|
126
|
+
scrollbar-width: none;
|
|
127
|
+
}
|
|
128
|
+
.cg-no-scrollbar::-webkit-scrollbar {
|
|
129
|
+
display: none;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/* ── Care flow drawings (CareSteps): ChatPreview, PlanTimeline, PhotoSequence ──
|
|
133
|
+
Ported from novo.creeta's globals.css. Only opacity and transform. */
|
|
134
|
+
|
|
135
|
+
/* ChatPreview: each bubble animates when it enters; the component sets the
|
|
136
|
+
rhythm (and the loop). Nothing animates without data-state="playing". */
|
|
137
|
+
@keyframes cg-bubble-in {
|
|
138
|
+
from {
|
|
139
|
+
opacity: 0;
|
|
140
|
+
transform: translateY(8px) scale(0.96);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
@keyframes cg-dot-pulse {
|
|
144
|
+
0%,
|
|
145
|
+
60%,
|
|
146
|
+
100% {
|
|
147
|
+
opacity: 0.35;
|
|
148
|
+
transform: none;
|
|
149
|
+
}
|
|
150
|
+
30% {
|
|
151
|
+
opacity: 1;
|
|
152
|
+
transform: translateY(-2px);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
.cg-chat[data-state="playing"] .cg-bubble {
|
|
156
|
+
animation: cg-bubble-in 320ms cubic-bezier(0.23, 1, 0.32, 1) both;
|
|
157
|
+
}
|
|
158
|
+
.cg-chat[data-state="playing"] .cg-typing i {
|
|
159
|
+
animation: cg-dot-pulse 900ms ease-in-out calc(var(--n) * 140ms) infinite;
|
|
160
|
+
}
|
|
161
|
+
.cg-chat[data-paused] .cg-bubble,
|
|
162
|
+
.cg-chat[data-paused] .cg-typing i {
|
|
163
|
+
animation-play-state: paused;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/* PlanTimeline, 6s loop: the line comes down from 0.2s to 1.7s and each dot
|
|
167
|
+
lights up when it arrives (0.2s, 0.95s, 1.7s); everything stays lit until
|
|
168
|
+
5.1s, goes off and restarts. One set of keyframes per dot. */
|
|
169
|
+
@keyframes cg-plan-line {
|
|
170
|
+
0%, 3.3% { opacity: 1; transform: scaleY(0); }
|
|
171
|
+
28.3%, 85% { opacity: 1; transform: scaleY(1); }
|
|
172
|
+
92%, 100% { opacity: 0; transform: scaleY(1); }
|
|
173
|
+
}
|
|
174
|
+
@keyframes cg-plan-dot-1 {
|
|
175
|
+
0%, 3.3% { opacity: 0; transform: scale(0.3); }
|
|
176
|
+
8.6%, 85% { opacity: 1; transform: none; }
|
|
177
|
+
92%, 100% { opacity: 0; transform: scale(0.3); }
|
|
178
|
+
}
|
|
179
|
+
@keyframes cg-plan-dot-2 {
|
|
180
|
+
0%, 15.8% { opacity: 0; transform: scale(0.3); }
|
|
181
|
+
21.1%, 85% { opacity: 1; transform: none; }
|
|
182
|
+
92%, 100% { opacity: 0; transform: scale(0.3); }
|
|
183
|
+
}
|
|
184
|
+
@keyframes cg-plan-dot-3 {
|
|
185
|
+
0%, 28.3% { opacity: 0; transform: scale(0.3); }
|
|
186
|
+
33.6%, 85% { opacity: 1; transform: none; }
|
|
187
|
+
92%, 100% { opacity: 0; transform: scale(0.3); }
|
|
188
|
+
}
|
|
189
|
+
/* The name out of turn stays at 75%, not less: ink at 75% over the card still
|
|
190
|
+
passes AA (creeta measured 5.03:1; at 45% it failed, WCAG 1.4.3). */
|
|
191
|
+
@keyframes cg-plan-name-1 {
|
|
192
|
+
0%, 3.3%, 92%, 100% { opacity: 0.75; }
|
|
193
|
+
8.6%, 85% { opacity: 1; }
|
|
194
|
+
}
|
|
195
|
+
@keyframes cg-plan-name-2 {
|
|
196
|
+
0%, 15.8%, 92%, 100% { opacity: 0.75; }
|
|
197
|
+
21.1%, 85% { opacity: 1; }
|
|
198
|
+
}
|
|
199
|
+
@keyframes cg-plan-name-3 {
|
|
200
|
+
0%, 28.3%, 92%, 100% { opacity: 0.75; }
|
|
201
|
+
33.6%, 85% { opacity: 1; }
|
|
202
|
+
}
|
|
203
|
+
.cg-plan[data-state="waiting"] .cg-plan-line { transform: scaleY(0); }
|
|
204
|
+
.cg-plan[data-state="waiting"] .cg-plan-dot { opacity: 0; }
|
|
205
|
+
.cg-plan[data-state="waiting"] .cg-plan-name { opacity: 0.75; }
|
|
206
|
+
.cg-plan[data-state="playing"] .cg-plan-line { animation: cg-plan-line 6s linear infinite; }
|
|
207
|
+
.cg-plan[data-state="playing"] .cg-plan-step[data-n="1"] .cg-plan-dot { animation: cg-plan-dot-1 6s cubic-bezier(0.23, 1, 0.32, 1) infinite; }
|
|
208
|
+
.cg-plan[data-state="playing"] .cg-plan-step[data-n="2"] .cg-plan-dot { animation: cg-plan-dot-2 6s cubic-bezier(0.23, 1, 0.32, 1) infinite; }
|
|
209
|
+
.cg-plan[data-state="playing"] .cg-plan-step[data-n="3"] .cg-plan-dot { animation: cg-plan-dot-3 6s cubic-bezier(0.23, 1, 0.32, 1) infinite; }
|
|
210
|
+
.cg-plan[data-state="playing"] .cg-plan-step[data-n="1"] .cg-plan-name { animation: cg-plan-name-1 6s ease infinite; }
|
|
211
|
+
.cg-plan[data-state="playing"] .cg-plan-step[data-n="2"] .cg-plan-name { animation: cg-plan-name-2 6s ease infinite; }
|
|
212
|
+
.cg-plan[data-state="playing"] .cg-plan-step[data-n="3"] .cg-plan-name { animation: cg-plan-name-3 6s ease infinite; }
|
|
213
|
+
/* Paused on the button, or off screen. Same weight as the rules above and after them. */
|
|
214
|
+
.cg-plan[data-state][data-stopped] .cg-plan-line,
|
|
215
|
+
.cg-plan[data-state][data-stopped] .cg-plan-step .cg-plan-dot,
|
|
216
|
+
.cg-plan[data-state][data-stopped] .cg-plan-step .cg-plan-name {
|
|
217
|
+
animation-play-state: paused;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/* PhotoSequence: the hidden checkbox pauses the photos through CSS. */
|
|
221
|
+
.cg-seq-pause:checked ~ .cg-seq img {
|
|
222
|
+
animation-play-state: paused !important;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
/* Reduced motion: the components do not even start; this is the second lock,
|
|
226
|
+
in case the preference changes with the page open. The sequence keeps the
|
|
227
|
+
first photo and loses the control (a nameless checkbox in the tab order
|
|
228
|
+
would fail WCAG 4.1.2). */
|
|
229
|
+
@media (prefers-reduced-motion: reduce) {
|
|
230
|
+
.cg-chat .cg-bubble,
|
|
231
|
+
.cg-chat .cg-typing i,
|
|
232
|
+
.cg-plan .cg-plan-line,
|
|
233
|
+
.cg-plan .cg-plan-dot,
|
|
234
|
+
.cg-plan .cg-plan-name {
|
|
235
|
+
animation: none !important;
|
|
236
|
+
opacity: 1;
|
|
237
|
+
transform: none;
|
|
238
|
+
}
|
|
239
|
+
.cg-seq img {
|
|
240
|
+
animation: none !important;
|
|
241
|
+
}
|
|
242
|
+
.cg-seq-control,
|
|
243
|
+
.cg-seq-pause {
|
|
244
|
+
display: none;
|
|
245
|
+
}
|
|
246
|
+
}
|
package/tokens/creeta.css
CHANGED
|
@@ -16,6 +16,8 @@
|
|
|
16
16
|
--cg-ink-body: #1e4f5b;
|
|
17
17
|
--cg-action: #ab2781; /* magenta (Agendar) */
|
|
18
18
|
--cg-action-text: #8f1f6c; /* darker magenta for text */
|
|
19
|
+
--cg-action-tint: #eae7ed; /* 6% magenta over mist: highlighted card */
|
|
20
|
+
--cg-action-line: #ab2781; /* magenta itself: 5.62:1 on mist */
|
|
19
21
|
--cg-on-action: #ffffff; /* white on magenta */
|
|
20
22
|
--cg-line: rgb(20 71 83 / 0.16);
|
|
21
23
|
--cg-font-heading: var(--font-quicksand), system-ui, sans-serif; /* Quicksand */
|
package/tokens/neutral.css
CHANGED
|
@@ -20,6 +20,8 @@
|
|
|
20
20
|
--cg-ink-body: #3f3f46;
|
|
21
21
|
--cg-action: #18181b;
|
|
22
22
|
--cg-action-text: #52525b;
|
|
23
|
+
--cg-action-tint: #e9e9ea;
|
|
24
|
+
--cg-action-line: #18181b;
|
|
23
25
|
--cg-on-action: #ffffff;
|
|
24
26
|
--cg-line: rgb(0 0 0 / 0.12);
|
|
25
27
|
--cg-font-heading: var(--font-quicksand), system-ui, sans-serif; /* Quicksand (fixed across the family) */
|
package/tokens/ttcab.css
CHANGED
|
@@ -3,9 +3,15 @@
|
|
|
3
3
|
- surface #fbf5e9 / ink #144753 ............ 9.41:1 (AAA)
|
|
4
4
|
- surface #fbf5e9 / ink-soft #54707a ....... 4.86:1 (AA)
|
|
5
5
|
- surface #fbf5e9 / ink-body #1e4f5b ....... 8.32:1 (AAA)
|
|
6
|
-
- surface #fbf5e9 / action-text #
|
|
6
|
+
- surface #fbf5e9 / action-text #bd3f0c .... 4.98:1 (AA)
|
|
7
7
|
- surface-panel #144753 / surface (text) ... 9.41:1 (AAA)
|
|
8
|
-
- action #
|
|
8
|
+
- action #e8541e / on-action #ffffff ...... 3.67:1 — the accent button
|
|
9
|
+
The action color is a vivid red-orange with WHITE text (decided 2026-10-29,
|
|
10
|
+
the Cloudflare/Airbnb route): 3.67:1 passes the 3:1 of UI components and of
|
|
11
|
+
large text, NOT the 4.5:1 of normal text. Conscious exception, limited to the
|
|
12
|
+
accent Button (one per block, same type scale as the other buttons). Small
|
|
13
|
+
controls never put white on it (ink, or action-tint + action-text). The logo
|
|
14
|
+
keeps its own #f6a22a.
|
|
9
15
|
*/
|
|
10
16
|
:root {
|
|
11
17
|
--cg-surface: #fbf5e9;
|
|
@@ -14,9 +20,11 @@
|
|
|
14
20
|
--cg-ink: #144753;
|
|
15
21
|
--cg-ink-soft: #54707a;
|
|
16
22
|
--cg-ink-body: #1e4f5b;
|
|
17
|
-
--cg-action: #
|
|
18
|
-
--cg-on-action: #
|
|
19
|
-
--cg-action-text: #
|
|
23
|
+
--cg-action: #e8541e; /* vivid red-orange: white on it 3.67:1 (large text / UI 3:1) */
|
|
24
|
+
--cg-on-action: #ffffff;
|
|
25
|
+
--cg-action-text: #bd3f0c; /* 4.98:1 on cream, 4.64:1 on the tint */
|
|
26
|
+
--cg-action-tint: #faebdd; /* 6% action over cream: highlighted card (ink 8.75:1) */
|
|
27
|
+
--cg-action-line: #e8541e; /* the action color itself: 3.38:1 on cream */
|
|
20
28
|
--cg-line: rgb(20 71 83 / 0.16);
|
|
21
29
|
--cg-font-heading: var(--font-quicksand), system-ui, sans-serif; /* Quicksand */
|
|
22
30
|
--cg-font-body: var(--font-figtree), system-ui, sans-serif; /* Figtree */
|