Windows-GPU-UNLOCK
RTX3090 UEFI 포트, 한국어 무리셋 윈도우 부팅 가이드, 검증된 소스와 벤치마크 제공
Modern alternative for SLDS + LWC
저장소 README에서 가져옴
README 전체를 불러오는 중입니다. 아래는 저장된 발췌입니다.
Why Should React Have All the Fun?
Fandry UI is an opinionated, extensible UI foundation for Lightning Web Components, built from scratch with native LWC. This repo is both the component library itself and its own marketing/docs site, built entirely out of the library's own primitives.
• Native LWC primitives for behavior & accessibility
• Strict boundaries to keep the system sane as it grows
• Extensibility over completeness as a core principle
This is infrastructure, not a component zoo — the docs site around it exists to prove that out, not to be the point.README 전문 보기 ↗The flexibility of modern UI development. The simplicity of LWC.
Fandry UI is a modern, composable UI component library for Salesforce LWC, built from scratch with native LWC. It gives developers and ISVs the freedom to build distinctive, customizable experiences, for Experience Cloud, LWR sites and their own products, without adding another UI framework. This repo is both the component library itself and its own marketing/docs site, built entirely out of the library's own primitives.
This is infrastructure, not a component zoo — the docs site around it exists to prove that out, not to be the point.
Live site: fandryui.forcetrails.com
fandry-*) across Layout, Typography, Forms, Feedback, and Overlays & Datastatic shadowSupportMode = 'native'), so it follows the web standard, behaves the same on LWR and in an org, and can be restyled from outside with ::part(). Lightning base components were built on Salesforce's synthetic-shadow polyfill and are only gradually moving to native shadow; fandry starts there.Why it exists, and what it trades away: /why-fandry.
The primitives themselves are deliberately small and un-flashy — see src/core/CORE_BOUNDARIES.md. The marketing site is where flashy is allowed, since its whole job is showing what the primitives can compose into.
src/
├── assets/ # Static assets, global styles
├── layouts/ # LWR's HTML shell (fonts, meta)
├── core/
│ └── fandry/ # Primitives (native LWC, TypeScript) -- the library itself
│ ├── base/ # Shared base class + design tokens (tokens.css)
│ ├── button/, card/, table/, ... # One folder per fandry-* primitive
├── blocks/
│ └── fandry/ # Blocks: installable patterns built only from primitives
│ ├── dataTable/, dataTableState/ # search, filters, inline edit, save hooks, ...
│ ├── form/, formState/, formField/ # fields, validation, read/edit mode, save hook
│ └── mediaGallery/, mediaGalleryState/, mediaGrid/, mediaViewer/, mediaViewerState/, ... # grid + full-screen viewer
└── modules/
└── fandryui/ # The site itself: real composites and pages
├── home/, heroSection/, featureGrid/, dashboardExample/, ...
├── examples/, exampleGallery/ # /examples -- 10 interactive patterns
├── componentsIndex/, componentDoc/ # /components -- per-primitive docs
├── blocksIndex/, blockDataTable/, blockForm/, blockMediaGallery/ # /blocks -- a working page per block
└── componentsData/ # Single source of truth for the docs nav/props/code
└── fandryuidemos/ # Docs-only illustration components (one demoX per
# primitive, rendered live inside componentDoc) --
# kept in their own namespace so they're never
# mistaken for real site chrome
Key rule: Primitives stay small. If something feels like an app feature, it does not belong in src/core/fandry/.
20.16.0 via Volta)From repo root:
npm install
Start the LWR development server:
npm run dev
Open http://localhost:3000 in your browser. You should see the marketing home page, with /examples (10 interactive patterns) and /components (live docs for all 30 primitives) as the other two routes.
| Command | What it does |
|---|---|
npm run dev | Start the LWR dev server (hot-reloading) |
npm run build | Static-site-generate a production build into site/ |
npm start | Serve a build already in site/ |
npm test / npm run test:watch | Run the Jest suite (@lwc/jest-preset) |
npm run typecheck | tsc --noEmit |
npm run build:npm | Generate the publishable fandryui package (both platforms, CLI, registry) into packages/ui/dist |
npm run verify:sfdx | Exercise the fandry CLI (init/add) against throwaway Salesforce DX and LWR projects |
npm run example:sfdx | Install the demo's components into examples/salesforce with the CLI |
npm run verify:npm | Pack it, install the tarball into a separate LWR app, production-build that app, and check the module graph |
npm run clean | Remove __lwr_cache__ and site/ |
npm run deploy | Build, then publish site/ to GitHub Pages |
One source, one package (fandryui), two platforms. Nothing is hand-maintained twice: npm run build:npm derives everything from src/core/fandry, src/salesforce/fandry and src/blocks/fandry, and the only difference is the namespace each platform uses.
| LWR / LWC OSS | Salesforce platform | |
|---|---|---|
| Get it | npm i fandryui, then npx fandry init | npx fandry init, then npx fandry add table lookup |
| Why | a bundler resolves the graph and ships only what a page uses | no bundler and no npm: components are copied in as source, with their dependencies |
| Namespace | custom fandry (a package can bring its own) | default c (on-platform code has no other) |
| Tag | <fandry-button> | <c-fandry-button> |
| Import | import Base from 'fandry/base' | import Base from 'c/fandryBase' |
| In the package | modules/fandry/button/button.js | sfdx/lwc/fandryButton/ (flat), .js-meta.xml written by fandry add |
registry.json (generated from what each bundle really imports and renders) is the dependency graph the CLI uses. @tanstack/table-core can't be imported on-platform, so the Salesforce flavor bundles it, unmodified, as fandryTableCore. Step-by-step guides live on the docs site under Get started (/getting-started, /getting-started/lwr-oss, /getting-started/salesforce), with theming at /getting-started/theming; consumer setup and limitations are also in packages/ui/README.md. A worked Salesforce DX project: examples/salesforce. Publishing runs from .github/workflows/npm-workflow.yml when a GitHub Release is published (npm Trusted Publishing, no token).
Use LWC for what LWC is good at. Use HTML and CSS for what HTML and CSS are
good at. LWC earns its keep on behavior, state, and accessibility; layout is
already a solved CSS problem, and wrapping it in a component would trade a
tool people already know for a black-boxed, rigid one they'd have to learn.
Fandry UI components should not own application layout. Containers, grids,
and stacks are CSS problems CSS already solves well, so instead of
fandry-container, fandry-grid, or fandry-stack components, Fandry
documents these as plain CSS classes/patterns (built on the same design
tokens as every primitive) in src/assets/styles/global.css:
<div class="fandry-container">
<fandry-heading level="1">Orders</fandry-heading>
<div class="fandry-grid">
<fandry-card>...</fandry-card>
<fandry-card>...</fandry-card>
<fandry-card>...</fandry-card>
</div>
</div>
.fandry-container — centers content, caps it at the site's standard
72rem max-width, and applies responsive inline padding via
--fd-space-6..fandry-grid — a responsive display: grid (repeat(auto-fit, minmax(280px, 1fr))) for cards, dashboard metrics, and similar content
blocks, with no breakpoints to configure.display: flex; flex-direction: column; gap: var(--fd-space-4); on any wrapper.See src/core/CORE_BOUNDARIES.md for why these are CSS patterns, not
components.
Fandry's motion is CSS-first, small, and lives inside each component. There
is no animation library, no <fandry-motion>/<fandry-transition> wrapper,
and no animation/duration/easing props: the transient primitives
(fandry-popover, fandry-menu inside it, fandry-dialog, fandry-tooltip,
fandry-toast, fandry-loading-overlay) already know how to enter and exit, so this is all a
consumer writes:
<fandry-dialog open={isOpen} label="Delete item" ontoggle={handleToggle}>...</fandry-dialog>
src/core/fandry/base/tokens.css): --fd-duration-fast (120ms),
--fd-duration-normal (200ms), --fd-duration-slow (320ms),
--fd-ease-standard, --fd-ease-emphasized -- set on any ancestor to change
them, like every other token (components read them as --_fd-*). Components enter with
normal and exit with fast.src/core/fandry/base/motion.css): internal @keyframes for
fade, fade-up, fade-scale, and slide (each with an -in/-out pair). They
animate only opacity and transforms. A component applies one to its own
panel, inside its own shadow tree — there's nothing global to select, and
internal markup stays an implementation detail.inert), until its exit animation has
finished, then unmounts. That's the whole lifecycle (entering → open →
exiting → removed) — CSS does the animating, and fandry/motion's
exitFinished() (a few lines over the native Web Animations API's
getAnimations()) is what tells the component when it's safe to remove the
panel. It resolves right away when nothing is animating, so a panel can
never get stuck in the DOM. Focus and scroll-lock are handed back at the
moment of closing, never after the exit.prefers-reduced-motion: reduce the duration
tokens become 0ms. Every state change and lifecycle step still happens,
instantly; consumers don't opt in. Looping loading indicators (spinner,
skeleton, indeterminate progress) keep running — they signal "still
working", not a transition.Live examples: the popover, menu, dialog, tooltip, and toast pages under
/components.
If a change feels exciting, it probably doesn't belong in src/core/fandry/.
Read these first:
They exist to protect the architecture, not to slow you down.
That's intentional.
MIT License - see the LICENSE file for details.