App configuration
App configuration sets, in one place, the values Chameleon's components use when they don't set their own. Use it to change how much Chameleon writes to the browser console, where toasts appear and how long they stay, the language of built-in text, and the keyboard a field offers on a phone.
App configuration in depth
Common changes
- See more of Chameleon's messages, or fewer. Set
minConsoleLoggingLeveltoLoggingLevel.Informationwhile you develop, or toLoggingLevel.Noneto silence the console. SetminScreenLoggingLevelto show warnings on the components themselves. - Move toasts and change how long they stay. Set
toastAnchorto the corner you want andtoastTimeoutto the time in milliseconds. - Choose one language for every user. Set
localeto a BCP 47 tag, such asde-CH, to use that language for built-in text and number formats whatever the user's browser language. - Offer a different on-screen keyboard. Set
defaultNumberFieldInputModetoInputMode.Numericfor whole numbers, for example. Each field type has its own setting.
A component's own value always wins over app configuration. A text field with its own inputmode keeps it.
Messages
| Setting | Values | Default | What it does |
|---|---|---|---|
minConsoleLoggingLevel |
LoggingLevel: None, Information, Warning, Error |
LoggingLevel.Warning |
Writes Chameleon's messages at this level or above to the browser console. None turns them off |
minScreenLoggingLevel |
LoggingLevel |
LoggingLevel.None |
Shows messages at this level or above as a warning on the component itself. Users see it too, so turn it on only while you develop |
Toasts
A toast that sets its own value keeps it. toastAnimation is the exception: it applies to every toast.
| Setting | Values | Default | What it does |
|---|---|---|---|
toastAnchor |
Corner: StartEnd, StartStart, EndEnd, EndStart |
Corner.StartEnd |
The corner where toasts appear. StartEnd is top right, StartStart top left, EndEnd bottom right, and EndStart bottom left. A right-to-left page mirrors them |
toastTimeout |
A number of milliseconds | 5000 |
How long a toast stays on screen when it closes on a timer |
defaultToastDismissMethod |
ToastDismissMethod: CloseButton, Timer, CloseButtonAndTimer |
ToastDismissMethod.CloseButtonAndTimer |
How a toast closes: with its close button, when its timer runs out, or whichever comes first |
defaultToastVariant |
ToastVariant: Primary, Secondary, Tertiary, Information, Success, Warning, Error, and a Container form of each, such as PrimaryContainer |
ToastVariant.PrimaryContainer |
The color role of a toast |
toastAnimation |
ToastAnimation: Fade, Slide, None |
ToastAnimation.Fade |
How toasts appear and leave. Users who ask their system for reduced motion get None |
toastDensity |
Density: Standard, Dense1 to Dense4 |
Density.Standard |
How compact a toast is |
defaultToastProgressWaveShape |
ProgressWaveShape: Flat, Wavy |
ProgressWaveShape.Flat |
The shape of the bar that shows a toast's remaining time |
Forms
Each setting picks the on-screen keyboard a field offers when it sets no inputmode of its own. Every one takes an InputMode: None, Decimal, Email, Numeric, Search, Tel, Text, or Url.
| Setting | Field | Default |
|---|---|---|
defaultEmailFieldInputMode |
Email field | InputMode.Email |
defaultNumberFieldInputMode |
Number field | InputMode.Decimal |
defaultPasswordFieldInputMode |
Password field | InputMode.Text |
defaultSearchFieldInputMode |
Search field | InputMode.Search |
defaultTelFieldInputMode |
Telephone field | InputMode.Tel |
defaultTextFieldInputMode |
Text field | InputMode.Text |
Language
| Setting | Values | Default | What it does |
|---|---|---|---|
locale |
A BCP 47 tag, such as de-CH |
Empty, which means the user's browser language | The language for built-in text, such as a dialog's Close label, and the number format of locale-aware fields, such as a number field's separators. A component's own locale wins |
Performance
Most apps leave these alone.
| Setting | Values | Default | What it does |
|---|---|---|---|
deferralGap |
DeferralGap: Off, None, Half, One, Two, Three |
DeferralGap.Half |
How far ahead of the visible area, in screen heights, components render as the page loads. The rest render as scrolling brings them close, or shortly after load. Off renders every component at once, and None renders only what's on screen |
deferralFlushDelay |
A number of milliseconds | 1500 |
The longest wait, once the visible components have rendered, before the rest render too. Every component must render for a screen reader to reach it, so keep it short |
redrawGap |
DeferralGap |
DeferralGap.Half |
In Firefox and Safari, how far beyond the visible area, in screen heights, components update at once after a theme switch. The rest follow, nearest first. Off updates every component at once. Lower it if a theme switch feels slow on a page with many components |
Advanced
Most apps leave these alone.
| Setting | Values | Default | What it does |
|---|---|---|---|
shadowRootVisibility |
ShadowRootVisibility: Closed, Open |
ShadowRootVisibility.Closed |
Whether a component's shadowRoot property returns its shadow root (Open) or null (Closed). Closed stops your code from depending on a component's internals by accident. It isn't a security boundary |
repaintOnColorSchemeChange |
true or false |
true |
In Safari and Firefox, repaints components in the new colors when the operating system switches between light and dark. With false, a component in those browsers can show the previous colors until it next updates |
How settings apply
- Set a setting to
"DEFAULT"to return it to Chameleon's default.localeandrepaintOnColorSchemeChangedon't take"DEFAULT"; set them to their default value instead. - Set
deferralGap,deferralFlushDelay, andshadowRootVisibilitybefore your first component appears, andredrawGapbefore the first theme switch, because later changes don't reach the page. Every other setting applies at once, to components already on screen. - Reading a setting you haven't set gives
"DEFAULT", not the value in the Default column.
Call setAppConfiguration() from the package you already import. There's nothing else to set up.
Set it
Call setAppConfiguration() in your entry point, straight after the package import, and pass only the settings you want to change. The rest keep their current values.
import {
Corner,
LoggingLevel,
setAppConfiguration,
} from "@materia-technologies-inc/chameleon-components-web";
setAppConfiguration({
minConsoleLoggingLevel: LoggingLevel.Information,
toastAnchor: Corner.EndEnd,
toastTimeout: 8000,
});
Call it again whenever a setting needs to change, from a settings panel, for example. Pass "DEFAULT" to return a setting to Chameleon's default.
setAppConfiguration({ toastAnchor: "DEFAULT" });
getAppConfiguration() returns the settings your app has set. Treat the object as read-only and change settings through setAppConfiguration().
import { getAppConfiguration } from "@materia-technologies-inc/chameleon-components-web";
const { toastTimeout, locale } = getAppConfiguration();
Components in your HTML
Components written into your page's HTML start before your call to setAppConfiguration() runs, so they keep the default shadowRootVisibility. To give them another value, add them from script after the call.
Import setAppConfiguration() from the React package. There's no provider or hook to add.
Set it
Call setAppConfiguration() in your entry point, before createRoot().render(), so every setting applies from the first render. Pass only the settings you want to change; the rest keep their current values.
import { createRoot } from "react-dom/client";
import {
DeferralGap,
InputMode,
setAppConfiguration,
} from "@materia-technologies-inc/chameleon-components-react";
import { App } from "./App";
setAppConfiguration({
defaultNumberFieldInputMode: InputMode.Numeric,
deferralGap: DeferralGap.One,
});
createRoot(document.getElementById("root")!).render(<App />);
Change it while your app runs
Call setAppConfiguration() from an event handler. Chameleon's components update themselves, so you don't need to hold the setting in React state.
import { CrButton, LoggingLevel, setAppConfiguration } from "@materia-technologies-inc/chameleon-components-react";
export function DiagnosticsButton() {
return (
<CrButton onClick={() => setAppConfiguration({ minScreenLoggingLevel: LoggingLevel.Warning })}>
Show warnings
</CrButton>
);
}
Read it
getAppConfiguration() returns the settings your app has set. It isn't React state, so a component of yours that shows a setting won't re-render when it changes; read it again after you call setAppConfiguration().
import { getAppConfiguration } from "@materia-technologies-inc/chameleon-components-react";
const { locale } = getAppConfiguration();
Set app configuration in Program.cs, where you add Chameleon's services, and change it at run time through IChameleonConfigurationService. Setting names start with a capital, as in ToastTimeout.
Set it
Assign an AppConfiguration in the options of AddChameleonServices(), with only the properties you want to change.
using Chameleon.Blazor;
builder.Services.AddChameleonServices(options =>
{
options.AppConfiguration = new AppConfiguration
{
MinConsoleLoggingLevel = LoggingLevel.Information,
ToastAnchor = Corner.EndEnd,
ToastTimeout = 8000,
};
});
Assign Default.UseDefault to return a setting to Chameleon's default. DeferralFlushDelay and ToastTimeout are double values in milliseconds.
Change it while your app runs
Inject IChameleonConfigurationService and assign a new AppConfiguration to its AppConfiguration property. The assignment replaces every setting, and any you leave out return to their defaults. Copy the current configuration with a with expression and change only what you need.
@inject IChameleonConfigurationService ConfigurationService
<CbButton OnClick="ShowWarnings">Show warnings</CbButton>
@code {
private void ShowWarnings()
{
ConfigurationService.AppConfiguration = ConfigurationService.AppConfiguration with
{
MinScreenLoggingLevel = LoggingLevel.Warning,
};
}
}
The same property returns the settings your app has set: ConfigurationService.AppConfiguration.ToastTimeout.
Settings that need the first render
Your settings reach the browser once the first Chameleon component renders interactively, never during prerendering. By then it's too late for DeferralGap and DeferralFlushDelay, which keep their defaults, and the components in that first render keep the default ShadowRootVisibility. Every other setting applies as soon as it arrives.