Theming & Styles
Style customization has four layers, from shallow to deep: CSS variables → classNames → slots → unstyled.
1. CSS variables (theme)
Section titled “1. CSS variables (theme)”Every meter-* rule produced by the Tailwind plugin resolves --meter-* CSS variables first (falling back to the host Tailwind palette), so switching themes is just a variable override. The core package exports a full set of theme utilities:
import { darkTheme, lightTheme, resolveTheme, themeCssVariables, themeStyles, type MeterTheme, type MeterThemeInput,} from '@meterry/component'themeCssVariables('dark')returns CSS text like:host, :root { --meter-surface: ...; };themeStyles(theme)returns a complete<style>tag string;MeterThemeInputcan be'light' | 'dark'or a partial override (colors/radius/chartColors/fontFamily/shadow/css).
Apply the dark theme to a local container:
import { themeCssVariables } from '@meterry/component'
const scopeVars = themeCssVariables('dark').replace(':host, :root', '.dark-scope')
<div className="dark-scope"> <style dangerouslySetInnerHTML={{ __html: scopeVars }} /> <MeterChart theme="dark" ... /></div>Also pass theme="dark" to the chart component so the ECharts palette follows.
Available CSS variables: --meter-surface, --meter-surface-muted, --meter-text, --meter-text-muted, --meter-text-subtle, --meter-border, --meter-border-strong, --meter-accent, --meter-accent-soft, --meter-focus, --meter-danger, --meter-danger-soft, --meter-radius-sm|md|lg, --meter-shadow, --meter-font-family, --meter-chart-1..n.
2. classNames: slot-by-slot overrides
Section titled “2. classNames: slot-by-slot overrides”All components support className (root node) and classNames (stable slots). Available slot names:
root, card, header, caption, title, description, body, toolbar, filter, table, empty, loading, error, pagination, actions, button, chart, legend, legendItem, value, unit
// rows: fetched from the meter service (see Getting Started)<MeterTable className="w-full" classNames={{ card: 'rounded-2xl border-slate-200 shadow-xl', header: 'bg-slate-50 px-6 py-5', title: 'text-slate-950', table: 'overflow-hidden rounded-xl', button: 'rounded-lg border-indigo-200 text-indigo-700', }} columns={columns} data={rows}/>Tailwind classes passed via classNames coexist with the default semantic classes (defaults first, custom last), and conflicting properties resolve in favor of the custom ones.
Making Tailwind scan the meter-* class names
Section titled “Making Tailwind scan the meter-* class names”The meter-* class names live as strings in the core package source, so Tailwind needs to scan them. With Tailwind v4, add in CSS:
/* when consuming the published package */@source "../node_modules/@meterry/component/dist/index.js";(Adjust the path relative to your page’s CSS file; the examples in the component library repository use a Vite alias and scan src/component.ts directly.)
3. slots: deep customization via render props
Section titled “3. slots: deep customization via render props”The React/Vue MeterUsage, MeterChart, and MeterTable all support slots render props to replace the rendering of the header / value / chart / toolbar / cell / pagination areas while keeping the component’s data fetching and state management:
<MeterUsage client={client} slots={{ value: ({ total, formattedTotal, measure }) => ( <div className="my-value">{formattedTotal} {measure}</div> ), header: ({ caption, title }) => <MyHeader caption={caption} title={title} />, chart: ({ model, option }) => <MyChart option={option} />, }}/>Context types for each slot: MeterHeaderSlotContext, MeterValueSlotContext, MeterChartSlotContext, MeterTableToolbarSlotContext, MeterTableCellSlotContext, MeterPaginationSlotContext (all exported from the core package).
4. unstyled: draw everything yourself
Section titled “4. unstyled: draw everything yourself”// rows: fetched from the meter service (see Getting Started)<MeterChart unstyled classNames={{ root: 'block', card: 'rounded-xl bg-white p-6 shadow', chart: 'mt-4', }} type="line" data={rows} x="bucket" series={[{ key: 'tokens', label: 'Tokens', value: 'tokens' }]}/>unstyled drops all default meter-* classes and keeps only the classes you provide.
ECharts container styling
Section titled “ECharts container styling”React renders charts with echarts-for-react and Vue 3 with vue-echarts:
classNames.chartstill controls the chart container’s size, spacing, and look via Tailwind- component APIs like
type,series, andthemestay unchanged
Tailwind plugin
Section titled “Tailwind plugin”@meterry/component-tailwindcss does two things:
- registers the
meterpalette (meter.background,meter.accent, …); - generates all
meter-*component styles (card, table, filters, pagination, chart legend, etc.), with every rule resolving colors and radii through--meter-*variables for runtime reskinning.
The color fallback chain: var(--meter-accent, indigo.600) — the runtime CSS variable wins, then it falls back to the host Tailwind theme, so the plugin automatically blends into the host’s brand colors.