@breathe-ds/ui 0.6.8 → 0.6.10
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 +9 -0
- package/components/FounderSpotlight.tsx +142 -0
- package/components/TestimonialsSection.tsx +60 -0
- package/package.json +3 -1
package/README.md
CHANGED
|
@@ -198,6 +198,15 @@ from color, not from extra markup.
|
|
|
198
198
|
portrait on the left (photo or `living`, the team pages' living portrait), then
|
|
199
199
|
eyebrow, name, role, registration, bio and `actions`. `variant` `plain` (on the page
|
|
200
200
|
color) or `card` (white card). Stacks on phones.
|
|
201
|
+
- **FounderSpotlight**: the family founder (Mariangela, creator of RTA and TTCAB) in one
|
|
202
|
+
block: `ProfileSpotlight` card + living portrait on hover, filled with the text validated
|
|
203
|
+
on ttcab (pt/en/es), her Instagram and the courses link. `<FounderSpotlight locale="pt" />`.
|
|
204
|
+
Media live in each site's `public/` (`/images/mariangela.png`, `/equipe/vivas/mariangela.mp4|.webp`).
|
|
205
|
+
Her bio lives HERE (source of truth); `[[rta:…]]`/`[[ttcab:…]]` link each method's site;
|
|
206
|
+
pass `site="rta"|"ttcab"` so a site does not link to itself. `founderBio(locale)` = plain text.
|
|
207
|
+
- **TestimonialsSection**: the testimonials block, as on ttcab (the standard): "Depoimentos /
|
|
208
|
+
Histórias de sucesso" (pt/en/es), masonry in two columns, video first, pull-quote cards that
|
|
209
|
+
open the side panel. Sites pass only `items`.
|
|
201
210
|
- **Texture & rhythm (opt-in)**: `.cg-grain` adds a barely-there paper grain (noise in
|
|
202
211
|
the ink color) to any background — the body, a band. `bg-surface-alt` (token
|
|
203
212
|
`--cg-surface-alt`, falls back to `surface`) is a band one step deeper than the page,
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
import { ProfileSpotlight } from "./ProfileSpotlight";
|
|
3
|
+
import { IconGraduationCap, IconInstagram } from "./icons";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* The founder of the family: Mariangela Pinheiro de Lima, who created the RTA
|
|
7
|
+
* Method and TTCAB. One block, one text, for every site of the family (ttcab,
|
|
8
|
+
* metodorta, creeta…), so she reads the same everywhere. The text is the one
|
|
9
|
+
* validated on the ttcab site (06/11/2026), in pt, en and es. THIS FILE IS THE
|
|
10
|
+
* SOURCE OF TRUTH of her bio: change it here, publish, bump the sites.
|
|
11
|
+
* In the bio, [[rta:…]] and [[ttcab:…]] become links to each method's site
|
|
12
|
+
* (the site you are on is not linked to itself: see `site`).
|
|
13
|
+
*
|
|
14
|
+
* Media stay in each site's `public/` (the package ships no binaries); copy them
|
|
15
|
+
* from the ttcab site, or pass your own paths:
|
|
16
|
+
* /images/mariangela.png still portrait (4:5)
|
|
17
|
+
* /equipe/vivas/mariangela.mp4 + .webp living portrait (plays on hover)
|
|
18
|
+
*/
|
|
19
|
+
export const FOUNDER = {
|
|
20
|
+
name: "Mariangela Pinheiro de Lima",
|
|
21
|
+
registration: "CREFITO-10/2894-F",
|
|
22
|
+
instagram: "https://www.instagram.com/mariangela.rta/",
|
|
23
|
+
courses: "https://metodorta.com.br/cursos-e-eventos/",
|
|
24
|
+
/** Sites of each method, linked from the bio ([[rta:…]] / [[ttcab:…]] in the text). */
|
|
25
|
+
sites: { rta: "https://metodorta.com.br/", ttcab: "https://torcicoloseassimetrias.com.br/" },
|
|
26
|
+
pt: {
|
|
27
|
+
eyebrow: "Idealizadora",
|
|
28
|
+
role: "Criadora do método Reequilíbrio Toracoabdominal e fundadora da Escola Brasileira de RTA e Biomecânica Respiratória",
|
|
29
|
+
roleShort: "Criadora do Método RTA e do TTCAB",
|
|
30
|
+
bio: "Mariangela tem mais de 40 anos de carreira na Fisioterapia, com experiências marcantes na área pediátrica e respiratória. Iniciou como professora na PUCPR e atuou por sete anos nos hospitais Pequeno Príncipe e César Pernetta, em Curitiba. Especializou-se no Método Bobath, com influência de Oacy Veronesi e Sherry Arndt. Seu interesse em Fisioterapia Respiratória a levou a criar o [[rta:Método Reequilíbrio Toracoabdominal (RTA)]], difundido há mais de três décadas por todo o Brasil. Também idealizou o [[ttcab:TTCAB]], a formação para o tratamento do torcicolo congênito e de outras assimetrias no bebê.",
|
|
31
|
+
instagram: "Instagram da Mariangela",
|
|
32
|
+
courses: "Cursos no site do Método RTA",
|
|
33
|
+
newTab: "(abre em nova aba)",
|
|
34
|
+
},
|
|
35
|
+
en: {
|
|
36
|
+
eyebrow: "Founder",
|
|
37
|
+
role: "Creator of the Reequilíbrio Toracoabdominal method and founder of the Escola Brasileira de RTA e Biomecânica Respiratória",
|
|
38
|
+
roleShort: "Creator of the RTA Method and of TTCAB",
|
|
39
|
+
bio: "Mariangela has a career of more than 40 years in Physiotherapy, with remarkable experience in paediatrics and respiratory care. She began as a lecturer at PUCPR and worked for seven years at the Pequeno Príncipe and César Pernetta hospitals in Curitiba. She specialised in the Bobath Concept, influenced by Oacy Veronesi and Sherry Arndt. Her interest in Respiratory Physiotherapy led her to create the [[rta:Thoracoabdominal Rebalancing Method (RTA)]], taught across Brazil for more than three decades. She also created [[ttcab:TTCAB]], the training in the treatment of congenital torticollis and other asymmetries in babies.",
|
|
40
|
+
instagram: "Mariangela's Instagram",
|
|
41
|
+
courses: "Courses on the Método RTA website",
|
|
42
|
+
newTab: "(opens in a new tab)",
|
|
43
|
+
},
|
|
44
|
+
es: {
|
|
45
|
+
eyebrow: "Idealizadora",
|
|
46
|
+
role: "Creadora del método Reequilíbrio Toracoabdominal y fundadora de la Escola Brasileira de RTA e Biomecânica Respiratória",
|
|
47
|
+
roleShort: "Creadora del Método RTA y del TTCAB",
|
|
48
|
+
bio: "Mariangela tiene más de 40 años de carrera en la Fisioterapia, con experiencias destacadas en el área pediátrica y respiratoria. Comenzó como profesora en la PUCPR y trabajó durante siete años en los hospitales Pequeno Príncipe y César Pernetta, en Curitiba. Se especializó en el Método Bobath, con influencia de Oacy Veronesi y Sherry Arndt. Su interés por la Fisioterapia Respiratoria la llevó a crear el [[rta:Método Reequilibrio Toracoabdominal (RTA)]], difundido desde hace más de tres décadas en todo Brasil. También ideó el [[ttcab:TTCAB]], la formación para el tratamiento de la tortícolis congénita y otras asimetrías en el bebé.",
|
|
49
|
+
instagram: "Instagram de Mariangela",
|
|
50
|
+
courses: "Cursos en el sitio del Método RTA",
|
|
51
|
+
newTab: "(se abre en una pestaña nueva)",
|
|
52
|
+
},
|
|
53
|
+
} as const;
|
|
54
|
+
|
|
55
|
+
export type FounderLocale = "pt" | "en" | "es";
|
|
56
|
+
|
|
57
|
+
type Props = {
|
|
58
|
+
locale?: FounderLocale;
|
|
59
|
+
/** The site showing the block: its own method is not linked to itself. */
|
|
60
|
+
site?: "rta" | "ttcab";
|
|
61
|
+
/** Where "courses" points (default: the Método RTA courses page). */
|
|
62
|
+
coursesHref?: string;
|
|
63
|
+
/** Media paths in the site's public/ (defaults above). */
|
|
64
|
+
photo?: string;
|
|
65
|
+
living?: { src: string; poster: string } | false;
|
|
66
|
+
/** Your own image element (e.g. next/image) in place of the photo. */
|
|
67
|
+
media?: ReactNode;
|
|
68
|
+
/** Links or buttons at the foot, after the text. */
|
|
69
|
+
actions?: ReactNode;
|
|
70
|
+
variant?: "plain" | "card";
|
|
71
|
+
headingLevel?: "h2" | "h3";
|
|
72
|
+
id?: string;
|
|
73
|
+
className?: string;
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Founder spotlight: `ProfileSpotlight` (card, living portrait on hover) filled
|
|
78
|
+
* with the founder's validated text, her Instagram and the courses link. Sites
|
|
79
|
+
* only drop it in: `<FounderSpotlight locale="pt" />`.
|
|
80
|
+
*/
|
|
81
|
+
/** Bio as plain text (JSON-LD, llms.txt, meta): the markers removed. */
|
|
82
|
+
export function founderBio(locale: FounderLocale = "pt"): string {
|
|
83
|
+
return FOUNDER[locale].bio.replace(/\[\[(?:rta|ttcab):([^\]]+)\]\]/g, "$1");
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/** Bio with the method names as links (same tab: these are family sites). */
|
|
87
|
+
function BioLinks({ text, site }: { text: string; site?: "rta" | "ttcab" }) {
|
|
88
|
+
const parts = text.split(/(\[\[(?:rta|ttcab):[^\]]+\]\])/g);
|
|
89
|
+
return (
|
|
90
|
+
<>
|
|
91
|
+
{parts.map((p, i) => {
|
|
92
|
+
const m = p.match(/^\[\[(rta|ttcab):([^\]]+)\]\]$/);
|
|
93
|
+
if (!m) return p;
|
|
94
|
+
const key = m[1] as "rta" | "ttcab";
|
|
95
|
+
if (key === site) return m[2];
|
|
96
|
+
return (
|
|
97
|
+
<a key={i} href={FOUNDER.sites[key]} className="font-semibold text-ink underline decoration-1 underline-offset-4 hover:decoration-2">
|
|
98
|
+
{m[2]}
|
|
99
|
+
</a>
|
|
100
|
+
);
|
|
101
|
+
})}
|
|
102
|
+
</>
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
export function FounderSpotlight({
|
|
107
|
+
locale = "pt",
|
|
108
|
+
site,
|
|
109
|
+
coursesHref = FOUNDER.courses,
|
|
110
|
+
photo = "/images/mariangela.png",
|
|
111
|
+
living = { src: "/equipe/vivas/mariangela.mp4", poster: "/equipe/vivas/mariangela.webp" },
|
|
112
|
+
media,
|
|
113
|
+
actions,
|
|
114
|
+
variant = "card",
|
|
115
|
+
headingLevel = "h2",
|
|
116
|
+
id,
|
|
117
|
+
className,
|
|
118
|
+
}: Props) {
|
|
119
|
+
const t = FOUNDER[locale];
|
|
120
|
+
return (
|
|
121
|
+
<ProfileSpotlight
|
|
122
|
+
variant={variant}
|
|
123
|
+
headingLevel={headingLevel}
|
|
124
|
+
id={id}
|
|
125
|
+
className={className}
|
|
126
|
+
eyebrow={t.eyebrow}
|
|
127
|
+
name={FOUNDER.name}
|
|
128
|
+
role={t.role}
|
|
129
|
+
registration={FOUNDER.registration}
|
|
130
|
+
bio={<p><BioLinks text={t.bio} site={site} /></p>}
|
|
131
|
+
photo={{ src: photo, alt: FOUNDER.name }}
|
|
132
|
+
living={living || undefined}
|
|
133
|
+
media={media}
|
|
134
|
+
actions={actions}
|
|
135
|
+
social={[
|
|
136
|
+
{ label: t.instagram, href: FOUNDER.instagram, Icon: IconInstagram },
|
|
137
|
+
{ label: t.courses, href: coursesHref, Icon: IconGraduationCap },
|
|
138
|
+
]}
|
|
139
|
+
newTabLabel={t.newTab}
|
|
140
|
+
/>
|
|
141
|
+
);
|
|
142
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import type { ComponentProps } from "react";
|
|
2
|
+
import { SectionHeading } from "./Heading";
|
|
3
|
+
import { TestimonialCard } from "./TestimonialCard";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Testimonials block of the family (0.6.10, 06/11/2026): the ttcab section made
|
|
7
|
+
* the standard. Heading "Depoimentos / Histórias de sucesso", cards in two
|
|
8
|
+
* masonry columns (short and long quotes have different heights), the video
|
|
9
|
+
* testimonial first, every card a pull quote that opens the whole testimonial in
|
|
10
|
+
* the side panel. Sites pass only the testimonials; the copy and the settings
|
|
11
|
+
* are the ones validated on ttcab. Put it inside your section's Container.
|
|
12
|
+
*/
|
|
13
|
+
const COPY = {
|
|
14
|
+
pt: { eyebrow: "Depoimentos", title: "Histórias de sucesso", panel: "Depoimento", readMore: "Ler depoimento completo", watchFull: "Assistir ao depoimento", close: "Fechar", newTab: " (abre em nova aba)", and: " e " },
|
|
15
|
+
en: { eyebrow: "Testimonials", title: "Success stories", panel: "Testimonial", readMore: "Read the full testimonial", watchFull: "Watch the testimonial", close: "Close", newTab: " (opens in a new tab)", and: " and " },
|
|
16
|
+
es: { eyebrow: "Testimonios", title: "Historias de éxito", panel: "Testimonio", readMore: "Leer el testimonio completo", watchFull: "Ver el testimonio", close: "Cerrar", newTab: " (se abre en una pestaña nueva)", and: " y " },
|
|
17
|
+
} as const;
|
|
18
|
+
|
|
19
|
+
type CardProps = ComponentProps<typeof TestimonialCard>;
|
|
20
|
+
|
|
21
|
+
/** One testimonial: what the card needs (the settings come from the block). */
|
|
22
|
+
export type Testimonial = Pick<CardProps, "quote" | "excerpt" | "excerptMarks" | "author" | "authorPhoto" | "authors" | "role" | "video" | "photo"> & { id: string | number };
|
|
23
|
+
|
|
24
|
+
type Props = {
|
|
25
|
+
items: Testimonial[];
|
|
26
|
+
locale?: "pt" | "en" | "es";
|
|
27
|
+
/** Override the heading only when the client asks; the default is the standard. */
|
|
28
|
+
eyebrow?: string;
|
|
29
|
+
title?: string;
|
|
30
|
+
/** Override labels (e.g. close from the site's own dictionary). */
|
|
31
|
+
labels?: CardProps["labels"];
|
|
32
|
+
/** id for the heading (aria-labelledby of the section). */
|
|
33
|
+
headingId?: string;
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
export function TestimonialsSection({ items, locale = "pt", eyebrow, title, labels, headingId }: Props) {
|
|
37
|
+
const c = COPY[locale];
|
|
38
|
+
// o vídeo primeiro (como no ttcab); o resto na ordem recebida
|
|
39
|
+
const sorted = [...items].sort((a, b) => Number(Boolean(b.video)) - Number(Boolean(a.video)));
|
|
40
|
+
return (
|
|
41
|
+
<>
|
|
42
|
+
<SectionHeading id={headingId} eyebrow={eyebrow ?? c.eyebrow} title={title ?? c.title} />
|
|
43
|
+
<ul className="mt-10 list-none gap-4 p-0 md:columns-2">
|
|
44
|
+
{sorted.map(({ id, ...item }) => (
|
|
45
|
+
<TestimonialCard
|
|
46
|
+
key={id}
|
|
47
|
+
as="li"
|
|
48
|
+
className="mb-4 break-inside-avoid"
|
|
49
|
+
{...item}
|
|
50
|
+
joiners={{ sep: ", ", last: c.and }}
|
|
51
|
+
mediaPlacement="panel"
|
|
52
|
+
clampLines={5}
|
|
53
|
+
panel={{ eyebrow: c.panel }}
|
|
54
|
+
labels={{ watch: "{description}", readMore: c.readMore, watchFull: c.watchFull, close: c.close, newTab: c.newTab, ...labels }}
|
|
55
|
+
/>
|
|
56
|
+
))}
|
|
57
|
+
</ul>
|
|
58
|
+
</>
|
|
59
|
+
);
|
|
60
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@breathe-ds/ui",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.10",
|
|
4
4
|
"description": "Breathe DS — the design system of the Cuidado Global family of sites (creeta, ttcab, metodorta). Themeable tokens + React components.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -100,6 +100,8 @@
|
|
|
100
100
|
"./components/SidePanel": "./components/SidePanel.tsx",
|
|
101
101
|
"./components/PullQuote": "./components/PullQuote.tsx",
|
|
102
102
|
"./components/ProfileSpotlight": "./components/ProfileSpotlight.tsx",
|
|
103
|
+
"./components/FounderSpotlight": "./components/FounderSpotlight.tsx",
|
|
104
|
+
"./components/TestimonialsSection": "./components/TestimonialsSection.tsx",
|
|
103
105
|
"./components/FilterBar": "./components/FilterBar.tsx",
|
|
104
106
|
"./components/Callout": "./components/Callout.tsx",
|
|
105
107
|
"./components/KenBurnsImage": "./components/KenBurnsImage.tsx"
|