ConfigProvider
Global theme tokens, typography, component configuration, and scoped customization API
ConfigProvider is the framework-level configuration boundary. It wraps a subtree of Mosmox UI components and provides three kinds of customization:
themechanges shared design tokens through CSS custom properties;componentschanges component-specific defaults where a component has an explicit configuration API;localesets the default language for localized components such as Calendar and Pagination.
The provider does not add styles to unrelated DOM outside its subtree, and it does not change component behavior unless a component-specific setting explicitly supports that behavior.
Basic usage
import { Button, CodeBlock, ConfigProvider, Input, List, Select, Skeleton, Tabs } from '@mosmox/ui';
<ConfigProvider
theme={{
colors: {
primary: '#123b38',
primaryHover: '#1b5752',
controlBorder: '#b8c8c2',
controlIcon: '#52665f',
focus: '#4f46e5',
},
radius: '6px',
typography: {
fontFamily: 'Inter, ui-sans-serif, system-ui, sans-serif',
fontWeightNormal: 400,
fontWeightMedium: 600,
},
}}
>
<Button>Save</Button>
<Input label="Name" />
<Select label="Team" options={teamOptions} />
</ConfigProvider>Every supported value is optional. Unspecified values keep the defaults from tokens.css.
Global locale
locale accepts en, uk, de or fr, and defaults to en. Calendar and Pagination read this value automatically. A component-level locale prop can override the provider for one instance.
<ConfigProvider locale="uk">
<Calendar />
<Pagination totalPages={12} showQuickJumper />
</ConfigProvider>
<ConfigProvider locale="de">
<Calendar locale="fr" /> {/* local override */}
</ConfigProvider>The provider locale is used as a fallback for built-in interface labels. It does not translate content that you pass yourself. Supported locales are en (English, the default), uk (Ukrainian), de (German), and fr (French). For a component that needs a different language, set its local locale prop. The precedence is: explicit component prop, nearest ConfigProvider, then en.
Theme tokens
theme.colors contains semantic values rather than component-specific selectors. The same token can affect several controls, which keeps Button, Input, Input OTP, Select, Checkbox, Radio, Switch, Textarea, and Switch Card visually consistent.
Color tokens
| Theme property | CSS variable | Default | Used for |
|---|---|---|---|
text | --mm-color-text | #0c1518 | Primary text and control content. |
primary | --mm-color-primary | #003231 | Primary actions, selected states, active controls, and focus borders. |
primaryHover | --mm-color-primary-hover | #004846 | Hover state of primary actions. |
secondary | --mm-color-secondary | #47634c | Secondary actions and supporting emphasis. |
secondaryHover | --mm-color-secondary-hover | #58775d | Hover state of secondary actions. |
surface | --mm-color-surface | #ffffff | Input surfaces, cards, menus, and control backgrounds. |
surfaceHover | --mm-color-surface-hover | #f8fafc | Hover and active surface state for controls and Select options. |
controlBorder | --mm-color-control-border | #d0d5dd | Input, Select, Textarea, Radio, Checkbox, menu, and divider borders. |
controlFilled | --mm-color-control-filled | #eef1f2 | Filled controls, selected chips, selected options, and muted control surfaces. |
controlSelected | --mm-color-control-selected | lightBackground | Light active and selected options in Select and AutoComplete menus. |
overlay | --mm-color-overlay | rgb(12 21 24 / 14%) | Modal backdrop color. |
controlIcon | --mm-color-control-icon | #667085 | Icons inside controls, password actions, Select actions, and adornments. |
mutedText | --mm-color-muted-text | #667085 | Descriptions, supporting text, secondary labels, and status text. |
placeholder | --mm-color-placeholder | #98a2b3 | Input, Select, Textarea, and OTP placeholders. |
focus | --mm-color-focus | #6366f1 | Keyboard focus rings. |
link | --mm-color-link | #1d4ed8 | Default color for the Link component and other link-style actions. An individual Link color="..." prop overrides it. |
lightBackground | --mm-color-light-background | #f6f6f7 | Neutral light surface for buttons, sections, and low-emphasis backgrounds. |
lightHover | --mm-color-light-hover | #e8dfd1 | Hover state for light actions. |
dangerBackground | --mm-color-danger-background | #fdecec | Destructive Button background and danger surfaces. |
danger | --mm-color-danger | #dc2626 | Destructive active states and progress treatments. |
dangerHover | --mm-color-danger-hover | #b91c1c | Hover state for danger actions. |
dangerText | --mm-color-danger-text | #b42318 | Error messages, invalid borders, and danger text. |
success | --mm-color-success | #059669 | Success actions and positive Switch tones. |
successHover | --mm-color-success-hover | #047857 | Hover state for success actions. |
warning | --mm-color-warning | #d97706 | Warning Switch tones and warning indicators. |
warningHover | --mm-color-warning-hover | #b45309 | Hover state for warning actions. |
warningText | --mm-color-warning-text | #b54708 | Warning status text and messages. |
Example of a complete semantic color override:
import { Plus } from '@mosmox-ui/icons';
<ConfigProvider
theme={{
colors: {
text: '#17211f',
primary: '#0f766e',
primaryHover: '#115e59',
secondary: '#4d7c0f',
secondaryHover: '#3f6212',
surface: '#ffffff',
surfaceHover: '#f0fdfa',
controlBorder: '#99f6e4',
controlFilled: '#f0fdfa',
controlIcon: '#0f766e',
mutedText: '#64748b',
placeholder: '#94a3b8',
focus: '#14b8a6',
link: '#2563eb',
success: '#16a34a',
successHover: '#15803d',
warning: '#d97706',
warningHover: '#b45309',
warningText: '#b45309',
dangerBackground: '#fef2f2',
danger: '#dc2626',
dangerHover: '#b91c1c',
dangerText: '#b91c1c',
},
}}
>
{children}
</ConfigProvider>Radius
theme.radius maps to --mm-radius-control and is the shared radius for form controls, buttons, cards, menus, and other component surfaces that use the common control shape.
<ConfigProvider theme={{ radius: '10px' }}>
<Input label="Rounded control" />
</ConfigProvider>Use a CSS length such as 0, 4px, 6px, or 999px. Individual components can still define an internal shape for sub-elements such as chips, icon buttons, or circular controls.
Typography
theme.typography controls the shared typography tokens:
| Property | CSS variable | Default | Description |
|---|---|---|---|
fontFamily | --mm-font-family-sans | 'Google Sans Flex', ui-sans-serif, system-ui, sans-serif | Font stack used by controls and labels. |
fontWeightNormal | --mm-font-weight-normal | 400 | Normal control and body text. |
fontWeightMedium | --mm-font-weight-medium | 500 | Labels and emphasized control text. |
fontWeightLight | --mm-font-weight-light | 300 | Compact and lightweight control text. |
<ConfigProvider
theme={{
typography: {
fontFamily: 'Manrope, ui-sans-serif, sans-serif',
fontWeightLight: 400,
fontWeightNormal: 500,
fontWeightMedium: 700,
},
}}
>
{children}
</ConfigProvider>Component-specific configuration
The components object is intentionally separate from global tokens. It is used for geometry or behavior that should affect one component family without changing every control.
Button
components.button currently supports:
| Property | Type | Default | Description |
|---|---|---|---|
gap | string | shared control gap | Gap between Button content and icons. |
iconSize | string | component default | Width and height applied to Button icons. |
radius | string | shared control radius | Button-only radius override. |
import { Plus } from '@mosmox-ui/icons';
<ConfigProvider
components={{
button: {
gap: '10px',
iconSize: '18px',
radius: '999px',
},
}}
>
<Button iconLeft={<Plus />}>Create</Button>
</ConfigProvider>The Button configuration does not change Input, Select, or other controls. Component-specific configuration is only available where the component exposes a typed configuration entry; passing arbitrary keys is not part of the supported API.
Skeleton
components.skeleton sets loading-placeholder defaults for all Skeleton descendants:
| Property | Type | Default | Description |
|---|---|---|---|
animation | pulse | wave | none | pulse | Default Skeleton animation. |
baseColor | string | theme control fill | Placeholder base color. |
highlightColor | string | translucent surface | Wave highlight color. |
radius | string | shared control radius | Default shape radius. |
<ConfigProvider
components={{
skeleton: {
animation: 'wave',
baseColor: '#dbeafe',
highlightColor: '#eff6ff',
radius: '12px',
},
}}
>
<Skeleton variant="rectangular" height={120} />
</ConfigProvider>An individual Skeleton can override these values with its own animation or radius prop. See the complete Skeleton documentation for all component props and variants.
CodeBlock
components.codeBlock configures defaults for the CodeBlock code viewer:
| Property | Type | Default | Description |
|---|---|---|---|
copyable | boolean | true | Whether code blocks show a copy action. |
fontSize | string | component default | Base code font size. |
radius | string | 8px | Default block radius. |
theme | light | dark | dark | Default color theme. |
<ConfigProvider components={{ codeBlock: { theme: 'light', fontSize: '14px', radius: '12px' } }}>
<CodeBlock code="const configured = true;" language="tsx" />
</ConfigProvider>See the complete CodeBlock documentation for all props and examples.
List
components.list sets default density, variant, and spacing for List descendants:
| Property | Type | Default | Description |
|---|---|---|---|
gap | string | 8px | Spacing between list sections. |
size | sm | default | lg | default | Default row density. |
variant | plain | divided | bordered | card | plain | Default visual treatment. |
<ConfigProvider components={{ list: { variant: 'card', size: 'sm', gap: '12px' } }}>
<List items={items} />
</ConfigProvider>See the complete List documentation for selection, links, loading, custom rendering, and all item fields.
Tabs
components.tabs configures default tab orientation, density, and width:
| Property | Type | Default | Description |
|---|---|---|---|
fullWidth | boolean | false | Stretches tabs across the available width. |
orientation | horizontal | vertical | horizontal | Tab list direction. |
size | sm | default | lg | default | Tab density. |
<ConfigProvider components={{ tabs: { size: 'sm', fullWidth: true } }}>
<Tabs items={items} />
</ConfigProvider>See the complete Tabs documentation for keyboard behavior, lazy panels, and all props.
Empty
components.empty provides defaults for the Empty state presentation:
| Property | Type | Default | Description |
|---|---|---|---|
bordered | boolean | component default | Whether the Empty state has a border. |
size | sm | default | default | Compact or regular Empty layout. |
<ConfigProvider components={{ empty: { size: 'sm', bordered: false } }}>
<Empty />
</ConfigProvider>The Empty component's own props take precedence over provider defaults. Its fallback title and description use the provider locale when they are not supplied explicitly.
CookieBanner
components.cookieBanner centralizes consent-banner presentation and layout:
| Property | Type | Default | Description |
|---|---|---|---|
layout | inline | stacked | component default | One-row or vertical content layout. |
presentation | bar | card | component default | Full-width bar or contained card. |
position | fixed | sticky | static | component default | How the banner participates in page layout. |
placement | top | bottom | component default | Edge placement for positioned banners. |
radius | number | string | component default | Banner corner radius. |
size | sm | default | default | Compact or regular spacing. |
surfaceColor | string | component default | Banner surface color. |
textColor | string | component default | Main text color. |
borderColor | string | component default | Border color. |
variant | default | soft | contrast | component default | Preset contrast treatment. |
showPreferences | boolean | component default | Shows or hides the preferences action. |
<ConfigProvider
locale="uk"
components={{
cookieBanner: {
presentation: 'card',
position: 'fixed',
placement: 'bottom',
layout: 'stacked',
variant: 'soft',
showPreferences: true,
radius: 16,
},
}}
>
<CookieBanner
title="Ми використовуємо cookies"
description="Це допомагає нам покращувати роботу сайту."
/>
</ConfigProvider>Cookie content and consent state remain the responsibility of the application. The provider supplies presentation defaults only.
PricingTable
components.pricingTable defines the default layout for nested pricing tables:
| Property | Type | Default | Description |
|---|---|---|---|
columns | number | component default | Number of pricing columns. |
size | sm | default | lg | default | Density of the pricing table. |
variant | cards | bordered | flat | spotlight | compact | cards | Visual treatment of plans. |
<ConfigProvider
components={{
pricingTable: {
columns: 3,
size: 'default',
variant: 'spotlight',
},
}}
>
<PricingTable plans={plans} />
</ConfigProvider>An individual PricingTable prop overrides the corresponding provider value.
Provider scope and nesting
All theme CSS variables are written to the provider wrapper, so they apply to descendants and inherit through nested DOM elements. Components outside the provider keep the root defaults.
Providers can be nested to create local themes:
<ConfigProvider theme={{ colors: { primary: '#003231' } }}>
<AppShell />
<ConfigProvider
theme={{
colors: { primary: '#7c3aed', primaryHover: '#6d28d9' },
radius: '12px',
}}
>
<BillingPanel />
</ConfigProvider>
</ConfigProvider>The nested provider overrides the CSS variables for its subtree. Unspecified nested values inherit from the outer provider or the root token defaults. Component configuration is scoped to the provider's React subtree.
Defaults that are not ThemeConfig properties
The theme token file also contains foundational values such as --mm-color-white, --mm-color-outline-border, --mm-color-muted-hover, --mm-size-icon, --mm-space-control-gap, and --mm-space-control-icon-gap. These are currently internal foundation tokens and are not accepted by ThemeConfig as public properties. They remain consistent across the framework unless the framework API is extended.
API Reference
| Property | Type | Default | Description |
|---|---|---|---|
children | ReactNode | — | Component subtree receiving the configuration. |
theme | ThemeConfig | {} | Global color, radius, and typography overrides. |
components | ComponentConfig | {} | Typed component-specific configuration. |
locale | en | uk | de | fr | en | Default language for localized components. |
ThemeConfig contains optional colors, radius, and typography groups. ComponentConfig contains button, skeleton, codeBlock, list, tabs, empty, cookieBanner, and pricingTable. The useConfig() hook exposes the component configuration context for framework components and custom integrations.
Configuration precedence
When the same setting is supplied at more than one level, use this order:
- An explicit prop on the component instance.
- The closest (nested)
ConfigProvider. - An outer
ConfigProvider. - The framework default from
tokens.cssor the component implementation.
This lets you define a product-wide baseline and create isolated exceptions without changing the rest of the application.
<ConfigProvider theme={{ colors: { primary: '#003231' }, radius: '6px' }}>
<Button>Uses the global primary color</Button>
<ConfigProvider theme={{ colors: { primary: '#7c3aed' }, radius: '12px' }}>
<Button>Uses the nested theme</Button>
<Button variant="danger">Its explicit variant still wins</Button>
</ConfigProvider>
</ConfigProvider>Using useConfig() in an integration
useConfig() reads the nearest provider context and returns the configured component defaults and locale. It is primarily intended for Mosmox UI components and custom integrations that need to follow the same provider boundary.
import { useConfig } from '@mosmox/ui';
function LocaleBadge() {
const { locale } = useConfig();
return <span>Current locale: {locale}</span>;
}When no provider is present, useConfig() returns an empty component configuration and the default en locale. Theme variables are not exposed by this hook; read them through CSS inheritance so custom integrations stay compatible with the token system.
Application-level setup
Place one provider near the root of a client-side application when the whole product should share a theme and locale. Keep nested providers close to the feature that needs a different visual context.
import { ConfigProvider } from '@mosmox/ui';
export function App() {
return (
<ConfigProvider
locale="uk"
theme={{
colors: {
primary: '#d90b2c',
primaryHover: '#b90825',
focus: '#d90b2c',
},
radius: '8px',
}}
>
<Router />
</ConfigProvider>
);
}Import ConfigProvider from the public @mosmox/ui entry point. Avoid importing its internal implementation path, since internal paths are not part of the public API.
CSS variable mapping
Theme values are translated to CSS custom properties at runtime. This means the values work with the existing component styles, inherit naturally, and can be inspected in browser DevTools on .mm-config-provider. Components should consume these tokens rather than hard-coding theme colors.