@wso2/oxygen-ui
v0.13.0
Published
WSO2 Oxygen UI | Design System - Powered with Material-UI component library with TypeScript support
Maintainers
Readme
@wso2/oxygen-ui
WSO2 Oxygen UI React component library - A comprehensive design system powered by Material-UI with TypeScript support.
Installation
npm install @wso2/oxygen-ui @emotion/react @emotion/styled @mui/material
# or
yarn add @wso2/oxygen-ui @emotion/react @emotion/styled @mui/material
# or
pnpm add @wso2/oxygen-ui @emotion/react @emotion/styled @mui/materialNote: The Inter Variable font is automatically bundled and loaded when you import from @wso2/oxygen-ui. No additional setup required!
Peer Dependencies
Make sure to install the required peer dependencies:
npm install react react-dom @emotion/react @emotion/styled @mui/material @mui/x-data-grid @mui/x-date-pickers @wso2/oxygen-ui-icons-reactUsage
Material-UI Components
Import and use Material-UI components directly from @wso2/oxygen-ui:
import { Box, Button, Stack, TextField } from '@wso2/oxygen-ui';
function MyComponent() {
return (
<Box>
<Stack spacing={2}>
<Button variant="contained">Click me</Button>
<TextField label="Name" />
</Stack>
</Box>
);
}Oxygen UI Custom Components
import {
OxygenUIThemeProvider,
ColorSchemeToggle,
Layout
} from '@wso2/oxygen-ui';
function App() {
return (
<OxygenUIThemeProvider>
<Layout>
<ColorSchemeToggle />
{/* Your app content */}
</Layout>
</OxygenUIThemeProvider>
);
}MUI X Data Grid
Data Grid components are exported as a namespace to avoid naming conflicts:
import { DataGrid } from '@wso2/oxygen-ui';
// Destructure the components you need
const {
DataGrid: DataGridComponent,
GridColDef,
GridToolbarContainer
} = DataGrid;
function MyDataGrid() {
const columns: GridColDef[] = [
{ field: 'id', headerName: 'ID', width: 90 },
{ field: 'name', headerName: 'Name', width: 150 },
];
const rows = [
{ id: 1, name: 'John Doe' },
{ id: 2, name: 'Jane Smith' },
];
return (
<DataGridComponent
rows={rows}
columns={columns}
/>
);
}MUI X Date Pickers
Date Picker components are exported as a namespace:
import { DatePickers } from '@wso2/oxygen-ui';
// Destructure the components you need
const {
DatePicker,
LocalizationProvider,
DateTimePicker
} = DatePickers;
function MyDatePicker() {
const [value, setValue] = useState<Date | null>(null);
return (
<LocalizationProvider dateAdapter={AdapterDayjs}>
<DatePicker
label="Select Date"
value={value}
onChange={(newValue) => setValue(newValue)}
/>
</LocalizationProvider>
);
}MUI X Charts
Chart components are exported as a namespace:
import { Charts } from '@wso2/oxygen-ui';
// Destructure the chart components you need
const { LineChart, BarChart, PieChart } = Charts;
function MyChart() {
const data = [
{ month: 'Jan', value: 30 },
{ month: 'Feb', value: 45 },
{ month: 'Mar', value: 60 },
];
return (
<LineChart
xAxis={[{ dataKey: 'month', scaleType: 'band' }]}
series={[{ dataKey: 'value', label: 'Sales' }]}
width={500}
height={300}
dataset={data}
/>
);
}MUI X Tree View
Tree View components are exported as a namespace:
import { TreeView } from '@wso2/oxygen-ui';
// Destructure the tree components you need
const { SimpleTreeView, TreeItem } = TreeView;
function MyTreeView() {
return (
<SimpleTreeView>
<TreeItem itemId="1" label="Parent 1">
<TreeItem itemId="2" label="Child 1.1" />
<TreeItem itemId="3" label="Child 1.2" />
</TreeItem>
<TreeItem itemId="4" label="Parent 2">
<TreeItem itemId="5" label="Child 2.1" />
</TreeItem>
</SimpleTreeView>
);
}Theme Switching
Oxygen UI provides built-in theme switching capabilities through OxygenUIThemeProvider and UI components for easy theme selection.
Basic Setup
Pass a themes array to OxygenUIThemeProvider:
import {
OxygenUIThemeProvider,
OxygenTheme,
OxygenThemeWithRadialBackground
} from '@wso2/oxygen-ui';
function App() {
return (
<OxygenUIThemeProvider
themes={[
{ key: 'default', label: 'Default', theme: OxygenTheme },
{ key: 'radial', label: 'Radial Background', theme: OxygenThemeWithRadialBackground },
]}
initialTheme="default"
>
<YourApp />
</OxygenUIThemeProvider>
);
}Using ThemeSwitcher Component
Add the ThemeSwitcher component to provide a select dropdown:
import {
OxygenUIThemeProvider,
ThemeSwitcher,
OxygenTheme,
OxygenThemeWithRadialBackground
} from '@wso2/oxygen-ui';
function App() {
return (
<OxygenUIThemeProvider
themes={[
{ key: 'default', label: 'Default', theme: OxygenTheme },
{ key: 'radial', label: 'Radial Background', theme: OxygenThemeWithRadialBackground },
]}
>
<header>
<ThemeSwitcher /> {/* Default select dropdown */}
</header>
<YourApp />
</OxygenUIThemeProvider>
);
}Custom Theme Switcher UI
Use render props for custom UI:
<ThemeSwitcher>
{({ currentTheme, themes, setTheme, isActive }) => (
<ButtonGroup>
{themes.map(theme => (
<Button
key={theme.key}
variant={isActive(theme.key) ? 'contained' : 'outlined'}
onClick={() => setTheme(theme.key)}
>
{theme.label}
</Button>
))}
</ButtonGroup>
)}
</ThemeSwitcher>Custom Themes
Add your own custom themes:
import { extendTheme } from '@mui/material/styles';
const customTheme = extendTheme({
palette: {
primary: { main: '#ff0000' },
},
});
function App() {
return (
<OxygenUIThemeProvider
themes={[
{ key: 'default', label: 'Default', theme: OxygenTheme },
{ key: 'custom', label: 'Custom Theme', theme: customTheme },
]}
>
<ThemeSwitcher showLabel label="Select Theme" />
<YourApp />
</OxygenUIThemeProvider>
);
}Programmatic Access
Use the useThemeSwitcher hook to access theme state:
import { useThemeSwitcher } from '@wso2/oxygen-ui';
function MyComponent() {
const { currentTheme, themes, setTheme, isActive } = useThemeSwitcher();
return (
<div>
<p>Current theme: {currentTheme}</p>
<button onClick={() => setTheme('radial')}>Switch to Radial</button>
</div>
);
}Content Security Policy (CSP)
Oxygen UI (via MUI and Emotion) injects styles at runtime using <style> tags. If your application enforces a strict CSP, pass a nonce so those tags are allowed. Follow the same directives recommended in the MUI Content Security Policy guide:
Content-Security-Policy:
default-src 'self';
style-src-elem 'self' 'nonce-<value>';
style-src-attr 'unsafe-inline';
font-src 'self' data:;style-src-elem— Emotion injects<style>elements; each needs a matching nonce.style-src-attr 'unsafe-inline'— MUI components apply dynamic inlinestyleattributes (dimensions, CSS custom properties, positioning). Nonces cannot cover style attributes.font-src 'self' data:— The bundled Inter font is embedded as base64data:URIs. Withoutdata:infont-src(which otherwise falls back todefault-src 'self'), the browser blocks the fonts even when the style tag itself is allowed.script-src 'nonce-...'— Only required if your app uses MUI'sInitColorSchemeScript. Oxygen UI does not ship that script.
Using the nonce prop
Pass your server-generated nonce to OxygenUIThemeProvider. It is applied to every style tag injected by the styling engine (components, CssBaseline, theme styles). The value must match the nonce in your CSP header:
import { OxygenUIThemeProvider } from '@wso2/oxygen-ui';
// `serverNonce` is generated per request on the server and must match the CSP header.
function App({ serverNonce }: { serverNonce: string }) {
return (
<OxygenUIThemeProvider nonce={serverNonce}>
<YourApp />
</OxygenUIThemeProvider>
);
}Using a custom Emotion cache
For full control over style injection (cache key, insertion point, stylis plugins, shadow DOM containers, SSR caches), pass a custom Emotion cache. createEmotionCache is re-exported from @emotion/cache for convenience.
Set prepend: true to preserve the previous injectFirst cascade (application styles can override Oxygen UI styles). Omitting it changes style order.
import { OxygenUIThemeProvider, createEmotionCache } from '@wso2/oxygen-ui';
const cache = createEmotionCache({
key: 'css',
nonce: serverNonce,
prepend: true,
});
function App() {
return (
<OxygenUIThemeProvider emotionCache={cache}>
<YourApp />
</OxygenUIThemeProvider>
);
}emotionCache takes precedence over nonce if both are provided.
Note that the nonce prop creates an Emotion cache per provider instance. If your app mounts multiple providers or remounts the provider (for example, on route-level key changes), each mount injects a fresh set of style tags. In that case, prefer a module-level cache passed via emotionCache (as in the example above) so styles are injected only once.
Server-side rendering (SSR)
Generate a unique nonce per request on the server, include it in the CSP header, and pass the same value to OxygenUIThemeProvider via nonce or a shared emotionCache on both server and client. Keep server and client Emotion caches aligned (same key, nonce, and insertion options). See the MUI CSP guide for framework-specific examples (Next.js, Vite, and Emotion SSR).
Bundled fonts and theme CSS
The bundled CSS — the Inter Variable font styles and the theme CSS — is injected as separate <style> tags when the package is imported (before React renders), so the nonce for those tags is resolved from well-known conventions instead of a prop:
- The
__webpack_nonce__global (webpack convention) - A
<meta property="csp-nonce" nonce="...">tag (Vite convention);contentis also accepted as a fallback - A
<meta name="csp-nonce" content="...">tag (MUI / Next.js convention)
Because the nonce is read at module evaluation time, the meta tag (or the __webpack_nonce__ assignment) must already be present in the document before the app bundle executes. A meta tag added later from JavaScript silently results in style tags without a nonce.
<!-- Vite convention -->
<meta property="csp-nonce" nonce="YOUR_SERVER_GENERATED_NONCE" />
<!-- MUI / Next.js convention -->
<meta name="csp-nonce" content="YOUR_SERVER_GENERATED_NONCE" />Known limitation: runtime theme loading
Loading themes from URLs (themes: [{ key: 'x', label: 'X', theme: '/themes/x.js' }]) evaluates the fetched theme file with new Function(...), which additionally requires script-src 'unsafe-eval'. Under a strict CSP, prefer passing theme objects directly instead of URL-based themes.
Available Exports
Custom Oxygen UI Components
OxygenTheme- Default theme configurationOxygenThemeWithRadialBackground- Theme variant with radial gradient backgroundsOxygenUIThemeProvider- Theme provider component with theme switching supportThemeSwitcher- Theme selection component (default select dropdown or render props)ThemeSelect- Standalone theme select dropdown componentColorSchemeImage- Image component that adapts to color schemeColorSchemeToggle- Toggle for light/dark modeLayout- Layout componentsuseThemeSwitcher- Hook to access theme switcher contextcreateEmotionCache- Create a custom Emotion cache (re-export of@emotion/cache, for CSP and advanced style injection)EmotionCache- Type for Emotion cache instances
Material-UI Components
All components from @mui/material are re-exported directly.
MUI X Components
DataGrid- Namespace containing all Data Grid componentsDatePickers- Namespace containing all Date Picker componentsCharts- Namespace containing all Chart componentsTreeView- Namespace containing all TreeView components
TypeScript Support
This package includes full TypeScript definitions. All types from Material-UI and MUI X are also available:
import type { ButtonProps, BoxProps } from '@wso2/oxygen-ui';
import { DataGrid } from '@wso2/oxygen-ui';
const { GridColDef } = DataGrid;
type MyGridColDef = typeof GridColDef;AI-Assisted Development
Oxygen UI includes built-in documentation for AI assistants.
Universal Setup (Works with any AI)
npx @wso2/oxygen-ui initCreates:
AGENTS.md- Streamlined AI guide at project root.ai/oxygen-ui/- Detailed documentation:components.md- Component API referencepatterns.md- Common UI patternstheming.md- Theme customizationmigration.md- Migration guide
Claude Code Setup (Recommended for Claude)
npx @wso2/oxygen-ui init --claudeCreates:
.claude/oxygen-ui/- Claude-optimized documentation.claude/skills/- Invokable skills:/oxygen-component- Generate Oxygen UI components/oxygen-layout- Generate app layouts/oxygen-form- Generate forms with validation/oxygen-migrate- Migrate MUI code
- Updates root
CLAUDE.mdwith reference
Updating After Upgrade
npx @wso2/oxygen-ui update # Universal
npx @wso2/oxygen-ui update --claude # Claude-specificAI Documentation
For detailed information, see the generated files:
- Components:
.ai/oxygen-ui/components.mdor.claude/oxygen-ui/components.md - Patterns:
.ai/oxygen-ui/patterns.mdor.claude/oxygen-ui/patterns.md - Theming:
.ai/oxygen-ui/theming.mdor.claude/oxygen-ui/theming.md - Migration:
.ai/oxygen-ui/migration.mdor.claude/oxygen-ui/migration.md
License
Apache-2.0 © WSO2 LLC
