// app/layout.tsx (Next.js App Router)import{ MedixProvider }from"@medixdeck/ui";exportdefaultfunctionRootLayout({ children }:{ children: React.ReactNode }){return(<htmllang="en"><body>{/* MedixProvider injects Satoshi + Inter fonts and all CSS vars automatically */}<MedixProviderdefaultColorMode="light">{children}</MedixProvider></body></html>);}
import{ Button, DoctorCard, OTPInput, PhoneInput, DataTable, Logo }from"@medixdeck/ui";// Button<Buttonvariant="solid"colorScheme="blue">Talk to a Doctor</Button>// Logo — inline SVG, no image assets needed<Logo/>// full blue, 32px<Logovariant="purple"type="icon"/>// icon-only, purple<Logovariant="white"height={28}/>// white full logo<Logovariant="black"type="icon"height={48}/>// black icon// Logo in a Navbar (or pass no logo prop for automatic default)<Navbarlogo={<Logovariant="purple"height={28}/>}navItems={[...]}/>// Phone input with country code<PhoneInputlabel="Phone number"defaultCountryCode="+234"onChange={setPhone}/>// OTP verification<OTPInputlength={6}label="Enter verification code"onComplete={verifyCode}/>// Data table with sorting<DataTablecolumns={[{ key:"name", label:"Patient", sortable:true}]}data={patients}rowKey="id"stripedonRowClick={(row)=> router.push(`/patients/${row.id}`)}/>
doctorName, date, time, type, status, onJoin, onReschedule, onCancel
Appointment summary
Design Tokens
Color Palette
Token
Light
Dark
Hex
bg
#FEFEFE
#0A1220
—
bg.surface
#F6F6F6
#152035
—
text.heading
#111926
#F5F6F8
—
text.body
#374151
#CBD5E1
—
text.muted
#6B7280
#94A3B8
—
border
#E2E8F0
#1E3554
—
blue.500
—
—
#0685FF
purple.500
—
—
#7700CC
Typography
// CSS custom properties injected by MedixProvider--font-body:"Satoshi", sans-serif
--font-heading:"Satoshi", sans-serif
Using tokens directly
import{ Box }from"@medixdeck/ui";// Use semantic tokens in any Box prop<Boxbg="bg.surface"color="text.heading"border="1px solid"borderColor="border">
Hello World
</Box>
Accessing the raw system object
import{ system }from"@medixdeck/ui";import{ ChakraProvider }from"@chakra-ui/react";// Use the design system without MedixProvider<ChakraProvidervalue={system}>{children}</ChakraProvider>
Dark Mode
Dark mode is managed by next-themes. MedixProvider handles it automatically by applying a .dark class to <html>.
// next-themes hook — use in any child componentimport{ useTheme }from"next-themes";functionDarkModeButton(){const{ theme, setTheme }=useTheme();return(<ButtononClick={()=>setTheme(theme ==="light"?"dark":"light")}>{theme ==="light"?"🌙 Dark":"☀️ Light"}</Button>);}
Or manage it manually — just add/remove dark from document.documentElement:
// Toggle dark mode without next-themes (e.g. in a Vite dev preview)useEffect(()=>{
document.documentElement.classList.toggle("dark", isDark);},[isDark]);
Important: Always apply the dark class on <html> (or a root ancestor that wraps all components including <Navbar>). Applying it on an inner <Box> while leaving sticky/portal components outside will break their dark mode.
Custom Link Renderer
For Next.js or React Router routing without anchor reloads:
import Link from"next/link";// or from react-router-dom// Navbar<NavbarnavItems={[{ label:"Home", href:"/"},{ label:"Doctors", href:"/doctors"}]}renderLink={(item, children)=>(<Linkhref={item.href}style={{ textDecoration:"none"}}>{children}</Link>)}/>// Breadcrumb<Breadcrumbitems={[{ label:"Home", href:"/"},{ label:"Doctors"}]}renderLink={(item, children)=><Linkhref={item.href}>{children}</Link>}/>
OTPInput / PinInput
<OTPInputlength={6}label="Enter verification code"helperText="We sent a 6-digit code to your registered phone"value={otp}onChange={setOtp}onComplete={(code)=>verifyOtp(code)}/>// Masked PIN mode<PinInputlength={4}masklabel="Enter your PIN"/>
PhoneInput
<PhoneInputlabel="Phone number"defaultCountryCode="+234"placeholder="80 000 0000"value={phone}onChange={setPhone}helperText="We'll send your confirmation here"/>