Skip to main content

Live gallery

Component showcase

Every component, server-rendered and interactive. Each demo is a real render*() call from @basenative/components — no mockups, no screenshots, no virtual DOM.

No sections match your filter.

Buttons

Real button elements. Variants, disabled state, and a hydrated counter to prove the click handler is native.

Variants
View source
renderButton('Primary',     { variant: 'primary' })
renderButton('Secondary',   { variant: 'secondary' })
renderButton('Destructive', { variant: 'destructive' })
renderButton('Ghost',       { variant: 'ghost' })
renderButton('Disabled',    { variant: 'primary', disabled: true })
Live counter (signal + effect)
0
View source
const count = signal(0);
effect(() => out.textContent = count());
inc.onclick   = () => count.set(c => c + 1);
dec.onclick   = () => count.set(c => c - 1);
reset.onclick = () => count.set(0);

Badges & avatars

Compact status pills and an initials-fallback avatar that reads from the name attribute. Both are built on a single span element.

Badge variants
Default Primary Success Warning Error
View source
renderBadge('Active',  { variant: 'success' })
renderBadge('Warning', { variant: 'warning' })
Avatar sizes
AJ BS CD DL
View source
renderAvatar({ name: 'Alice Johnson', size: 'lg' })

Form controls

Native form fields with label / help / error wiring, plus a live-validating input that toggles aria-invalid based on signal state.

Inputs (default + error)
We will not share your email.
Must be at least 3 characters
View source
renderInput({ name: 'email',    label: 'Email',    type: 'email', helpText: '...' })
renderInput({ name: 'username', label: 'Username', value: 'ab',   error: '...' })
Live validation
View source
const value = signal('');
const valid = computed(() => value().length >= 3);
effect(() => input.setAttribute('aria-invalid', String(!valid())));
Textarea, select, combobox, multiselect
JavaScriptCSS
View source
renderTextarea({ name: 'bio',       rows: 3 })
renderSelect({   name: 'role',      items: [...] })
renderCombobox({ name: 'framework', items: [...] })
renderMultiselect({ name: 'tags',   items: [...], selected: [...] })
Checkbox, radio group, toggle
Plan
View source
renderCheckbox({   name: 'terms',         label: '...' })
renderRadioGroup({ name: 'plan',          items: [...], selected: 'Pro' })
renderToggle({     name: 'notifications', checked: true })

Feedback

Inline alerts, native progress, CSS spinners, skeletons, and an animated progress bar that ticks via setInterval bound to a signal.

Alerts
This is an informational message.
Operation completed successfully.
Proceed with caution.
Something went wrong.
View source
renderAlert('Saved.',   { variant: 'success' })
renderAlert('Heads up.',{ variant: 'warning' })
renderAlert('Failed.',  { variant: 'error', dismissible: true })
Live progress (signal-driven)
0%
View source
const v = signal(0);
effect(() => bar.value = v());
setInterval(() => v.set(p => (p + 5) % 105), 200);
Spinners
View source
renderSpinner({ size: 'lg', label: 'Loading' })
Skeleton
View source
renderSkeleton({ width: '100%', height: '1rem', count: 3 })

Cards & layout

Article-shaped cards, accordions built on the native details element, and ARIA tablists with arrow-key navigation.

Card
Card Title

Card body content with descriptive text about the feature or item being presented.

Updated 2 hours ago
View source
renderCard({ header, body, footer })
Accordion (native )
What is BaseNative?
A signal-based runtime over native HTML — ~120 lines for the core primitives.
How does SSR work?
The server renderer evaluates @if, @for, @switch directives at request time and emits clean HTML with hydration markers.
What about hydration?
hydrate() walks the DOM, binds reactive expressions, and attaches event handlers without reconstructing the tree.
View source
renderAccordion({ items: [{ title, content }, ...] })
Tabs (arrow-key navigation)

BaseNative brings Angular-inspired control flow to native template elements.

View source
renderTabs({ tabs: [{ id, label, content }, ...] })

Navigation

Wayfinding primitives wrapped in a semantic nav element with proper aria-label and aria-current wiring.

Breadcrumb
View source
renderBreadcrumb({ items: [{ label, href }, ...] })
Pagination
View source
renderPagination({ currentPage: 3, totalPages: 10, baseUrl: '/items' })

Data display

From a basic table to a sortable data grid, an aria-tree, and a windowed virtual list of 200 rows.

Table
Team members
NameRoleStatus
Alice JohnsonAdminActive
Bob SmithEditorActive
Carol DavisViewerInactive
View source
renderTable({ columns: [...], rows: [...], caption: 'Team members' })
Data grid (sortable + selectable)
Project tasks
Task ↑AssigneePriorityStatus
Design token systemAliceHighDone
Signal reactivityBobHighDone
Server renderingCarolMediumActive
Client hydrationDanMediumPending
Component libraryAliceLowActive
Showing 1–5 of 5
View source
renderDataGrid({ columns, rows, sortBy: 'task', sortDir: 'asc', selectable: true })
Tree
  • 📁src
    • 📁runtime
      • 📄signals.js
      • 📄hydrate.js
      • 📄bind.js
View source
renderTree({ items: [...], expanded: new Set(['1', '1-1']), selected: '1-1-1' })
Virtual list (200 rows, windowed)
Row 1 — generated server-side, scrolled client-side
Row 2 — generated server-side, scrolled client-side
Row 3 — generated server-side, scrolled client-side
Row 4 — generated server-side, scrolled client-side
Row 5 — generated server-side, scrolled client-side
Row 6 — generated server-side, scrolled client-side
Row 7 — generated server-side, scrolled client-side
Row 8 — generated server-side, scrolled client-side
Row 9 — generated server-side, scrolled client-side
Row 10 — generated server-side, scrolled client-side
Row 11 — generated server-side, scrolled client-side
Row 12 — generated server-side, scrolled client-side
Row 13 — generated server-side, scrolled client-side
Row 14 — generated server-side, scrolled client-side
Row 15 — generated server-side, scrolled client-side
Row 16 — generated server-side, scrolled client-side
View source
renderVirtualList({ items: [...], itemHeight: 44, containerHeight: 240 })

Overlays

Native dialog, drawer that slides in, popover-anchored menus and tooltips, and a Cmd+K command palette.

Dialog (native showModal)

Confirm action

Are you sure you want to proceed? This cannot be undone.

View source
const d = renderDialog({ title, content, footer, id: 'my-dialog' });
document.getElementById('my-dialog').showModal();
Drawer (slide-in)
View source
renderDrawer({ title, content, position: 'right' })
Dropdown menu (Popover API)
View source
renderDropdownMenu({ trigger: 'Actions', items: [{ label, action, icon }, ...] })
Tooltip
This is a tooltip with helpful context. Triggers on hover or focus.
View source
renderTooltip({ trigger, content, position: 'top' })
Command palette
Ctrl + K
Navigation
Actions
↑↓ Navigate ↵ Select Esc Close
View source
renderCommandPalette({ commands: [{ label, action, group, shortcut }, ...] })
Toasts (live region)
View source
import { showToast } from '@basenative/components';
showToast({ message: 'Saved.', variant: 'success' });

Block components

Higher-order layouts: a layout grid, a week calendar, and a pipeline board — all server-rendered, all on native primitives.

Layout grid (6-col)
Header
Sidebar
Main content
Aside
Footer
View source
renderLayoutGrid({ columns: 6, cells: [{ id, label, colSpan, rowSpan }, ...] })
Week calendar
Sun 4/26
Mon 4/27
Tue 4/28
Wed 4/29
Thu 4/30
Fri 5/1
Sat 5/2
8am
9am
10am
11am
12pm
1pm
2pm
3pm
4pm
5pm
Sprint review Alice 9:00 AM – 10:30 AM
Customer call: Greenput Bob 1:00 PM – 2:00 PM
Release cut Carol 4:00 PM – 5:00 PM
Office hours Dan 11:00 AM – 12:00 PM
View source
renderCalendar({ startDate, events: [...], hours: { start: 8, end: 18 } })
Pipeline board
Todo
Wire showcase hydration
web
Audit page navigation
web
In progress
Render every package
docs
Cards for all 30+ @basenative/* packages.
Done
Fix Open dialog handler
overlay
Tooltip hover
overlay
View source
renderPipeline({ columns: [...], cards: [{ id, columnId, title, ... }, ...] })

Live runtime

Pure-runtime demos that prove signals + effects work without virtual DOM, without rebuilds, without classes.

Live clock (signal + setInterval)

Updates every second. The <time> element is server-rendered with a placeholder; hydration takes over on the client.

View source
const time = signal(new Date());
effect(() => el.textContent = time().toLocaleTimeString());
setInterval(() => time.set(new Date()), 1000);
Theme picker (CSS custom property swap)
Live preview
View source
btn.onclick = (e) => {
  document.documentElement.style
    .setProperty('--accent', e.target.dataset.bnAccent);
};
Computed signals (counter → doubled / parity)
Value
0
Doubled
0
Parity
even
View source
const n       = signal(0);
const doubled = computed(() => n() * 2);
const parity  = computed(() => n() % 2 === 0 ? 'even' : 'odd');
effect(() => { value.textContent = n();
               doubledEl.textContent = doubled();
               parityEl.textContent = parity(); });