|
| 1 | +# Migration: v4 → v5 (dual theme) |
| 2 | + |
| 3 | +v5 introduces a **dual-theme** system. The same components now render under two |
| 4 | +themes, selected by a `data-theme` attribute: |
| 5 | + |
| 6 | +- **`neutral`** (default) — de-branded, shadcn-like. Applied on `:root`, so it is |
| 7 | + what you get with no extra setup. |
| 8 | +- **`uzh`** — the UZH corporate-design theme (UZH blue/red palette, Source Sans 3). |
| 9 | + |
| 10 | +Both themes share one set of components; only the CSS custom properties differ. |
| 11 | +There is no JS theme engine — switching is a pure CSS-variable cascade. |
| 12 | + |
| 13 | +## Breaking change: UZH apps must opt in |
| 14 | + |
| 15 | +In v4 the design system was UZH-branded by default. In v5 the default is |
| 16 | +`neutral`. **The three UZH apps must explicitly select the `uzh` theme**, or they |
| 17 | +will render de-branded. |
| 18 | + |
| 19 | +Pick one of: |
| 20 | + |
| 21 | +```html |
| 22 | +<!-- Simplest: set it once on the document root --> |
| 23 | +<html data-theme="uzh"></html> |
| 24 | +``` |
| 25 | + |
| 26 | +```tsx |
| 27 | +// Or wrap the app subtree with the design-system provider |
| 28 | +import { ThemeProvider } from '@uzh-bf/design-system' |
| 29 | + |
| 30 | +export function App({ children }) { |
| 31 | + return <ThemeProvider theme="uzh">{children}</ThemeProvider> |
| 32 | +} |
| 33 | +``` |
| 34 | + |
| 35 | +Anything inside a `data-theme="uzh"` container (set directly or via |
| 36 | +`ThemeProvider`) resolves its tokens against the UZH theme. Nesting is allowed: |
| 37 | +a `uzh` subtree inside a `neutral` page works, and vice versa. |
| 38 | + |
| 39 | +## New exports |
| 40 | + |
| 41 | +| Export | Purpose | |
| 42 | +| --------------- | ------------------------------------------------------------- | |
| 43 | +| `ThemeProvider` | Renders a `data-theme` container; controlled or uncontrolled. | |
| 44 | +| `useTheme` | Reads `{ theme, setTheme }` from the nearest `ThemeProvider`. | |
| 45 | +| `Theme` | `'neutral' \| 'uzh'` type. | |
| 46 | + |
| 47 | +`ThemeProvider` is optional — a plain `data-theme="uzh"` attribute is enough. |
| 48 | +Use the provider when you want an in-app theme toggle via `useTheme`. |
| 49 | + |
| 50 | +## Fonts |
| 51 | + |
| 52 | +The design system now `@import`s its webfonts (Source Sans 3 for `uzh`, JetBrains |
| 53 | +Mono for monospace) from Google Fonts inside `tailwind.css`. No per-app font setup |
| 54 | +is required. `neutral` uses the system font stack. |
| 55 | + |
| 56 | +## New component props & variants |
| 57 | + |
| 58 | +These are **additive** — existing usage keeps working. |
| 59 | + |
| 60 | +- **`Alert`** — new `variant`s: `neutral`, `info`, `success`, `warning`, `error` |
| 61 | + (tinted background + coloured left border + status icon). `default` and |
| 62 | + `destructive` are unchanged. |
| 63 | +- **`Badge`** — new `variant`s: `success`, `warning`, `info`, `error` (solid). |
| 64 | +- **`Input` / `Textarea`** — new `invalid?: boolean` prop → native `aria-invalid` |
| 65 | + (destructive border + ring). The Formik field wrappers wire this automatically |
| 66 | + from `error && touched`. |
| 67 | +- **`Avatar`** — new `size?: 'sm' | 'md' | 'lg'` (28 / 40 / 56 px). Omit for the |
| 68 | + legacy 32 px default. |
| 69 | +- **shadcn `TableRow`** (from the `Table`/`TableHeader`/`TableBody`/… family in |
| 70 | + `ui/table`, not the legacy `Table` component) — new `hoverable?: boolean` |
| 71 | + (default `true`) to opt out of row hover. |
| 72 | +- **`Tabs`** — restyled to an underline pattern (active tab gets a primary |
| 73 | + bottom-border instead of a filled pill). API unchanged. |
| 74 | + |
| 75 | +## Visual changes to verify |
| 76 | + |
| 77 | +- **`AvatarFallback`** background changed from `bg-muted` to `bg-primary-20 |
| 78 | +text-primary-100` (theme-tinted initials). Override via `className` if you |
| 79 | + relied on the grey fallback. |
| 80 | +- **`Tabs`** look different (underline, not pill). Layout/markup is unchanged. |
| 81 | + |
| 82 | +Everything else is theme-token routing: components that hardcoded UZH colours now |
| 83 | +read semantic tokens, so they follow whichever `data-theme` is active. |
0 commit comments