@mieweb/ui 0.11.0-dev.17 → 0.11.0-dev.19

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.
@@ -0,0 +1,53 @@
1
+ ---
2
+ name: mieweb-ui-icons
3
+ description: Icon usage for the @mieweb/ui design system — the lucide-react policy, the *Icon aliases re-exported from @mieweb/ui, sizing conventions, and icon accessibility. USE WHEN adding or replacing an icon, checking which icon alias exists, or reviewing hand-rolled SVGs / foreign icon libraries.
4
+ ---
5
+
6
+ <!-- GENERATED by scripts/build-agent-skills.mjs — do not edit by hand. Regenerate with `pnpm agent:skills`. -->
7
+
8
+ # @mieweb/ui icons
9
+
10
+ **Every icon comes from `lucide-react`** (Rule 17 of the installed `mieweb-ui.instructions.md`). Never hand-roll an `<svg>` icon or add another icon library — `@fortawesome/*` is ESLint-blocked in the library itself.
11
+
12
+ Two ways to import:
13
+
14
+ ```tsx
15
+ // 1. Convenience aliases re-exported from @mieweb/ui (188 icons, listed below)
16
+ import { SearchIcon, TrashIcon } from '@mieweb/ui';
17
+
18
+ // 2. The full Lucide set, directly — for anything not aliased
19
+ import { Stethoscope, Syringe } from 'lucide-react';
20
+ ```
21
+
22
+ ## Conventions
23
+
24
+ - **Sizing:** `className="h-4 w-4"` (16px) is the default inline size; `h-5 w-5` for emphasis; `h-3.5 w-3.5` in dense UI. Lucide's `size={16}` prop is equivalent.
25
+ - **Accessibility:** icon-only controls need `aria-label`; decorative icons get `aria-hidden="true"`. A `Tooltip` is a description, not a name.
26
+ - **Dynamic icons:** type icon props as `LucideIcon` and spread `LucideProps` — both re-exported from `@mieweb/ui`.
27
+ - Aliases where the Lucide name differs are shown as `Alias` (`LucideName`); import the alias from `@mieweb/ui` or the Lucide name from `lucide-react`. ⚠ marks aliases shadowed at the root — see below.
28
+
29
+ ## Aliased icons by category
30
+
31
+ - **Navigation & UI:** `HomeIcon`, `MenuIcon`, `CloseIcon` (`X`) ⚠, `ChevronDownIcon`, `ChevronUpIcon`, `ChevronLeftIcon`, `ChevronRightIcon`, `ArrowLeftIcon`, `ArrowRightIcon`, `ExternalLinkIcon`, `MoreHorizontalIcon`, `MoreVerticalIcon`
32
+ - **User & Account:** `UserIcon`, `UsersIcon`, `UserPlusIcon`, `UserMinusIcon`, `UserCheckIcon`, `CircleUserIcon`, `LogInIcon`, `LogOutIcon`
33
+ - **Actions:** `PlusIcon`, `MinusIcon`, `PencilIcon`, `TrashIcon` (`Trash2`), `CopyIcon`, `CheckIcon`, `XIcon`, `SearchIcon`, `FilterIcon`, `DownloadIcon`, `UploadIcon`, `ShareIcon`, `SaveIcon`, `RefreshIcon` (`RefreshCw`) ⚠, `ThumbsUpIcon`, `ThumbsDownIcon`, `BanIcon`, `ArrowUpIcon`, `ArrowUpDownIcon`, `GripVerticalIcon`, `StickyNoteIcon`
34
+ - **Status & Feedback:** `AlertCircleIcon`, `AlertTriangleIcon`, `CheckCircleIcon`, `XCircleIcon`, `InfoIcon`, `HelpCircleIcon`, `LoaderIcon` (`Loader2`)
35
+ - **Communication:** `BellIcon`, `BellOffIcon`, `BotIcon`, `MailIcon`, `MessageIcon` (`MessageSquare`), `MicIcon`, `PhoneIcon`, `SendIcon` ⚠, `StopIcon` (`Square`)
36
+ - **Media & Files:** `FileIcon`, `FileTextIcon`, `FolderIcon`, `FolderOpenIcon`, `ImageIcon`, `CameraIcon`, `PaperclipIcon`, `PrinterIcon`
37
+ - **Data & Charts:** `ActivityIcon`, `ChartIcon` (`BarChart3`), `TrendingUpIcon`, `TrendingDownIcon`, `PieChartIcon`
38
+ - **Settings & Tools:** `SettingsIcon`, `SlidersIcon`, `WrenchIcon`, `CogIcon`
39
+ - **Time & Calendar:** `CalendarIcon`, `CalendarCheckIcon`, `ClockIcon`, `TimerIcon`, `HistoryIcon`
40
+ - **Layout & View:** `EyeIcon`, `GridIcon` (`LayoutGrid`), `ListIcon`, `TableIcon`, `ColumnsIcon`, `MaximizeIcon`, `MinimizeIcon`, `EyeOffIcon`
41
+ - **Theme:** `SunIcon`, `MoonIcon`, `MonitorIcon`, `PaletteIcon`
42
+ - **Security:** `ShieldIcon`, `ShieldCheckIcon`, `LockIcon`, `UnlockIcon`, `KeyIcon`
43
+ - **Healthcare & Medical:** `AmbulanceIcon`, `BandageIcon`, `BoneIcon`, `BrainIcon`, `BriefcaseMedicalIcon`, `DnaIcon`, `EarIcon`, `FingerprintIcon`, `HeartPulseIcon`, `HospitalIcon`, `MicroscopeIcon`, `PillIcon`, `StethoscopeIcon`, `SyringeIcon`, `TestTubeIcon` (`TestTube2`), `TestTubesIcon`, `ThermometerIcon`, `ThermometerSunIcon`, `BabyIcon`, `AccessibilityIcon`, `BedIcon`, `BedDoubleIcon`, `BedSingleIcon`, `PatientIcon` (`CircleUserRound`), `PersonIcon` (`UserRound`), `UserRoundCheckIcon`, `UserRoundPlusIcon`, `UserRoundMinusIcon`, `UserRoundXIcon`, `CrossIcon`, `FlaskIcon` (`FlaskConical`), `FlaskRoundIcon`, `DropletIcon`, `DropletsIcon`, `ScanIcon`, `ScanLineIcon`, `ScanEyeIcon`, `RadiationIcon`, `BiohazardIcon`, `CigaretteIcon`, `CigaretteOffIcon`, `CannabisIcon`, `WeightIcon`, `ScaleIcon`, `RulerIcon`, `FootprintsIcon`, `HandIcon`, `HandMetalIcon`, `GlassesIcon`, `ScalingIcon`, `TabletsIcon`, `AllergyIcon` (`Wheat`), `AllergyOffIcon` (`WheatOff`), `HeartOffIcon`, `ShieldPlusIcon`, `ClipboardPlusIcon`, `ClipboardCheckIcon`, `FileHeartIcon`, `FilePlusIcon`, `FilePlus2Icon`, `FileCheckIcon`, `FileCheck2Icon`, `NotebookPenIcon`, `BookOpenIcon`, `BookOpenCheckIcon`, `TruckIcon`, `SparkleIcon`, `BadgeCheckIcon`, `BadgeAlertIcon`, `BadgeXIcon`, `BadgePlusIcon`, `BadgeMinusIcon`, `CircleDotIcon`, `CircleDotDashedIcon`
44
+ - **Misc:** `HeartIcon`, `StarIcon`, `BookmarkIcon`, `FlagIcon`, `TagIcon`, `HashIcon`, `AtSignIcon`, `LinkIcon`, `ClipboardIcon`, `ClipboardListIcon`, `MapPinIcon`, `GlobeIcon`, `BuildingIcon`, `BriefcaseIcon`, `CreditCardIcon`, `DollarSignIcon`, `ZapIcon`, `SparklesIcon` ⚠
45
+
46
+ ## ⚠ Root-barrel overrides — NOT Lucide
47
+
48
+ - `CloseIcon` from `@mieweb/ui` is a **custom component** from `src/components/AI`, not the Lucide `X` — Lucide props like `size={16}` do not apply
49
+ - `RefreshIcon` from `@mieweb/ui` is a **custom component** from `src/components/AI`, not the Lucide `RefreshCw` — Lucide props like `size={16}` do not apply
50
+ - `SendIcon` from `@mieweb/ui` is a **custom component** from `src/components/AI`, not the Lucide `Send` — Lucide props like `size={16}` do not apply
51
+ - `SparklesIcon` from `@mieweb/ui` is a **custom component** from `src/components/AI`, not the Lucide `Sparkles` — Lucide props like `size={16}` do not apply
52
+
53
+ For the Lucide version, import the Lucide name from `lucide-react` (`X`, `RefreshCw`, `Send`, `Sparkles`) or the alias from `@mieweb/ui/components/Icons`.
@@ -0,0 +1,126 @@
1
+ ---
2
+ name: mieweb-ui-tailwind4
3
+ description: Installing and wiring @mieweb/ui in a consumer app — Tailwind 4 `@source` setup vs the Tailwind 3 preset, PostCSS config, dark-mode variant and CSS-variable fallbacks, peer dependencies per entry point, and connecting headless modules to a data layer. USE WHEN setting up @mieweb/ui, components render unstyled/broken, dark mode or brand CSS misbehaves after install, peer-dep errors appear, or a ViewSet/SuperChat-style module needs wiring to app data.
4
+ ---
5
+
6
+ # Installing @mieweb/ui (Tailwind 4 era)
7
+
8
+ Sourced from `lessons/tailwind4-integration.md`, `lessons/adopting-mieweb-ui.md`, and `lessons/wiring-headless-modules.md` in the mieweb/ui repo. Token tables live in the `mieweb-ui-tokens` skill; brand procedures in `mieweb-ui-brands`; entry points and their peer deps in `mieweb-ui-catalog`.
9
+
10
+ ## Install
11
+
12
+ ```bash
13
+ npm install @mieweb/ui react react-dom
14
+ npm install -D tailwindcss@4 @tailwindcss/postcss autoprefixer
15
+ ```
16
+
17
+ `react` / `react-dom` (>=18) are the only **required** peers. Every other peer is **optional** and only needed when you import the entry that uses it (`/maps` → leaflet, `/globe` → react-globe.gl + three, `/kerebron` → @kerebron/\*, `/motion` → motion, `/q` → @mieweb/q, …) — see the catalog skill's entry-point table. A peer-dep warning for an entry you never import is noise, not a problem. Under pnpm's strict node_modules there is no hoisting: required peers must be in the app's own `package.json`; diagnose resolution with `pnpm why <pkg>`.
18
+
19
+ ## Tailwind 4 vs Tailwind 3 vs no Tailwind — pick the right mechanism
20
+
21
+ | Consumer | Mechanism |
22
+ | --- | --- |
23
+ | Tailwind 4 (CSS-first) | `@source "../node_modules/@mieweb/ui/dist";` in the CSS entry — TW4 does **not** scan `node_modules` on its own |
24
+ | Tailwind 3 (config-first) | `presets: [miewebUIPreset]` from `@mieweb/ui/tailwind-preset` + the exported `miewebUISafelist` + `node_modules/@mieweb/ui/dist/**/*.js` in `content` |
25
+ | No Tailwind | `import '@mieweb/ui/styles.css'` (+ a brand CSS after it) — precompiled, fully supported; no Tailwind, PostCSS, or `@source` needed |
26
+
27
+ In a Tailwind consumer, missing `@source` (TW4) or content/safelist coverage (TW3) means the library's utility classes are tree-shaken away: **black borders, missing backgrounds, broken layout** on every component. The `@source`/safelist/PostCSS checks below apply **only** when the consumer runs its own Tailwind pipeline — don't prescribe Tailwind tooling to a precompiled-CSS app.
28
+
29
+ ## CSS entry — quick start vs manual
30
+
31
+ **Option A (quick start)** — three lines, all in **your own** CSS entry (the first two resolve relative to your file, so they cannot live inside the package):
32
+
33
+ ```css
34
+ @import 'tailwindcss';
35
+ @source "../node_modules/@mieweb/ui/dist"; /* path relative to THIS file */
36
+ @import '@mieweb/ui/init.css'; /* dark variant + @theme fallbacks + default brand + base styles */
37
+ ```
38
+
39
+ **Option B (manual, full control)** — every line matters, in this order:
40
+
41
+ ```css
42
+ /* 1. Base stylesheet THEN brand (both plain/unlayered — see brands skill) */
43
+ @import '@mieweb/ui/styles.css';
44
+ @import '@mieweb/ui/brands/bluehive.css';
45
+
46
+ /* 2. Tailwind */
47
+ @import 'tailwindcss';
48
+
49
+ /* 3. Scan the library output for class names */
50
+ @source "../node_modules/@mieweb/ui/dist";
51
+
52
+ /* 4. Dark variant (TW4 doesn't reliably honor tailwind.config darkMode) */
53
+ @custom-variant dark (&:where([data-theme=dark], [data-theme=dark] *));
54
+
55
+ /* 5. Map Tailwind color tokens to @mieweb/ui variables — WITH fallbacks */
56
+ @theme {
57
+ --color-primary-500: var(--mieweb-primary-500);
58
+ --color-neutral-900: var(--mieweb-neutral-900, #171717);
59
+ /* … full block with fallback hex values: see init.css in the package */
60
+ }
61
+ ```
62
+
63
+ Primary needs no fallbacks (every brand defines it). **All other scales must carry hex fallbacks** — if the base stylesheet is missing, `var()` resolves to nothing and `dark:bg-neutral-900` renders transparent. This is the single most time-expensive gotcha.
64
+
65
+ ## PostCSS
66
+
67
+ ```js
68
+ // postcss.config.cjs
69
+ module.exports = {
70
+ plugins: {
71
+ '@tailwindcss/postcss': {}, // Tailwind 4 plugin
72
+ autoprefixer: {},
73
+ },
74
+ };
75
+ ```
76
+
77
+ `tailwindcss: {}` is the Tailwind **3** plugin — with Tailwind 4 installed it silently fails or produces wrong output.
78
+
79
+ ## Dark mode toggle — match the configured variant
80
+
81
+ The variant selector decides which hook works: `init.css` accepts **either** `.dark` or `data-theme="dark"`, while the manual Option B variant above is attribute-only. A single-hook toggle against `init.css` is valid — diagnose by comparing the toggle to the `@custom-variant` actually in effect, not by demanding both hooks. Setting both is the compatibility-safe recommendation for new code:
82
+
83
+ ```ts
84
+ function applyTheme(t: 'light' | 'dark') {
85
+ document.documentElement.classList.toggle('dark', t === 'dark');
86
+ document.documentElement.setAttribute('data-theme', t);
87
+ }
88
+ ```
89
+
90
+ "Dark mode toggles but half the page stays light" usually means the toggle sets a hook the configured `@custom-variant` doesn't match. Brand switching at runtime uses the `brands` barrel loader — see the `mieweb-ui-brands` skill.
91
+
92
+ ## Wiring headless modules
93
+
94
+ Modules never fetch, subscribe, navigate, or write — you supply a small adapter. The recipe below is the **collection-view contract** (`ViewSet` and friends). `SuperChatInbox` follows the same principles (host-owned state, promise-returning callbacks) but has its own props — `conversations`, `onMessageSent`, `onConversationOpened` — see the catalog skill and component docs; don't hand it collection-view props.
95
+
96
+ 1. **Fetch with your stack** (Meteor `useSubscribe`/`useTracker`, TanStack `useQuery`, …) and pass `items` / `loading` / `error` straight through.
97
+ 2. **Describe records once** via `accessors` (`getId`, `getTitle`, `getStatus`, …) — defined at module scope or memoized; they sit in `useMemo` deps.
98
+ 3. **Return the promise from `on*` callbacks** (`onMove={(id, s) => update(id, s)}`). The view shows pending state and reverts on rejection. TanStack: `mutateAsync`, not `mutate`; Meteor: `Meteor.callAsync`, don't catch-and-swallow.
99
+ 4. **Pass both `onOpen` and `getHref`** — `getHref` makes rows real anchors (⌘-click, copy link); `onOpen` intercepts plain clicks for client routing.
100
+
101
+ Filters/selection/pagination state is yours (usually the URL); `ViewSet` owns only which view is showing. The `table` slot takes a DataVis NITRO grid — `ViewSet` has no table of its own.
102
+
103
+ ## Troubleshooting
104
+
105
+ | Symptom | Likely cause | Fix |
106
+ | --- | --- | --- |
107
+ | Black/missing borders, unstyled components | TW4 tree-shaking (Tailwind consumers only) | Add the `@source` directive |
108
+ | Dark mode toggle does nothing | Missing `@custom-variant dark`, or toggle sets a hook the variant doesn't match | Add the variant; align toggle with its selectors |
109
+ | Dark toggles but surfaces stay light | Missing `var()` fallbacks / missing base stylesheet | Hex fallbacks in `@theme`; import `styles.css` or `init.css` |
110
+ | Brand switch has no effect | Wrong import path | Barrel: `from '@mieweb/ui/brands'` |
111
+ | Brand CSS loads but doesn't apply (TW4) | Brand import wrapped in `layer(theme)` | Keep base + brand imports plain/unlayered (brands skill) |
112
+ | PostCSS does nothing | TW3 plugin configured | `@tailwindcss/postcss`, not `tailwindcss` |
113
+ | `var()` renders transparent | Variable undefined | Fallback: `var(--token, #hex)` |
114
+ | Peer-dep install errors | Required vs optional confusion | Only react/react-dom are required; match optional peers to imported entries |
115
+ | Module shows failed action as success | `on*` promise swallowed | Return the real promise (`mutateAsync` / `callAsync`) |
116
+ | Views regroup on every render | Unstable `accessors` | Module scope or `useMemo` |
117
+
118
+ ## Verification checklist
119
+
120
+ - [ ] Tailwind consumer: `@source` (TW4) or preset + safelist + content (TW3) in place. No Tailwind: `styles.css` imported
121
+ - [ ] `@custom-variant dark` defined (Tailwind consumers); toggle sets a hook the variant matches (both `.dark` and `data-theme` for maximum compatibility)
122
+ - [ ] All non-primary `var()` mappings carry hex fallbacks (or `init.css` is used)
123
+ - [ ] PostCSS uses `@tailwindcss/postcss`
124
+ - [ ] Base stylesheet imported before brand CSS, both unlayered
125
+ - [ ] Dark mode works with a non-default brand active
126
+ - [ ] `npx tsc --noEmit` clean; no console errors on theme/brand switch
@@ -0,0 +1,236 @@
1
+ ---
2
+ name: mieweb-ui-tokens
3
+ description: Design tokens for the @mieweb/ui design system — color scales, semantic colors, radius, typography, shadows, animations, and how CSS variables and dark mode work. USE WHEN auditing or writing styles, choosing a color/radius/shadow class, checking what a token resolves to, or fixing hardcoded colors.
4
+ ---
5
+
6
+ <!-- GENERATED by scripts/build-agent-skills.mjs — do not edit by hand. Regenerate with `pnpm agent:skills`. -->
7
+
8
+ # @mieweb/ui design tokens
9
+
10
+ All tokens are CSS variables (`--mieweb-*`) with baked-in defaults, mapped to Tailwind classes by `@mieweb/ui/tailwind-preset`. Brands (`@mieweb/ui/brands/*.css`) override the variables; components never change. See the `mieweb-ui-brands` skill for brand switching and creating brands.
11
+
12
+ **Rules that always apply** (from the installed `mieweb-ui.instructions.md`):
13
+
14
+ - Never hardcode palette colors (`bg-blue-500`, `text-violet-600`, hex values, inline gradients). Use `primary-*`, `secondary-*`, `neutral-*` or a semantic token so brand switching keeps working.
15
+ - Status styling uses the semantic scales (`success`, `warning`, `destructive`, `info`) — not raw `green`/`amber`/`red` utilities.
16
+ - Radius comes from the mapped `rounded-sm|md|lg|xl|2xl` classes (brand tokens), never arbitrary values like `rounded-[20px]`. `rounded-full` is fine for circles/pills.
17
+
18
+ **Dark mode:** `darkMode: ["class","[data-theme=\"dark\"]"]` — a `.dark` class or `[data-theme="dark"]` on an ancestor switches the semantic variables; components need no dark-specific code beyond `dark:` variants already in the library.
19
+
20
+ **Tailwind setup:** TW4 consumers add `@source "../node_modules/@mieweb/ui/dist";` to their CSS; TW3 consumers use the exported `miewebUISafelist` (classes used by components that Tailwind can't detect in node_modules).
21
+
22
+ ## Color scales
23
+
24
+ Use as `bg-<token>`, `text-<token>`, `border-<token>`, `ring-<token>`, etc.
25
+
26
+ ### `primary`
27
+
28
+ | Token | Value (CSS variable, default) |
29
+ | --- | --- |
30
+ | `primary-50` | `var(--mieweb-primary-50, #e6f7fc)` |
31
+ | `primary-100` | `var(--mieweb-primary-100, #b3e6f6)` |
32
+ | `primary-200` | `var(--mieweb-primary-200, #80d5f0)` |
33
+ | `primary-300` | `var(--mieweb-primary-300, #4dc4ea)` |
34
+ | `primary-400` | `var(--mieweb-primary-400, #27aae1)` |
35
+ | `primary-500` | `var(--mieweb-primary-500, #27aae1)` |
36
+ | `primary-600` | `var(--mieweb-primary-600, #1f98ca)` |
37
+ | `primary-700` | `var(--mieweb-primary-700, #1786b3)` |
38
+ | `primary-800` | `var(--mieweb-primary-800, #0f749c)` |
39
+ | `primary-900` | `var(--mieweb-primary-900, #086285)` |
40
+ | `primary-950` | `var(--mieweb-primary-950, #00506e)` |
41
+ | `primary` | `var(--mieweb-primary, var(--mieweb-primary-500, #27aae1))` |
42
+ | `primary-foreground` | `var(--mieweb-primary-foreground, hsl(210 40% 98%))` |
43
+
44
+ ### `ozwell`
45
+
46
+ | Token | Value (CSS variable, default) |
47
+ | --- | --- |
48
+ | `ozwell` | `var(--mieweb-ozwell, #0BA0E0)` |
49
+ | `ozwell-foreground` | `var(--mieweb-ozwell-foreground, hsl(0 0% 100%))` |
50
+
51
+ ### `secondary`
52
+
53
+ | Token | Value (CSS variable, default) |
54
+ | --- | --- |
55
+ | `secondary-50` | `var(--mieweb-secondary-50, #eef2ff)` |
56
+ | `secondary-100` | `var(--mieweb-secondary-100, #e0e7ff)` |
57
+ | `secondary-200` | `var(--mieweb-secondary-200, #c7d2fe)` |
58
+ | `secondary-300` | `var(--mieweb-secondary-300, #a5b4fc)` |
59
+ | `secondary-400` | `var(--mieweb-secondary-400, #818cf8)` |
60
+ | `secondary-500` | `var(--mieweb-secondary-500, #6366f1)` |
61
+ | `secondary-600` | `var(--mieweb-secondary-600, #4f46e5)` |
62
+ | `secondary-700` | `var(--mieweb-secondary-700, #4338ca)` |
63
+ | `secondary-800` | `var(--mieweb-secondary-800, #3730a3)` |
64
+ | `secondary-900` | `var(--mieweb-secondary-900, #312e81)` |
65
+ | `secondary-950` | `var(--mieweb-secondary-950, #1e1b4b)` |
66
+ | `secondary` | `var(--mieweb-secondary-500, #6366f1)` |
67
+ | `secondary-foreground` | `var(--mieweb-secondary-foreground, #ffffff)` |
68
+
69
+ ### `neutral`
70
+
71
+ | Token | Value (CSS variable, default) |
72
+ | --- | --- |
73
+ | `neutral-50` | `var(--mieweb-neutral-50, #fafafa)` |
74
+ | `neutral-100` | `var(--mieweb-neutral-100, #f5f5f5)` |
75
+ | `neutral-200` | `var(--mieweb-neutral-200, #e5e5e5)` |
76
+ | `neutral-300` | `var(--mieweb-neutral-300, #d4d4d4)` |
77
+ | `neutral-400` | `var(--mieweb-neutral-400, #a3a3a3)` |
78
+ | `neutral-500` | `var(--mieweb-neutral-500, #737373)` |
79
+ | `neutral-600` | `var(--mieweb-neutral-600, #525252)` |
80
+ | `neutral-700` | `var(--mieweb-neutral-700, #404040)` |
81
+ | `neutral-800` | `var(--mieweb-neutral-800, #262626)` |
82
+ | `neutral-900` | `var(--mieweb-neutral-900, #171717)` |
83
+ | `neutral-950` | `var(--mieweb-neutral-950, #0a0a0a)` |
84
+ | `neutral` | `var(--mieweb-neutral-500, #737373)` |
85
+
86
+ ### `card`
87
+
88
+ | Token | Value (CSS variable, default) |
89
+ | --- | --- |
90
+ | `card` | `var(--mieweb-card, hsl(0 0% 100%))` |
91
+ | `card-foreground` | `var(--mieweb-card-foreground, hsl(222.2 84% 4.9%))` |
92
+
93
+ ### `muted`
94
+
95
+ | Token | Value (CSS variable, default) |
96
+ | --- | --- |
97
+ | `muted` | `var(--mieweb-muted, hsl(210 40% 96.1%))` |
98
+ | `muted-foreground` | `var(--mieweb-muted-foreground, hsl(215.4 16.3% 46.9%))` |
99
+
100
+ ### `destructive`
101
+
102
+ | Token | Value (CSS variable, default) |
103
+ | --- | --- |
104
+ | `destructive-50` | `var(--mieweb-destructive-50, #fef2f2)` |
105
+ | `destructive-100` | `var(--mieweb-destructive-100, #fee2e2)` |
106
+ | `destructive-200` | `var(--mieweb-destructive-200, #fecaca)` |
107
+ | `destructive-300` | `var(--mieweb-destructive-300, #fca5a5)` |
108
+ | `destructive-400` | `var(--mieweb-destructive-400, #f87171)` |
109
+ | `destructive-500` | `var(--mieweb-destructive-500, #dc2626)` |
110
+ | `destructive-600` | `var(--mieweb-destructive-600, #dc2626)` |
111
+ | `destructive-700` | `var(--mieweb-destructive-700, #b91c1c)` |
112
+ | `destructive-800` | `var(--mieweb-destructive-800, #991b1b)` |
113
+ | `destructive-900` | `var(--mieweb-destructive-900, #7f1d1d)` |
114
+ | `destructive-950` | `var(--mieweb-destructive-950, #450a0a)` |
115
+ | `destructive` | `var(--mieweb-destructive, var(--mieweb-destructive-500, #dc2626))` |
116
+ | `destructive-foreground` | `var(--mieweb-destructive-foreground, hsl(210 40% 98%))` |
117
+
118
+ ### `success`
119
+
120
+ | Token | Value (CSS variable, default) |
121
+ | --- | --- |
122
+ | `success-50` | `var(--mieweb-success-50, #f0fdf4)` |
123
+ | `success-100` | `var(--mieweb-success-100, #dcfce7)` |
124
+ | `success-200` | `var(--mieweb-success-200, #bbf7d0)` |
125
+ | `success-300` | `var(--mieweb-success-300, #86efac)` |
126
+ | `success-400` | `var(--mieweb-success-400, #4ade80)` |
127
+ | `success-500` | `var(--mieweb-success-500, #22c55e)` |
128
+ | `success-600` | `var(--mieweb-success-600, #16a34a)` |
129
+ | `success-700` | `var(--mieweb-success-700, #15803d)` |
130
+ | `success-800` | `var(--mieweb-success-800, #166534)` |
131
+ | `success-900` | `var(--mieweb-success-900, #14532d)` |
132
+ | `success-950` | `var(--mieweb-success-950, #052e16)` |
133
+ | `success` | `var(--mieweb-success-500, #22c55e)` |
134
+ | `success-foreground` | `var(--mieweb-success-foreground, hsl(355.7 100% 97.3%))` |
135
+
136
+ ### `warning`
137
+
138
+ | Token | Value (CSS variable, default) |
139
+ | --- | --- |
140
+ | `warning-50` | `var(--mieweb-warning-50, #fffbeb)` |
141
+ | `warning-100` | `var(--mieweb-warning-100, #fef3c7)` |
142
+ | `warning-200` | `var(--mieweb-warning-200, #fde68a)` |
143
+ | `warning-300` | `var(--mieweb-warning-300, #fcd34d)` |
144
+ | `warning-400` | `var(--mieweb-warning-400, #fbbf24)` |
145
+ | `warning-500` | `var(--mieweb-warning-500, #f59e0b)` |
146
+ | `warning-600` | `var(--mieweb-warning-600, #d97706)` |
147
+ | `warning-700` | `var(--mieweb-warning-700, #b45309)` |
148
+ | `warning-800` | `var(--mieweb-warning-800, #92400e)` |
149
+ | `warning-900` | `var(--mieweb-warning-900, #78350f)` |
150
+ | `warning-950` | `var(--mieweb-warning-950, #451a03)` |
151
+ | `warning` | `var(--mieweb-warning-500, #f59e0b)` |
152
+ | `warning-foreground` | `var(--mieweb-warning-foreground, hsl(26 83.3% 14.1%))` |
153
+
154
+ ### `info`
155
+
156
+ | Token | Value (CSS variable, default) |
157
+ | --- | --- |
158
+ | `info-50` | `var(--mieweb-info-50, #f0f9ff)` |
159
+ | `info-100` | `var(--mieweb-info-100, #e0f2fe)` |
160
+ | `info-200` | `var(--mieweb-info-200, #bae6fd)` |
161
+ | `info-300` | `var(--mieweb-info-300, #7dd3fc)` |
162
+ | `info-400` | `var(--mieweb-info-400, #38bdf8)` |
163
+ | `info-500` | `var(--mieweb-info-500, #0ea5e9)` |
164
+ | `info-600` | `var(--mieweb-info-600, #0284c7)` |
165
+ | `info-700` | `var(--mieweb-info-700, #0369a1)` |
166
+ | `info-800` | `var(--mieweb-info-800, #075985)` |
167
+ | `info-900` | `var(--mieweb-info-900, #0c4a6e)` |
168
+ | `info-950` | `var(--mieweb-info-950, #082f49)` |
169
+ | `info` | `var(--mieweb-info-500, #0ea5e9)` |
170
+ | `info-foreground` | `var(--mieweb-info-foreground, #ffffff)` |
171
+
172
+ ### `chart`
173
+
174
+ | Token | Value (CSS variable, default) |
175
+ | --- | --- |
176
+ | `chart-1` | `var(--mieweb-chart-1, #27aae1)` |
177
+ | `chart-2` | `var(--mieweb-chart-2, #22c55e)` |
178
+ | `chart-3` | `var(--mieweb-chart-3, #f59e0b)` |
179
+ | `chart-4` | `var(--mieweb-chart-4, #ef4444)` |
180
+ | `chart-5` | `var(--mieweb-chart-5, #6366f1)` |
181
+
182
+ ## Semantic single tokens
183
+
184
+ | Token | Value (CSS variable, default) |
185
+ | --- | --- |
186
+ | `accent` | `var(--mieweb-accent, var(--mieweb-primary-400))` |
187
+ | `border` | `var(--mieweb-border, hsl(214.3 31.8% 91.4%))` |
188
+ | `input` | `var(--mieweb-input, hsl(214.3 31.8% 91.4%))` |
189
+ | `ring` | `var(--mieweb-ring, hsl(221.2 83.2% 53.3%))` |
190
+ | `background` | `var(--mieweb-background, hsl(0 0% 100%))` |
191
+ | `foreground` | `var(--mieweb-foreground, hsl(222.2 84% 4.9%))` |
192
+
193
+ ## Typography
194
+
195
+ | Token | Value (CSS variable, default) |
196
+ | --- | --- |
197
+ | `font-sans` | `var(--mieweb-font-sans, ui-sans-serif), system-ui, sans-serif` |
198
+
199
+ ## Border radius
200
+
201
+ | Token | Value (CSS variable, default) |
202
+ | --- | --- |
203
+ | `rounded-2xl` | `var(--mieweb-radius-2xl, 1rem)` |
204
+ | `rounded-lg` | `var(--mieweb-radius-lg, 0.75rem)` |
205
+ | `rounded-md` | `var(--mieweb-radius-md, 0.5rem)` |
206
+ | `rounded-sm` | `var(--mieweb-radius-sm, 0.25rem)` |
207
+ | `rounded-xl` | `var(--mieweb-radius-xl, 1rem)` |
208
+
209
+ ## Shadows
210
+
211
+ | Token | Value (CSS variable, default) |
212
+ | --- | --- |
213
+ | `shadow-card` | `var(--mieweb-shadow-card, 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1))` |
214
+
215
+ ## Animations
216
+
217
+ | Class | Animation |
218
+ | --- | --- |
219
+ | `animate-fade-in` | `fade-in 150ms ease-out` |
220
+ | `animate-fade-out` | `fade-out 150ms ease-in` |
221
+ | `animate-slide-in-from-top` | `slide-in-from-top 150ms ease-out` |
222
+ | `animate-slide-in-from-bottom` | `slide-in-from-bottom 150ms ease-out` |
223
+ | `animate-slide-in-right` | `slide-in-right 300ms ease-out` |
224
+ | `animate-slide-in-left` | `slide-in-left 300ms ease-out` |
225
+ | `animate-loading-bar` | `loading-bar 1.5s ease infinite` |
226
+ | `animate-loading-bar-rtl` | `loading-bar-rtl 1.5s ease infinite` |
227
+ | `animate-shimmer` | `shimmer 2s linear infinite` |
228
+ | `animate-shimmer-rtl` | `shimmer-rtl 2s linear infinite` |
229
+ | `animate-scale-in` | `scale-in 150ms ease-out` |
230
+ | `animate-ozwell-message-flare` | `ozwell-message-flare 1.8s ease-out` |
231
+
232
+ RTL variants (`*-rtl`) exist because transform-based animations do not flip automatically in right-to-left layouts.
233
+
234
+ ## Line clamp
235
+
236
+ Extends Tailwind's 1–6 scale with `line-clamp-7`, `line-clamp-8` (used by ClampedText).