Shared React UI component library for MedixDeck, published as
@medixdeck/ui.
@medixdeck/ui is a Vite library-mode package built with React 18, TypeScript 5, Chakra UI v3, semantic design tokens, and dual ESM/CJS output for npm publishing.
npm install @medixdeck/ui @chakra-ui/react react react-domimport {
Button,
Logo,
MedixProvider,
Navbar,
useThemeMode,
} from "@medixdeck/ui";
// Next.js App Router: mark this component "use client" when using hooks.
function ThemeToggle() {
const { mounted, themeMode, toggleThemeMode } = useThemeMode();
// Avoid hydration mismatch: next-themes resolves the theme after mount.
if (!mounted) return null;
return (
<Button variant="solid" colorScheme="blue" onClick={toggleThemeMode}>
Switch to {themeMode === "dark" ? "light" : "dark"} mode
</Button>
);
}
export function App() {
return (
<MedixProvider defaultColorMode="light">
<Navbar
navItems={[{ label: "Docs", href: "#docs" }]}
ctaLabel="Talk to a Doctor"
ctaHref="/consult"
/>
<ThemeToggle />
<Logo variant="purple" height={28} />
</MedixProvider>
);
}| Area | Exports |
|---|---|
| Provider + theme | MedixProvider, useThemeMode, useIsDarkMode, useColorScheme, system, medixConfig, token exports |
| Primitive | Button, IconButton, Badge, Avatar, AvatarGroup, Spinner, FullPageSpinner, Tag, Divider, Logo |
| Form | Input, SearchInput, Textarea, Select, Checkbox, RadioGroup, Switch, FormControl, OTPInput, PinInput, PhoneInput, DatePicker, DateRangePicker, Calendar, Combobox, FileUpload |
| Layout | Card, CardHeader, CardBody, CardFooter, StatCard, Container, SectionHeader, ThemeColorPalette, DashboardLayout, Footer |
| Navigation | Navbar, Breadcrumb, Tabs, Pagination, Stepper |
| Feedback | Alert, Skeleton, SkeletonText, SkeletonCard, Progress, Modal, Drawer, Tooltip, EmptyState, Toaster, toast, dismissToast |
| Data display | Accordion, TestimonialCard, BlogCard, DataTable |
| Healthcare | DoctorCard, VitalBadge, AppointmentCard |
| Chakra re-exports | Box, Flex, Grid, Stack, Text, Heading, Link, Image, Icon, Center, Wrap, WrapItem, others in lib/index.ts |
- Use Chakra UI v3 APIs only.
- All library source lives in
lib\;src\is dev-preview only. - Use semantic tokens such as
bg.surface,text.heading, andborderinstead of raw hex for normal component styling. - For color-critical interactive controls, prefer the repo's native-first pattern instead of Chakra recipes.
- Apply dark mode on
document.documentElement, not an inner container.
import { useIsDarkMode, useThemeMode } from "@medixdeck/ui";
function ThemeStatus() {
const { themeMode, themeSetting, setThemeMode, toggleThemeMode } = useThemeMode();
const isDarkMode = useIsDarkMode();
return (
<>
<p>Resolved mode: {themeMode}</p>
<p>Following: {themeSetting ?? "system"}</p>
<p>Dark mode active: {String(isDarkMode)}</p>
<button onClick={() => setThemeMode("dark")}>Dark</button>
<button onClick={() => setThemeMode("light")}>Light</button>
<button onClick={() => setThemeMode("system")}>System</button>
<button onClick={toggleThemeMode}>Toggle</button>
</>
);
}Five components — Navbar, Footer, Accordion, BlogCard, and DashboardLayout — accept a colorScheme prop that switches every brand accent between MedixDeck blue (#0685FF) and purple (#7700CC).
import {
Navbar,
Footer,
Accordion,
BlogCard,
DashboardLayout,
} from "@medixdeck/ui";
<Navbar colorScheme="purple" navItems={[...]} ctaLabel="Talk to a Doctor" />
<Footer colorScheme="purple" />
<Accordion colorScheme="purple" items={[...]} />
<BlogCard colorScheme="purple" title="..." />
<DashboardLayout colorScheme="purple">{/* ... */}</DashboardLayout>Use the useColorScheme hook to manage the active scheme in state and keep multiple components in sync:
import { useColorScheme, Navbar, Footer, Accordion } from "@medixdeck/ui";
function Page() {
const { colorScheme, toggleColorScheme } = useColorScheme(); // defaults to "blue"
return (
<>
<button onClick={toggleColorScheme}>
Switch to {colorScheme === "blue" ? "purple" : "blue"}
</button>
<Navbar colorScheme={colorScheme} navItems={[...]} />
<Accordion colorScheme={colorScheme} items={[...]} />
<Footer colorScheme={colorScheme} />
</>
);
}useColorScheme(initialScheme?) returns:
| Field | Type | Description |
|---|---|---|
colorScheme |
"blue" | "purple" |
Currently active scheme |
setColorScheme |
(scheme) => void |
Explicit setter |
toggleColorScheme |
() => void |
Flips blue ↔ purple |
isBlue |
boolean |
true when scheme is "blue" |
isPurple |
boolean |
true when scheme is "purple" |
import { ThemeColorPalette } from "@medixdeck/ui";
export function DesignTokensPage() {
return <ThemeColorPalette mt="8" />;
}ThemeColorPalette renders the semantic design tokens side by side for light and dark mode, then lists the raw brand, status, and neutral scales that power the theme.
lib\ library source and npm entrypoint
src\ local showcase app only
.github\workflows\publish.yml npm publish workflow
AGENTS.md full multi-agent repo guide
COPILOT.md concise AI contributor guide
.github\copilot-instructions.md GitHub Copilot repo instructions
CONTRIBUTING.md contributor workflow
CHANGELOG.md release history
LICENSE package license
package.json npm metadata and scriptsnpm run dev
npm run build
npm run test
npm run pack:check- The package publishes from
dist\with ESM, CJS, sourcemaps, and.d.tsdeclarations. - Public API changes must stay in sync across
lib\index.ts,README.md,src\App.tsx, Storybook stories, andCHANGELOG.md. - The GitHub Actions workflow installs dependencies, runs build and test checks, performs
npm pack --dry-run, and then publishes to npm.
medixdeck-ui\
├── lib\
│ ├── index.ts
│ ├── theme\
│ └── components\
│ ├── provider\
│ ├── primitive\
│ ├── form\
│ ├── layout\
│ ├── navigation\
│ ├── feedback\
│ ├── data\
│ └── healthcare\
├── src\
├── .github\
│ ├── copilot-instructions.md
│ └── workflows\publish.yml
├── AGENTS.md
├── COPILOT.md
├── CONTRIBUTING.md
├── CHANGELOG.md
├── LICENSE
├── package.json
├── vite.config.ts
├── vitest.config.ts
└── tsconfig.build.json