npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

dashstudio

v0.2.0

Published

A standalone, publishable React component library for pixel-aesthetic dashboards.

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 dashstudio

Import 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 demo

This 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:

  1. Fork the repository on Codeberg.
  2. Create a branch from master.
  3. Follow Conventional Commits for commit messages.
  4. 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.