Skip to content

Material UI and other design systems

The viewer and designer take every color, the corner radius and the font from CSS variables. The theme prop sets them, and themeFromMui builds that theme from a Material UI theme in one call. When your app switches between light and dark mode, the report UI follows.

ReportScreen.tsx
import { useMemo } from 'react';
import { useTheme } from '@mui/material/styles';
import { ReportDesigner, ReportViewer, themeFromMui } from '@ariana-reports/react';
export function ReportScreen({ template, data }) {
const muiTheme = useTheme();
// Memoize: a new object on every render would re-apply the variables each time.
const theme = useMemo(() => themeFromMui(muiTheme), [muiTheme]);
return (
<>
<div style={{ height: 600 }}>
<ReportViewer theme={theme} template={template} data={data} />
</div>
<div style={{ height: 800 }}>
<ReportDesigner theme={theme} template={template} sampleData={data} />
</div>
</>
);
}

themeFromMui reads the palette (primary.main, background, text, divider, error), palette.mode, shape.borderRadius and typography.fontFamily/fontSize. It accepts any object of that shape, so the packages have no dependency on Material UI. Use the second argument to override single values:

themeFromMui(muiTheme, { bandColor: muiTheme.palette.grey[800], radius: 8 });

The result is a plain object. The pages and the design surface stay white like paper in every theme, because a report is a printed document.

Build the theme object yourself from your design system’s tokens. Every property is optional:

import { ReportViewer, type ArianaTheme } from '@ariana-reports/react';
const theme: ArianaTheme = {
mode: 'light',
primary: 'var(--brand-500)',
surface: 'var(--surface)',
border: 'var(--border)',
text: 'var(--text)',
radius: 8,
fontFamily: 'Inter, sans-serif',
};
<ReportViewer theme={theme} template={template} data={data} />;

Values can be any CSS color, including var(--your-token).

viewer-theme.tsx
import { useState } from 'react';
import { DARK_THEME, ReportViewer, themeFromMui } from '@ariana-reports/react';
import { salesData, salesTemplate } from './report-data';
// Any object shaped like a Material UI theme works, so in a MUI app pass useTheme() directly.
const grape = themeFromMui({
palette: { mode: 'light', primary: { main: '#7b1fa2' }, background: { default: '#f3e5f5', paper: '#ffffff' } },
shape: { borderRadius: 14 },
});
const themes = { default: undefined, dark: DARK_THEME, grape } as const;
export default function ViewerTheme() {
const [name, setName] = useState<keyof typeof themes>('grape');
return (
<div style={{ display: 'flex', flexDirection: 'column', height: '100%' }}>
<label style={{ padding: 8, background: '#fff', font: '13px system-ui' }}>
Theme{' '}
<select value={name} onChange={(e) => setName(e.target.value as keyof typeof themes)}>
{Object.keys(themes).map((t) => (
<option key={t}>{t}</option>
))}
</select>
</label>
<div style={{ flex: 1, minHeight: 0 }}>
<ReportViewer template={salesTemplate} data={salesData} theme={themes[name]} zoomMode="fitWidth" showIssues />
</div>
</div>
);
}

Without the prop, set the variables in a rule for .ar-root. The package’s defaults have zero specificity, so your rule wins whatever the stylesheet order:

.ar-root {
--ar-primary: #6750a4;
--ar-radius: 12px;
}

See Theming for the list of variables.