Ply works without configuration. Out of the box, components use Tailwind blue, English labels, and left-to-right layout. Change only what your app needs.
Set --ply-brand in any stylesheet. Buttons, focus rings, and blue-* utilities follow it, and it works whatever order your stylesheets load in.
:root {
--ply-brand: #7c3aed;
--ply-brand-hover: #6d28d9;
--ply-brand-active: #5b21b6;
} Other tokens, such as --ply-radius, are defined in ply-ui.css, so override them in your global stylesheet after its import. To pick a palette with a live preview, use Theme Studio.
Ply's built-in strings default to English: empty states, pagination, labels such as Close and Cancel, and screen reader text. Override them once in app.config.ts. This covers Ply's built-in strings only, not your app's own copy.
import { provideBaseUiI18n } from './components/i18n/i18n';
export const appConfig: ApplicationConfig = {
providers: [
provideBaseUiI18n({
close: 'Fermer',
noResults: 'Aucun résultat',
rangeOf: (start, end, total) => `${start}–${end} sur ${total}`,
}),
],
}; Inputs on a single instance, such as emptyMessage, still win. Install with npx ply-ui-cli add i18n. The data table, combobox, dialog, and paginator copy it for you.
Components follow the nearest dir. Set it on <html> for the whole app, or import PlyDirDirective and set plyDir on one section. plyDir="auto" picks the direction from the document language, so Arabic, Hebrew, Persian, and Urdu resolve to right-to-left.
<html lang="ar" dir="rtl"> <section plyDir="ltr">…</section> <section plyDir="auto">…</section> </html>
To switch at runtime, for example from a language picker:
import { DirectionRegistry } from './components/direction/direction.service';
const direction = inject(DirectionRegistry);
direction.setDocumentDirection('rtl'); In your own markup, use logical utilities such as ms-*, pe-*, start-*, text-start, and border-s. Ply components already do:
position="left" stays left.top-end. Scroll-to-top and speed dial default to bottom-end.left slot is the edge where reading starts.left or right in their name mirror. Set mirror="off" to keep one fixed. Install with npx ply-ui-cli add direction. Components that follow direction copy it for you.
Icons load from assets/icons.svg and assets/icons-filled.svg. If your sprites live somewhere else, or you want a different default size, set them once in app.config.ts:
import { provideBaseUI } from './components/config/config';
export const appConfig: ApplicationConfig = {
providers: [
provideBaseUI({
iconPath: 'assets/icons.svg',
filledIconPath: 'assets/icons-filled.svg',
defaultSize: 20,
}),
],
};[path], [filledPath], and [size] on a single icon still win. Install with npx ply-ui-cli add config. The icon component copies it for you.
data-table, custom-select, and dialog ship Angular CDK component harnesses next to their source, so add copies them too. Dialogs open in an overlay on document.body, so load them with documentRootLoader:
import { TestbedHarnessEnvironment } from '@angular/cdk/testing/testbed';
import { DataTableHarness } from './components/data-table/data-table.harness';
import { DialogHarness } from './components/dialog/dialog.harness';
const loader = TestbedHarnessEnvironment.loader(fixture);
const table = await loader.getHarness(DataTableHarness);
const dialogs = TestbedHarnessEnvironment.documentRootLoader(fixture);
const dialog = await dialogs.getHarness(DialogHarness);