import '@jungherz-de/notionkit-elements/components/nk-btn.js';
<!-- build-free: map NotionKit's sheet once, the files import it -->
<scripttype="importmap">{ "imports": { "@jungherz-de/notionkit/notionkit-styles.js": "/node_modules/@jungherz-de/notionkit/notionkit-styles.js" } }</script>
Prerequisites
Load notionkit.css on the document and put class="nk-body" on <body>. The shadow roots inherit font, colour and the scoped reset from there; the elements ship no visual CSS of their own. The bundle additionally injects the design tokens as a cascade layer (@layer notionkit-defaults), so a page without the stylesheet still renders, and any unlayered :root { --nk-* } of yours wins.
Every <nk-*> host is display: contents: it generates no box of its own, so the inner .nk-* element takes part in the parent layout exactly where the class markup would β a button stays inline, a sidebar is a direct flex child of the app, a tree row and its children box are siblings. That is what makes the pixel parity hold. Consequence: style the parent (or the tokens), not the host; hidden on the host still works; getBoundingClientRect() of a host is empty.
<!-- β spacing on a wrapper you own -->
<divstyle="margin-top:16px"><nk-btnvariant="primary">Save</nk-btn></div>
<!-- β the host has no box; this margin does nothing -->
<nk-btnstyle="margin-top:16px" variant="primary">Save</nk-btn>
Theming & branding
Set data-theme="light|dark" on <html> β nowhere else. One observer mirrors it into every element. To re-brand, declare tokens on :root in a plain stylesheet: every element follows, in both themes.
The texts the elements bring along β button labels, placeholders, the names a screen reader announces β come in English and German. The language is the elementβs own: its nearest lang attribute, across shadow roots, else <html lang>. An attribute on the element wins, for a label with a meaning of its own. setStrings() adds or replaces texts, for every language or for one, and the elements on the page take them at once; your own NkElement reads them with this.str(key). Percentages follow the language as Intl writes them β 45 % in German.
<htmllang="de"> <!-- the elements speak German: Kopieren, Heute, οΌ Neue Seite β¦ -->
<scripttype="module">
import { setStrings } from '@jungherz-de/notionkit-elements';
setStrings({ newPage: 'οΌ New course' }); // every language
setStrings({ copy: 'Copier' }, 'fr'); // a language of its own
</script>
<!-- an attribute wins -->
<nk-copy-fieldvalue="https://β¦" copy-label="Copy link"></nk-copy-field>
Forms
Form controls are form-associated custom elements: inside a <form> they appear in FormData, follow reset, honour required and <fieldset disabled>. Outside a form value and events still work, but nothing is submitted.
Elements that copy their children (nk-select options, breadcrumb crumbs) watch them with a MutationObserver, so a framework that swaps children keeps the element in step. element.refresh() is the escape hatch. The empty string is a valid value.
const sel = document.querySelector('nk-select');
sel.innerHTML = roles.map(r => `<optionvalue="${r.id}">${r.name}</option>`).join('');
// the shadow <select> follows; sel.value is preserved when the option still exists
Passing icons
::slotted() only matches the assigned node itself. Pass an icon as a direct child with the slot name β never wrapped in a container.
<!-- β the icon is the slotted node -->
<nk-callout><spanslot="icon">π</span>β¦</nk-callout>
<!-- β wrapped: ::slotted() cannot reach the inner node -->
<nk-callout><spanslot="icon"><em>π</em></span>β¦</nk-callout>
Overlays
Put nk-modal, nk-sheet, nk-peek, nk-cmdk, nk-toast and a floating nk-menu directly under <body>. Inside a transformed or clipping container a fixed overlay is trapped. Give an overlay you open from a URL hash another id than the hash: the browser scrolls to the fragment target and takes the focus the overlay just gave.
Editor
NotionKit ships no editor. nk-block-host is the optical shell; mount TipTap into a light-DOM .nk-block-host with the recipe below (the demo app uses exactly this file). <nk-editor>, a thin TipTap wrapper, follows in v1.1 as an optional import β never part of the core bundle.
<!-- the shell: hover wash, focus ring, drag handle -->
<divclass="nk-block-host" id="editor">
<p>Server-rendered content becomes the initial document.</p>
</div>
<!-- the recipe: TipTap + slash menu + bubble menu + block handle (docs-editor.js) -->
<scripttype="module" src="docs-editor.js"></script>
Renders button.nk-btn, or a.nk-btn when href is set. Modifier classes become attributes. A slotted <svg> is sized by the stylesheet β pass it directly, never wrapped. Stretched across a column β a full-width button on a sign-in page β it keeps its label centred.
Visual variant. topbar and share render .nk-topbar-btn for the top bar. tool renders .nk-db-tool, a tool in the database toolbar (slot="tools" of nk-database). sidebar is the β° .nk-topbar-btn.nk-sidebar-toggle: shown below 860px only, a click opens the nk-sidebar of its app as a drawer and sets aria-expanded.
active
boolean
β
A tool in effect β a set filter β takes the accent (variant="tool").
small
boolean
β
Compact padding and 12.5px text.
disabled
boolean
β
Disabled; clicks are swallowed.
type
button | submit | reset
button
For submit/reset the surrounding <form> is submitted or reset.
href
URL
β
Renders a link instead of a button.
Slots
Slot
Description
(default)
Label text and an optional <svg> icon.
Events
Event
detail
Description
click
(native, composed)
The native click bubbles out of the shadow root.
On a small screen:Unchanged. The button grows with its label; combine with small in dense toolbars.
A native <input> inside the shadow root, wired into the surrounding form through ElementInternals: FormData, reset and required validation work as with a plain input.
On a small screen:Minimum width 210px β inside a panel never wider than the tile; use wide to fill the row.
Replaces.nk-input.wide
<nk-copy-field> Copy field
A value to take along β a link, an address, a key β as tall as an input, with Copy inside on the right: it writes the clipboard and says βCopiedβ in green for a moment; where the clipboard is not allowed, the value is shown and selected for βC. secret masks it behind Show/Hide, Copy still copies the real value. value set as a property is not reflected, so a key never lands in the markup. Each button carries an icon beside its word: on a phone, and with icons anywhere, the icon stands in for the word β two overlapping squares, an eye, a check in green for the moment after β and a masked key keeps a dozen characters more. The word stays the buttonβs name, and while the icons show, its tooltip for nk-tooltip.
Icons instead of words at every width, not only on a phone.
mono
boolean
β
Monospace β addresses, keys, code.
wrap
boolean
β
A long value breaks instead of an ellipsis.
wide
boolean
β
Fills the row.
copy-label
string
Copy Β· Kopieren
Button text.
copied-label
string
Copied Β· Kopiert
Text for the moment after.
show-label
string
Show Β· Zeigen
Reveal (secret).
hide-label
string
Hide Β· Verbergen
Mask again.
Slots
none
Events
Event
detail
Description
nk-action
{ action: 'copy', value, ok }
Copy clicked; ok is false where the clipboard refused.
Properties:valuesecreticons
Methods:copy()
On a small screen:Keeps to its column β inside a panel even below its 210px: the value is cut, never the actions. The actions are icons, with the words as their names and tooltips.
A picture for a person or a workspace, on NotionKitβs profile row: round, or square for a workspace icon, with Upload / Change and Remove beside it. From GlassKit Elements: the file is decoded with its EXIF rotation, drawn no larger than max and handed over as a data URL in nk-change β upload it yourself; an unreadable file fires nk-error. JPEG is drawn on white; type="image/png" keeps transparency. src as a property is not reflected, so megabytes never land in the DOM.
Notionβs date picker as one element (NotionKit 1.9.0): a month with Today and βΉ βΊ, the keys, bounds and a form value. The value is a day (YYYY-MM-DD); with range an interval start/end, picked in two clicks in either order; with time a day and a time (YYYY-MM-DDTHH:MM). weeks puts the ISO calendar week in front of each row (βKWβ in German), weekend greys the days not worked, the days property adds holidays (off with a label) and up to three marks per day in the nine colours β deadlines, milestones. Days outside min/max are announced as unavailable and cannot be picked. Arrows move by a day or a week, Home/End to the ends of the week, PageUp/PageDown by a month (with Shift a year), Enter or Space picks; one day is in the tab order. Month names, weekdays and the first day of the week come from the pageβs language; week-start="1" fixes Monday. With floating sheet it is a popover that show(anchor) opens under a property or a cell, and a bottom sheet on a phone; a pick closes it. Put a floating one directly under <body>: an open nk-dialog, nk-modal or nk-sheet leaves it usable, so it opens from a field in a dialog as well.
Multi-line sibling of nk-input. The initial value is the value attribute or the elementβs text content.
Wave 1
<nk-textareaname="bio" rows="3" placeholder="A sentence about you"></nk-textarea>
<textareaclass="nk-textarea" name="bio" rows="3" placeholder="A sentence about you"></textarea>
Attributes
Attribute
Type
Default
Description
value
string
β
Current value.
placeholder
string
β
Placeholder text.
rows
number
β
Visible rows.
name
string
β
Form field name (FormData key).
disabled
boolean
β
Disables the control.
required
boolean
β
Required field.
wide
boolean
β
Full width.
Slots
Slot
Description
(default)
Initial text (used when value is absent).
Events
Event
detail
Description
nk-change
{ value, name }
On commit.
nk-input
{ value, name }
On every keystroke.
On a small screen:Resizes vertically only; wide fills the row.
Replaces.nk-textarea.wide
<nk-select> Select
Light-DOM <option> and <optgroup> children are copied into the shadow <select> and kept in step when a framework swaps them. The empty string is a valid value; a value naming no option leaves the selection alone. A value β attribute or property β whose option is not there yet waits and is applied once the option arrives, over the browserβs preselection of the first option, unless someone has chosen another in the meantime; settling on it fires no nk-change.
120px minimum width (.compact), e.g. inside a member row.
wide
boolean
β
Full width (.nk-select.wide).
Slots
Slot
Description
(default)
<option> / <optgroup> children β direct children only.
Events
Event
detail
Description
nk-change
{ value, name }
On selection.
Properties:valueselectedIndexoptions
Methods:refresh()
On a small screen:Uses the native picker of the platform (color-scheme follows the theme).
Replaces.nk-select.compact
<nk-switch> Switch
Renders button.nk-switch[role=switch]; the stylesheet keys the knob on aria-checked, the element does the toggling. Submits value (default on) when checked, nothing otherwise β like a checkbox.
Visible text beside the switch (alternative to the default slot).
label
string
β
Accessible name (aria-label) when there is no visible text.
Slots
Slot
Description
(default)
Visible text beside the switch; part of the hit area. Without it the element renders the bare button.
Events
Event
detail
Description
nk-change
{ checked, value, name }
On toggle.
Methods:toggle()
On a small screen:34Γ20px β below the 44px touch target. Give it a label row (nk-field) to enlarge the hit area.
Replaces.nk-switch.nk-switch-label
<nk-check> Checkbox
A label.nk-check with a custom-drawn checkbox; the label text is slotted, so clicking it toggles the box. indeterminate shows a dash (NotionKit 1.21.0) β for a box over a group partly chosen.
On a small screen:Row height ~24px; the whole label is the hit area.
Replaces.nk-check
<nk-radio> Radio
Same optics as nk-check with a round mark. Radios with the same name in the same tree and form form one group β across shadow roots, which native radios cannot do. One tab stop per group; arrow keys move, wrap and skip disabled entries. There is deliberately no nk-radio-group.
On a small screen:210px wide; the native thumb is touch-sized by the platform.
Replaces.nk-slider.nk-slider-value
<nk-field> Field row
The settings row: label and description left, control right. Put any control β nk-input, nk-switch, nk-select β in the default slot. stacked puts the label above a full-width control (textareas, long descriptions) and sets wide on the control for you; compact shrinks the label to 12px tertiary text. Inside nk-fields both are on by default.
Wave 1
Display name
Shown next to your comments.
Email notifications
Short bio
<nk-fieldlabel="Display name" desc="Shown next to your comments.">
<nk-inputvalue="Ada Lovelace"></nk-input>
</nk-field>
<nk-fieldlabel="Email notifications">
<nk-switch checked></nk-switch>
</nk-field>
<nk-fieldlabel="Short bio" stacked>
<nk-textarearows="2" placeholder="A sentence about you"></nk-textarea>
</nk-field>
<divclass="nk-field">
<div><divclass="f-label">Display name</div><divclass="f-desc">Shown next to your comments.</div></div>
<divclass="f-control"><inputclass="nk-input" value="Ada Lovelace"></div>
</div>
<divclass="nk-field">
<div><divclass="f-label">Email notifications</div></div>
<divclass="f-control"><buttonclass="nk-switch" role="switch" aria-checked="true"></button></div>
</div>
<divclass="nk-field stacked">
<div><divclass="f-label">Short bio</div></div>
<divclass="f-control"><textareaclass="nk-textarea wide" rows="2" placeholder="A sentence about you"></textarea></div>
</div>
Attributes
Attribute
Type
Default
Description
label
string
β
Label text.
desc
string
β
Secondary description.
stacked
boolean
β
Label above a full-width control.
compact
boolean
β
Small tertiary label, no row padding.
Slots
Slot
Description
(default)
The control.
label
Rich label content (instead of the attribute).
desc
Rich description.
Events
none
On a small screen:Stays a row; long descriptions wrap under the label. Use stacked where the control needs the whole width.
Several short fields in one row: a grid of minmax(150px, 1fr) columns that wraps as the width allows. Every nk-field inside renders itself stacked and compact β a 12px label above a full-width control β so nothing collides.
The fields share the row instead of keeping 150px columns β two fields in a wide dialog are two halves.
Slots
Slot
Description
(default)
nk-field children.
Events
none
On a small screen:Wraps to one or two columns on its own; no breakpoint needed.
Replaces.nk-fields.fit
Content elements
Wave 1
<nk-tag> Tag
The select option as Notion draws it, in its nine colours. The colour modifier class becomes the color attribute; without one it is the grey tag. Each pair is tuned per theme.
Wave 1
Not startedArchivePlannedReviewDoneIn progressDesignIdeaBlocked
Not startedArchivePlannedReviewDoneIn progressDesignIdeaBlocked
A 60px bar with an optional label. value/max set the fill; the bar carries role="progressbar". wide fills its row, and in a flex column β a panel β it stays a 6px bar. With a label the bar and its label form one .nk-progress-row: the label sits beside the bar, on its middle, in a panel too, where the host β display: contents β would let them stand one under the other.
One thought that must not be missed. The icon comes from the icon attribute or a slot="icon" node β the node itself, never wrapped.
Wave 1
Core idea: A callout carries one thought that must not be missed.
π‘
Core idea: A callout carries one thought that must not be missed.
<nk-callouticon="π‘"><b>Core idea:</b> A callout carries one thought that must not be missed.</nk-callout>
<divclass="nk-callout"><spanclass="c-icon">π‘</span><div><b>Core idea:</b> A callout carries one thought that must not be missed.</div></div>
Attributes
Attribute
Type
Default
Description
icon
string
π‘
Emoji or text icon.
Slots
Slot
Description
(default)
Body.
icon
Icon node (e.g. <span slot="icon">π</span>).
Events
none
On a small screen:Unchanged; wraps with the text.
Replaces.nk-callout.c-icon
<nk-bookmark> Bookmark
Notionβs link block, filled from what you know of the page β og:title, og:description, og:image: title, two lines of description and the address with its icon on the left, the image on the right in a third, 240px at most. title is the heading, never a tooltip; without it the host name stands in. url shows an address other than href. Opens in a new tab unless target says otherwise; a part without a value is left out.
<divstyle="max-width:600px"><nk-bookmarkhref="https://notionkit.jungherz.com" title="NotionKit β the calm workspace look as CSS" desc="NotionKit is a pure CSS component library in the Notion idiom: sidebar, page tree, document shell, database views, settings and AI surfaces." favicon="/favicon.svg" cover="/covers/notionkit-og.jpg"></nk-bookmark></div>
<divstyle="max-width:600px"><aclass="nk-bookmark" href="https://notionkit.jungherz.com" target="_blank" rel="noopener"><spanclass="bm-text"><spanclass="bm-title">NotionKit β the calm workspace look as CSS</span><spanclass="bm-desc">NotionKit is a pure CSS component library in the Notion idiom: sidebar, page tree, document shell, database views, settings and AI surfaces.</span><spanclass="bm-url"><imgclass="bm-favicon" src="/favicon.svg" alt=""><span>https://notionkit.jungherz.com</span></span></span><spanclass="bm-cover"><imgsrc="/covers/notionkit-og.jpg" alt=""></span></a></div>
Attributes
Attribute
Type
Default
Description
href
URL
β
The link.
title
string
β
Title β og:title.
desc
string
β
Description, two lines β og:description.
favicon
URL
β
The siteβs icon, 16px.
cover
URL
β
Preview image β og:image.
url
string
β
The address shown (default: href).
target
string
_blank
Link target.
Slots
none
Events
Event
detail
Description
click
(native)
The link is a plain <a>.
Properties:titlehref
On a small screen:The image keeps its third and is cropped at the centre; title and address end in an ellipsis.
A section heading. level chooses the real heading element (h1βh4), so the document outline stays honest.
Wave 1
Section heading
Section heading
<nk-heading>Section heading</nk-heading>
<h2class="nk-heading">Section heading</h2>
Attributes
Attribute
Type
Default
Description
level
1 | 2 | 3 | 4
2
Heading level.
Slots
Slot
Description
(default)
Heading text.
Events
none
On a small screen:Unchanged.
Replaces.nk-heading
<nk-toggle> Toggle block
A <details> block. The summary is rendered inside the element (its marker is a pseudo-element and cannot be styled on slotted content); the body is slotted.
On a small screen:Scrolls horizontally instead of wrapping.
Replaces.nk-code.lang.tag.attr
<nk-quote> Quote
A block quote with an optional citation line.
Wave 1
The best interface is the one that gets out of the way.
The best interface is the one that gets out of the way.Unknown
<nk-quotecite="Unknown">The best interface is the one that gets out of the way.</nk-quote>
<blockquoteclass="nk-quote">The best interface is the one that gets out of the way.<citeclass="q-cite">Unknown</cite></blockquote>
Attributes
Attribute
Type
Default
Description
cite
string
β
Citation text.
Slots
Slot
Description
(default)
Quote text.
Events
none
On a small screen:Unchanged.
Replaces.nk-quote.q-cite
App shell & navigation
Wave 2
<nk-app> App shell
The outermost element of a workspace app: a full-height flex row with the sidebar slot left and main.nk-main right. Everything in the default slot β nk-topbar, nk-page β becomes a flex child of the main column.
The main column makes room for the side peek β <nk-peek inset> sets it while open.
Slots
Slot
Description
sidebar
An nk-sidebar.
(default)
Topbar, page β the main column.
Events
none
On a small screen:Below 860px the sidebar is hidden; open it as a drawer with sidebar.open = true.
Replaces.nk-app.nk-main.peek-inset
<nk-sidebar> Sidebar
The left rail: workspace slot on top, a scrolling default slot for the tree, a pinned footer slot. Footer tree items automatically get compact (26px rows). The host is display: contents, so the aside is a direct flex child of the app β exactly like the class markup. collapsible adds Notionβs Β« beside the workspace row, shown while the pointer is over the sidebar: on the desktop it collapses the sidebar β it slides out, the main column takes the width, nothing in it takes focus β and <nk-btn variant="sidebar"> in the topbar shows and brings it back; β\ or Ctrl+\ toggles it. collapsed is the state, nk-collapse the moment to keep it.
On a small screen:Hidden below 860px. open shows it as a drawer over the page with a scrim β NotionKitβs own rules since 1.7.0 (.nk-sidebar.open, .nk-sidebar-backdrop), the same as the class markupβs; <nk-btn variant="sidebar"> in the topbar is the β° that opens it. Escape and the scrim close it. The drawer slides in over 240ms and the scrim fades, closing runs backwards β CSS only (transition-behavior: allow-discrete + @starting-style; older browsers switch hard, reduced motion snaps). In landscape the drawer grows by the left safe-area inset, so its rows clear the Dynamic Island.
The row at the very top of the sidebar. A click toggles open and shows whatever sits in the menu slot below it (an nk-menu, from wave 4); outside clicks and Escape close it.
Container for nk-tree-items: keeps exactly one item active (listening to nk-select at any depth), gives the whole tree a single tab stop with arrow-key navigation (ββ move, β expands or enters, β collapses or leaves, Home/End), and renders items from tree.data. tree.value is read-only β select programmatically with item.select() or the active attribute. Section labels may sit between items; their οΌ fires nk-action { action: 'add' } without a value.
Wave 2
FavouritesProject overview
NotionKit MVPVoice-Office-HubKnowledge base
OnboardingDesign system
On a small screen:Rows are 28px; raise the hit area in a touch drawer via the sidebarβs open state styling of your own.
Replaces
<nk-tree-item> Tree item
One row of the page tree β and its children box. Text content is the label, nested nk-tree-items are the children (the arrow appears only then), slot="icon" and slot="end" go where they say. Hover actions οΌ/β― report through nk-action; a click fires nk-select (cancelable). Outside an nk-tree (sidebar footer) an item marks itself active on click unless the event is cancelled.
The 44px bar above the page: breadcrumb in the default slot, buttons in the actions slot (right-aligned). Use nk-btn variant="topbar" / "share" and nk-theme-toggle there, and <span class="nk-topbar-meta"> for passive text such as βEdited 2 min agoβ.
Wave 2
π Project overviewπ NotionKit MVPLast edited 2 min agoShareβ
On a small screen:Below 860px only the last crumb stays and ends in an ellipsis, nk-topbar-meta hides, and the actions keep to one line β as in Notionβs mobile app.
Give it plain <span> or <a> children; they are cloned into the bar with separators between them and the last one marked current (or the child with a current attribute). Text changes, added or removed children are picked up automatically (refresh() only for what the observer cannot see). Clicking a crumb fires nk-select and forwards the click to the original child, so links navigate exactly once.
Crumb children (direct children only, no slot attribute).
Events
Event
detail
Description
nk-select
{ index, value, label, href, current }
Crumb clicked; preventDefault() stops the forwarded click.
Methods:refresh()
On a small screen:Stays on one line; keep crumbs short.
Replaces.nk-breadcrumb.crumb.sep.current
<nk-theme-toggle> Theme toggle
The βοΈ/π button. Flips data-theme on <html>, remembers the choice in localStorage, applies a stored or system preference on first connect when <html> has no theme yet, and accepts postMessage({ nkTheme }) from a parent page. apply(mode) does everything a click does: sets, persists and fires nk-change. modes="auto light dark" adds a third state: auto follows prefers-color-scheme, live, and is what no stored value means β so the inline script before first paint keeps working and a choice made without modes still counts. A click then goes from auto to the theme not on screen, to the other one, back to auto, so every click but the last changes something. The glyph shows the mode (nk-theme-glyph, sun and moon diagonally for auto) instead of the next theme, the title names the mode and the next one, and another tab's choice arrives through the storage event. Two states stay the default, where nothing about this element changes.
Mode applied; theme is what is on screen (without auto both are the theme).
Properties:valuethememodemodes
Methods:apply(mode)nextMode()themeFor(mode)
On a small screen:Unchanged.
Replaces.nk-theme-toggle.nk-theme-glyph
<nk-tab-bar> Tab bar (mobile)
The thumb-reachable twin of the sidebar for phones and installed PWAs. Put it last inside nk-app: it is slotted into the main column below the scrolling page, so it never moves and no bottom padding is needed. Keeps the nk-tab-bar-item whose value is value active (listening to nk-select); a drawer item opens the sidebar instead. A value no item has β a page without a tab of its own, opened from the drawer β marks the drawer item, as iOS marks βMoreβ; without one no item is active. Needs NotionKit CSS 1.2.0.
Active item value (default: the item with active, else the first); a value no item has marks the drawer item.
always
boolean
β
Visible at every width, not only below 860px.
fixed
boolean
β
Pinned to the viewport bottom instead of sitting in the column β for standalone PWAs; a spacer keeps its height (--nk-tab-bar-height + safe area) in the flow.
floating
boolean
β
A fixed capsule with rounded corners instead of the full-width bar.
label
string
β
aria-label of the nav.
Slots
Slot
Description
(default)
nk-tab-bar-item children, up to five.
Events
Event
detail
Description
nk-change
{ value }
Active item changed.
nk-select
{ value, label, href, item, drawer }
Bubbles from the tapped item; cancelable.
Properties:valueitems
On a small screen:This is where it lives: hidden above 860px (the sidebar is the navigation there), shown below. always shows it at every width β previews, phone frames. The bottom padding is the larger of 6px and env(safe-area-inset-bottom); in landscape the side padding grows to the left/right insets.
One destination of nk-tab-bar: an icon over a short label. A tap emits nk-select (cancelable), then moves the barβs value; with href it navigates afterwards. drawer turns it into the βMoreβ item that opens the nearest nk-sidebar as a drawer and never becomes active. Standalone it toggles its own active.
Opens the sidebar drawer instead of becoming active.
disabled
boolean
β
Not selectable.
Slots
Slot
Description
(default)
Label.
icon
Icon node instead of the attribute.
Events
Event
detail
Description
nk-select
{ value, label, href, item, drawer }
Tapped; cancelable.
Methods:select()focus()
On a small screen:Made for the thumb: 20px icon, 10.5px label, the whole column is the hit area.
Replaces.nk-tab-bar-item.icon.label.active
Page shell & blocks
Wave 3
<nk-page> Page
The document column: a scrolling wrapper, an optional cover, the 760px page with 64px side padding, and the page icon (rendered here because its slotted twin is keyed on the parent). narrow drops the scroll wrapper for pages that are the document itself. With a cover the icon overlaps its bottom edge; a cover without an icon leaves the page its top padding, so the title never touches the picture.
Wave 3
<divstyle="display:flex;flex-direction:column;height:100%"><nk-pageicon="π" cover>
<nk-page-title>NotionKit MVP</nk-page-title>
<nk-page-actions><span>π€ Marcel Karas</span><span>π Created 12 May 2026</span><span>π·οΈ <nk-tagcolor="purple">Design system</nk-tag></span></nk-page-actions>
<pclass="lead">A calm, document-centric workspace app β built from elements only.</p>
</nk-page></div>
<divstyle="display:flex;flex-direction:column;height:100%"><divclass="nk-page-scroll"><divclass="nk-cover"></div><divclass="nk-page">
<divclass="nk-page-icon">π</div>
<h1class="nk-page-title">NotionKit MVP</h1>
<divclass="nk-page-meta"><span>π€ Marcel Karas</span><span>π Created 12 May 2026</span><span>π·οΈ <spanclass="nk-tag purple">Design system</span></span></div>
<pclass="lead">A calm, document-centric workspace app β built from elements only.</p>
</div></div></div>
Attributes
Attribute
Type
Default
Description
icon
string
β
Page emoji; click fires nk-action.
full
boolean
β
Page option βFull widthβ: the column fills the window instead of stopping at 760px.
small
boolean
β
Page option βSmall textβ: document text 14px instead of 16px; headings, lead, prose and editor follow.
cover
boolean
β
Shows the cover strip; the icon then overlaps its bottom edge and the page drops its top padding (the stylesheetβs covered state, also set for a slotted nk-page-cover). Without it the icon sits in 24px top padding, fully visible.
narrow
boolean
β
No scroll wrapper (landing / docs page).
Slots
Slot
Description
(default)
Title, meta, blocks β anything with class="lead" on a <p> becomes the lead paragraph.
cover
An nk-page-cover (instead of the cover attribute).
icon
Custom icon node.
Events
Event
detail
Description
nk-action
{ action: 'icon', value }
Icon clicked (open an emoji picker).
On a small screen:Side padding drops to 24px below 860px.
The cover band, as tall as the token --nk-cover-height (200px) β on :root, or on the element for one cover: style="--nk-cover-height: clamp(200px, 30vh, 300px)" comes close to Notionβs 30vh. Without src it shows the token gradient; with src a picture β an <img> inside the band, cropped rather than stretched. position moves the crop, as Notionβs βRepositionβ does.
The quiet row under the title: owner, date, tags β any inline content, 16px apart.
Wave 3
π€ Marcel Karasπ Created 12 May 2026π·οΈ Design system
π€ Marcel Karasπ Created 12 May 2026π·οΈ Design system
<nk-page-actions><span>π€ Marcel Karas</span><span>π Created 12 May 2026</span><span>π·οΈ <nk-tagcolor="purple">Design system</nk-tag></span></nk-page-actions>
<divclass="nk-page-meta"><span>π€ Marcel Karas</span><span>π Created 12 May 2026</span><span>π·οΈ <spanclass="nk-tag purple">Design system</span></span></div>
Attributes
none
Slots
Slot
Description
(default)
Meta items.
Events
none
On a small screen:Wraps naturally.
Replaces.nk-page-meta
<nk-props> Page properties
The properties under the title of a database page, the pattern Notion is known for: a list of nk-prop rows. The rows are hosts with display: contents, so each renders as a row of this list β no markup of their own around them. flush drops the outer margin meant for the flow under a title, for a list inside a panel or a flex column.
Wave 3
In progressALAda Lovelace2 June 2026Design systemCSS
<dlclass="nk-props" style="max-width:520px">
<divclass="nk-prop"><dtclass="p-name"><spanclass="p-icon">β</span>Status</dt><ddclass="p-value"><spanclass="nk-tag blue">In progress</span></dd></div>
<divclass="nk-prop"><dtclass="p-name"><spanclass="p-icon">π€</span>Owner</dt><ddclass="p-value"><spanclass="nk-avatar small purple">AL</span>Ada Lovelace</dd></div>
<divclass="nk-prop"><dtclass="p-name"><spanclass="p-icon">π </span>Due</dt><ddclass="p-value">2 June 2026</dd></div>
<divclass="nk-prop"><dtclass="p-name"><spanclass="p-icon">π·οΈ</span>Tags</dt><ddclass="p-value"><spanclass="nk-tag purple">Design system</span><spanclass="nk-tag">CSS</span></dd></div>
<divclass="nk-prop"><dtclass="p-name"><spanclass="p-icon">β°</span>Progress</dt><ddclass="p-value"><spanclass="nk-progress wide"><istyle="width:65%"></i></span><spanclass="nk-progress-label">65 %</span></dd></div>
</dl>
Attributes
Attribute
Type
Default
Description
flush
boolean
β
No outer margin.
Slots
Slot
Description
(default)
nk-prop children.
Events
none
On a small screen:Below 860px each property stacks: the name above its value. In a column narrower than 380px the value moves under its name as well.
Replaces.nk-props.flush
<nk-prop> Page property
One property: the name with its type icon in a 160px column, the value beside it, 34px with the hover wash on both halves. The value is the elementβs content β tags, an avatar and a name, a date, <nk-progress wide>. A click fires nk-action with the half that was hit, the moment Notion opens the propertyβs editor. text lets a value that is text β a sentence, an address, a model name with a tag β flow as text instead of setting its parts one under the other. The value keeps at least 220px: in a column narrower than 380px it moves under its name.
Wave 3
2 June 2026support+design@notionkit.example.com Β· Verified
π Due
2 June 2026
βοΈAddress
support+design@notionkit.example.com Β· Verified
<nk-propsstyle="max-width:520px"><nk-proplabel="Due" icon="π ">2 June 2026</nk-prop><nk-proplabel="Address" icon="βοΈ" text>support+design@notionkit.example.com Β· <nk-tagcolor="green">Verified</nk-tag></nk-prop></nk-props>
<dlclass="nk-props" style="max-width:520px"><divclass="nk-prop"><dtclass="p-name"><spanclass="p-icon">π </span>Due</dt><ddclass="p-value">2 June 2026</dd></div><divclass="nk-prop"><dtclass="p-name"><spanclass="p-icon">βοΈ</span>Address</dt><ddclass="p-value text">support+design@notionkit.example.com Β· <spanclass="nk-tag green">Verified</span></dd></div></dl>
Attributes
Attribute
Type
Default
Description
label
string
β
Property name.
icon
string
β
Type icon.
text
boolean
β
The value flows as text.
Slots
Slot
Description
(default)
The value.
icon
Icon node.
Events
Event
detail
Description
nk-action
{ action: 'name' | 'value', label }
Name or value clicked.
On a small screen:Stacks below 860px, and in a column narrower than 380px.
Replaces.nk-prop.p-name.p-icon.p-value.text
<nk-panels> Panels
A grid of nk-panels: columns of at least 200px that share the row. The panels are hosts with display: contents, so each is a cell of this grid. flush drops the outer margin, for a grid inside a flex column with a gap of its own.
Wave 3
2 min ago
Yesterday
Three pages changed, one comment is waiting for an answer.
Three pages changed, one comment is waiting for an answer.
<nk-panels>
<nk-panelhref="#" cover="/covers/aurora.svg" icon="π" title="NotionKit MVP"><p>2 min ago</p></nk-panel>
<nk-panelhref="#" cover="/covers/dunes.svg" icon="π" title="Knowledge base"><p>Yesterday</p></nk-panel>
<nk-paneltitle="Weekly review"><p>Three pages changed, one comment is waiting for an answer.</p></nk-panel>
</nk-panels>
<divclass="nk-panels">
<aclass="nk-panel" href="#"><divclass="nk-cover"><imgsrc="/covers/aurora.svg" alt=""></div><divclass="nk-page-icon">π</div><h3>NotionKit MVP</h3><p>2 min ago</p></a>
<aclass="nk-panel" href="#"><divclass="nk-cover"><imgsrc="/covers/dunes.svg" alt=""></div><divclass="nk-page-icon">π</div><h3>Knowledge base</h3><p>Yesterday</p></a>
<divclass="nk-panel"><h3>Weekly review</h3><p>Three pages changed, one comment is waiting for an answer.</p></div>
</div>
Attributes
Attribute
Type
Default
Description
flush
boolean
β
No outer margin.
Slots
Slot
Description
(default)
nk-panel children.
Events
none
On a small screen:Falls to one column as soon as two 200px columns no longer fit.
Replaces.nk-panels.flush
<nk-panel> Panel
A neutral surface for content that belongs together β the cards on Notionβs Home, the boxes in its settings. title is the heading (never a tooltip); the content goes in as <p>s and blocks. cover without a value draws the gradient band, with a URL a picture; icon overlaps the cover as on a page β a page tile. With href the panel is a link. slot="end" sits at the right edge of the title β a state as a tag, a button β as Notionβs settings boxes show a connection, and moves under the title where both do not fit. The cover is --nk-panel-cover-height tall (64px) β set it on :root or on one panel. Inputs, selects and copy fields inside never run past the panelβs edge, however narrow the tile.
Wave 3
2 min ago
In progress
Three pages changed, one comment is waiting for an answer.
Three pages changed, one comment is waiting for an answer.
<divstyle="max-width:360px;display:grid;gap:12px"><nk-panelhref="#" cover icon="π" title="NotionKit MVP"><p>2 min ago</p></nk-panel>
<nk-paneltitle="Weekly review"><nk-tagslot="end" color="blue">In progress</nk-tag><p>Three pages changed, one comment is waiting for an answer.</p></nk-panel></div>
<divstyle="max-width:360px;display:grid;gap:12px"><aclass="nk-panel" href="#"><divclass="nk-cover"></div><divclass="nk-page-icon">π</div><h3>NotionKit MVP</h3><p>2 min ago</p></a>
<divclass="nk-panel"><divclass="p-head"><h3>Weekly review</h3><spanclass="p-end"><spanclass="nk-tag blue">In progress</span></span></div><p>Three pages changed, one comment is waiting for an answer.</p></div></div>
Attributes
Attribute
Type
Default
Description
title
string
β
Heading.
icon
string
β
Page icon.
cover
URL | empty
β
Cover band: empty for the gradient, a URL for a picture.
href
URL
β
Makes the panel a link.
target
string
β
Link target.
Slots
Slot
Description
(default)
Content: <p>, a prose block, a progress bar.
end
Beside the title, at its right edge: a tag, a button.
Events
none
On a small screen:Takes the width of its grid cell.
The optical shell for editor content: hover wash, focus ring, drop-target line, an optional drag handle. It stays behaviour-neutral β mount your editor into the light DOM; nk-editor (v1.1) will do that for TipTap.
Wave 3
Block content lives here β click to focus.
β Ώ
Block content lives here β click to focus.
<nk-block-host handle><pstyle="margin:0" contenteditable="true">Block content lives here β click to focus.</p></nk-block-host>
<divclass="nk-block-host"><spanclass="nk-block-handle">β Ώ</span><pstyle="margin:0" contenteditable="true">Block content lives here β click to focus.</p></div>
Attributes
Attribute
Type
Default
Description
handle
boolean
β
Render the β Ώ drag handle (shown on hover).
drop-target
boolean
β
Drop indicator line above the block.
Slots
Slot
Description
(default)
Block content / the editor root.
Events
none
On a small screen:The handle sits 26px left of the column and is hidden when there is no room.
A tinted notice row. The colour modifier becomes variant; the action β a <button> β goes into slot="action" and sits at the right edge.
Wave 3
βΉοΈ This page is a component preview β every element follows the same design tokens.β οΈ The βProject overviewβ database has 2 overdue entries.β All changes have been synced.β The connection to Notion was lost.
βΉοΈ This page is a component preview β every element follows the same design tokens.
β οΈ The βProject overviewβ database has 2 overdue entries.
β All changes have been synced.
β The connection to Notion was lost.
<nk-bannervariant="info">βΉοΈ <span>This page is a <b>component preview</b> β every element follows the same design tokens.</span><buttonslot="action" type="button">Open palette</button></nk-banner>
<nk-bannervariant="warning">β οΈ <span>The βProject overviewβ database has 2 overdue entries.</span><buttonslot="action" type="button">View</button></nk-banner>
<nk-bannervariant="success">β <span>All changes have been synced.</span></nk-banner>
<nk-bannervariant="danger">β <span>The connection to Notion was lost.</span></nk-banner>
<divclass="nk-banner info">βΉοΈ <span>This page is a <b>component preview</b> β every element follows the same design tokens.</span><buttonclass="b-action" type="button">Open palette</button></div>
<divclass="nk-banner warning">β οΈ <span>The βProject overviewβ database has 2 overdue entries.</span><buttonclass="b-action" type="button">View</button></div>
<divclass="nk-banner success">β <span>All changes have been synced.</span></div>
<divclass="nk-banner danger">β <span>The connection to Notion was lost.</span></div>
Attributes
Attribute
Type
Default
Description
variant
info | success | warning | danger
β
Tint.
Slots
Slot
Description
(default)
Icon and text.
action
The action β a <button>, shown as underlined text on the right.
Events
none
On a small screen:Below 860px the action moves under the text instead of squeezing it into a narrow column.
Dashed box with icon, title, description and whatever call to action you slot in.
Wave 3
οΌ New entryImport
ποΈ
No entries yet
Create the first entry or import existing data.
<nk-emptyicon="ποΈ" title="No entries yet" desc="Create the first entry or import existing data."><nk-btnvariant="primary" small>οΌ New entry</nk-btn><nk-btnvariant="secondary" small>Import</nk-btn></nk-empty>
<divclass="nk-empty"><divclass="e-icon">ποΈ</div><divclass="e-title">No entries yet</div><divclass="e-desc">Create the first entry or import existing data.</div><divclass="e-actions"><buttonclass="nk-btn primary small">οΌ New entry</button><buttonclass="nk-btn secondary small">Import</button></div></div>
Attributes
Attribute
Type
Default
Description
icon
string
β
Emoji.
title
string
β
Title. Read once and taken off the host, so it never shows as a tooltip.
desc
string
β
Description.
Slots
Slot
Description
(default)
Call to action β several buttons sit in a centred row, 8px apart.
icon
Rich icon.
title
Rich title.
desc
Rich description.
Events
none
On a small screen:Unchanged.
Replaces.nk-empty.e-icon.e-title.e-desc.e-actions
<nk-skeleton> Skeleton
Shimmering placeholder lines. lines renders several; widths gives each its own width.
On a small screen:Unchanged; respects reduced motion.
Replaces.nk-skeleton
<nk-synced> Synced block
Content that appears in several places, framed with a badge.
Wave 3
Our mission: Take real weight off the working day β calm, clear, effective.
β³ 3 places
Our mission: Take real weight off the working day β calm, clear, effective.
<nk-syncedbadge="β³ 3 places"><divstyle="font-size:14px;line-height:1.55"><b>Our mission:</b> Take real weight off the working day β calm, clear, effective.</div></nk-synced>
<divclass="nk-synced"><spanclass="synced-badge">β³ 3 places</span><divstyle="font-size:14px;line-height:1.55"><b>Our mission:</b> Take real weight off the working day β calm, clear, effective.</div></div>
Attributes
Attribute
Type
Default
Description
badge
string
β³ synced Β· β³ synchronisiert
Badge text.
Slots
Slot
Description
(default)
Content.
Events
none
On a small screen:Unchanged.
Replaces.nk-synced.synced-badge
<nk-tabs> Tabs
A tab strip with panels. nk-tab children are the tabs; elements with slot="panel" and a matching data-tab are the panels β the tabs hide every panel but the active one through hidden. Arrow keys move between tabs. scroll keeps many tabs in one row that scrolls sideways, scrollbar hidden, and holds the active tab in view β after the first layout, on every change and when the rowβs width changes.
Wave 3
π Notesβ Tasksπ Files
Free-form notes on the project β meeting minutes, ideas, rough drafts.
Tasks for this project, linked to the database below.
Attached files and exports.
π Notesβ Tasksπ Files
Free-form notes on the project β meeting minutes, ideas, rough drafts.
<nk-tabsvalue="notes">
<nk-tabvalue="notes">π Notes</nk-tab>
<nk-tabvalue="tasks">β Tasks</nk-tab>
<nk-tabvalue="files">π Files</nk-tab>
<divslot="panel" data-tab="notes" class="nk-tab-panel">Free-form notes on the project β meeting minutes, ideas, rough drafts.</div>
<divslot="panel" data-tab="tasks" class="nk-tab-panel">Tasks for this project, linked to the database below.</div>
<divslot="panel" data-tab="files" class="nk-tab-panel">Attached files and exports.</div>
</nk-tabs>
<divclass="nk-tabs">
<spanclass="nk-tab active">π Notes</span>
<spanclass="nk-tab">β Tasks</span>
<spanclass="nk-tab">π Files</span>
</div>
<divclass="nk-tab-panel">Free-form notes on the project β meeting minutes, ideas, rough drafts.</div>
Attributes
Attribute
Type
Default
Description
value
string
β
Active tab value (default: the tab with active, else the first).
scroll
boolean
β
One row that scrolls sideways and keeps the active tab in view.
Slots
Slot
Description
(default)
nk-tab children.
panel
Panels with data-tab.
Events
Event
detail
Description
nk-change
{ value }
Active tab changed.
nk-select
{ value, label }
From the clicked tab.
Properties:valuescroll
On a small screen:The strip stays on one line; one longer than the screen takes scroll.
Plain <button value> children stay in the light DOM (the stylesheetβs slotted twins shape them); the element moves .active, handles arrow keys and submits value with the form. With scroll the chosen option stays in view: after the first layout, on every change and when the rowβs width changes, the row β never the page β scrolls the least distance, right to left as well.
Selected value (default: the button with .active, else the first).
scroll
boolean
β
Horizontally scrollable row, scrollbar hidden.
wrap
boolean
β
Segments wrap onto further rows.
name
string
β
Form field name (FormData key).
disabled
boolean
β
Disables the control.
Slots
Slot
Description
(default)
<button value="β¦"> children.
Events
Event
detail
Description
nk-change
{ value, name }
Selection changed.
On a small screen:One row by default, which five filter options overflow on a phone: scroll keeps one thumb-swipeable row capped at the parent width (scrollbar hidden), wrap breaks it onto further rows.
Replaces.nk-segmented.active.scroll.wrap
<nk-steps> Steps
A short flow β connecting an account, setting up a model β calm and vertical: a numbered circle per step joined by a hairline, done steps with a check on the green tag, the current one ringed in the accent and marked aria-current="step". current counts from 1; one past the last marks every step done, and next() moves on. The steps attribute is a comma-separated list; the property also takes { label, desc } objects for a line under the label. A state in such an object β done, skipped or open β wins over the order, for a wizard that lets a step be skipped while a later one is done; a skipped step shows a dashed ring around a dash. selectable makes each label a button: a click or Enter fires nk-select { index, value, step } β index counts from 1, like current β and, unless cancelled, makes that step current. A step with href shows its label as a link, with or without selectable β to open a chapter in a new tab or copy its address. A plain click, and Enter, fire the same nk-select; cancel it and the browser stays, for a router of your own. A middle click or one with Cmd, Ctrl, Shift or Alt fires nothing and does what a link does. horizontal sets the steps in one row above a wizard.
<nk-stepslabel="Connect your own model" current="2"></nk-steps>
<script>{ document.currentScript.previousElementSibling.steps = [{ label: 'Choose a provider', desc: 'Anthropic' }, 'Enter the API key', 'Test the connection']; }</script>
<divstyle="margin-top:16px"><nk-stepsid="stepsWizard" label="Connect your own model" current="3" horizontal selectable></nk-steps></div>
<script>{ document.getElementById('stepsWizard').steps = [{ label: 'Choose a provider', state: 'done', href: '#nk-steps' }, { label: 'Enter the API key', desc: 'skipped', state: 'skipped' }, 'Test the connection']; }</script>
<olclass="nk-steps" aria-label="Connect your own model">
<liclass="nk-step done"><spanclass="st-mark">β</span><span>Choose a provider<spanclass="st-desc">Anthropic</span></span></li>
<liclass="nk-step current" aria-current="step"><spanclass="st-mark">2</span><span>Enter the API key</span></li>
<liclass="nk-step"><spanclass="st-mark">3</span><span>Test the connection</span></li>
</ol>
<divstyle="margin-top:16px"><olclass="nk-steps horizontal" aria-label="Connect your own model">
<liclass="nk-step done"><spanclass="st-mark">β</span><aclass="st-label" href="#nk-steps">Choose a provider</a></li>
<liclass="nk-step skipped"><spanclass="st-mark">β</span><buttontype="button" class="st-label">Enter the API key<spanclass="st-desc">skipped</span></button></li>
<liclass="nk-step current" aria-current="step"><spanclass="st-mark">3</span><buttontype="button" class="st-label">Test the connection</button></li>
</ol></div>
Attributes
Attribute
Type
Default
Description
steps
list
β
Comma-separated step labels.
current
number
1
The current step, from 1.
label
string
β
The listβs accessible name.
selectable
boolean
β
Labels are buttons that jump to their step.
horizontal
boolean
β
One row above a wizard.
Slots
none
Events
Event
detail
Description
nk-select
{ index, value, step }
A step clicked (with selectable, or its link with a plain click or Enter); cancel it to stay.
Properties:stepscurrentselectablehorizontal
Methods:next()select(index)
On a small screen:Vertical steps stay as they are. horizontal keeps its row below 860px, with every mark but only the current stepβs label.
<nk-stats><nk-statlabel="Active pages" value="128" delta="β² 12 this week" trend="up"></nk-stat></nk-stats>
<divclass="nk-stats"><divclass="nk-stat"><divclass="s-label">Active pages</div><divclass="s-value">128</div><divclass="s-delta up">β² 12 this week</div></div></div>
Attributes
Attribute
Type
Default
Description
label
string
β
Label.
value
string
β
Value.
delta
string
β
Trend text.
trend
up | down
β
Delta colour.
Slots
Slot
Description
label
Rich label.
value
Rich value.
delta
Rich delta (add class="up" / "down").
Events
none
On a small screen:Unchanged.
Replaces.nk-stat
<nk-avatar-group> Avatar group
Overlapping .mini-avatar children (light DOM, styled by the slotted twins) plus a βmoreβ bubble from the attribute. Pass .mini-avatar, not .nk-avatar: the document rule of .nk-avatar sets its own 24px, and for slotted nodes the document wins over the groupβs 26px.
Wave 3
MKSLTW5 people have access
MKSLTW+2
5 people have access
<divstyle="display:flex;align-items:center;gap:12px"><nk-avatar-groupmore="+2"><spanclass="mini-avatar" style="background:linear-gradient(135deg,var(--nk-decor-purple),var(--nk-decor-blue))">MK</span><spanclass="mini-avatar" style="background:var(--nk-color-green)">SL</span><spanclass="mini-avatar" style="background:var(--nk-color-orange)">TW</span></nk-avatar-group><spanstyle="font-size:12.5px;color:var(--nk-text-tertiary)">5 people have access</span></div>
<divstyle="display:flex;align-items:center;gap:12px"><divclass="nk-avatar-group"><spanclass="nk-avatar">MK</span><spanclass="nk-avatar green">SL</span><spanclass="nk-avatar orange">TW</span><spanclass="mini-avatar more">+2</span></div><spanstyle="font-size:12.5px;color:var(--nk-text-tertiary)">5 people have access</span></div>
A person or a workspace: initials, an emoji or a photo in a circle. size small (20px), default 24px, large (32px), xlarge (56px); color one of Notionβs nine names or any CSS background, without it the avatar gradient; square for a workspace icon. Without content the initials come from name; with src a photo fills the circle and name becomes its alt text. Initials from name are the first letter or digit of each word: βPlaner (Dev)β β PD, βAnna-Lena GroΓβ β AG.
<divstyle="display:flex;align-items:center;gap:10px"><spanclass="nk-avatar small blue">TW</span><spanclass="nk-avatar">AL</span><spanclass="nk-avatar green">SL</span><spanclass="nk-avatar large orange">MK</span><spanclass="nk-avatar xlarge purple">AL</span><spanclass="nk-avatar large square">A</span></div>
Attributes
Attribute
Type
Default
Description
size
small | large | xlarge
β
Size; default 24px.
color
colour name | CSS
β
gray, brown, orange, yellow, green, blue, purple, pink, red β or any CSS background.
square
boolean
β
Corners instead of a circle.
name
string
β
Initials when empty; alt text of the photo.
src
URL
β
Photo.
Slots
Slot
Description
(default)
Initials or an emoji.
Events
none
On a small screen:Unchanged. A fixed size, so a row of avatars never reflows.
A radio-like card. Cards with the same name form a group; the selected one submits value with the form.
Wave 3
Mona Pro
Best for long documents and research.
Mona Fast
Quick answers, lower cost.
<nk-model-cardname="model" value="pro" title="Mona Pro" desc="Best for long documents and research." selected></nk-model-card>
<nk-model-cardname="model" value="fast" title="Mona Fast" desc="Quick answers, lower cost."></nk-model-card>
<divclass="nk-model-card selected"><divclass="m-radio"></div><div><divclass="m-name">Mona Pro</div><divclass="m-desc">Best for long documents and research.</div></div></div>
<divclass="nk-model-card"><divclass="m-radio"></div><div><divclass="m-name">Mona Fast</div><divclass="m-desc">Quick answers, lower cost.</div></div></div>
Attributes
Attribute
Type
Default
Description
title
string
β
Name line. Read once and taken off the host, so it never shows as a tooltip.
<nk-danger-zonetitle="Danger zone"><nk-fieldlabel="Delete workspace" desc="Deleting the workspace removes every page."><nk-btnvariant="danger-solid" small>Delete</nk-btn></nk-field></nk-danger-zone>
<divclass="nk-danger-zone"><divclass="dz-title">Danger zone</div><divclass="nk-field"><div><divclass="f-label">Delete workspace</div><divclass="f-desc">Deleting the workspace removes every page.</div></div><divclass="f-control"><buttonclass="nk-btn danger-solid small">Delete</button></div></div></div>
Attributes
Attribute
Type
Default
Description
title
string
β
Red heading. Read once and taken off the host, so it never shows as a tooltip.
Slots
Slot
Description
(default)
Fields and buttons.
Events
none
On a small screen:Unchanged.
Replaces.nk-danger-zone.dz-title
<nk-member-list> Member list
Rows of nk-member-row; the list marks the last row so it loses its bottom border. Each row shows avatar (initials + color), name, mail and a slot="role" control on the right.
Avatar colour: one of the nine names (gray β¦ red) or any CSS background; without it the avatar gradient.
last
boolean
β
No bottom border.
Slots
Slot
Description
role
Control on the right.
avatar
Custom avatar.
(default)
Extra content.
Events
none
On a small screen:Unchanged.
Replaces.nk-member-row
Overlays
Wave 4
<nk-modal> Settings modal
The settings overlay: backdrop, a 960Γ640 dialog with a nav column and a content column. The nav rows are rendered by the modal from the panesβ label/icon/group, so the 27px rows and the 860px icon rail come straight from the stylesheet. Escape and the backdrop close it; focus moves in and back; the page behind is scroll-locked and inert. Place it directly under <body>.
Notionβs mobile surface for menus, properties and more β the phoneβs twin of the modal, with its contract: show(), close(), toggle(); Escape and the backdrop close it; focus moves in and back; the page behind is scroll-locked and inert. The panel rises from the bottom edge with a grabber, title sits under it and names the dialog. Rows inside are 40px, a thumbβs height. Choosing a row does not close the sheet β nk-select bubbles out and the app decides. For a menu that is a popover on the desktop and a sheet on the phone, use <nk-menu floating sheet>. Place it directly under <body>.
Heading under the grabber and the dialogβs name β never a tooltip.
Slots
Slot
Description
(default)
The content: an nk-tree, menu items, fields.
Events
Event
detail
Description
nk-toggle
{ open }
Opened / closed.
Properties:opentitle
Methods:show()close()toggle()
On a small screen:Made for the phone: full width, above the tab bar, bottom padding from the safe area; the content scrolls inside the sheet. On larger screens at most 640px wide, centred.
Notionβs side peek: a database row opens at the right edge, full height, next to the table, which stays usable β no scrim, nothing inert. The bar carries Β» to close and your actions (slot="actions"); the body is the page β nk-page-title (32px here), nk-props, a .nk-prose, nk-comments. show() slides it in and moves focus to it; Β», Escape and a click elsewhere close it, and a click that calls show() again β another row β only swaps the content. Clicks inside other overlays leave it open. Place it directly under <body>. resizable gives it Notionβs drag on the left edge, inset moves the page aside instead of covering it.
Wave 4
<nk-peek open resizable resize-label="Resize" label="Database Table-View">
<nk-btnslot="actions" variant="topbar" aria-label="Open as page"><svgviewBox="0 0 24 24" aria-hidden="true"><pathd="M15 3h6v6M9 21H3v-6M21 3l-7 7M3 21l7-7"/></svg></nk-btn>
<nk-page-title>ποΈ Database Table-View</nk-page-title>
<nk-props>
<nk-proplabel="Status" icon="β"><nk-tagcolor="blue">In progress</nk-tag></nk-prop>
<nk-proplabel="Due" icon="π ">20.05.2026</nk-prop>
</nk-props>
<divclass="nk-prose"><p>Table, board and list read the same rows; filters and sort act on all three.</p></div>
</nk-peek>
<divclass="nk-peek-backdrop open"><asideclass="nk-peek" role="dialog" aria-label="Database Table-View">
<divclass="pk-resize" role="separator" aria-orientation="vertical" aria-label="Resize" tabindex="0"></div>
<divclass="pk-bar"><buttonclass="nk-topbar-btn" aria-label="Close"><svgviewBox="0 0 24 24" aria-hidden="true"><pathd="m6 17 5-5-5-5M13 17l5-5-5-5"/></svg></button><buttonclass="nk-topbar-btn" aria-label="Open as page"><svgviewBox="0 0 24 24" aria-hidden="true"><pathd="M15 3h6v6M9 21H3v-6M21 3l-7 7M3 21l7-7"/></svg></button></div>
<divclass="pk-body">
<h1class="nk-page-title">ποΈ Database Table-View</h1>
<dlclass="nk-props">
<divclass="nk-prop"><dtclass="p-name"><spanclass="p-icon">β</span>Status</dt><ddclass="p-value"><spanclass="nk-tag blue">In progress</span></dd></div>
<divclass="nk-prop"><dtclass="p-name"><spanclass="p-icon">π </span>Due</dt><ddclass="p-value">20.05.2026</dd></div>
</dl>
<divclass="nk-prose"><p>Table, board and list read the same rows; filters and sort act on all three.</p></div>
</div>
</aside></div>
Attributes
Attribute
Type
Default
Description
open
boolean
β
Shown.
label
string
β
The dialogβs name β the entryβs title.
close-label
string
Close Β· SchlieΓen
Name of Β».
resizable
boolean
β
The left edge makes it wider or narrower β pointer and arrow keys; the width is the token --nk-peek-width on :root.
width
px
560
Sets the width, within min and max.
min
px
380
Narrowest.
max
px
window β 320
Widest.
resize-label
string
Resize Β· Breite Γ€ndern
Name of the edge.
inset
boolean
β
While open on the desktop, the pageβs nk-app makes room instead of lying under it β for a chart whose bars must stay visible.
Slots
Slot
Description
(default)
The page: title, properties, prose, comments.
actions
Buttons beside Β» β open as page, share.
Events
Event
detail
Description
nk-toggle
{ open }
Opened / closed.
nk-resize
{ width }
A drag or a key changed the width β the moment to keep it.
Properties:openwidth
Methods:show()close()toggle()
On a small screen:Below 860px a bottom sheet over a dimmed page, title in 28px β and modal there: the page is inert and scroll-locked, a tap on the dimmed page closes it.
A question or a short form β βMove to trash?β, the name of a new view, the link between two tasks β with the contract of nk-modal and nk-sheet: show(), close(), toggle(), nk-toggle; Escape β captured, before a peek, a menu or a modal behind it β and the backdrop close it; focus moves in, to an [autofocus] element or the first field or button, and back; the page behind is inert and scroll-locked. It lies above the modal and the sheet. title is the heading, the default slot the text or the fields, slot="actions" the buttons, the confirming one last. A button in slot="actions" with a value closes it with that value, one anywhere inside with data-close too β another button with a value, an option of nk-segmented say, leaves it open β and so does the submit of a <form method="dialog"> inside; before it closes, nk-close fires and can be cancelled β the place to check an input. alert for a question, wide (560px) for a form. show(from) hands focus back to from β the β― of a menu that closed. Place it directly under <body>. While it is open the page behind is inert, but floating menus and date pickers under <body> β and the tooltip and toast β stay usable, so a field in the dialog can open one.
Wave 4
<nk-dialog open alert title="Move βNotionKit MVPβ to trash?">
The page and its sub-pages can be restored from Trash for 30 days.
<nk-btnslot="actions" variant="secondary" value="">Cancel</nk-btn>
<nk-btnslot="actions" variant="danger-solid" value="trash">Move to trash</nk-btn>
</nk-dialog>
<divclass="nk-dialog-backdrop open"><divclass="nk-dialog" role="alertdialog" aria-modal="true" aria-label="Move to trash">
<divclass="dl-title">Move βNotionKit MVPβ to trash?</div>
<divclass="dl-body">The page and its sub-pages can be restored from Trash for 30 days.</div>
<divclass="dl-actions"><buttonclass="nk-btn secondary">Cancel</button><buttonclass="nk-btn danger-solid">Move to trash</button></div>
</div></div>
Attributes
Attribute
Type
Default
Description
open
boolean
β
Shown.
title
string
β
Heading and the dialogβs name β never a tooltip.
alert
boolean
β
An alertdialog, described by its text.
wide
boolean
β
560px instead of 440px.
Slots
Slot
Description
(default)
The text or the fields.
actions
The buttons, right; a value closes with it.
Events
Event
detail
Description
nk-close
{ value }
About to close β cancel it to keep it open.
nk-toggle
{ open }
Opened / closed.
Properties:openreturnValuetitle
Methods:show(from)close(value)toggle()
On a small screen:Below 860px a bottom sheet with a grabber, the buttons stacked across the width, the confirming one on top.
On a small screen:Below 860px only the avatar remains.
Replaces.nk-settings-user.avatar.u-text.name.mail
<nk-cmdk> Command palette
βK. Feed it palette.commands = [{ group, items: [{ id, icon, label, shortcut, keywords, action }] }]; it searches fuzzily over label and keywords, keeps group order, moves the selection with ββ, picks with Enter or click (nk-command plus the itemβs action), and closes on Escape or the backdrop. The hotkey is mod+k unless changed. Place it directly under <body>.
A 230px context menu. Items are nk-menu-items (type="separator" / "label" for the rest); ββ move, Enter selects, nk-select bubbles up. Inside nk-pop or the workspace switcher it is part of their surface. With floating it is a menu over the page of its own, NotionKitβs .nk-pop.floating: menu.show(button) opens it under the button, right edges aligned (align="start": left edges), and it fades in like the palette. A tap outside closes it and reaches nothing else; Escape and a chosen item close it, a switch row keeps it open. Opened from the keyboard, focus moves to the first item and back when it closes. Put it directly under <body>, like the other overlays. Floating, it opens upwards where the window ends below and there is more room above, and a menu longer than the room scrolls inside; in an nk-modal or nk-dialog it sits right as well, and opened from one of them it stays usable β an open dialog, modal or sheet leaves floating menus alone.
On a small screen:With sheet the floating menu is a bottom sheet below 860px β full width, a grabber, 40px rows, the page dimmed β whatever position show() wrote: one markup, two presentations, as Notionβs mobile app opens every menu.
One row of nk-menu: icon, label, shortcut; danger for destructive actions. type switches to a separator or a group label, or to a row with a switch on the right β βSmall textβ in Notionβs page menu: a click flips checked and fires nk-change, so the menu stays open. type="check" puts a β where the shortcut stands, as in a filter menu β for a choice of several: a click flips checked and fires nk-change { value, checked } instead of nk-select, and the menu stays open.
Anchors a floating surface to a trigger. The trigger goes in slot="trigger" and toggles open; outside clicks, Escape and an nk-select from inside close it. Content is wrapped in .nk-pop unless it brings its own surface (nk-menu, nk-emoji-picker) or bare is set.
On a small screen:Positioned relative to the trigger; keep it near the viewport edge in mind.
Replaces.nk-pop
<nk-emoji-picker> Emoji picker
Search field, 8-column grid, category strip. Ships with a built-in set (names for search); picker.emojis = [{ char, name, cat }] replaces it. A click fires nk-select { emoji }.
One inverted pill at the bottom centre, above every overlay; over a tab bar at the bottom of the screen it rises 12px above the bar. toast.show("Saved") shows it and hides it after duration ms; open is the state. With an action β show("Moved to trash", { action: { label: "Undo", value: "undo" } }) or a <button slot="action"> β it is Notionβs toast with a button and an Γ: it stays until one of them is used, unless show() names a duration, and waits while the pointer or the focus is on it. The action fires nk-action and, unless cancelled, closes it; Escape closes it while the focus is inside.
Wave 4
<nk-toast open duration="0" icon="ποΈ">Moved to trash<buttonslot="action" value="undo">Undo</button></nk-toast>
Auto-hide delay (0 = stay); a toast with an action stays unless show() names one.
icon
string
β
Leading glyph.
Slots
Slot
Description
(default)
Static content (when show() gets no message).
action
A button for the action; its value goes out with nk-action.
Events
Event
detail
Description
nk-toggle
{ open }
Shown / hidden.
nk-action
{ action, value, label }
The action used; cancel it to keep the toast.
Properties:openmessage
Methods:show(message?, { duration, action: { label, value } })close()
On a small screen:Unchanged.
Replaces.nk-toast.show.t-action.t-close
<nk-tooltip> Tooltip
Notionβs hover hint in the toastβs colours, a shortcut muted beside it. One <nk-tooltip> without for serves every element with data-tooltip (and data-tooltip-key) on the page, inside shadow roots too β a whole toolbar in one element, and it follows pointer and keyboard from one such element to the next within the same shadow root; with for it belongs to one element and shows its own content and shortcut. It appears after delay ms (400) under the pointer and at once on keyboard focus, never on touch; leaving β the window too β, a press, blur, scrolling and Escape hide it. It sits 6px below its target and centred, above it where the window ends, 8px inside the window β placeNear in util/floating.js. show(target, text, shortcut) takes an element or a rect, for what has no element of its own: the bars of a chart. The targetβs aria-describedby names it while it shows. Hover the buttons. A tooltip shown with show(rect, β¦) stays until hide(), the pointer on another [data-tooltip], a press or Escape; the wheel hides it too, also inside a shadow root. A line break in the text is kept.
β―ββ°
Open sidebar
<divstyle="display:flex;gap:16px;align-items:center;padding:4px 0 44px">
<nk-btnvariant="topbar" aria-label="Style, export and more" data-tooltip="Style, export and more">β―</nk-btn>
<nk-btnvariant="topbar" aria-label="Add to Favourites" data-tooltip="Add to Favourites">β</nk-btn>
<nk-btnvariant="topbar" id="ttSidebar" aria-label="Open sidebar">β°</nk-btn>
</div>
<nk-tooltip></nk-tooltip>
<nk-tooltipfor="ttSidebar" shortcut="β\">Open sidebar</nk-tooltip>
Attributes
Attribute
Type
Default
Description
for
id
β
The one element it belongs to; without it, every [data-tooltip].
shortcut
string
β
With for: the shortcut beside the text.
delay
ms
400
Wait under the pointer.
placement
bottom | top
bottom
Preferred side.
Slots
Slot
Description
(default)
With for: the text.
Events
none
Properties:open
Methods:show(target, text, shortcut)hide()
On a small screen:No hover on a phone: it shows nothing on touch.
Replaces.nk-tooltip.open.tt-key
Data & collaboration
Wave 5
<nk-database> Database
The view switcher with Notionβs toolbar: child views (nk-table-view, nk-board-view, nk-list-view) become the tabs on the left, slot="tools" holds the viewβs tools on the right β <nk-btn variant="tool"> for Filter, Sort and search, then βNewβ β and slot="filters" the nk-filter-bar under them. columns and rows are pushed into every view. view selects the active one; count on a view shows the row count as badge. No fetching: give it data, listen to events.
The tools right of the tabs: <nk-btn variant="tool">, a small primary βNewβ.
filters
Under the toolbar: nk-filter-bar.
Events
Event
detail
Description
nk-view-change
{ view }
Tab switched.
nk-action
{ action: 'add-view' }
οΌ clicked.
nk-select / nk-change / nk-action
(from the views)
Bubble up from the active view.
Properties:columnsrowsviewviews
Methods:refresh()
On a small screen:The tabs scroll sideways when the row gets narrow; the tools keep their place. Tables and boards scroll horizontally; nothing breaks.
Renders columns Γ rows as the NotionKit table. Cells are polymorphic (text, select, multi-select, date, person, checkbox, url, number, progress) and rendered as plain markup by the exported renderPropertyCell() β every cell rule starts with .nk-table, so a cell element of its own would never be styled. Header clicks sort with sortable. A number column stands right-aligned in figures of equal width, formatted by its locale and format (Intl.NumberFormat options); a personβs color takes one of the nine names. A column of type actions (NotionKit 1.12.0) sets buttons in each row from column.actions β [{ action, label, icon, danger, disabled, tooltip }] β, and a rowβs value β a list of action names β picks which of them it shows; a click fires nk-action { action, row, id, anchor } instead of selecting the row. A url value may be { href, label, target }: a link of your own, to another page of the app, with its own text. A text value may be { text, desc, color, tooltip } (NotionKit 1.15.0): a quiet second line, one of Notionβs nine text colours β orange for an error β, the whole text in a tooltip. Sorting goes by the value, not the text shown: dates by their time, selects by the order of their options, empty cells last; sortKey on a column sorts by another field of the row, a sort in a cellβs object by that value. A date column with format β 'short', 'relative' or the options of Intl.DateTimeFormat β shows ISO dates and date-times formatted in its locale. A checkbox column with selectAll: true (1.21.0) is a selection column: its header is a checkbox β empty, a dash for some rows, a check for all β that sorts nothing; a click or Space sets the column for every row the view has (a dash selects all, as in Notion) and fires one nk-change { key, value, all: true, rows }. What βallβ means beyond these rows β more pages, a filter on the server β stays with the app. Its name comes from the texts (selectAll).
Groups rows by a select column (group-by, default: the first select column) into one column per option. Cards show the title column and the meta-keys (default: dates and progress). Drag a card onto another column: the rowβs value changes and nk-change fires.
The third database view: one line per row β icon and title, the meta-keys on the right (default: the select and date columns, in column order). Dates and text stand as text, selects as tags, a person as avatar and name. Rows fire nk-select; new-row adds the add row.
The fourth database view (NotionKit 1.9.0): a month, the rows as cards on their dates. date-key names the date column (default: the first one) β YYYY-MM-DD or D.M.YYYY, a range on its start. Today sits on a red pill, days of other months are washed; weeks puts the calendar week in front, weekend washes the days not worked. A card fires nk-select like a row of the table; Today and βΉ βΊ change the month (nk-month). In nk-database it is a tab like the others and shows the same rows.
The fifth database view: the rows as cards with a picture on top, in a grid that fills the row β Notionβs gallery, for a course catalog or a reading list. cover-key names the row field with the pictureβs URL (default: cover); a row without one shows the cover gradient, no-cover leaves the pictures out. The picture stands in 2:1, cropped to fill; fit shows it whole, for logos. size small, medium or large sets the card size β columns from 180, 260 or 340px. Cards show the title and the meta-keys (default: the select and date columns) and fire nk-select on a click, Enter or Space; new-row adds the add card. href-key names the row field with a cardβs address: such a card is a link, <a class="nk-card" href> in a .card-item that carries the list itemβs role β to open a course in a new tab or copy its address. A plain click, and Enter, fire the same nk-select; cancel it and the browser stays. A middle click or one with Cmd, Ctrl, Shift or Alt fires nothing and does what a link does.
The filters in effect as NotionKitβs filter pills β .active with an accent tint, a Γ to remove each, a quiet add pill at the end β with no inline style. In slot="filters" of nk-database the row sits under the toolbar. A pillβs label fires nk-action { action: "edit" }, the add pill { action: "add" }, each with the clicked button as anchor for menu.show(anchor). bar.apply(rows) keeps rows where every filter matches by strict equality (row[key] === value, so use the option value) β or differs with op: "is-not" β and the search text appears in any string field (a personβs name); the data logic stays yours. Its own Filter and Sort tools and the search field are there for a bar without a database toolbar. It keeps its own copy of filters: the array you pass is never changed, a removed pill is reported in nk-change.
A left-ruled thread of nk-comments with an input row. Enter or the button fires nk-submit { text }; appending the new comment is yours.
Wave 5
The board view already feels very close to the original. πAII have flagged the overdue entries and prepared a summary.
SL
Sara Lindt Β· 1 hr ago
The board view already feels very close to the original. π
β¨
MonaAI Β· 20 min ago
I have flagged the overdue entries and prepared a summary.
<nk-commentsplaceholder="Comment β¦" send-label="Send">
<nk-commentauthor="Sara Lindt" time="1 hr ago" color="#448361">The board view already feels very close to the original. π</nk-comment>
<nk-commentauthor="Mona" time="20 min ago" avatar="β¨" color="var(--nk-text-tertiary)"><spanslot="head" class="nk-tag blue" style="font-size:10.5px">AI</span>I have flagged the overdue entries and prepared a summary.</nk-comment>
</nk-comments>
<divclass="nk-comments">
<divclass="nk-comment"><spanclass="mini-avatar" style="background:#448361">SL</span><div><divclass="c-head"><b>Sara Lindt</b> Β· 1 hr ago</div><divclass="c-body">The board view already feels very close to the original. π</div></div></div>
<divclass="nk-comment"><spanclass="mini-avatar" style="background:var(--nk-text-tertiary)">β¨</span><div><divclass="c-head"><b>Mona</b><spanclass="nk-tag blue" style="font-size:10.5px">AI</span> Β· 20 min ago</div><divclass="c-body">I have flagged the overdue entries and prepared a summary.</div></div></div>
<divclass="nk-comment-input"><inputclass="nk-input" placeholder="Comment β¦"><buttonclass="nk-btn primary small">Send</button></div>
</div>
Attributes
Attribute
Type
Default
Description
placeholder
string
β
Input placeholder.
send-label
string
Send Β· Senden
Button text.
no-input
boolean
β
Read-only thread.
disabled
boolean
β
Input disabled.
Slots
Slot
Description
(default)
nk-comment children.
Events
Event
detail
Description
nk-submit
{ text }
New comment typed; preventDefault() keeps the text.
One comment: avatar (initials + color), bold author, time, body. slot="head" adds content after the name.
Wave 5
The board view already feels very close to the original. π
SL
Sara Lindt Β· 1 hr ago
The board view already feels very close to the original. π
<nk-comments no-input><nk-commentauthor="Sara Lindt" time="1 hr ago" color="green">The board view already feels very close to the original. π</nk-comment></nk-comments>
<divclass="nk-comments"><divclass="nk-comment"><spanclass="nk-avatar green">SL</span><div><divclass="c-head"><b>Sara Lindt</b> Β· 1 hr ago</div><divclass="c-body">The board view already feels very close to the original. π</div></div></div></div>
Attributes
Attribute
Type
Default
Description
author
string
β
Name.
time
string
β
Relative time.
avatar
string
β
Initials/emoji (default: from the author).
color
colour name | CSS
β
Avatar colour: one of the nine names or any CSS background; without it the avatar gradient.
Slots
Slot
Description
(default)
Body.
head
After the name (tag, badge).
avatar
Custom avatar.
Events
none
On a small screen:Unchanged.
Replaces.nk-comment.c-head.c-body
<nk-ai-thread> AI thread
The conversation column: nk-ai-msg children (role="user" gets the gradient avatar), followed by an nk-ai-input-row. Action buttons in slot="actions" fire nk-action { action, value } β both carry the buttonβs value (or its text).
Wave 5
Summarise the open tasks for this project.Two tasks are open: the table view sits at 65 % (due 20 May), the board with drag and drop is planned.
MK
You
Summarise the open tasks for this project.
β¨
Mona Β· AI
Two tasks are open: the table view sits at 65 % (due 20 May), the board with drag and drop is planned.
β¨
<nk-ai-thread>
<nk-ai-msgrole="user" name="You" avatar="MK">Summarise the open tasks for this project.</nk-ai-msg>
<nk-ai-msgrole="assistant" name="Mona" badge="Β· AI">Two tasks are open: the <b>table view</b> sits at 65 % (due 20 May), the <b>board with drag and drop</b> is planned.
<buttonslot="actions" value="copy">π Copy</button><buttonslot="actions" value="rephrase">β» Rephrase</button><buttonslot="actions" value="like">π</button>
</nk-ai-msg>
</nk-ai-thread>
<nk-ai-input-rowplaceholder="Ask Mona something β¦"></nk-ai-input-row>
<divclass="nk-ai-thread">
<divclass="nk-ai-msg user"><spanclass="mini-avatar">MK</span><divclass="a-body"><divclass="a-name">You</div>Summarise the open tasks for this project.</div></div>
<divclass="nk-ai-msg"><spanclass="mini-avatar">β¨</span><divclass="a-body"><divclass="a-name">Mona <span>Β· AI</span></div>Two tasks are open: the <b>table view</b> sits at 65 % (due 20 May), the <b>board with drag and drop</b> is planned.<divclass="nk-ai-actions"><button>π Copy</button><button>β» Rephrase</button><button>π</button></div></div></div>
</div>
<divclass="nk-ai-input-row"><spanstyle="font-size:14px">β¨</span><inputplaceholder="Ask Mona something β¦"><buttonclass="nk-ai-send">β</button></div>
One message. role="user" flips the avatar to the gradient; badge is the grey suffix after the name (βΒ· AIβ); plain <button slot="actions">s form the action row.
Wave 5
What is still open on this page?Two tasks are open: the table view sits at 65 % (due 20 May), the board with drag and drop is planned.
What is still open on this page?
β¨
Mona Β· AI
Two tasks are open: the table view sits at 65 % (due 20 May), the board with drag and drop is planned.
<nk-ai-thread><nk-ai-msgrole="user" bubble>What is still open on this page?</nk-ai-msg><nk-ai-msgrole="assistant" name="Mona" badge="Β· AI">Two tasks are open: the <b>table view</b> sits at 65 % (due 20 May), the <b>board with drag and drop</b> is planned.<buttonslot="actions" value="copy">π Copy</button></nk-ai-msg></nk-ai-thread>
<divclass="nk-ai-thread"><divclass="nk-ai-msg user bubble"><divclass="a-body">What is still open on this page?</div></div><divclass="nk-ai-msg"><spanclass="mini-avatar">β¨</span><divclass="a-body"><divclass="a-name">Mona <span>Β· AI</span></div>Two tasks are open: the <b>table view</b> sits at 65 % (due 20 May), the <b>board with drag and drop</b> is planned.<divclass="nk-ai-actions"><button>π Copy</button></div></div></div></div>
Attributes
Attribute
Type
Default
Description
role
user | assistant
assistant
Who speaks.
name
string
β
Name line.
badge
string
β
Grey suffix.
avatar
string
β
Initials/emoji.
color
CSS color
β
Avatar background override.
bubble
boolean
β
The message as a grey bubble without avatar or name; with role="user" on the right, as Notionβs AI chat shows your own question.