Components
How a Vuesax component is built, what props it accepts, and the conventions every one of them follows.
A component is one native Web Component in a single file:
vs-button.js ← the custom element — copy this
It defines a standard custom element (customElements.define('vs-button', …))
with zero dependencies, so it runs unchanged in React, Svelte, Vue, Angular,
Solid or a plain HTML page.
Some components reuse another tag: vs-notification pulls in a toast child,
vs-file-tree pulls in its node element. Those come as sibling vs-*.js files
imported by a relative path — the code panel lists everything, and the copy
bundles them together. Nothing is hidden.
The shared prop language
Almost every component speaks the same four props, so switching between them never means relearning an API.
| Prop | Values | Notes |
|---|---|---|
size | sm · md · lg | Reads the control scale — see Theming |
variant | primary · secondary · ghost | Visual weight |
tone | default · danger · warn · success | Semantic color |
radius | none · subtle · rounded · pill · squircle | Corner shape |
Plus two that show up wherever they make sense:
disabled— non-interactive, effects off.glow— the proximity light on the border.trueby default; setfalsein dense UI.
<vs-button label="Delete" variant="secondary" tone="danger" size="sm" radius="pill"></vs-button>
Defaults come from the control bar
The controls you see on a component’s page are its real props, and their starting values are its real defaults. What you tune in the browser is exactly what the prop does in your app — there is no separate “demo config”.
Effects that are already wired
Two behaviors are baked into most interactive components:
Proximity glow — the border lights up as the cursor approaches, before any hover. It is driven by a single shared pointer engine that writes CSS variables directly and skips offscreen elements — no re-render, no per-element listeners.
Press ripple + tilt — a droplet ripple from the exact press point, with a slight 3D tilt toward the cursor. Both are disabled automatically under reduced motion.
Both ship inlined inside the component’s own file — there is no effects.css to
add. They just work the moment the element is on the page.
Slots
Where a component renders content you might want to replace, it exposes a slot with a sensible fallback:
<vs-button>
<span class="icon"><svg><!-- your icon --></svg></span>
Save
</vs-button>
Slots are the native <slot> mechanism, so they work in any framework. The
label attribute is the shortcut; the default slot is the escape hatch.
Values: properties and events
Anything with a value exposes a value property and fires input / change
events — the standard form-control contract. Because it is a native element,
your framework’s two-way binding maps straight onto it with no adapter:
<!-- vanilla -->
<vs-input type="email" label="Email"></vs-input>
<!-- Vue --> <vs-input v-model="email" label="Email" />
<!-- Svelte --> <vs-input bind:value={email} label="Email" />
<!-- React --> <vs-input value={email} onInput={e => setEmail(e.target.value)} label="Email" />
Pass object or array inputs (a select’s options, a tree’s nodes) as DOM
properties rather than attributes: el.options = [...].
Accessibility
Components ship with roles, aria-* state and keyboard handling — arrow keys
in menus and tabs, Esc to dismiss overlays, focus returned to the trigger on
close, visible focus rings that survive theming. Keep those attributes when you
edit the copy; they are not decoration.
Variants and families
Many components have siblings: VsDropdown, VsDropdownBlur,
VsDropdownFold, VsDropdownGlow… Same skeleton and same props, one different
motion or surface treatment. In the catalog they are grouped under the base
name in the left rail. Pick the one whose feel you want; they are
interchangeable in markup.
Editing your copy
It is your file now. Rename it, strip the props you don’t use, delete the ripple, change the markup — nothing phones home and nothing will overwrite it. The two things worth keeping:
- The token fallbacks (
var(--x, 12px)) — that pattern is what lets the component survive in a project without tokens. - The reduced-motion guards — see Effects & motion.