Set app-wide default props for Bridge UI components.
Every Bridge UI component ships with library defaults (for example Button uses color="primary", size="md", variant="solid"). Override those defaults once in the provider so every instance inherits them unless you pass a prop.
Configure the provider
Pass components.<Name>.defaultProps to BridgeUIProvider:
<script setup lang="ts">
import { BridgeUIProvider } from "@bridge-ui/vue";
</script>
<template>
<BridgeUIProvider
:components="{
Modal: {
defaultProps: {
size: 'lg',
blur: 'sm',
transition: 'fade',
},
},
Button: {
defaultProps: {
rounded: 'lg',
color: 'secondary',
variant: 'outline',
},
},
Snackbar: {
defaultProps: {
duration: 4000,
progressbar: true,
position: 'top-end',
},
},
}"
>
<slot />
</BridgeUIProvider>
</template>
import { BridgeUIProvider } from "@bridge-ui/react";
import type { PropsWithChildren } from "react";
export default function DefaultProps({ children }: PropsWithChildren) {
return (
<BridgeUIProvider
components={{
Modal: {
defaultProps: {
size: "lg",
blur: "sm",
transition: "fade",
},
},
Button: {
defaultProps: {
rounded: "lg",
color: "secondary",
variant: "outline",
},
},
Snackbar: {
defaultProps: {
duration: 4000,
progressbar: true,
position: "top-end",
},
},
}}
>
{children}
</BridgeUIProvider>
);
}
On Vue you can also pass the same shape to createBridgeUI() in your plugin; the provider merges with those options.
Form density defaults
Set global.formDefaults to apply shared size and rounded across form controls—TextField, Select, Checkbox, FileUpload, Slider, Rating, OtpField, Autocomplete, NumberField, PasswordField, Textarea, RichTextEditor, Radio, Switch, ColorField, and the date/time fields (DateField, DateRangeField, DateTimeField, TimeField, TimeRangeField, DateTimeRangeField).
<script setup lang="ts">
import { BridgeUIProvider } from "@bridge-ui/vue";
</script>
<template>
<BridgeUIProvider :global="{ formDefaults: { size: 'lg', rounded: 'md' } }">
<slot />
</BridgeUIProvider>
</template>
import type { PropsWithChildren } from "react";
import { BridgeUIProvider } from "@bridge-ui/react";
export default function FormDefaults({ children }: PropsWithChildren) {
return (
<BridgeUIProvider
global={{
formDefaults: { size: "lg", rounded: "md" },
}}
>
{children}
</BridgeUIProvider>
);
}
Radio and Switch receive size only—their rounded stays shape-driven (full) unless you override it per component via defaultProps or instance props. BaseField and FormControl also ignore rounded from formDefaults.
Default color
Set global.defaultColor to replace the library default color (primary, dark, or secondary) on every colorable component: Button, ButtonGroup, Badge, Alert, Avatar, Link, Tabs, ToggleGroup, Snackbar, Progress, Spinner, Stepper, Pagination, Accordion, Calendar, ActionFooter, form fields, and pickers. Divider and Tooltip keep their neutral defaults.
Use "black" for a monochrome UI instead of repeating color in every components.<Name>.defaultProps. To rebrand primary, change the palette in theme colors instead.
<script setup lang="ts">
import { BridgeUIProvider } from "@bridge-ui/vue";
</script>
<template>
<BridgeUIProvider
:global="{ defaultColor: 'black' }"
:components="{ Alert: { defaultProps: { color: 'info' } } }"
>
<slot />
</BridgeUIProvider>
</template>
import type { PropsWithChildren } from "react";
import { BridgeUIProvider } from "@bridge-ui/react";
export default function DefaultColor({ children }: PropsWithChildren) {
return (
<BridgeUIProvider
global={{ defaultColor: "black" }}
components={{ Alert: { defaultProps: { color: "info" } } }}
>
{children}
</BridgeUIProvider>
);
}
Component defaultProps, shared chrome, and instance props still win over defaultColor, and error / invalid states are unaffected. In the example above, every Alert stays info while the rest of the UI turns black.
Shared form chrome
FormField, FormControl, BaseField, and TimePanel are registry keys. Set them once to theme a family; a public entry such as components.TextField still overrides defaultProps. Chrome tokens live on the shared key (components.FormField.tokens, components.BaseField.tokens). Dropdown tokens live on components.Listbox. Set components.Listbox.defaultProps.matchWidth so Select / Autocomplete menus match the field width. Time overlay chrome: components.TimePanel (TimePicker / TimeRangePicker override). Cancel / Apply in pickers and listboxes live on components.ActionFooter.
Prefer public fields and controls in apps. Theme all text-like fields via components.FormField, toggle-row chrome via components.FormControl, and composite chrome (OtpField, Slider) via components.BaseField. Theme Cancel / Apply via components.ActionFooter rather than importing it.
<script setup lang="ts">
import { BridgeUIProvider } from "@bridge-ui/vue";
</script>
<template>
<BridgeUIProvider
:components="{
FormField: {
defaultProps: {
variant: 'filled',
color: 'secondary',
},
},
TextField: {
defaultProps: { variant: 'outline' },
},
BaseField: {
tokens: {
size: { md: { text: 'text-base', group: 'gap-3' } },
},
},
}"
>
<slot />
</BridgeUIProvider>
</template>
import { BridgeUIProvider } from "@bridge-ui/react";
import type { PropsWithChildren } from "react";
export default function SharedChrome({ children }: PropsWithChildren) {
return (
<BridgeUIProvider
components={{
TextField: {
defaultProps: { variant: "outline" },
},
BaseField: {
tokens: {
size: { md: { group: "gap-3", text: "text-base" } },
},
},
FormField: {
defaultProps: {
variant: "filled",
color: "secondary",
},
},
}}
>
{children}
</BridgeUIProvider>
);
}
Set components.Listbox.defaultProps.matchWidth so Select / Autocomplete menus match the field:
<script setup lang="ts">
import { BridgeUIProvider } from "@bridge-ui/vue";
</script>
<template>
<BridgeUIProvider
:components="{
Listbox: {
defaultProps: { matchWidth: true },
},
}"
>
<slot />
</BridgeUIProvider>
</template>
import { BridgeUIProvider } from "@bridge-ui/react";
import type { PropsWithChildren } from "react";
export default function ListboxMatchWidth({ children }: PropsWithChildren) {
return (
<BridgeUIProvider
components={{
Listbox: {
defaultProps: { matchWidth: true },
},
}}
>
{children}
</BridgeUIProvider>
);
}
Picker and listbox footer
ActionFooter is a registry key for the Cancel / Apply pair inside pickers and listboxes — the same idea as FormField for field chrome. Set components.ActionFooter.defaultProps once; nested hosts inherit those tokens. Instance customProps.applyButton / customProps.cancelButton still win, including a per-button color.
The typed defaults are applyVariant, cancelVariant, and color. Both buttons share one color; the variants set their hierarchy.
Inside pickers, listboxes, and the RichTextEditor link editor, the footer follows the host color (<DateField color="success" showFooter /> gets a green footer). There, components.ActionFooter.defaultProps.color does not apply — set color on the host (or global.defaultColor) instead.
<script setup lang="ts">
import { BridgeUIProvider } from "@bridge-ui/vue";
</script>
<template>
<BridgeUIProvider
:components="{
ActionFooter: {
defaultProps: {
applyVariant: 'solid',
cancelVariant: 'outline',
},
},
}"
>
<slot />
</BridgeUIProvider>
</template>
import { BridgeUIProvider } from "@bridge-ui/react";
import type { PropsWithChildren } from "react";
export default function ActionFooterDefaults({ children }: PropsWithChildren) {
return (
<BridgeUIProvider
components={{
ActionFooter: {
defaultProps: {
applyVariant: "solid",
cancelVariant: "outline",
},
},
}}
>
{children}
</BridgeUIProvider>
);
}
Merge order
For each prop, Bridge UI merges (later wins):
-
Library defaults
Hard-coded in the component.
-
defaultColor
From global.defaultColor — colorable components only.
-
formDefaults
From global.formDefaults — form controls only.
-
Shared chrome
From components.FormField, FormControl, BaseField, or TimePanel — form chrome families only.
-
defaultProps
From components on the provider (and Vue plugin). Public entries such as TextField override chrome.
-
Instance props
What you pass on <Button /> / <Button> (wins).
// Library → defaultColor → formDefaults → chrome (FormField) → components.TextField.defaultProps → instance
// Provider sets formDefaults.size="lg" and TextField defaultProps.variant="filled"
<TextField label="Name" />
{/* Uses lg + filled */}
<TextField label="Email" size="sm" variant="outline" />
{/* Uses sm + outline */}
Global options
global configures shared app settings (not visual tokens):
| Key | Type | Default | Description |
|---|---|---|---|
| dates | DateAdapter | — | Date adapter (Dates). Each provider creates its own native adapter when this is omitted. |
| defaultColor | BridgeUIDefaultColor | — | Default color for every colorable component, replacing the library default. See Default color. |
| direction | "ltr" | "rtl" | "ltr" | Text direction |
| formDefaults | BridgeUIFormDefaults | — | Shared size / rounded for form controls |
| i18n | I18nAdapter | — | i18n adapter (i18n) |
| icons | IconAdapter | — | Icon adapter (Icons) |
| locale | string | "en-US" | Locale. setLocale also calls optional i18n.setLocale and dates.setLocale. |
| mobileBreakpoint | string | "sm" | Threshold used by overlay="auto" and useBreakpoint().mobile |
| theme | string | "light" | Theme name |
| timeZone | string | system IANA zone | Default zone for pickers. setTimeZone updates it and calls optional dates.setTimeZone. The value Date stays a UTC instant. |
<BridgeUIProvider
components={{}}
global={{
locale: "pt-BR",
direction: "rtl",
formDefaults: { size: "lg", rounded: "md" },
}}
>
{children}
</BridgeUIProvider>
Which keys are available?
Each component exposes a typed subset under defaultProps (for example Button: color, density, rounded, size, variant). See each component API table for the full list, or Type overrides for how Framework packages refine those types.
Next steps
- Classes — shared class slots from the provider
- Tokens — add new token values you can set as defaults
- Type overrides — stronger typing for defaultProps