Your UI, your identity
Link to section Your UI, your identitySalesforce 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.
/* 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 configurationEach 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.
<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
Tokens
Set
--fd-*on:root, a section or one element to change colors, type, spacing, radius and motion. - 2
Parts and states
Restyle one element inside a component with
::part(), including states likecheckedordisabled. - 3
Slots and messages
Replace or add content and text. Every visible string is a slot or a
messagesentry, so sites can translate it. - 4
Extend the state class
Components with real state ship it as a template-less class. Keep the behavior, write your own markup.
- 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 controlEvery 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 UIFandry 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 LWCA 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 UIThey 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 addcopies 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.