Installation
Wisty UI is a set of React components in Salesforce's Lightning look, built on shadcn/ui. shadcn/ui isn't a package from npm. Its CLI copies each component's source into your project, where it becomes your code: you can read and change it, and it changes only when you add it again. Wisty UI is a registry for that CLI, the address it downloads the components from.
Any React project that uses shadcn/ui is ready for Wisty UI, including an app generated from one of Salesforce's React templates for Multi-Framework apps (notes at the end of this page). To start a project without one, follow shadcn's installation guide, then come back here. Installing takes three commands.
Add the registry
Add Wisty UI to the registries in your project's components.json:
{
"registries": {
"@wisty": "https://ui.wisty.ai/r/{style}/{name}.json"
}
}The CLI fills in {style} from your project, so a Radix project gets Radix files and a Base UI project gets Base UI files.
Add the theme
Do this once per project, before your first component. Until you do, components keep shadcn's default look: a Wisty button renders black instead of Cosmos blue.
npx shadcn@latest add @wisty/cosmosIt writes the theme into the stylesheet components.json names under tailwind.css, replacing the values in its :root and .dark rules. Your fonts stay as they are. If the step stops with a "no such file" error, that path in components.json is wrong. Correct it and run the step again. Components never touch the stylesheet, so adding the theme later only changes what you see in between.
Cosmos is Salesforce's current look. @wisty/lightning-blue and @wisty/neutral install the same way, and each theme replaces the one before it. Theming compares them.
Add a component
npx shadcn@latest add @wisty/buttonThe file lands where shadcn's would, like components/ui/button.tsx, with the same exports, props and variant names, so code written against shadcn's button keeps working. Components shadcn lacks, like the lookup, go in components/wisty/.
The theme by hand
Every install also copies the theme as files, to styles/wisty/ (src/styles/wisty/ in a project with src/). Import them instead of running the theme step when you can't change components.json, or when one page needs more than one theme (see Theming). In the stylesheet that imports Tailwind, add tokens.css and one theme file after the Tailwind import, with paths relative to that stylesheet. Then remove the stylesheet's own :root and .dark rules: they hold shadcn's default theme and would win over the import. In a Vite app's src/index.css:
@import "tailwindcss";
@import "./styles/wisty/tokens.css";
@import "./styles/wisty/cosmos.css";Another theme's file comes from npx shadcn@latest add @wisty/neutral-css or @wisty/lightning-blue-css. Import it in place of cosmos.css and set data-theme on <html>.
Salesforce's React templates
The reactinternalapp, reactexternalapp and reactbasic templates ship shadcn/ui on Radix, so the steps above apply. To create an app from one, see Generate an App from a Template. Trailhead's Multi-Framework recipes app is built on the internal template and works the same way.
- Run the commands from the app's folder,
force-app/main/default/uiBundles/<app>, where itscomponents.jsonis. - The template's
components.jsonnames its stylesheetstyles/global.css, but the file issrc/styles/global.css. Components install anyway. The theme step fails until you changetailwind.csstosrc/styles/global.css. To leave the template as it is, import the theme by hand instead: insrc/styles/global.cssthe lines are@import "./wisty/tokens.css";and@import "./wisty/cosmos.css";. - The template already has 23 shadcn components. Adding Wisty's version replaces the file with the same exports, including sonner's
toast, so you can swap them one at a time.