@breathe-ds/ui 0.1.0 → 0.2.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/LICENSE +21 -0
- package/README.md +157 -142
- package/components/Accordion.tsx +11 -10
- package/components/AnchorNav.tsx +33 -21
- package/components/BackgroundVideo.tsx +14 -14
- package/components/BottomNav.tsx +69 -68
- package/components/BreatheMark.tsx +12 -11
- package/components/Button.tsx +12 -12
- package/components/Card.tsx +5 -5
- package/components/Container.tsx +4 -4
- package/components/Curtain.tsx +152 -0
- package/components/Footer.tsx +186 -77
- package/components/Header.tsx +32 -17
- package/components/LanguageSwitcher.tsx +139 -0
- package/components/Lockup.tsx +40 -39
- package/components/PageVideoHero.tsx +53 -53
- package/components/PillList.tsx +4 -4
- package/components/SectionKicker.tsx +3 -3
- package/components/icons.tsx +6 -6
- package/components/marks/creeta.tsx +22 -22
- package/components/marks/ttcab.tsx +13 -13
- package/package.json +7 -5
- package/theme.css +21 -21
- package/tokens/creeta.css +10 -11
- package/tokens/neutral.css +7 -7
- package/tokens/ttcab.css +8 -8
- package/components/Cortina.tsx +0 -152
|
@@ -1,23 +1,23 @@
|
|
|
1
1
|
import type { CSSProperties } from "react";
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
*
|
|
5
|
-
* public/brand/creeta-simbolo.svg
|
|
6
|
-
*
|
|
7
|
-
* Lockup
|
|
8
|
-
*
|
|
4
|
+
* Creeta brand (Centro de Reequilíbrio Toracoabdominal), copied from the site's
|
|
5
|
+
* public/brand/creeta-simbolo.svg and creeta-tipo.svg. Symbol (three waves +
|
|
6
|
+
* magenta dot) and "creeta" wordmark kept separate, so the Curtain and the
|
|
7
|
+
* Lockup can assemble the arrangements. Do not edit by hand: the drawing is
|
|
8
|
+
* the one from the manual. The symbol colors are the logo's, not the site tokens.
|
|
9
9
|
*/
|
|
10
10
|
export const CREETA_COLORS = {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
11
|
+
midWave: "#3B9BAF",
|
|
12
|
+
arc: "#266675",
|
|
13
|
+
lightWave: "#63CACD",
|
|
14
|
+
dot: "#A2158A",
|
|
15
15
|
} as const;
|
|
16
16
|
|
|
17
17
|
type SymbolProps = {
|
|
18
|
-
/**
|
|
18
|
+
/** Side in px (square box, 86 × 86). */
|
|
19
19
|
size?: number;
|
|
20
|
-
/**
|
|
20
|
+
/** Single color for every part (e.g. "#fff" on a dark panel). Default: the brand colors. */
|
|
21
21
|
color?: string;
|
|
22
22
|
className?: string;
|
|
23
23
|
title?: string;
|
|
@@ -27,31 +27,31 @@ export function CreetaSymbol({ size = 48, color, className, title = "Creeta" }:
|
|
|
27
27
|
const c = (k: keyof typeof CREETA_COLORS) => color ?? CREETA_COLORS[k];
|
|
28
28
|
return (
|
|
29
29
|
<svg width={size} height={size} viewBox="0 0 86 86" fill="none" role="img" aria-label={title} className={className}>
|
|
30
|
-
<path d="M85.4746 46.2096C83.9959 65.2746 70.0266 80.8266 51.7546 84.696C51.6493 84.7214 51.544 84.7481 51.4507 84.761C48.7053 85.3293 45.8666 85.62 42.9613 85.6334H42.816C26.4706 84.973 13.4266 71.5053 13.4266 54.9892C13.4266 44.1626 19.0387 34.6309 27.5147 29.1908C30.7093 27.1309 34.3133 25.6397 38.196 24.9001C30.5106 26.8798 24.7547 33.6668 24.3453 41.8653C24.3187 42.1824 24.3186 42.4986 24.3186 42.8157C24.3186 43.1334 24.3187 43.449 24.3453 43.7668C24.8347 60.2574 38.3666 73.473 54.9893 73.473C61.1026 73.473 66.7919 71.6908 71.5719 68.6012C79.1506 63.7293 84.4319 55.6096 85.4746 46.2096Z" fill={c("
|
|
31
|
-
<path d="M55.98 12.16V12.173C55.9667 18.8012 50.672 24.1746 44.084 24.32H43.8067C43.6747 24.32 43.5427 24.32 43.4107 24.3334H43.3587C43.1733 24.32 43.0014 24.32 42.8174 24.32C41.2854 24.32 39.7933 24.5038 38.38 24.861C38.3147 24.8746 38.2614 24.8881 38.196 24.9012C34.3147 25.6397 30.7094 27.132 27.5147 29.1918C19.0387 34.6309 13.428 44.1642 13.428 54.9892C13.428 71.5064 26.472 84.973 42.8174 85.6334C19.1707 85.6334 0 66.4626 0 42.8173C0 19.1705 19.1707 -3.8147e-05 42.8174 -3.8147e-05C43.028 -3.8147e-05 43.2387 -3.52981e-05 43.4507 0.013298C43.9 0.013298 44.3613 0.0266218 44.8107 0.0399551C51.056 0.554622 55.98 5.78262 55.98 12.16Z" fill={c("
|
|
32
|
-
<path d="M73.4467 31.2278C70.6867 31.2278 68.152 32.1387 66.1187 33.684C63.188 35.9012 61.2867 39.4267 61.2867 43.3882V42.8335C61.2867 53.0387 53.0093 61.3174 42.8027 61.3174C32.9013 61.3174 24.8214 53.5534 24.332 43.784C24.8214 60.2747 38.3534 73.4908 54.976 73.4908C61.0894 73.4908 66.7787 71.708 71.5587 68.619C79.0947 63.7731 84.3547 55.7158 85.44 46.3824C85.4694 45.6944 85.6067 43.4491 85.6067 43.1892C85.5014 36.5611 80.1013 31.2278 73.4467 31.2278Z" fill={c("
|
|
33
|
-
<path d="M71.2799 26.5798C77.1253 26.5798 81.8626 21.8252 81.8626 15.9585C81.8626 10.0933 77.1253 5.33731 71.2799 5.33731C65.4346 5.33731 60.6973 10.0933 60.6973 15.9585C60.6973 21.8252 65.4346 26.5798 71.2799 26.5798Z" fill={c("
|
|
30
|
+
<path d="M85.4746 46.2096C83.9959 65.2746 70.0266 80.8266 51.7546 84.696C51.6493 84.7214 51.544 84.7481 51.4507 84.761C48.7053 85.3293 45.8666 85.62 42.9613 85.6334H42.816C26.4706 84.973 13.4266 71.5053 13.4266 54.9892C13.4266 44.1626 19.0387 34.6309 27.5147 29.1908C30.7093 27.1309 34.3133 25.6397 38.196 24.9001C30.5106 26.8798 24.7547 33.6668 24.3453 41.8653C24.3187 42.1824 24.3186 42.4986 24.3186 42.8157C24.3186 43.1334 24.3187 43.449 24.3453 43.7668C24.8347 60.2574 38.3666 73.473 54.9893 73.473C61.1026 73.473 66.7919 71.6908 71.5719 68.6012C79.1506 63.7293 84.4319 55.6096 85.4746 46.2096Z" fill={c("midWave")} />
|
|
31
|
+
<path d="M55.98 12.16V12.173C55.9667 18.8012 50.672 24.1746 44.084 24.32H43.8067C43.6747 24.32 43.5427 24.32 43.4107 24.3334H43.3587C43.1733 24.32 43.0014 24.32 42.8174 24.32C41.2854 24.32 39.7933 24.5038 38.38 24.861C38.3147 24.8746 38.2614 24.8881 38.196 24.9012C34.3147 25.6397 30.7094 27.132 27.5147 29.1918C19.0387 34.6309 13.428 44.1642 13.428 54.9892C13.428 71.5064 26.472 84.973 42.8174 85.6334C19.1707 85.6334 0 66.4626 0 42.8173C0 19.1705 19.1707 -3.8147e-05 42.8174 -3.8147e-05C43.028 -3.8147e-05 43.2387 -3.52981e-05 43.4507 0.013298C43.9 0.013298 44.3613 0.0266218 44.8107 0.0399551C51.056 0.554622 55.98 5.78262 55.98 12.16Z" fill={c("arc")} />
|
|
32
|
+
<path d="M73.4467 31.2278C70.6867 31.2278 68.152 32.1387 66.1187 33.684C63.188 35.9012 61.2867 39.4267 61.2867 43.3882V42.8335C61.2867 53.0387 53.0093 61.3174 42.8027 61.3174C32.9013 61.3174 24.8214 53.5534 24.332 43.784C24.8214 60.2747 38.3534 73.4908 54.976 73.4908C61.0894 73.4908 66.7787 71.708 71.5587 68.619C79.0947 63.7731 84.3547 55.7158 85.44 46.3824C85.4694 45.6944 85.6067 43.4491 85.6067 43.1892C85.5014 36.5611 80.1013 31.2278 73.4467 31.2278Z" fill={c("lightWave")} />
|
|
33
|
+
<path d="M71.2799 26.5798C77.1253 26.5798 81.8626 21.8252 81.8626 15.9585C81.8626 10.0933 77.1253 5.33731 71.2799 5.33731C65.4346 5.33731 60.6973 10.0933 60.6973 15.9585C60.6973 21.8252 65.4346 26.5798 71.2799 26.5798Z" fill={c("dot")} />
|
|
34
34
|
</svg>
|
|
35
35
|
);
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
type WordmarkProps = {
|
|
39
|
-
/**
|
|
40
|
-
*
|
|
39
|
+
/** Height. Default `var(--cg-wordmark, 1em)`: inside the Lockup/Curtain the
|
|
40
|
+
* variable comes from the manual's ratio (`wordmarkPerSymbol`); standalone, 1em. */
|
|
41
41
|
height?: string;
|
|
42
|
-
/**
|
|
42
|
+
/** Default `currentColor`: inherits `ink` (or white on a panel). */
|
|
43
43
|
color?: string;
|
|
44
44
|
className?: string;
|
|
45
45
|
style?: CSSProperties;
|
|
46
46
|
title?: string;
|
|
47
47
|
};
|
|
48
48
|
|
|
49
|
-
/**
|
|
50
|
-
*
|
|
51
|
-
/**
|
|
49
|
+
/** Ratio from the manual: wordmark height ÷ symbol height in the horizontal
|
|
50
|
+
* logo (40.3 / 86, with the name at 1.4643× in the horizontal logo). Pass it as `wordmarkRatio` to the Lockup/Curtain. */
|
|
51
|
+
/** In creeta the symbol sits to the left of the name (the family default). */
|
|
52
52
|
export const CREETA_LOCKUP = { wordmarkPerSymbol: 0.469, symbolSide: "left" } as const;
|
|
53
53
|
|
|
54
|
-
/**
|
|
54
|
+
/** Box tight to the letterforms: 116.66 × 27.53. */
|
|
55
55
|
export function CreetaWordmark({ height = "var(--cg-wordmark, 1em)", color = "currentColor", className, style, title = "creeta" }: WordmarkProps) {
|
|
56
56
|
return (
|
|
57
57
|
<svg
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import type { CSSProperties } from "react";
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* wordmark
|
|
7
|
-
*
|
|
4
|
+
* TTCAB brand (Torcicolo Congênito e Assimetrias do Bebê), copied from the
|
|
5
|
+
* site's public/brand files. Symbol (mother + baby, orange) and "TTCAB"
|
|
6
|
+
* wordmark kept separate, so the Curtain and the Lockup can assemble the
|
|
7
|
+
* arrangements. Do not edit by hand: the drawing is the one from the brand manual.
|
|
8
8
|
*/
|
|
9
9
|
type SymbolProps = {
|
|
10
|
-
/**
|
|
10
|
+
/** Width in px; height follows the aspect ratio (136:126). */
|
|
11
11
|
size?: number;
|
|
12
|
-
/**
|
|
12
|
+
/** Single color (e.g. "currentColor" or "#fff" on a dark panel). Default: the brand orange. */
|
|
13
13
|
color?: string;
|
|
14
14
|
className?: string;
|
|
15
15
|
title?: string;
|
|
@@ -28,22 +28,22 @@ export function TtcabSymbol({ size = 48, color = TTCAB_ORANGE, className, title
|
|
|
28
28
|
}
|
|
29
29
|
|
|
30
30
|
type WordmarkProps = {
|
|
31
|
-
/**
|
|
32
|
-
*
|
|
31
|
+
/** Height. Default `var(--cg-wordmark, 1em)`: inside the Lockup/Curtain the
|
|
32
|
+
* variable comes from the manual's ratio (`wordmarkPerSymbol`); standalone, 1em. */
|
|
33
33
|
height?: string;
|
|
34
|
-
/**
|
|
34
|
+
/** Default `currentColor`: inherits `ink` (or white on a panel). */
|
|
35
35
|
color?: string;
|
|
36
36
|
className?: string;
|
|
37
37
|
style?: CSSProperties;
|
|
38
38
|
title?: string;
|
|
39
39
|
};
|
|
40
40
|
|
|
41
|
-
/**
|
|
42
|
-
*
|
|
43
|
-
/**
|
|
41
|
+
/** Ratio from the manual: wordmark height ÷ symbol height in the horizontal
|
|
42
|
+
* logo (43.67 / 78.39). Pass it as `wordmarkRatio` to the Lockup/Curtain. */
|
|
43
|
+
/** In TTCAB the symbol sits to the RIGHT of the name (the manual's horizontal logo). */
|
|
44
44
|
export const TTCAB_LOCKUP = { wordmarkPerSymbol: 0.557, symbolSide: "right" } as const;
|
|
45
45
|
|
|
46
|
-
/**
|
|
46
|
+
/** Box tight to the letterforms: 149.75 × 43.67. */
|
|
47
47
|
export function TtcabWordmark({ height = "var(--cg-wordmark, 1em)", color = "currentColor", className, style, title = "TTCAB" }: WordmarkProps) {
|
|
48
48
|
return (
|
|
49
49
|
<svg
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@breathe-ds/ui",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Breathe DS
|
|
5
|
-
"license": "
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "Breathe DS — the design system of the Cuidado Global family of sites (creeta, ttcab, metodorta). Themeable tokens + React components.",
|
|
5
|
+
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"sideEffects": [
|
|
8
8
|
"*.css"
|
|
@@ -11,7 +11,8 @@
|
|
|
11
11
|
"theme.css",
|
|
12
12
|
"tokens",
|
|
13
13
|
"components",
|
|
14
|
-
"README.md"
|
|
14
|
+
"README.md",
|
|
15
|
+
"LICENSE"
|
|
15
16
|
],
|
|
16
17
|
"exports": {
|
|
17
18
|
"./theme.css": "./theme.css",
|
|
@@ -28,11 +29,12 @@
|
|
|
28
29
|
"./components/Header": "./components/Header.tsx",
|
|
29
30
|
"./components/BottomNav": "./components/BottomNav.tsx",
|
|
30
31
|
"./components/BreatheMark": "./components/BreatheMark.tsx",
|
|
31
|
-
"./components/
|
|
32
|
+
"./components/Curtain": "./components/Curtain.tsx",
|
|
32
33
|
"./components/Lockup": "./components/Lockup.tsx",
|
|
33
34
|
"./tokens/neutral.css": "./tokens/neutral.css",
|
|
34
35
|
"./components/icons": "./components/icons.tsx",
|
|
35
36
|
"./components/AnchorNav": "./components/AnchorNav.tsx",
|
|
37
|
+
"./components/LanguageSwitcher": "./components/LanguageSwitcher.tsx",
|
|
36
38
|
"./components/marks/ttcab": "./components/marks/ttcab.tsx",
|
|
37
39
|
"./components/marks/creeta": "./components/marks/creeta.tsx"
|
|
38
40
|
},
|
package/theme.css
CHANGED
|
@@ -1,40 +1,40 @@
|
|
|
1
1
|
/*
|
|
2
2
|
@breathe-ds/ui — theme.css (tokens-first, v0.1)
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
4
|
+
Token contract of the Cuidado Global family (RTA/Mariangela ecosystem).
|
|
5
|
+
COLORS are ROLES: the value of each one comes from a `--cg-*` CSS var that
|
|
6
|
+
EACH SITE defines (ttcab petrol/cream, creeta petrol/mist/magenta…).
|
|
7
|
+
This way the sites inherit the SAME structure and names, with their own palette.
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
Usage in a site's globals.css (Tailwind v4):
|
|
10
10
|
@import "tailwindcss";
|
|
11
11
|
@import "@breathe-ds/ui/theme.css";
|
|
12
|
-
@import "@breathe-ds/ui/tokens/ttcab.css"; (
|
|
12
|
+
@import "@breathe-ds/ui/tokens/ttcab.css"; (or define the --cg-* inline)
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
Fixed scales (typography roles, radius, motion) are shared here.
|
|
15
|
+
Measured contrasts of each palette: see README.md and the tokens/* files.
|
|
16
16
|
*/
|
|
17
17
|
@theme {
|
|
18
|
-
/* ──
|
|
19
|
-
--color-surface: var(--cg-surface); /*
|
|
20
|
-
--color-surface-panel: var(--cg-surface-panel); /*
|
|
21
|
-
--color-ink: var(--cg-ink); /*
|
|
22
|
-
--color-ink-soft: var(--cg-ink-soft); /*
|
|
23
|
-
--color-ink-body: var(--cg-ink-body); /*
|
|
24
|
-
--color-action: var(--cg-action); /* CTA/
|
|
25
|
-
--color-action-text: var(--cg-action-text); /*
|
|
26
|
-
--color-on-action: var(--cg-on-action); /*
|
|
27
|
-
--color-line: var(--cg-line); /* hairlines/
|
|
18
|
+
/* ── Colors (roles) — value comes from the site's --cg-* ── */
|
|
19
|
+
--color-surface: var(--cg-surface); /* base background */
|
|
20
|
+
--color-surface-panel: var(--cg-surface-panel); /* dark panel (footer/CTA) */
|
|
21
|
+
--color-ink: var(--cg-ink); /* primary text / headings */
|
|
22
|
+
--color-ink-soft: var(--cg-ink-soft); /* secondary text */
|
|
23
|
+
--color-ink-body: var(--cg-ink-body); /* body copy */
|
|
24
|
+
--color-action: var(--cg-action); /* CTA/highlight — never plain text */
|
|
25
|
+
--color-action-text: var(--cg-action-text); /* text in the action color (AA) */
|
|
26
|
+
--color-on-action: var(--cg-on-action); /* text ON the action color (button) */
|
|
27
|
+
--color-line: var(--cg-line); /* hairlines/borders */
|
|
28
28
|
|
|
29
|
-
/* ──
|
|
29
|
+
/* ── Typography (roles; actual family comes from --cg-font-*) ── */
|
|
30
30
|
--font-heading: var(--cg-font-heading, system-ui, sans-serif);
|
|
31
31
|
--font-body: var(--cg-font-body, Arial, system-ui, sans-serif);
|
|
32
32
|
|
|
33
|
-
/* ──
|
|
33
|
+
/* ── Radius ── */
|
|
34
34
|
--radius-xl: 24px;
|
|
35
35
|
--radius-2xl: 28px;
|
|
36
36
|
--radius-pill: 9999px;
|
|
37
37
|
|
|
38
|
-
/* ── Motion —
|
|
38
|
+
/* ── Motion — the family's signature curve ── */
|
|
39
39
|
--ease-cg: cubic-bezier(0.2, 0.8, 0.2, 1);
|
|
40
40
|
}
|
package/tokens/creeta.css
CHANGED
|
@@ -1,21 +1,20 @@
|
|
|
1
1
|
/*
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
- surface #eef3f4 / ink #144753 ............ ~9
|
|
5
|
-
- surface #eef3f4 / ink-soft #52707a ....... ~4
|
|
6
|
-
- action #ab2781 (magenta)
|
|
2
|
+
Creeta palette (RTA clinic in Floripa) — petrol + mist + magenta.
|
|
3
|
+
Values from novo.creeta. Measured contrasts (WCAG formula):
|
|
4
|
+
- surface #eef3f4 / ink #144753 ............ ~9.1:1 (AAA)
|
|
5
|
+
- surface #eef3f4 / ink-soft #52707a ....... ~4.7:1 (AA)
|
|
6
|
+
- action #ab2781 (magenta) is the CTA ("Agendar"); text on it = white.
|
|
7
7
|
*/
|
|
8
8
|
:root {
|
|
9
|
-
--cg-surface: #eef3f4; /*
|
|
10
|
-
--cg-surface-panel: #144753; /*
|
|
11
|
-
--cg-ink: #144753; /*
|
|
9
|
+
--cg-surface: #eef3f4; /* mist */
|
|
10
|
+
--cg-surface-panel: #144753; /* petrol */
|
|
11
|
+
--cg-ink: #144753; /* petrol */
|
|
12
12
|
--cg-ink-soft: #52707a;
|
|
13
13
|
--cg-ink-body: #1e4f5b;
|
|
14
14
|
--cg-action: #ab2781; /* magenta (Agendar) */
|
|
15
|
-
--cg-action-text: #8f1f6c; /* magenta
|
|
16
|
-
--cg-on-action: #ffffff; /*
|
|
15
|
+
--cg-action-text: #8f1f6c; /* darker magenta for text */
|
|
16
|
+
--cg-on-action: #ffffff; /* white on magenta */
|
|
17
17
|
--cg-line: rgb(20 71 83 / 0.16);
|
|
18
18
|
--cg-font-heading: var(--font-quicksand), system-ui, sans-serif; /* Quicksand */
|
|
19
19
|
--cg-font-body: var(--font-figtree), system-ui, sans-serif; /* Figtree */
|
|
20
20
|
}
|
|
21
|
-
CSS
|
package/tokens/neutral.css
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
/*
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
2
|
+
NEUTRAL palette — the Breathe default. The design system is neutral on
|
|
3
|
+
purpose: color comes from EACH application (ttcab, creeta…). Use this as the
|
|
4
|
+
base and override the --cg-* in your site's :root. Monochrome (gray/near-black)
|
|
5
|
+
to make it clear it is a "bring your own color" placeholder.
|
|
6
6
|
- surface #ffffff / ink #18181b ............ ~17:1 (AAA)
|
|
7
|
-
- surface #ffffff / ink-soft #71717a ....... ~4
|
|
7
|
+
- surface #ffffff / ink-soft #71717a ....... ~4.8:1 (AA)
|
|
8
8
|
*/
|
|
9
9
|
:root {
|
|
10
10
|
--cg-surface: #ffffff;
|
|
@@ -16,6 +16,6 @@
|
|
|
16
16
|
--cg-action-text: #52525b;
|
|
17
17
|
--cg-on-action: #ffffff;
|
|
18
18
|
--cg-line: rgb(0 0 0 / 0.12);
|
|
19
|
-
--cg-font-heading: var(--font-quicksand), system-ui, sans-serif; /* Quicksand (
|
|
20
|
-
--cg-font-body: var(--font-figtree), system-ui, sans-serif; /* Figtree (
|
|
19
|
+
--cg-font-heading: var(--font-quicksand), system-ui, sans-serif; /* Quicksand (fixed across the family) */
|
|
20
|
+
--cg-font-body: var(--font-figtree), system-ui, sans-serif; /* Figtree (fixed across the family) */
|
|
21
21
|
}
|
package/tokens/ttcab.css
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
/*
|
|
2
|
-
|
|
3
|
-
- surface #fbf5e9 / ink #144753 ............ 9
|
|
4
|
-
- surface #fbf5e9 / ink-soft #54707a ....... 4
|
|
5
|
-
- surface #fbf5e9 / ink-body #1e4f5b ....... 8
|
|
6
|
-
- surface #fbf5e9 / action-text #9a5d07 .... 4
|
|
7
|
-
- surface-panel #144753 / surface (
|
|
8
|
-
- action #f6a22a
|
|
2
|
+
TTCAB palette (petrol + cream). Measured contrasts:
|
|
3
|
+
- surface #fbf5e9 / ink #144753 ............ 9.41:1 (AAA)
|
|
4
|
+
- surface #fbf5e9 / ink-soft #54707a ....... 4.86:1 (AA)
|
|
5
|
+
- surface #fbf5e9 / ink-body #1e4f5b ....... 8.32:1 (AAA)
|
|
6
|
+
- surface #fbf5e9 / action-text #9a5d07 .... 4.90:1 (AA)
|
|
7
|
+
- surface-panel #144753 / surface (text) ... 9.41:1 (AAA)
|
|
8
|
+
- action #f6a22a is DECORATIVE/CTA — never text on cream.
|
|
9
9
|
*/
|
|
10
10
|
:root {
|
|
11
11
|
--cg-surface: #fbf5e9;
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
--cg-ink-soft: #54707a;
|
|
15
15
|
--cg-ink-body: #1e4f5b;
|
|
16
16
|
--cg-action: #f6a22a;
|
|
17
|
-
--cg-on-action: #144753; /* ink
|
|
17
|
+
--cg-on-action: #144753; /* ink on orange */
|
|
18
18
|
--cg-action-text: #9a5d07;
|
|
19
19
|
--cg-line: rgb(20 71 83 / 0.16);
|
|
20
20
|
--cg-font-heading: var(--font-quicksand), system-ui, sans-serif; /* Quicksand */
|
package/components/Cortina.tsx
DELETED
|
@@ -1,152 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
|
|
3
|
-
import { useEffect, useRef, useState, type CSSProperties, type ReactNode } from "react";
|
|
4
|
-
import { BreatheMark } from "./BreatheMark";
|
|
5
|
-
|
|
6
|
-
type Props = {
|
|
7
|
-
/** Nome da marca (ex.: "creeta", "TTCAB", "Breathe"). */
|
|
8
|
-
name: ReactNode;
|
|
9
|
-
/** Linha abaixo do nome (ex.: "Centro de Reequilíbrio Toracoabdominal"). */
|
|
10
|
-
tagline?: ReactNode;
|
|
11
|
-
/** Símbolo à esquerda do nome. Padrão: o BreatheMark (anel + ponto). Cada
|
|
12
|
-
* site injeta o seu logotipo aqui. */
|
|
13
|
-
logo?: ReactNode;
|
|
14
|
-
/** Quando `name` é um wordmark svg: altura dele como fração da altura do
|
|
15
|
-
* símbolo, do manual da marca (ex.: `CREETA_LOCKUP.wordmarkPerSymbol`). */
|
|
16
|
-
wordmarkRatio?: number;
|
|
17
|
-
/** Lado do símbolo. Padrão `left`; o TTCAB é `right` (`TTCAB_LOCKUP.symbolSide`). */
|
|
18
|
-
symbolSide?: "left" | "right";
|
|
19
|
-
/** Chave do sessionStorage (quando há o script de cabeça). */
|
|
20
|
-
storageKey?: string;
|
|
21
|
-
/** Chamado quando a cortina termina de subir. */
|
|
22
|
-
onDone?: () => void;
|
|
23
|
-
className?: string;
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* Cortina de entrada da família Cuidado Global — tela cheia, na cor do site
|
|
28
|
-
* (tokens surface/ink), com o logotipo + nome se formando no centro e a
|
|
29
|
-
* tagline embaixo; depois ela sobe e mostra a página. Espelha a `Cortina` do
|
|
30
|
-
* creeta, mas neutra: a paleta e o logotipo vêm de cada app.
|
|
31
|
-
*
|
|
32
|
-
* - É toda em CSS (estilo embutido): sem JavaScript ela sobe do mesmo jeito,
|
|
33
|
-
* então nunca fica presa na frente do site.
|
|
34
|
-
* - Não recebe clique nem foco e não existe para leitor de tela (aria-hidden).
|
|
35
|
-
* - Com movimento reduzido (ou impressão) não aparece.
|
|
36
|
-
* - Para aparecer só na 1ª visita da sessão, ponha `cortinaHeadScript()` no
|
|
37
|
-
* <head> (antes da pintura): em visita repetida o <html> já nasce com
|
|
38
|
-
* data-cg-cortina="vista" e a cortina não é desenhada — sem piscar.
|
|
39
|
-
*
|
|
40
|
-
* Ao terminar de subir, o <html> ganha data-cg-cortina-fim (para o topo das
|
|
41
|
-
* páginas "pousar" só depois dela, nunca numa troca de tela) e chama onDone.
|
|
42
|
-
*/
|
|
43
|
-
export function Cortina({ name, tagline, logo, wordmarkRatio, symbolSide = "left", storageKey, onDone, className }: Props) {
|
|
44
|
-
const el = useRef<HTMLDivElement>(null);
|
|
45
|
-
const [gone, setGone] = useState(false);
|
|
46
|
-
|
|
47
|
-
useEffect(() => {
|
|
48
|
-
const node = el.current;
|
|
49
|
-
if (!node) return;
|
|
50
|
-
const aoTerminar = (e: AnimationEvent) => {
|
|
51
|
-
if (e.animationName !== "cg-cortina-sobe") return;
|
|
52
|
-
document.documentElement.setAttribute("data-cg-cortina-fim", "");
|
|
53
|
-
try {
|
|
54
|
-
if (storageKey) sessionStorage.setItem(storageKey, "1");
|
|
55
|
-
} catch {
|
|
56
|
-
/* sessionStorage bloqueado: a cortina só aparece de novo, nada quebra */
|
|
57
|
-
}
|
|
58
|
-
onDone?.();
|
|
59
|
-
setGone(true);
|
|
60
|
-
};
|
|
61
|
-
node.addEventListener("animationend", aoTerminar);
|
|
62
|
-
return () => node.removeEventListener("animationend", aoTerminar);
|
|
63
|
-
}, [onDone, storageKey]);
|
|
64
|
-
|
|
65
|
-
if (gone) return null;
|
|
66
|
-
|
|
67
|
-
return (
|
|
68
|
-
<div ref={el} className={`cg-cortina${className ? ` ${className}` : ""}`} aria-hidden="true">
|
|
69
|
-
<style>{CORTINA_CSS}</style>
|
|
70
|
-
{/* Símbolo à esquerda: ele abraça o bloco nome+tagline. À direita (TTCAB):
|
|
71
|
-
ele encosta no nome, na mesma linha, e a tagline fica embaixo — senão
|
|
72
|
-
o símbolo iria parar depois da tagline, longe do wordmark. */}
|
|
73
|
-
{(() => {
|
|
74
|
-
const mark = <span className="cg-cortina__mark">{logo ?? <BreatheMark size={60} duration={5} />}</span>;
|
|
75
|
-
const nameEl = (
|
|
76
|
-
<span
|
|
77
|
-
className="cg-cortina__name"
|
|
78
|
-
style={wordmarkRatio ? ({ "--cg-wordmark": `calc(var(--cg-cortina-mark) * ${wordmarkRatio})` } as CSSProperties) : undefined}
|
|
79
|
-
>
|
|
80
|
-
{name}
|
|
81
|
-
</span>
|
|
82
|
-
);
|
|
83
|
-
const tag = tagline ? <span className="cg-cortina__tag">{tagline}</span> : null;
|
|
84
|
-
return symbolSide === "right" ? (
|
|
85
|
-
<div className="cg-cortina__lockup cg-cortina__lockup--right">
|
|
86
|
-
<span className="cg-cortina__row">{nameEl}{mark}</span>
|
|
87
|
-
{tag}
|
|
88
|
-
</div>
|
|
89
|
-
) : (
|
|
90
|
-
<div className="cg-cortina__lockup">
|
|
91
|
-
{mark}
|
|
92
|
-
<span className="cg-cortina__text">{nameEl}{tag}</span>
|
|
93
|
-
</div>
|
|
94
|
-
);
|
|
95
|
-
})()}
|
|
96
|
-
</div>
|
|
97
|
-
);
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
/**
|
|
101
|
-
* Script para o <head> (antes da pintura): marca a cortina como vista nesta
|
|
102
|
-
* sessão, para não repetir ao navegar nem ao recarregar. Sem ele, a cortina
|
|
103
|
-
* aparece a cada carregamento.
|
|
104
|
-
* // Next (app/layout):
|
|
105
|
-
* <script dangerouslySetInnerHTML={{ __html: cortinaHeadScript("cg-cortina") }} />
|
|
106
|
-
*/
|
|
107
|
-
export function cortinaHeadScript(storageKey = "cg-cortina") {
|
|
108
|
-
const k = JSON.stringify(storageKey);
|
|
109
|
-
return `try{var d=document.documentElement;if(sessionStorage.getItem(${k})){d.setAttribute('data-cg-cortina','vista')}else{sessionStorage.setItem(${k},'1')}}catch(e){}`;
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
const CORTINA_CSS = `
|
|
113
|
-
.cg-cortina{
|
|
114
|
-
--cg-cortina-mark: clamp(40px,7.4vw,60px); /* altura do símbolo */
|
|
115
|
-
position:fixed; inset:0 0 -40px; padding-bottom:40px;
|
|
116
|
-
z-index:120; display:grid; place-items:center;
|
|
117
|
-
border-radius:0 0 32px 32px;
|
|
118
|
-
background:var(--color-surface,#fff); color:var(--color-ink,#14323a);
|
|
119
|
-
box-shadow:0 24px 60px -20px rgba(0,0,0,.28);
|
|
120
|
-
pointer-events:none;
|
|
121
|
-
animation:cg-cortina-sobe 700ms cubic-bezier(.77,0,.175,1) 2200ms both;
|
|
122
|
-
}
|
|
123
|
-
/* gap ≈ 1/3 do corpo do nome: o anel é curvo, então o vão óptico lê um pouco maior que o geométrico */
|
|
124
|
-
.cg-cortina__lockup{ display:flex; align-items:center; gap:clamp(10px,1.6vw,16px); padding:0 24px; }
|
|
125
|
-
.cg-cortina__lockup--right{ flex-direction:column; align-items:flex-start; }
|
|
126
|
-
.cg-cortina__row{ display:flex; align-items:center; gap:clamp(10px,1.6vw,16px); }
|
|
127
|
-
.cg-cortina__lockup--right .cg-cortina__name{ animation-name:cg-cortina-nome-dir; }
|
|
128
|
-
.cg-cortina__mark{ display:inline-flex; color:var(--color-ink,#14323a);
|
|
129
|
-
animation:cg-cortina-mark 700ms var(--ease-cg,cubic-bezier(.2,.8,.2,1)) both; }
|
|
130
|
-
/* símbolo ~1.25× o corpo do nome (a caixa do SVG é justa ao glifo), fluido.
|
|
131
|
-
Por altura: um símbolo injetado não-quadrado (TTCAB) mantém a proporção. */
|
|
132
|
-
.cg-cortina__mark svg{ height:var(--cg-cortina-mark); width:auto; }
|
|
133
|
-
.cg-cortina__text{ display:flex; flex-direction:column; min-width:0; }
|
|
134
|
-
.cg-cortina__name{
|
|
135
|
-
font-family:var(--font-heading,system-ui,sans-serif);
|
|
136
|
-
font-weight:700; font-size:clamp(2rem,6vw,3rem); line-height:1; letter-spacing:-.02em;
|
|
137
|
-
animation:cg-cortina-nome 600ms var(--ease-cg,cubic-bezier(.2,.8,.2,1)) 480ms both;
|
|
138
|
-
}
|
|
139
|
-
.cg-cortina__tag{
|
|
140
|
-
margin-top:.55rem; font-family:var(--font-body,system-ui,sans-serif);
|
|
141
|
-
font-size:clamp(.8rem,2.4vw,1rem); line-height:1.3; color:var(--color-ink-soft,#54707a);
|
|
142
|
-
animation:cg-cortina-tag 500ms ease 820ms both;
|
|
143
|
-
}
|
|
144
|
-
@keyframes cg-cortina-sobe{ to{ transform:translateY(-100%); visibility:hidden; } }
|
|
145
|
-
@keyframes cg-cortina-mark{ from{ opacity:0; transform:scale(.6) rotate(-16deg); } }
|
|
146
|
-
@keyframes cg-cortina-nome{ from{ opacity:0; transform:translateX(-8px); } }
|
|
147
|
-
@keyframes cg-cortina-nome-dir{ from{ opacity:0; transform:translateX(8px); } }
|
|
148
|
-
@keyframes cg-cortina-tag{ from{ opacity:0; transform:translateY(4px); } }
|
|
149
|
-
html[data-cg-cortina="vista"] .cg-cortina{ display:none; }
|
|
150
|
-
@media (prefers-reduced-motion:reduce){ .cg-cortina{ display:none; } }
|
|
151
|
-
@media print{ .cg-cortina{ display:none; } }
|
|
152
|
-
`;
|