Components Guide
Defining a Component
import { defineComponent, h } from "nexa-framework";
const MyComponent = defineComponent({
setup(props, { emit, slots }) {
const count = signal(0);
return { count };
},
render(ctx) {
return h("div", null, [String(ctx.count.value)]);
},
});Props and Emit
defineComponent({
setup(props, { emit }) {
return {
submit: () => emit("submit", props.value),
};
},
render(ctx) {
return h("button", { onClick: ctx.submit }, ["Submit"]);
},
});Slots
<!-- Child component -->
<template>
<div class="card">
<header>
<slot name="header" />
</header>
<main>
<slot />
</main>
</div>
</template><!-- Parent component -->
<template>
<Card>
<template #header>
<h1>Title</h1>
</template>
<p>Default slot content</p>
</Card>
</template>Scoped Slots
<!-- Child passes data to slot -->
<template>
<ul>
<li v-for="item in items">
<slot :item="item" :index="index" />
</li>
</ul>
</template>Lifecycle Hooks
import { onMounted, onBeforeUnmount, onUpdated } from 'nexa-framework'
setup() {
onMounted(() => console.log('mounted'))
onBeforeUnmount(() => console.log('cleanup'))
onUpdated(() => console.log('re-rendered'))
}v-show— togglesdisplayvia signalv-model— two-way binding for inputsv-if— conditional renderingv-for— list rendering
Event Modifiers
Nexa supports event modifiers to handle common event patterns efficiently:
.prevent— callsevent.preventDefault().stop— callsevent.stopPropagation().self— only triggers if the event was dispatched from the element itself (not a child)
<button @click.prevent="submit">Submit</button>
<div @click.self="closeModal">Click outside to close</div>Component Resolution
Nexa components should be named using PascalCase in templates to distinguish them from standard HTML elements. The compiler automatically resolves these names from the component's setup context.
<template>
<MyCustomButton>Click Me</MyCustomButton>
</template>
<script setup>
import MyCustomButton from "./MyCustomButton.nexa";
</script>Transitions
Nexa provides enter/leave transitions via _enter and _leave props on any VNode:
import { h, mount } from "nexa-framework";
const vnode = h(
"div",
{
_enter: "fade", // apply 'fade-enter-*' classes on mount
_leave: "fade", // apply 'fade-leave-*' classes on unmount
},
["Hello"],
);Enter Animation
When a VNode with _enter is mounted:
{name}-enter-from+{name}-enter-activeclasses are applied immediately- On the next animation frame,
-enter-fromis removed and-enter-tois added - On
transitionend/animationend(or 300ms timeout), all enter classes are removed
Leave Animation
When a VNode with _leave is removed:
{name}-leave-from+{name}-leave-activeclasses are applied- DOM removal is deferred until the animation completes
- On the next frame,
-leave-fromis removed and-leave-tois added - On
transitionend/animationend(or 300ms timeout), the element is removed
CSS Example
.fade-enter-active,
.fade-leave-active {
transition: opacity 0.3s ease;
}
.fade-enter-from,
.fade-leave-to {
opacity: 0;
}Default Prefix
Pass true instead of a name to use the v- prefix:
h("div", { _enter: true }, ["content"]);
// uses v-enter-from, v-enter-active, etc.Nexa UI Library
Nexa comes with an optional premium component library called nexa-ui-kit. These components are designed with a modern, high-quality aesthetic (glassmorphism, premium shadows, and smooth transitions).
For the complete and detailed API documentation of all 29 components (including props, events, slots, and interactive examples), please refer to the:
The package includes:
- Forms & Inputs:
NInput,NPassword,NAutocomplete,NSelect,NMultiSelect,NInputNumber,NCheckbox,NRadio,NSwitch,NChips,NDatepicker - Buttons & Layout:
NButton,NCard,NModal,NBottomSheet,NTabs - Data Display:
NDataTable,NPaginator,NTreeMenu,NAvatar,NTag,NBadge - Feedback & Loading:
NAlert,NToastContainer(withuseToast),NProgressBar,NSkeleton,NTooltip - Form Container & Validation:
NForm,NFormField
Common Pitfalls (Avoid Missing Renders)
- Signals are explicit: use
.valuein conditions and comparisons.- Good:
:disabled="loading.value",v-if="isOpen.value" - Bad:
:disabled="loading",v-if="isOpen"
- Good:
- Some components accept dynamic
:classvalues; prefer strings/objects/arrays consistently. <Teleport>only renders if the target exists; ifto="#some-target"does not match any element, the content will not mount.
Usage Example
<script setup>
import { NButton, NCard, useToast } from "nexa-ui-kit";
const { success } = useToast();
</script>
<template>
<NCard title="Nexa UI">
<p>Premium components for your next project.</p>
<NButton variant="primary" @click="success('Hello!')">Click Me</NButton>
</NCard>
</template>