@weave-framework/ui
v3.5.0
Published
Weave UI — signal-native component library (Material+CDK equivalent) with the Weave design system. Ships SCSS; zero third-party runtime deps.
Readme
@weave-framework/ui
Weave UI — a signal-native component library with the Weave design system, plus a headless behavior layer (CDK). Ships a prebuilt stylesheet and the Sass it was built from; zero third-party runtime deps.
Part of Weave — a fine-grained reactive, signal-native UI framework: no Virtual DOM, zero third-party runtime dependencies.
npm install @weave-framework/uiQuick start
Two steps: register the library's stylesheet as a global entry, then import components per subpath. Full walkthrough: UI → Installation.
1. Styles — the package ships weave-ui.css, prebuilt: the theme's default token values as :root
custom properties plus every component's CSS. One line in weave.config.ts, no Sass:
// weave.config.ts
export default defineConfig({
styles: ['@weave-framework/ui/weave-ui.css'], // global — component stylesheets are scoped, and a
}); // scoped `:root` compiles to a selector that never matchesRetheme from plain CSS — every token is a custom property, so :root { --weave-color-accent: #b25dff; }
in a global stylesheet of your own recolours every component. For theme($overrides) or for shipping only
the components you use, emit the styles yourself from a Sass entry instead (styleLang: 'scss'):
// src/styles/main.scss
@use 'pkg:@weave-framework/ui' as weave;
@include weave.theme(); // the token values — :root custom properties
@include weave.all-styles(); // the component CSS that consumes them2. Components — each is a default export on its own subpath:
import Button from '@weave-framework/ui/button';
import Icon from '@weave-framework/ui/icon';<Button on:click={{ save }}>Save</Button>
<Button variant={{ 'outline' }}>Cancel</Button>
<Button variant={{ 'icon' }} label={{ 'Delete' }}><Icon name={{ 'trash-2' }} /></Button>Components are native-first: <Button> renders one real <button>, so keyboard, focus, and form submission come for free — no wrappers, no re-implemented semantics.
Components
Each has a JS entry at @weave-framework/ui/<name> and its own Sass entry at the same subpath.
| | | |
|---|---|---|
| Buttons & indicators | button · button-toggle · badge · icon · ripple | progress-bar · progress-spinner |
| Form controls | input · form-field · checkbox · radio · slide-toggle | select · autocomplete · chips · slider |
| Date & time | datepicker · date-range-picker · timepicker | |
| Layout & surfaces | card · toolbar · sidenav · expansion · grid-list | list · tabs · stepper |
| Popups & overlays | dialog · bottom-sheet · snackbar · tooltip | menu · menubar · context-menu · popover-edit |
| Data | table · tree · paginator | |
@weave-framework/ui/divider and @weave-framework/ui/overlay are style-only entries (Sass, no JS).
Every icon in the library is a real inline SVG rendered by <Icon> from the icon registry — the built-in Lucide set by default — never a CSS-drawn shape or a Unicode glyph. Pass name to look one up, or svg / src to render your own.
Theming
Tokens are plain CSS custom properties in two tiers — global (--weave-color-accent, --weave-shape-radius) and per-component (--weave-button-background). You re-skin by changing token values, never by overriding component selectors.
@include weave.theme((
color: (accent: #2f9e8f, ink: #101216),
shape: (radius: 8px),
));Because they're real custom properties, you can also override them anywhere in plain CSS — no Sass needed:
.dark-corner { --weave-color-accent: #b25dff; } /* recolours every Weave component inside */Prefer leaner CSS? Skip all-styles() and pull only what you use: @use 'pkg:@weave-framework/ui/button';
The CDK
@weave-framework/ui/cdk is the headless layer the styled components are built on — behavior and state, zero styling. Use it directly when you're building your own components:
overlays and portals · connected positioning · scroll strategies · focus trap and focus monitor · live announcer · typeahead/list key managers · resize and intersection observers as signals · breakpoint observer · clipboard · selection model · data sources · virtual scroll · infinite-scroll sentinel · input masking · drag & drop · date adapters.
Everything is in-house and zero-dep, RTL-aware, and honours prefers-reduced-motion.
Testing your components
@weave-framework/ui/testing drives a component the way a person does — it opens the overlay, moves the
focus, presses the key — so a test asserts what the user gets rather than what the implementation did.
import { mount, click, press, overlay, focused, tick } from '@weave-framework/ui/testing';
const { el, dispose } = mount(Select, { options });
click(el.querySelector('.weave-select__field')!);
await tick();
// A dialog, menu, tooltip or picker renders OUTSIDE the component — `overlay()` is where the
// library puts it, which is the one thing a consumer cannot work out on their own.
press(overlay('.weave-select__panel')!, 'ArrowDown');
console.log(focused());
dispose();📚 Guides + per-component API: Component docs · Styling & theming · Live examples
License
MIT
