Chapter 13 — Core Components

Built-in nc- tags are batteries for Deskflow polish. Your app components (task-card, …) stay first-class; nc- fill in buttons, overlays, and feedback so you are not reinventing them.

Live catalog: nativecorejs.com/components (or /components on a local showcase). Source of truth in an app:

  • src/components/core/nc-*.js|ts
  • src/components/frameworkRegistry.*

How to learn any nc-* (2 minutes)

  1. Open the file for that tag
  2. Read observedAttributes / attributeOptions
  3. Search for this.emit( — those are the public events
  4. Prefer attributes + events over poking internal DOM

nc-button is special: use the native click event (no nc-button-click).


Recipe 1 — Primary actions with nc-button

<nc-button ref="addBtn" variant="primary">Add task</nc-button>
<nc-button ref="cancelBtn" variant="ghost">Cancel</nc-button>
this.on(this.addBtn, 'click', () => this.addTask());

Useful attributes: variant, size, disabled, loading.


Recipe 2 — Toast feedback with nc-snackbar

In the view (once per page is enough):

<nc-snackbar ref="snackEl"></nc-snackbar>

Prefer the static helper (finds the first <nc-snackbar> in the document):

import { NcSnackbar } from '@components/core/nc-snackbar.js';

this.on(this.addBtn, 'click', () => {
    this.addTask();
    NcSnackbar.show({ message: 'Task added', variant: 'success' });
});

Put one <nc-snackbar></nc-snackbar> in index.html (or the page) so NcSnackbar.show has a host element.


Recipe 3 — Open count badge

<h1>
    Tasks
    <nc-badge ref="badgeEl">0</nc-badge>
</h1>
this.openCount = this.compute(
    () => this.tasks.value.filter((t) => !t.done).length
);
this.bind(this.openCount, this.badgeEl);

Recipe 4 — Confirm delete with nc-modal

<nc-modal ref="confirmModal">
    <span slot="header">Delete task?</span>
    <p>This cannot be undone.</p>
    <div slot="footer">
        <nc-button ref="cancelDeleteBtn" variant="ghost">Cancel</nc-button>
        <nc-button ref="confirmDeleteBtn" variant="danger">Delete</nc-button>
    </div>
</nc-modal>
this.on(this.cancelDeleteBtn, 'click', () => {
    this.confirmModal.removeAttribute('open');
});
this.on(this.confirmDeleteBtn, 'click', () => {
    this.deletePending();
    this.confirmModal.removeAttribute('open');
});

// Somewhere when user asks to delete:
this.pendingDeleteId = id;
this.confirmModal.setAttribute('open', '');

Modal / drawer set open as a boolean attribute. They emit open / close if you need to react.


Recipe 5 — Filters in a nc-drawer

<nc-button ref="filterBtn" variant="outline">Filters</nc-button>
<nc-drawer ref="filterDrawer" placement="right" size="320px">
    <span slot="header">Filters</span>
    <label><input ref="showDoneEl" type="checkbox" checked /> Show done</label>
</nc-drawer>
this.on(this.filterBtn, 'click', () => {
    this.filterDrawer.setAttribute('open', '');
});

Categories cheat sheet

CategoryExamples
Inputsnc-input, nc-textarea, nc-select, nc-checkbox, nc-switch
Actionsnc-button, nc-copy-button
Feedbacknc-alert, nc-snackbar, nc-badge, nc-progress
Overlaysnc-modal, nc-drawer, nc-popover, nc-tooltip
Navigationnc-tabs, nc-breadcrumb, nc-pagination
Datanc-table, nc-timeline, nc-code

Shell chrome (opt-in): app-header, app-sidebar, app-footer.

Keep your own UI under src/components/ui/ via make:component. Pull newer framework tags into an existing app with npm run sync:components when available.


Challenges

Bronze — Add nc-snackbar and toast when a task is added.

Silver — Show open count in nc-badge; keep it in sync when toggling done.

Gold — Confirm deletes with nc-modal before removing from the array.


Verify

  • [ ] No “unknown custom element” warnings for tags you use
  • [ ] Tags resolve via frameworkRegistry (built-ins) or appRegistry (yours)
  • [ ] You did not copy-paste APIs you did not confirm in source

Next

Chapter 14 — Slots and composition