UI Components
resuxjs/ui is Resux's optional Vue UI and motion package. This section is the component catalog; every public component has its own page with its actual props, emitted events, slots, styling hooks, accessibility behavior, runtime cost, examples, and current limitations.
Vue runtime boundary
The components exported by resuxjs/ui are Vue defineComponent components. They belong inside a Vue island or another explicit Vue runtime boundary. They are not zero-hydration Resux template primitives. Use normal Resux templates when you do not need Vue-owned state or event handling.
Before choosing a component
Read Component Anatomy once before working through the catalog. It explains the repeated model behind these pages:
- why
resuxjs/uiis a Vue boundary even when a primitive itself is static, - how props, native attrs, custom events, slots, and
v-modelare implemented, - how to distinguish an accepted string prop from a variant that actually has built-in CSS,
- what
unstyleddoes, - how mount animations and reduced motion work,
- why root/native elements matter for accessibility,
- how to decide between an
Rx*component and normal Resux/native HTML.
A component name is not a promise of design-system-level behavior. The individual page documents the current source. For example, a component named Modal or Dropdown must not be assumed to include focus trapping or complete keyboard navigation unless the implementation actually provides it.
How to read each page
The detailed component pages answer the same practical questions wherever they apply:
- What does it render? Root/native element and structure.
- When should I use it? Including when native Resux HTML is better.
- How do I import it?
Rx*plus matching alias. - What are every prop/default and verified variant?
- Which events are custom vs native/fallthrough listeners?
- Which slots exist?
- Does it keep internal state or support
v-model? - How do built-in classes and
unstyledwork? - Which accessibility behaviors exist and which are application-owned?
- What happens during SSR/browser mount?
- What does it cost if it creates/requires a Vue boundary?
- What are the current limitations and common mistakes?
That standard is intentionally more demanding than a one-line component catalog.
Install and enable
resuxjs/ui ships with the resuxjs package; there is no separate UI dependency.
export default defineResuxConfig({
modules: [
['resuxjs/ui', {
defaultStyles: true,
animations: {
enabled: true,
defaultPreset: 'fade-up'
}
}]
]
})Import components from the package entry point:
import { RxButton, RxInput, RxModal } from 'resuxjs/ui'Every Rx* component has a matching Resux* alias that points to the same component object. For example, RxButton === ResuxButton.
Forms and input
| Component | Use it for | Runtime note |
|---|---|---|
| Button | Native button actions | Vue event handling when listeners are attached |
| Input | Single-line input with v-model | Emits update:modelValue from the native input event |
| Textarea | Multi-line text input | Emits update:modelValue |
| Select | Small custom option picker | Custom keyboard handling; see accessibility limitations |
| DatePicker | Native date selection | Renders <input type="date"> |
| Switch | Boolean on/off state | Button semantics plus role="switch" |
Content and feedback
| Component | Use it for | Notes |
|---|---|---|
| Card | Grouped visual content | Non-interactive <div> container; choose stronger native semantics when appropriate |
| Badge | Status/category labels | Non-interactive inline content; do not rely on color alone |
| Avatar | Identity image/fallback initials | Uses a native <img> when src is provided |
| Alert | Important feedback | Renders role="alert"; optional dismiss event |
| Skeleton | Visual loading placeholder | Default shimmer does not currently suppress itself for reduced motion |
| Divider | Visual separation | No automatic separator ARIA role; built-in vertical style is not implied |
| Kbd | Keyboard key notation | Renders semantic <kbd>; it is not an interactive shortcut system |
Disclosure, navigation, and overlays
| Component | Use it for | Important limitation |
|---|---|---|
| Accordion | Simple local disclosure | open initializes internal state; it is not a controlled v-model API |
| Tabs | Selecting a tab key | Renders tab buttons only; panel rendering is application-owned |
| Popover | Click-toggled floating content | No built-in focus management or outside-click behavior |
| Dropdown | Small action menu | No arrow-key menu navigation/focus management |
| Tooltip | Pointer-hover supplemental text | Hover-only in the current implementation; do not rely on it for required information |
| Modal | Simple overlay content | No built-in focus trap, Escape handling, or dialog ARIA contract |
Motion
| Component/API | Behavior |
|---|---|
| Motion | Runs a configured Web Animations preset on mount |
| Reveal | Runs a preset on mount; despite the name it is not viewport-observed |
| AutoAnimate | Runs a one-time scale-in animation on mount; it does not observe child-list/layout changes |
useAnimate() | Imperative Web Animations helper |
vAnime / vAnimate | IntersectionObserver-based Vue directive |
UI icon primitive
RxIcon is a small UI primitive that renders a text placeholder such as [check]. It is not the full SVG icon system.
For the SVG registry, remote Iconify-compatible loading, caching, and lazy loading, use Icon / ResuxIcon from resuxjs/icons.
Styling model
When defaultStyles is enabled, the UI module injects its built-in primitive CSS into document head output. Components append stable rx-* classes unless unstyled is true.
<RxButton class="my-save-button">Save</RxButton>
<RxButton unstyled class="my-button">Headless styling</RxButton>unstyled removes Resux-generated component classes; attributes and your own class still pass through. For motion primitives, read their pages carefully because unstyled also gates their mount animation behavior.
tokens are stored under public runtime UI configuration, but the current primitive CSS does not automatically translate arbitrary token keys into CSS variables. Treat defineUiTokens() as a typed configuration helper, not as proof that every token changes built-in CSS.
SSR, resumability, and hydration
The key distinction is ownership:
- Resux template primitives such as
ResuxImg,ResuxPicture, andResuxVideoare handled by the Resux renderer and can preserve Resux's resumable/progressive model. resuxjs/uicomponents are Vue components. Their server-renderable markup may appear during SSR, but their Vue state, emitted events, mount hooks, and motion behavior need the Vue runtime boundary that owns them.- Non-interactive UI components such as Card, Badge, Divider, Kbd, Skeleton, and Avatar have little client behavior themselves, but using them through a Vue island still incurs that island's Vue runtime cost.
- Interactive components such as Select, Switch, Popover, Dropdown, Tabs, Accordion, Tooltip, Modal, Input, and Textarea rely on Vue event/state behavior for interaction.
Read Vue Islands, Execution Contexts, Rendering Lifecycle, and Architecture Deep Dive before using a large Vue-owned UI subtree.
Accessibility baseline
The source code is the source of truth, not component names. Some primitives use useful native semantics (button, input, textarea, kbd, role="switch", role="alert"), while several custom overlays/navigation widgets are intentionally small and do not implement the complete WAI-ARIA interaction patterns expected from a production design-system widget.
Each component page calls out the exact current behavior and what the application must add or test. Do not infer keyboard navigation, focus trapping, accessible names, or ARIA state that the implementation does not provide.
Package-level APIs
The UI package also exports:
ResuxUiModuleOptionsdefineUiTokens()AnimationPresetAnimateOptionsisReducedMotion()useAnimate()vAnimevAnimate- the default UI module
See the UI package reference for these APIs.