Fandry UI

Why Fandry UI exists

The flexibility of modern UI development, with the simplicity of LWC. What Fandry is for, what it trades away, and where to check each claim.

Your UI, your identity

Link to section Your UI, your identity

Salesforce ISVs and teams building Experience Cloud and LWR sites ship products with their own brand. Their users should see that product, not the standard Salesforce interface.

Every Fandry component reads its colors, type, spacing, radius and motion from one token scale. Set the public --fd-* tokens on :root to theme everything, or on one section or element to theme just that part of the page.

your-site.css
/* The whole site */
:root {
  --fd-primary: 24 70% 38%;
  --fd-font-heading: Georgia, serif;
  --fd-radius-md: 0;
}

/* One section of it */
.promo {
  --fd-primary: 160 84% 30%;
}
​

Composition over configuration

Link to section Composition over configuration

Each component ships a sensible default. When you need something different, you compose: replace a slot, restyle a part, extend the class that holds the behavior. A component gets a new prop only for a genuinely binary behavior like disabled, not for every variation someone might want.

Markup in a slot, not a prop
<fandry-input label="Email">
  <span slot="help-text">
    We only use it for <a href="/privacy">order updates</a>.
  </span>
</fandry-input>
​

Every component keeps the same five steps open, from the quickest change to a full rewrite, so you go only as far as you need:

  1. 1

    Tokens

    Set --fd-* on :root, a section or one element to change colors, type, spacing, radius and motion.

  2. 2

    Parts and states

    Restyle one element inside a component with ::part(), including states like checked or disabled.

  3. 3

    Slots and messages

    Replace or add content and text. Every visible string is a slot or a messages entry, so sites can translate it.

  4. 4

    Extend the state class

    Components with real state ship it as a template-less class. Keep the behavior, write your own markup.

  5. 5

    Copy the component

    The source is short, plain LWC. Copy it into your namespace and change anything, keeping the tokens.

A UI you control

Link to section A UI you control

Every component renders in native shadow DOM, on LWR and in a Salesforce org, even one that loads the synthetic-shadow polyfill. Encapsulation keeps your global CSS from breaking a component by accident, and CSS parts give you a deliberate way in.

Parts and states
/* One element inside a component, in one state */
.checkout fandry-switch::part(control checked) {
  background: hsl(160 84% 30%);
}
​

Fandry ships as plain LWC source, not a compiled runtime. Components with real state, like the table, keep it in a template-less class you can extend with your own markup:

orderGrid.ts
// Same sorting, paging and selection, your own template
import FdTableState from 'fandry/tableState';

export default class OrderGrid extends FdTableState {}
​

Tokens and parts are public API: renaming or removing one is a breaking change, so your design system evolves when you decide, not as a side effect of an upgrade.

Less dependence on Salesforce's UI

Link to section Less dependence on Salesforce's UI

Fandry has its own component implementations and its own design system. It doesn't render lightning-* components or depend on SLDS, so a change to Lightning Base Components or their styling doesn't change how your product looks.

Your UI should evolve when your product evolves, not when Salesforce changes its components. That is a claim about base components only: Fandry still runs on LWC, LWR and Lightning Web Security, and follows the platform like any other code.

The simplicity of LWC

Link to section The simplicity of LWC

A Fandry component is a Lightning Web Component. You set @api properties, fill slots and listen for standard input, change, focus and blur events, the same way you already work. There is no second framework, virtual DOM or build pipeline to add, and your own components and lightning-* components sit alongside Fandry's.

Lightning Base Components and Fandry UI

Link to section Lightning Base Components and Fandry UI

They solve different problems. Neither is better in general; pick the one whose goals match yours.

Lightning Base Components

Optimized for:

  • Standard Salesforce UI patterns

  • Consistency with Lightning Experience

  • Enterprise stability, maintained by Salesforce

  • Styling hooks and some slots within the SLDS look

Fandry UI

Optimized for:

  • Custom interfaces with your own product identity

  • Composition: slots, parts and extendable state

  • Theming from one token scale

  • Source you can read, copy and evolve on your schedule

The trade-offs

Link to section The trade-offs
Fewer components

Fandry is a small set of primitives and a few blocks, not the full Lightning Base Components catalog. Some screens will still call for a lightning-* component, and slotting one into a fandry component works.

It does not look like Salesforce

That is the point, and also the cost. If your app should feel like part of Lightning Experience, base components are the better fit.

Opinionated, on purpose

Customization goes through tokens, parts, slots and state classes, not a growing list of props. Some changes mean composing or copying rather than flipping a flag.

Updates are yours to take

On Salesforce, fandry add copies source into your project. Running it again updates the components you have not edited and leaves your changes alone, so you decide when anything changes.

Still a Salesforce platform citizen

Fandry depends on LWC, LWR and Lightning Web Security like any other component. Independence from base components is not independence from the platform.

Not a React replacement

Fandry is a component library. It has no router, state store or rendering model of its own; your application stays plain LWC.

One component, three identities

Link to section One component, three identities

The same markup three times. Only the --fd-* tokens on each wrapper differ.

Default New

Spring collection

Get early access and member pricing.

Email No tokens set. Editorial New

Spring collection

Get early access and member pricing.

Email Serif headings, square corners, warm palette. Midnight New

Spring collection

Get early access and member pricing.

Email Dark surfaces, rounder corners, bright accent.

Get started

Link to section Get started

One npm package and the same components on both platforms. Pick the one you build on.

npm

LWR / LWC OSS

Install one npm package, point your project at it, and use <fandry-*> components. Your bundler ships only the ones you use.

npm install fandryui
npx fandry init
​ Start with LWR → sfdx

Salesforce DX

The platform has no bundler and cannot import npm packages, so the CLI copies components into your project as source you own, with everything they depend on.

npm install --save-dev fandryui
npx fandry init
npx fandry add button
​ Start with Salesforce DX →

Then make it your own with the theming guide, or see more in Examples.