dashstudio
v0.2.0
Published
A standalone, publishable React component library for pixel-aesthetic dashboards.
Maintainers
Readme
DashStudio
A standalone React component library for building pixel-aesthetic dashboards. Each component accepts data through props, supports theming via CSS custom properties, and can be dropped into any React project with minimal configuration.
Installation
npm install dashstudioImport the stylesheet once at your application root:
import 'dashstudio/dist/dashstudio.css';Note: DashStudio does not load fonts automatically. Add Inter and JetBrains Mono to your project for the intended appearance:
<link rel="preconnect" href="https://fonts.googleapis.com"> <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&family=JetBrains+Mono:wght@400;500;700&display=swap" rel="stylesheet">
ThemeProvider
Wrap your application (or any subtree) in ThemeProvider to inject CSS custom properties and make theme tokens available to all child components via useTheme().
import { ThemeProvider } from 'dashstudio';
function App() {
return (
<ThemeProvider theme={{ accent: '#00BCD4' }}>
{/* your components */}
</ThemeProvider>
);
}Props
| Prop | Type | Default | Description |
|-------------|----------|----------|--------------------------------------------------|
| theme | object | {} | Partial or full token map merged with defaults |
| as | string | 'div' | HTML tag to render as the container element |
| className | string | — | CSS class on the container element |
| style | object | — | Inline styles on the container element |
| children | node | required | Content to render inside the provider |
Default Token Reference
| Token | Default Value | CSS Variable |
|----------------|-----------------------------------|---------------------|
| bg | #1E1E20 | --bg |
| card | #2A2A2D | --card |
| accent | #FF5722 | --accent |
| text | #E0E0E5 | --text |
| text-muted | #A0A0A5 | --text-muted |
| text-dim | #6B6B70 | --text-dim |
| border | #3A3A3D | --border |
| font-body | 'Inter', sans-serif | --font-body |
| font-mono | 'JetBrains Mono', monospace | --font-mono |
| grid | 8px | --grid |
Components
Sidebar
A vertical navigation sidebar with logo and grouped navigation sections.
import { Sidebar } from 'dashstudio';
const sections = [
{
title: 'Main',
items: [
{ icon: 'chart', label: 'Dashboard', active: true },
{ icon: 'terminal', label: 'Logs' },
],
},
];
<Sidebar sections={sections} logo={{ letter: 'D', text: 'DashStudio' }} onNavClick={(item) => console.log(item)} />| Prop | Type | Default | Description |
|--------------|----------|---------|----------------------------------------------------------|
| sections | array | required | Array of { title, items } objects |
| logo | object | {} | Logo config: { letter, text, href } |
| onNavClick | function | — | Called with the item object when a nav item is clicked |
Logo
Standalone logo block.
import { Logo } from 'dashstudio';
<Logo letter="D" text="DashStudio" href="/" />| Prop | Type | Default | Description |
|----------|--------|--------------|-------------------------------------|
| letter | string | 'M' | Single character shown in the icon |
| text | string | 'AI Studio'| Label text next to the icon |
| href | string | — | If provided, renders logo as an <a> tag |
NavSection
A labeled group of navigation items.
import { NavSection } from 'dashstudio';
<NavSection title="Tools" items={[{ icon: 'file', label: 'Files' }]} onItemClick={(item) => {}} />| Prop | Type | Default | Description |
|---------------|----------|---------|--------------------------------------------------|
| title | string | required | Section heading |
| items | array | required | Array of { icon, label, active, href } objects |
| onItemClick | function | — | Forwarded to each NavItem as onClick |
NavItem
A single navigation row with a pixel icon and label.
import { NavItem } from 'dashstudio';
<NavItem icon="settings" label="Settings" active={false} onClick={() => {}} />| Prop | Type | Default | Description |
|-----------|----------|---------|---------------------------------------------------|
| icon | string | required | Icon name (see PixelIcon for available names) |
| label | string | required | Display text |
| active | boolean | false | Applies the active style |
| onClick | function | — | Click handler |
| href | string | — | If provided, renders as an <a> tag |
TrendChart
A multi-line step chart built on Recharts.
import { TrendChart } from 'dashstudio';
const data = [
{ date: 'Jan', requests: 120, errors: 4 },
{ date: 'Feb', requests: 240, errors: 8 },
];
const lines = [
{ dataKey: 'requests', stroke: '#FF5722' },
{ dataKey: 'errors', stroke: '#B388FF', strokeDasharray: '6 3' },
];
<TrendChart data={data} title="API Requests Over Time" lines={lines} xKey="date" />| Prop | Type | Default | Description |
|---------|--------|----------|------------------------------------------------------|
| data | array | required | Data array for the chart |
| title | string | 'Trend' | Card heading |
| lines | array | [] | Line descriptors: { dataKey, stroke, strokeDasharray? } |
| xKey | string | 'date' | Key in data objects to use as the X axis |
HistogramChart
A bar chart for frequency distributions.
import { HistogramChart } from 'dashstudio';
const data = [
{ range: '0-50', count: 32 },
{ range: '50-100', count: 78 },
];
<HistogramChart data={data} title="Latency Distribution (ms)" xKey="range" dataKey="count" />| Prop | Type | Default | Description |
|------------|--------|----------------|---------------------------------|
| data | array | required | Data array for the chart |
| title | string | 'Distribution' | Card heading |
| xKey | string | 'range' | Key used for X axis labels |
| dataKey | string | 'count' | Key used for bar heights |
| barColor | string | theme accent | Bar fill color |
| barSize | number | 20 | Bar width in pixels |
WaffleChart
A 10x10 grid chart showing proportional data as colored cells.
import { WaffleChart } from 'dashstudio';
const data = [
{ label: 'GPT-4', value: 55, color: '#FF5722' },
{ label: 'Mistral', value: 30, color: '#B388FF' },
{ label: 'Other', value: 15, color: '#18FFFF' },
];
<WaffleChart data={data} title="Model Usage" columns={10} showLegend />| Prop | Type | Default | Description |
|--------------|---------|------------------|--------------------------------------------------|
| data | array | required | Segments: { label, value (%), color } — must sum to 100 |
| title | string | 'Distribution' | Card heading |
| columns | number | 10 | Number of columns in the grid |
| showLegend | boolean | true | Whether to render the legend below the grid |
StatusCard
A card with a colored top border and optional content. Shows skeleton blocks by default.
import { StatusCard } from 'dashstudio';
<StatusCard title="Create" accent="#FF5722" />
// With custom content:
<StatusCard title="Observe" accent="#B388FF">
<p>Custom content here</p>
</StatusCard>| Prop | Type | Default | Description |
|------------|--------|------------------|-----------------------------------------------------|
| title | string | required | Card heading |
| accent | string | 'var(--accent)'| Top border color |
| children | node | — | Custom content; skeleton blocks shown when omitted |
TagBar
A bar of removable tag chips. Supports uncontrolled (internal state) and controlled modes.
import { TagBar } from 'dashstudio';
const tags = [
{ id: 1, label: 'production', color: 'orange' },
{ id: 2, label: 'v2', color: 'violet' },
];
// Uncontrolled — manages its own removal state:
<TagBar tags={tags} title="Active Tags" />
// Controlled — parent owns state:
<TagBar tags={tags} title="Active Tags" onRemove={(id) => setTags(t => t.filter(x => x.id !== id))} />| Prop | Type | Default | Description |
|------------|----------|----------------|---------------------------------------------------------------|
| tags | array | [] | Tag objects: { id, label, color } |
| title | string | 'Active Tags'| Card heading |
| onRemove | function | — | When provided, switches to controlled mode; called with tag id |
Available colors: violet, red, green, cyan, orange, gray.
Tag
A standalone tag chip.
import { Tag } from 'dashstudio';
<Tag label="production" color="orange" onRemove={() => {}} />| Prop | Type | Default | Description |
|-------------|----------|---------|---------------------------------------------|
| label | string | required | Display text |
| color | string | required | Color variant name |
| onRemove | function | — | Click handler for the remove button |
| className | string | '' | Additional CSS class |
CalendarWidget
A monthly calendar with highlight and click support.
import { CalendarWidget } from 'dashstudio';
<CalendarWidget
year={2026}
month={3}
today={9}
highlightedDays={[14, 21]}
onDayClick={(day) => console.log(day)}
title="Calendar"
/>Omitting year and month defaults to the current month.
| Prop | Type | Default | Description |
|-------------------|----------|------------------|-----------------------------------------------------|
| year | number | current year | Full year (e.g. 2026) |
| month | number | current month | 1-indexed month (1 = January) |
| today | number | — | Day number to highlight as today |
| highlightedDays | number[] | [] | Array of day numbers to highlight |
| onDayClick | function | — | Called with the day number when a day is clicked |
| title | string | 'Calendar' | Card heading |
SkeletonBlock
A simple loading placeholder rectangle.
import { SkeletonBlock } from 'dashstudio';
<SkeletonBlock width="80%" height={12} />| Prop | Type | Default | Description |
|-------------|--------|-----------|------------------------------|
| width | any | '100%' | CSS width value |
| height | number | 12 | Height in pixels |
| style | object | {} | Additional inline styles |
| className | string | '' | Additional CSS class |
DashboardGrid
A CSS grid container for dashboard layouts.
import { DashboardGrid, DashboardGridFull } from 'dashstudio';
<DashboardGrid columns={2}>
<TrendChart ... />
<DashboardGridFull>
<StatusCard ... />
</DashboardGridFull>
</DashboardGrid>DashboardGrid
| Prop | Type | Default | Description |
|------------|--------|---------|--------------------------------------|
| children | node | required | Grid children |
| columns | number | 2 | Number of equal-width grid columns |
DashboardGridFull — spans all columns, no props beyond children.
PixelIcon
An SVG icon rendered at pixel-perfect scale.
import { PixelIcon } from 'dashstudio';
<PixelIcon name="chart" size={24} />| Prop | Type | Default | Description |
|-------------|--------|---------|--------------------------------------------------------------|
| name | string | required | Icon name |
| size | number | 24 | Width and height in pixels |
| className | string | '' | Additional CSS class |
| style | object | {} | Additional inline styles |
Available icons: user, clipboard, eye, checkbox, settings, file, terminal, chart, search, close, info, warning, check.
Forms
Label
A standalone form label with optional required marker.
import { Label } from 'dashstudio';
<Label label="Username" htmlFor="username" required />| Prop | Type | Default | Description |
|------------|---------|---------|--------------------------------------|
| label | string | required | Display text |
| htmlFor | string | — | Associated input id |
| required | boolean | false | Shows a red asterisk when true |
Input
A labeled text input with error and disabled states.
import { Input } from 'dashstudio';
<Input
label="Email"
type="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
error="Invalid email address"
required
/>| Prop | Type | Default | Description |
|---------------|----------|----------|--------------------------------------|
| label | string | — | Field label |
| type | string | 'text' | HTML input type |
| value | string | required | Controlled value |
| onChange | function | required | Change handler |
| error | string | — | Error message shown below the input |
| disabled | boolean | false | Disables the input |
| required | boolean | false | Marks the label as required |
| placeholder | string | '' | Placeholder text |
Select
A labeled dropdown with error and disabled states.
import { Select } from 'dashstudio';
<Select
label="Framework"
value={val}
onChange={(e) => setVal(e.target.value)}
options={[
{ value: 'react', label: 'React' },
{ value: 'vue', label: 'Vue' },
]}
/>| Prop | Type | Default | Description |
|------------|----------|---------|----------------------------------------------|
| label | string | — | Field label |
| options | array | [] | { value, label } objects |
| value | string | required | Controlled value |
| onChange | function | required | Change handler |
| error | string | — | Error message shown below the select |
| disabled | boolean | false | Disables the select |
| required | boolean | false | Marks the label as required |
SearchBox
A text input with a search icon and an optional clear button.
import { SearchBox } from 'dashstudio';
<SearchBox
value={query}
onChange={(e) => setQuery(e.target.value)}
onClear={() => setQuery('')}
placeholder="Search components…"
/>| Prop | Type | Default | Description |
|---------------|----------|---------------|------------------------------------------------|
| value | string | required | Controlled value |
| onChange | function | required | Change handler |
| onClear | function | — | Called when the clear button is clicked; hides the button when omitted |
| placeholder | string | 'Search…' | Placeholder text |
Checkbox
A controlled checkbox with a pixel-art check indicator.
import { Checkbox } from 'dashstudio';
<Checkbox
label="Enable notifications"
checked={checked}
onChange={(e) => setChecked(e.target.checked)}
/>| Prop | Type | Default | Description |
|------------|----------|---------|------------------------------|
| label | string | — | Display text |
| checked | boolean | required | Controlled state |
| onChange | function | required | Change handler |
| disabled | boolean | false | Disables the checkbox |
Radio
A controlled radio button.
import { Radio } from 'dashstudio';
<Radio
label="Option A"
name="group"
value="a"
checked={selected === 'a'}
onChange={() => setSelected('a')}
/>| Prop | Type | Default | Description |
|------------|----------|---------|---------------------------------------------------|
| label | string | — | Display text |
| name | string | required | Input group name |
| value | string | required | Value for this option |
| checked | boolean | required | Controlled state |
| onChange | function | required | Change handler |
| disabled | boolean | false | Disables the radio |
FileInput
A styled file picker with selected filename display.
import { FileInput } from 'dashstudio';
<FileInput
label="Upload config"
accept=".json,.yaml"
multiple
onChange={(e) => console.log(e.target.files)}
/>| Prop | Type | Default | Description |
|------------|----------|---------|--------------------------------------------------|
| label | string | — | Field label |
| accept | string | — | MIME types or extensions (".json,.yaml") |
| multiple | boolean | false | Allows multiple file selection |
| onChange | function | — | Called with the native change event |
| disabled | boolean | false | Disables the trigger button |
| error | string | — | Error message shown below |
Button
A styled button with variant and size options.
import { Button } from 'dashstudio';
<Button variant="primary" size="md" onClick={() => {}}>
Save
</Button>| Prop | Type | Default | Description |
|------------|----------|-------------|------------------------------------------------------|
| variant | string | 'primary' | 'primary' | 'secondary' | 'danger' |
| size | string | 'md' | 'sm' | 'md' | 'lg' |
| disabled | boolean | false | Disables the button |
| type | string | 'button' | HTML button type |
| onClick | function | — | Click handler |
| children | node | required | Button content |
Interaction
ProgressBar
A labeled progress bar with optional value display and custom accent color.
import { ProgressBar } from 'dashstudio';
<ProgressBar label="CPU Usage" value={72} showValue accent="#69F0AE" />| Prop | Type | Default | Description |
|-------------|---------|-----------------|----------------------------------------------|
| value | number | 0 | Fill percentage (0–100) |
| label | string | — | Label shown above the track |
| showValue | boolean | false | Shows the numeric percentage when true |
| accent | string | theme accent | Fill color; overrides the theme accent |
Toggle
A sliding toggle switch, theme-aware.
import { Toggle } from 'dashstudio';
<Toggle
label="Dark mode"
checked={enabled}
onChange={(e) => setEnabled(e.target.checked)}
/>| Prop | Type | Default | Description |
|------------|----------|---------|------------------------------|
| checked | boolean | required | Controlled state |
| onChange | function | required | Change handler |
| label | string | — | Display text |
| disabled | boolean | false | Disables the toggle |
Tabs / TabPanel
A tab navigation bar with swappable content panels.
import { Tabs, TabPanel } from 'dashstudio';
<Tabs
tabs={[{ id: 'a', label: 'Overview' }, { id: 'b', label: 'Details' }]}
activeTab={active}
onTabChange={setActive}
>
<TabPanel id="a" activeTab={active}>Overview content</TabPanel>
<TabPanel id="b" activeTab={active}>Details content</TabPanel>
</Tabs>Tabs
| Prop | Type | Default | Description |
|---------------|----------|---------|----------------------------------------------------|
| tabs | array | [] | Tab descriptors: { id, label } |
| activeTab | string | required | Id of the currently active tab |
| onTabChange | function | required | Called with the tab id when a tab is clicked |
| children | node | — | TabPanel children |
TabPanel
| Prop | Type | Default | Description |
|-------------|--------|----------|------------------------------------------|
| id | string | required | Must match a tab id |
| activeTab | string | required | The currently active tab id; panel only renders when id === activeTab |
| children | node | — | Panel content |
Badge
A small status label with color variants and an optional dot indicator.
import { Badge } from 'dashstudio';
<Badge label="live" variant="success" dot />| Prop | Type | Default | Description |
|-----------|---------|-------------|----------------------------------------------------------------------|
| label | string | required | Display text |
| variant | string | 'neutral' | 'info' | 'success' | 'warning' | 'danger' | 'neutral' |
| dot | boolean | false | Shows a filled dot before the label |
Alert
A dismissible alert banner with variant-appropriate icon.
import { Alert } from 'dashstudio';
<Alert
variant="warning"
title="Heads up"
dismissible
onDismiss={() => setVisible(false)}
>
Your session expires in 5 minutes.
</Alert>| Prop | Type | Default | Description |
|---------------|----------|----------|--------------------------------------------------------------|
| variant | string | 'info' | 'info' | 'warning' | 'error' | 'success' |
| title | string | — | Bold heading text |
| children | node | — | Body message |
| dismissible | boolean | false | Shows a close button when true |
| onDismiss | function | — | Called when the close button is clicked |
Overlay
Modal
A centered modal dialog with backdrop overlay.
import { Modal } from 'dashstudio';
<Modal isOpen={show} title="Confirm" onClose={() => setShow(false)}>
<p>Content here</p>
</Modal>| Prop | Type | Default | Description | |------|------|---------|-------------| | isOpen | boolean | required | Controls visibility | | onClose | function | required | Close handler | | title | string | required | Modal title | | children | node | - | Body content | | footer | node | - | Footer actions |
ConfirmationModal
A confirmation dialog with cancel/confirm buttons.
import { ConfirmationModal } from 'dashstudio';
<ConfirmationModal
isOpen={show}
title="Delete Item"
message="This cannot be undone."
onConfirm={handleDelete}
onClose={() => setShow(false)}
variant="danger"
/>| Prop | Type | Default | Description |
|------|------|---------|-------------|
| isOpen | boolean | required | Controls visibility |
| onClose | function | required | Close handler |
| title | string | required | Modal title |
| message | string | required | Confirmation message |
| onConfirm | function | required | Confirm handler |
| confirmLabel | string | 'Confirm' | Confirm button text |
| cancelLabel | string | 'Cancel' | Cancel button text |
| variant | string | 'default' | 'default' or 'danger' |
ToastProvider / useToast
Toast notification context and hook.
import { ToastProvider, useToast } from 'dashstudio';
function App() {
return (
<ToastProvider>
<Dashboard />
</ToastProvider>
);
}
function Dashboard() {
const { push } = useToast();
push({ type: 'success', title: 'Saved', message: 'Done!' });
}FilePreviewModal
Modal for previewing files with download support.
import { FilePreviewModal } from 'dashstudio';
<FilePreviewModal
file={{ name: 'photo.jpg', type: 'image/jpeg', url: '/photo.jpg', size: 1200000 }}
isOpen={show}
onClose={() => setShow(false)}
/>ShareModal
Modal for creating and managing share links.
import { ShareModal } from 'dashstudio';
<ShareModal
isOpen={show}
onClose={() => setShow(false)}
onCreateLink={createLink}
onDeleteLink={deleteLink}
links={shareLinks}
/>Navigation
Breadcrumb
Navigation breadcrumb component.
import { Breadcrumb } from 'dashstudio';
<Breadcrumb items={[
{ label: 'Home', onClick: () => navigate('/') },
{ label: 'Products', onClick: () => navigate('/products') },
{ label: 'Item #123' }
]} />| Prop | Type | Default | Description |
|------|------|---------|-------------|
| items | array | required | { label, onClick? } objects |
Upload
UploadZone
Drag-and-drop file upload zone.
import { UploadZone } from 'dashstudio';
<UploadZone
onUpload={(files) => handleFiles(files)}
accept=".jpg,.png"
multiple
/>| Prop | Type | Default | Description | |------|------|---------|-------------| | onUpload | function | required | Called with File[] | | accept | string | - | MIME types to accept | | multiple | boolean | true | Allow multiple files | | disabled | boolean | false | Disable zone | | children | node | - | Custom content |
Chat
ChatMessage
Chat message bubble with markdown support.
import { ChatMessage } from 'dashstudio';
<ChatMessage role="assistant" content="Hello! Try **bold** and `code`." />
<ChatMessage role="user" content="Got it!" />| Prop | Type | Default | Description |
|------|------|---------|-------------|
| role | string | required | 'user' or 'assistant' |
| content | string | required | Message text |
| avatar | string | - | Avatar image URL |
ChatInput
Auto-resizing chat input.
import { ChatInput } from 'dashstudio';
<ChatInput
onSubmit={(msg) => send(msg)}
placeholder="Type a message..."
/>| Prop | Type | Default | Description | |------|------|---------|-------------| | onSubmit | function | required | Called with message | | disabled | boolean | false | Disable input | | placeholder | string | - | Placeholder text |
Auth
LoginForm
Login form with username and password.
import { LoginForm } from 'dashstudio';
<LoginForm
onSubmit={({ username, password }) => login(username, password)}
loading={isLoading}
error={loginError}
/>| Prop | Type | Default | Description |
|------|------|---------|-------------|
| onSubmit | function | required | Called with { username, password } |
| loading | boolean | false | Loading state |
| error | string | - | Error message |
| usernameLabel | string | 'Username' | Username label |
| passwordLabel | string | 'Password' | Password label |
OtpForm
6-digit OTP input form.
import { OtpForm } from 'dashstudio';
<OtpForm
onSubmit={(otp) => verify(otp)}
onResend={resendCode}
/>| Prop | Type | Default | Description | |------|------|---------|-------------| | onSubmit | function | required | Called with OTP string | | onResend | function | - | Resend handler | | loading | boolean | false | Loading state | | error | string | - | Error message |
ConfirmCode
Verification code display.
import { ConfirmCode } from 'dashstudio';
<ConfirmCode code="AB3-994" status="confirmed" />| Prop | Type | Default | Description |
|------|------|---------|-------------|
| code | string | required | Code to display |
| status | string | required | 'waiting', 'confirmed', or 'error' |
Notes
NoteCard
Inline-editable note card.
import { NoteCard } from 'dashstudio';
<NoteCard
note={{ id: '1', title: 'Shopping', content: 'Eggs, milk', pinned: false }}
onUpdate={(id, data) => update(id, data)}
onDelete={(id) => remove(id)}
onPin={(id) => togglePin(id)}
/>NoteGrid
Grid layout for note cards.
import { NoteGrid } from 'dashstudio';
<NoteGrid notes={notes} onCreate={createNote}>
{notes.map(n => <NoteCard key={n.id} note={n} ... />)}
</NoteGrid>| Prop | Type | Default | Description | |------|------|---------|-------------| | notes | array | - | Notes array (for count) | | onCreate | function | required | Create handler | | children | node | - | Note cards |
Widgets (Extended)
TimeWidget
Self-contained clock widget.
import { TimeWidget } from 'dashstudio';
<TimeWidget />DiskWidget
Disk usage display.
import { DiskWidget } from 'dashstudio';
<DiskWidget used={42000000000} total={100000000000} />| Prop | Type | Default | Description |
|------|------|---------|-------------|
| used | number | required | Used bytes |
| total | number | required | Total bytes |
| label | string | 'Disk' | Display label |
RamWidget
RAM usage display.
import { RamWidget } from 'dashstudio';
<RamWidget used={8589934592} total={17179869184} />UptimeWidget
System uptime display.
import { UptimeWidget } from 'dashstudio';
<UptimeWidget seconds={345600} />WeatherWidget
Weather display from Open-Meteo API.
import { WeatherWidget } from 'dashstudio';
<WeatherWidget lat={48.8566} lon={2.3522} location="Paris" />| Prop | Type | Default | Description |
|------|------|---------|-------------|
| lat | number | required | Latitude |
| lon | number | required | Longitude |
| location | string | - | Display name |
| unit | string | 'celsius' | 'celsius' or 'fahrenheit' |
DockerServicesWidget
Docker services display.
import { DockerServicesWidget } from 'dashstudio';
<DockerServicesWidget services={services} onRefresh={fetchServices} />AppStatusWidget
Application health display.
import { AppStatusWidget } from 'dashstudio';
<AppStatusWidget apps={[{ name: 'API', status: 'up', latency: 45 }]} />MetricGauge
Generic metric gauge.
import { MetricGauge } from 'dashstudio';
<MetricGauge used={4500} total={10000} label="API Usage" unit="tokens" />UnderConstruction
"Under construction" display.
import { UnderConstruction } from 'dashstudio';
<UnderConstruction />MonitorWidget
URL monitoring widget.
import { MonitorWidget } from 'dashstudio';
<MonitorWidget monitors={monitors} onAdd={addUrl} onDelete={del} onToggle={toggle} />ContainerRow
Docker container row.
import { ContainerRow } from 'dashstudio';
<ContainerRow container={container} onStart={start} onStop={stop} onRestart={restart} />Overlay
Modal
A centered modal dialog with backdrop overlay.
import { Modal } from 'dashstudio';
<Modal isOpen={show} title="Title" onClose={() => setShow(false)}>
<p>Content</p>
</Modal>| Prop | Type | Default | Description | |-------------|----------|---------|------------------------------------| | isOpen | boolean | required | Controls modal visibility | | onClose | function | required | Close handler | | title | string | required | Modal header title | | children | node | — | Modal body content | | footer | node | — | Modal footer actions |
ConfirmationModal
A confirmation dialog with cancel/confirm buttons.
import { ConfirmationModal } from 'dashstudio';
<ConfirmationModal
isOpen={show}
title="Delete"
message="Are you sure?"
onConfirm={handleDelete}
onClose={() => setShow(false)}
variant="danger"
/>| Prop | Type | Default | Description |
|---------------|----------|-------------|----------------------------|
| isOpen | boolean | required | Controls visibility |
| onClose | function | required | Close handler |
| title | string | required | Modal title |
| message | string | required | Confirmation message |
| onConfirm | function | required | Confirm handler |
| confirmLabel | string | 'Confirm' | Confirm button text |
| cancelLabel | string | 'Cancel' | Cancel button text |
| variant | string | 'default' | 'default' or 'danger' |
ToastProvider / useToast
Toast notification context and hook.
import { ToastProvider, useToast } from 'dashstudio';
function App() {
return (
<ToastProvider>
<Dashboard />
</ToastProvider>
);
}
function Dashboard() {
const { push } = useToast();
push({ type: 'success', title: 'Saved', message: 'Done!' });
}FilePreviewModal
Modal for previewing files with download capability.
import { FilePreviewModal } from 'dashstudio';
<FilePreviewModal
file={{ name: 'img.png', type: 'image/png', url: '/file.png', size: 12345 }}
isOpen={show}
onClose={() => setShow(false)}
/>ShareModal
Modal for creating and managing share links.
import { ShareModal } from 'dashstudio';
<ShareModal
isOpen={show}
onClose={() => setShow(false)}
onCreateLink={({ allowDownload }) => createLink(allowDownload)}
onDeleteLink={(id) => deleteLink(id)}
links={[{ id: '1', url: '...', expiresAt: '...', allowDownload: true, createdAt: '...' }]}
/>Navigation
Breadcrumb
A navigation breadcrumb showing location hierarchy.
import { Breadcrumb } from 'dashstudio';
<Breadcrumb items={[
{ label: 'Home', onClick: () => {} },
{ label: 'Products', onClick: () => {} },
{ label: 'Item #123' }
]} />| Prop | Type | Default | Description |
|---------|-------|-----------|--------------------------|
| items | array | required | Array of { label, onClick? } |
Upload
UploadZone
Drag-and-drop file upload zone.
import { UploadZone } from 'dashstudio';
<UploadZone
onUpload={(files) => handleFiles(files)}
accept=".jpg,.png"
multiple
/>| Prop | Type | Default | Description |
|------------|----------|---------|-----------------------------|
| onUpload | function | required | Called with File[] |
| accept | string | — | MIME types to accept |
| multiple | boolean | true | Allow multiple files |
| disabled | boolean | false | Disable the zone |
Chat
ChatMessage
Chat bubble with markdown support.
import { ChatMessage } from 'dashstudio';
<ChatMessage role="assistant" content="Hello, **how** can I help?" />
<ChatMessage role="user" content="What is `React`?" />| Prop | Type | Default | Description |
|-----------|---------------------|---------|-----------------------|
| role | 'user'|'assistant'| required | Message sender |
| content | string | required | Message text |
| avatar | string | — | Avatar image URL |
ChatInput
Auto-resizing chat input.
import { ChatInput } from 'dashstudio';
<ChatInput onSubmit={(msg) => send(msg)} placeholder="Type..." />| Prop | Type | Default | Description |
|---------------|----------|---------|-----------------------|
| onSubmit | function | required | Called with message |
| disabled | boolean | false | Disable input |
| placeholder | string | — | Placeholder text |
Auth
LoginForm
Username/password login form.
import { LoginForm } from 'dashstudio';
<LoginForm
onSubmit={({ username, password }) => login(username, password)}
loading={isLoading}
error={error}
/>| Prop | Type | Default | Description |
|----------------|----------|--------------|-----------------------|
| onSubmit | function | required | Called with credentials |
| loading | boolean | false | Show loading state |
| error | string | — | Error message |
| usernameLabel | string | 'Username' | Username field label |
| passwordLabel | string | 'Password' | Password field label |
OtpForm
6-digit OTP input form.
import { OtpForm } from 'dashstudio';
<OtpForm
onSubmit={(otp) => verify(otp)}
onResend={() => resendCode()}
/>| Prop | Type | Default | Description |
|-----------|----------|---------|---------------------|
| onSubmit | function | required | Called with OTP |
| onResend | function | — | Resend handler |
| loading | boolean | false | Loading state |
| error | string | — | Error message |
ConfirmCode
Verification code display.
import { ConfirmCode } from 'dashstudio';
<ConfirmCode code="AB3-994" status="confirmed" />| Prop | Type | Default | Description |
|---------|-------------------------------|-----------|---------------------|
| code | string | required | Verification code |
| status | 'waiting'|'confirmed'|'error' | required | Current status |
Notes
NoteCard
Inline-editable note card.
import { NoteCard } from 'dashstudio';
<NoteCard
note={{ id: '1', title: 'Title', content: 'Note', pinned: false }}
onUpdate={(id, data) => update(id, data)}
onDelete={(id) => remove(id)}
onPin={(id) => togglePin(id)}
/>NoteGrid
Grid layout for notes.
import { NoteGrid } from 'dashstudio';
<NoteGrid notes={notes} onCreate={() => createNote()}>
{notes.map(n => <NoteCard key={n.id} note={n} ... />)}
</NoteGrid>| Prop | Type | Default | Description | |------------|----------|---------|----------------------| | notes | array | — | Notes array | | onCreate | function | required | Create handler | | children | node | — | Note cards |
Widgets (Extended)
TimeWidget
Self-contained clock showing current time and date.
import { TimeWidget } from 'dashstudio';
<TimeWidget />DiskWidget
Disk usage display with progress bar.
import { DiskWidget } from 'dashstudio';
<DiskWidget used={42000000000} total={100000000000} label="Disk" />| Prop | Type | Default | Description |
|--------|--------|---------|-----------------|
| used | number | required | Used bytes |
| total | number | required | Total bytes |
| label | string | 'Disk' | Display label |
RamWidget
RAM usage display with progress bar.
import { RamWidget } from 'dashstudio';
<RamWidget used={8589934592} total={17179869184} />UptimeWidget
System uptime display.
import { UptimeWidget } from 'dashstudio';
<UptimeWidget seconds={345600} />
<UptimeWidget uptime="4d 0h 0m" />| Prop | Type | Default | Description | |---------|--------|---------|---------------------| | seconds | number | — | Uptime in seconds | | uptime | string | — | Pre-formatted string |
WeatherWidget
Weather display from Open-Meteo API.
import { WeatherWidget } from 'dashstudio';
<WeatherWidget lat={48.8566} lon={2.3522} location="Paris" unit="celsius" />| Prop | Type | Default | Description |
|------------|-------------------------|------------|----------------------|
| lat | number | required | Latitude |
| lon | number | required | Longitude |
| location | string | — | Display name |
| unit | 'celsius'|'fahrenheit'| 'celsius'| Temperature unit |
DockerServicesWidget
Docker services/containers display.
import { DockerServicesWidget } from 'dashstudio';
<DockerServicesWidget
services={[{ name: 'nginx', state: 'running', image: 'nginx:latest' }]}
onRefresh={fetchServices}
/>AppStatusWidget
Application health display.
import { AppStatusWidget } from 'dashstudio';
<AppStatusWidget
apps={[{ name: 'API', status: 'up', latency: 45 }]}
/>MetricGauge
Generic metric gauge.
import { MetricGauge } from 'dashstudio';
<MetricGauge used={4500} total={10000} label="API Usage" unit="tokens" />UnderConstruction
"Under construction" display.
import { UnderConstruction } from 'dashstudio';
<UnderConstruction />MonitorWidget
URL monitoring widget with history sparkline.
import { MonitorWidget } from 'dashstudio';
<MonitorWidget
monitors={[{ id: '1', url: 'https://example.com', status: 'up', latency: 45, history: [true, true, false] }]}
onAdd={(url) => add(url)}
onDelete={(id) => remove(id)}
onToggle={(id) => toggle(id)}
/>ContainerRow
Single Docker container row with actions.
import { ContainerRow } from 'dashstudio';
<ContainerRow
container={{ id: 'abc', name: 'nginx', state: 'running', image: 'nginx:latest', ports: ['80:80'] }}
onStart={(id) => start(id)}
onStop={(id) => stop(id)}
onRestart={(id) => restart(id)}
/>Design Philosophy
DashStudio is built around three constraints:
Pixel aesthetic. All border radii are forced to zero. Icons use pixel-art SVG paths. Fonts are monospaced for structural content. The result is a deliberately hard-edged look suited to developer tools, monitoring dashboards, and technical interfaces.
CSS custom properties, not CSS-in-JS. Theming is done entirely through CSS variables injected onto a container DOM node. There is no runtime style injection, no styled-components, no Emotion. This makes DashStudio safe to use in SSR environments and compliant with strict Content Security Policies.
Prop-driven data. No component imports data from a file or makes a network request. Every piece of data — chart series, navigation items, tag lists — is passed as a prop. This makes each component independently testable, composable, and portable.
Demo
Run the component gallery locally:
npm run demoThis starts a Vite dev server serving demo/index.html. The demo has five sections (Widgets, Charts, Sidebar, Formulaires, Interaction) navigated via the sidebar. No build step is required.
Contributing
DashStudio is open source. Pull requests are welcome.
Primary maintainer: fauza ([email protected]) Repository: https://codeberg.org/fauza/DashStudio
To contribute:
- Fork the repository on Codeberg.
- Create a branch from
master. - Follow Conventional Commits for commit messages.
- Open a pull request with a clear description of the change and any relevant context.
FAQ
Do I need to wrap my entire app in ThemeProvider? No. ThemeProvider can wrap any subtree. Multiple providers can coexist in the same render tree with different themes.
Can I use DashStudio without Recharts? Yes. If you do not import TrendChart, HistogramChart, or WaffleChart, Recharts will be tree-shaken out of your bundle. The sidebar, widget, and layout components have no dependency on Recharts.
Does DashStudio work with React 18?
Yes. The peer dependency is react >= 18.0.0. It is developed and tested on React 19.
Why no CSS-in-JS? CSS-in-JS adds runtime overhead, complicates SSR hydration, and can conflict with CSP rules. Plain CSS with custom properties achieves the same theming flexibility without those tradeoffs.
Can I override the pixel aesthetic?
The border-radius: 0 !important rule is intentional and load-bearing for the design system. If you need rounded corners, DashStudio is not the right library for that use case.
License
MIT. Copyright (c) 2026 fauza.
