From 8f5d4925fef6da1e6e7d4777afd99c885e236a48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20L=C3=BCder?= Date: Thu, 23 Apr 2026 09:00:15 -0500 Subject: [PATCH 1/2] feat(ui)!: bake social icons and disclaimer into OpenFooter MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The three OSS sites (fhir-brasil, medbench-brasil, datasus-brasil) ship identical GitHub/npm icons and the same medical/research disclaimer in their footers. Keep those in the component itself so consumers stop duplicating SVG paths and disclaimer copy across repos. Icons and disclaimer copy are now baked in. Per-project URLs stay configurable via new discrete props: - \`githubUrl\` (required) — repository URL. - \`npmUrl\` (optional) — npm package or org URL; omit for projects that don't publish to npm yet (e.g. datasus-brasil). BREAKING CHANGE: OpenFooter no longer accepts \`socials\` or \`disclaimer\` props; the \`OpenFooterSocial\` type is removed. Migration for consumers: \`\`\`diff -, label: 'GitHub' }, - { href: 'https://www.npmjs.com/...', icon: , label: 'npm' }, - ]} -/> + \`\`\` --- packages/ui/src/layout/OpenFooter.tsx | 103 +++++++++++++++++--------- packages/ui/src/layout/index.ts | 2 +- 2 files changed, 68 insertions(+), 37 deletions(-) diff --git a/packages/ui/src/layout/OpenFooter.tsx b/packages/ui/src/layout/OpenFooter.tsx index 842876b..bd7ffde 100644 --- a/packages/ui/src/layout/OpenFooter.tsx +++ b/packages/ui/src/layout/OpenFooter.tsx @@ -2,15 +2,6 @@ import type { ComponentProps, ReactNode } from 'react'; import { cn } from '../utils/cn.js'; -export interface OpenFooterSocial { - /** Target href. */ - href: string; - /** Icon element (typically an inline SVG or lucide icon). */ - icon: ReactNode; - /** Accessible label for the link. */ - label: string; -} - export interface OpenFooterBrand { /** URL the logo + wordmark link to. */ href: string; @@ -23,28 +14,32 @@ export interface OpenFooterBrand { export interface OpenFooterProps extends Omit, 'children'> { /** "Maintained by" brand block on the left. */ brand: OpenFooterBrand; - /** Disclaimer / legal paragraph rendered at the bottom. */ - disclaimer: ReactNode; + /** GitHub repository URL (rendered as a social icon). */ + githubUrl: string; /** "Maintained by" label. Default: "Mantido por". */ maintainedByLabel?: ReactNode; - /** Social links rendered on the right as round icon buttons. */ - socials?: OpenFooterSocial[]; + /** + * Optional npm package or org URL (rendered as a social icon when set). + * Omit for projects that don't publish to npm yet. + */ + npmUrl?: string; } /** * Footer for the OSS sites (fhir-brasil, medbench-brasil, datasus-brasil). * - * Layout: "Mantido por " on the left + social icon row on the - * right, with a thin divider + full-width disclaimer paragraph below. - * All copy is consumer-provided — the component ships the structure, - * typography and spacing conventions only. + * Layout: "Mantido por " on the left + GitHub (and optional npm) + * social icons on the right, with a thin divider + a shared medical + * disclaimer paragraph below. Icons and disclaimer are intentionally + * baked in — they're identical across the OSS sites — so consumers only + * supply their brand and the per-project repo / npm URLs. */ export function OpenFooter({ brand, className, - disclaimer, + githubUrl, maintainedByLabel = 'Mantido por', - socials, + npmUrl, ...props }: OpenFooterProps) { return ( @@ -81,29 +76,65 @@ export function OpenFooter({ - {socials && socials.length > 0 ? ( - - ) : null} +

- {disclaimer} + {DISCLAIMER}

); } + +function SocialLink({ + children, + href, + label, +}: { + children: ReactNode; + href: string; + label: string; +}) { + return ( + + {children} + + ); +} + +function GitHubIcon() { + return ( + + ); +} + +function NpmIcon() { + return ( + + ); +} + +const DISCLAIMER = + 'Este software é fornecido exclusivamente para fins informativos, de pesquisa e educacionais. Não constitui aconselhamento médico, diagnóstico ou recomendação de tratamento. Os resultados aqui apresentados não substituem a avaliação de um profissional de saúde qualificado. Consulte sempre um profissional de saúde antes de tomar decisões clínicas.'; diff --git a/packages/ui/src/layout/index.ts b/packages/ui/src/layout/index.ts index dc9efff..d0bdcd7 100644 --- a/packages/ui/src/layout/index.ts +++ b/packages/ui/src/layout/index.ts @@ -2,7 +2,7 @@ export type { HeaderProps } from './Header.js'; export { Header } from './Header.js'; export type { MobileDrawerHeader, MobileDrawerItem, MobileDrawerProps } from './MobileDrawer.js'; export { MobileDrawer } from './MobileDrawer.js'; -export type { OpenFooterBrand, OpenFooterProps, OpenFooterSocial } from './OpenFooter.js'; +export type { OpenFooterBrand, OpenFooterProps } from './OpenFooter.js'; export { OpenFooter } from './OpenFooter.js'; export type { PageContainerProps } from './PageContainer.js'; export { PageContainer } from './PageContainer.js'; From 8cdc1e3e1102fc4fedecad8894746e6328ace2cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20L=C3=BCder?= Date: Thu, 23 Apr 2026 09:05:00 -0500 Subject: [PATCH 2/2] refactor(ui): drop stale key prop from SocialLink The key={href} inside SocialLink was a leftover from the previous loop-based render; in the current OpenFooter layout SocialLink is used twice statically, so the key serves no purpose. Refs: #24 --- packages/ui/src/layout/OpenFooter.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/ui/src/layout/OpenFooter.tsx b/packages/ui/src/layout/OpenFooter.tsx index bd7ffde..cf3d08c 100644 --- a/packages/ui/src/layout/OpenFooter.tsx +++ b/packages/ui/src/layout/OpenFooter.tsx @@ -108,7 +108,6 @@ function SocialLink({ }) { return (