Jede Komponente mit Live-Vorschau, dem Markup zum Kopieren, den beteiligten Klassen und ihrem Verhalten auf kleinen Schirmen. Nichts hier ist aus einem Screenshot erzeugt – die Vorschauen sind echt.
Installation
Ein Stylesheet. Nimm den Weg, der zu deinem Projekt passt.
html<!-- CDN -->
<linkrel="stylesheet" href="https://cdn.jsdelivr.net/npm/@jungherz-de/notionkit@1/notionkit.min.css">
<!-- local -->
<linkrel="stylesheet" href="notionkit.css">
<!-- your own theme, after the library -->
<linkrel="stylesheet" href="theme-override.css">
htmlnpm install @jungherz-de/notionkit
Das Theme sitzt auf <html>. Hell ist die Vorgabe, das Attribut braucht es also nur für Dunkel:
Ergänze class="nk-body" an deinem <body>, um Schrift, Hintergrund und Textfarbe zu übernehmen. Das ist opt-in: Ohne diese Klasse fasst NotionKit nichts außerhalb seiner eigenen Klassen an.
Design-Tokens
Jeder visuelle Wert ist eine Custom Property. Die beiden Blöcke unten sind die gesamte Token-Fläche – :root für Hell, [data-theme="dark"] für die Abweichungen.
Token
Hell
Dunkel
Bedeutung
--nk-bg
#ffffff
#191919
Seitenhintergrund
--nk-bg-sidebar
#f7f6f3
#202020
Sidebar und Settings-Navigation
--nk-bg-hover
rgba(0,0,0,0.045)
rgba(255,255,255,0.055)
Hover-Hauch – eine Verdunkelung, nie ein Farbwechsel
--nk-bg-active
rgba(0,0,0,0.06)
rgba(255,255,255,0.08)
Aktive/ausgewählte Zeile
--nk-bg-callout
#f1f1ef
#252525
Callouts, Badges, Tasten, Segment-Schiene
--nk-bg-code
#f7f6f3
#202020
Hintergrund von Code-Blöcken
--nk-bg-card
#ffffff
#202020
Board-Karten – getrennt von --nk-bg, damit Dark Mode sie abheben kann
--nk-text
#37352f
rgba(255,255,255,0.81)
Fließtext. Nie reines Schwarz
--nk-text-secondary
rgba(55,53,47,0.65)
rgba(255,255,255,0.46)
Sekundärtext, inaktive Baum-Einträge
--nk-text-tertiary
rgba(55,53,47,0.45)
rgba(255,255,255,0.28)
Meta, Platzhalter, Bildunterschriften
--nk-border
rgba(55,53,47,0.09)
rgba(255,255,255,0.094)
Haarlinien-Trenner
--nk-border-strong
rgba(55,53,47,0.16)
rgba(255,255,255,0.16)
Input-Rahmen, Scrollbar-Griffe, gestrichelte Rahmen
--nk-accent
#2383e2
#529CCA
Die eine Markenfarbe. Alles Akzentuierte wird daraus gemischt
Rebranding ist eine Deklaration. Alles Abgeleitete – Fokusring, Checked-Zustände, ausgewählte Modell-Karte, Danger-Hover – wird per color-mix() aus einem Token gemischt und zieht mit:
html:root {
--nk-accent: #16a34a;
}
Theming
Umgeschaltet wird über ein Attribut. Mehr bewegt sich nicht.
html<htmldata-theme="light"> <!-- default, the attribute may be omitted -->
<htmldata-theme="dark">
Die Token-Blöcke setzen auch color-scheme, damit vom Browser gezeichnete Oberflächen – Datumswähler, Zahlenfelder, Select-Popups, Scrollbars, Autofill – dem Theme ohne Zutun folgen.
Rebranding live sehen: der 🎨-Button in der Kopfleiste wendet die Beispiel-Paletten aus theme-override.css (Forest, Slate, Sunset, Hoher Kontrast) direkt auf diese Seite an. Die Demo-App hat denselben Schalter unter Einstellungen → Darstellung.
Zustandsklassen
NotionKit liefert Zustände, kein Verhalten. Diese Klassen setzt und entfernst du selbst; in der Library steckt kein JavaScript.
Markiert das aktuelle Element. Baum-Einträge bekommen den Aktiv-Hintergrund, Reiter die Unterlinie, Panes werden sichtbar.
.open
nk-modal-backdropnk-cmdk-backdropnk-toggle-arrow
Blendet das Overlay ein und macht es bedienbar; dreht den Toggle-Pfeil um 90°.
.collapsed
nk-tree-children
Klappt einen Unterbaum per display: none weg.
.selected
nk-cmdk-itemnk-model-cardnk-slash-item
Die per Tastatur hervorgehobene oder gewählte Option. Anders als active: Auswahl ist flüchtig, active ist der Ort, an dem du bist.
.show
nk-toast
Fährt den Toast von unten hoch und blendet ihn ein.
.aria-checked="true"
nk-switch (button form)
Füllt die Schiene mit dem Akzent und schiebt den Knopf. Ein Attribut, keine Klasse – der Zustand wird so auch an assistive Technik gemeldet.
.:checked
nk-todo inputnk-check inputnk-switch (input form)
Nativer Zustand. Zeichnet Haken oder Punkt und streicht ein To-do-Label durch.
.nk-drop-target
nk-block-host
Drag-Rückmeldung: eine 2px-Akzentlinie über dem Block.
Kontraste
Gemessene Kontrastwerte der Standardpalette, jeweils gegen die Fläche, auf der das Paar tatsächlich sitzt. Fließtext erfüllt WCAG AA in beiden Themes deutlich. Sekundär- und Tertiärtext, die Tag-Paare, die Beschriftung des Primärbuttons und die Danger-Farbe liegen unter 4,5:1 – das sind Notions eigene Werte, bewusst beibehalten.
Paar
Hell
Dunkel
AA Fließtext
--nk-text / --nk-bg
12.26
11.78
✓
--nk-text / --nk-bg-sidebar
11.35
11.06
✓
--nk-text-secondary / --nk-bg
4.19
4.63
✗
--nk-text-tertiary / --nk-bg
2.49
2.53
—
--nk-accent / --nk-bg
3.88
5.83
—
--nk-on-accent / --nk-accent
3.88
3.01
✗
--nk-danger / --nk-bg
3.48
5.05
✗
tag blue
3.95
4.57
—
tag green
3.99
4.48
—
tag orange
2.83
6.82
—
tag purple
4.09
3.84
—
Wenn dein Projekt überall AA braucht: theme-override.css enthält einen fertigen High-Contrast-Block. Einkommentieren hebt die durchgefallenen Paare an, der Rest des Designs bleibt unangetastet.
Editor-Integration
NotionKit liefert keinen Editor. Was es liefert, ist .nk-block-host – die optische Hülle – plus eine darin gescopte, gestylte Adapter-Schicht. Der Integrationsvertrag ist eine Klasse am Host-Element.
TipTap / ProseMirror – der Vanilla-JS-Weg
TipTap als ES-Modul von einem CDN laden und in ein Element mit nk-block-host einhängen. Den Rest erledigen die Adapter-Regeln: Typografie, Überschriften, Listen, Zitate, Code, Links, Selektion und Placeholder werden aus --nk-*-Tokens gestylt.
html<divclass="nk-block-host" id="editor"></div><scripttype="module">
import { Editor } from 'https://esm.sh/@tiptap/core@2';
import StarterKit from 'https://esm.sh/@tiptap/starter-kit@2';
import Placeholder from 'https://esm.sh/@tiptap/extension-placeholder@2';
new Editor({
element: document.getElementById('editor'),
extensions: [StarterKit, Placeholder.configure({ placeholder: 'Type "/" for commands …' })],
content: '<p>Hello NotionKit.</p>',
});
</script>
BlockNote – der React-Weg
Dieselbe Idee: die BlockNote-View in einem Block-Host rendern. .bn-container, .bn-editor, .bn-block-content, Side-Menu und Drag-Handle sind abgedeckt, und .bn-suggestion-menu übernimmt die Slash-Menü-Optik automatisch.
Novel baut auf ProseMirror auf, die TipTap-Regeln greifen also bereits. .novel-editor und .novel-prose bekommen Schrift und Farbe, und die Prosa-Breitenbegrenzung wird gelöst, damit die Seitenspalte sie bestimmt.
Der Editor unten ist echtes TipTap, von einem CDN geladen, ohne eigenes CSS. Fahre über einen Block für die + / ⠿-Leiste und zieh ihn, markiere Text für die Bubble-Toolbar, drücke / für das Slash-Menü und schalte das Theme um – alles Sichtbare kommt aus dem Adapter-Abschnitt von notionkit.css.
Das vollständige Rezept – Slash-Menü auf @tiptap/suggestion, Bubble-Toolbar, Block-Handle mit Drag & Drop und Block-Menü – ist docs-editor.js, rund 300 Zeilen schlichtes JavaScript. Es setzt NotionKit-Klassen auf sein DOM (nk-slash-menu, nk-bubble-menu, nk-block-actions, nk-menu) und überlässt den Rest dem Stylesheet.
Web Components
Das Stylesheet wird zweigeteilt ausgeliefert, damit Web Components die Komponentenregeln adoptieren können, ohne die Tokens in ihren Shadow Roots neu zu deklarieren.
htmlimport { componentsSheet, tokensCss } from '@jungherz-de/notionkit/notionkit-styles.js';
// Tokens go on the document once, wrapped in a layer so a brand
// stylesheet wins no matter the load order.
const tokens = new CSSStyleSheet();
tokens.replaceSync(`@layer notionkit-defaults { ${tokensCss} }`);
document.adoptedStyleSheets = [...document.adoptedStyleSheets, tokens];
class NkCallout extends HTMLElement {
constructor() {
super();
const root = this.attachShadow({ mode: 'open' });
root.adoptedStyleSheets = [componentsSheet]; // components only
}
}
Warum die Teilung zählt
Ein Shadow Root, der das ganze Sheet adoptiert, adoptiert auch die :root- und [data-theme]-Blöcke. In diesem Root treffen die Selektoren den eigenen Theme-Wrapper des Elements, jedes Token wird also lokal neu deklariert – und eine treffende Regel schlägt immer einen geerbten Wert. Ein :root { --nk-accent: … } des Consumers käme nie an. Also nur componentsSheet adoptieren und tokensCss aufs Dokument legen.
Die ::slotted()-Zwillinge
Von außen übergebener Inhalt bleibt im Light DOM und ist kein Nachfahre von irgendetwas im Shadow Tree – .nk-callout .c-icon erreicht ihn also nicht. Jede solche Regel hat deshalb einen ::slotted()-Zwilling daneben, 92 an der Zahl – darunter ein [slot="…"]-Zwilling für jeden benannten Slot von NotionKit Elements. Zwei Grenzen: ::slotted() trifft nur den zugewiesenen Knoten, nie etwas darin (Icons direkt übergeben, nie verpackt), und bei geslottetem Inhalt gewinnt der äußere Baum gegen den Shadow Tree.
Ein lauffähiger Nachweis liegt als elements-poc.html bei – ein <nk-callout> und ein <nk-tag color="…">, die componentsSheet adoptieren, über data-theme umthemen und das Branding der Seite übernehmen. Die Seite misst das live (sie braucht einen Build und einen Server: npm run build, dann den Ordner ausliefern).
App-Shell & Layout
PRD 5.1
App-Shell .nk-app
nk-app ist eine flex-Zeile über die volle Höhe: Sidebar links, Hauptspalte rechts. Es ist das äußerste Element einer Workspace-App und der einzige Ort, an den eine feste Höhe gehört. In der Sidebar ist nk-sidebar-scroll der scrollende Baumbereich und nk-sidebar-footer der fixierte Fuß (Einstellungen, Papierkorb).
📊 Projektübersicht
Produkt-Roadmap
Ein kurzer Lead-Absatz führt in die Seite ein – ruhiger und etwas größer gesetzt als der Fließtext, der darunter beginnt.
html<divclass="nk-app" style="height:100%"><asideclass="nk-sidebar"><divclass="nk-workspace"><divclass="avatar">A</div>Acme GmbH<spanclass="chev">⌄</span></div><divclass="nk-sidebar-scroll"><divclass="nk-tree-item"><spanclass="icon">🔍</span><spanclass="label">Suche</span></div><divclass="nk-tree-item active"><spanclass="icon">🏠</span><spanclass="label">Start</span></div><divclass="nk-tree-item"><spanclass="icon">📥</span><spanclass="label">Posteingang</span></div></div><divclass="nk-sidebar-footer"><divclass="nk-tree-item"><spanclass="icon">⚙️</span><spanclass="label">Einstellungen</span></div></div></aside><mainclass="nk-main"><headerclass="nk-topbar"><divclass="nk-breadcrumb"><spanclass="crumb current">📊 Projektübersicht</span></div><divclass="nk-topbar-actions"><buttonclass="nk-topbar-btn nk-share-btn">Teilen</button></div></header><divclass="nk-page-scroll"><divclass="nk-page" style="padding-top:16px"><h1class="nk-page-title" style="font-size:28px">Produkt-Roadmap</h1><pclass="lead">Ein kurzer Lead-Absatz führt in die Seite ein – ruhiger und etwas größer gesetzt als der Fließtext, der darunter beginnt.</p></div></div></main></div>
Auf kleinem Schirm:Unter 860px verschwindet die Sidebar vollständig, die Hauptspalte nimmt die volle Breite. Eine Off-Canvas-Schublade ist Sache des Consumers (und eine geplante Elements-Komponente).
Auf kleinem Schirm:Verschwindet unter 860px zusammen mit der Sidebar.
.nk-workspace.avatar.chev
Topbar .nk-topbar
Eine 45px hohe Zeile: links der Breadcrumb, rechts die Aktionen. nk-topbar-actions schiebt sich per margin-left:auto nach rechts – ein Platzhalter ist nie nötig.
Auf kleinem Schirm:Bricht um, statt zu kürzen. Auf kleinen Schirmen den Pfad serverseitig kürzen.
.nk-breadcrumb.crumb.sep.current
Abschnitts-Label .nk-section-label
Die kleine Versal-Beschriftung zwischen Sidebar-Gruppen. Das .plus erscheint erst beim Hovern – so bleibt die Hinzufügen-Aktion erreichbar, ohne die Leiste zu schmücken.
Auf kleinem Schirm:In der Settings-Navigation unter 860px ausgeblendet, wo diese auf Icons zusammenschrumpft.
.nk-section-label.plus
Navigation / Seitenbaum
PRD 5.2
Baum-Eintrag .nk-tree-item
Das Arbeitstier der Sidebar. Mindesthöhe 28px, das Label kürzt mit Ellipse, und der .actions-Block bleibt bis zum Hovern verborgen. .active markiert die aktuelle Seite.
Auf kleinem Schirm:Kommt auf 28px und liegt damit unter dem 44px-Touch-Ziel. In einer Touch-Schublade min-height am Eintrag anheben – die Klasse erzwingt keine Höhe.
.nk-tree-item.icon.label.actions.active.compact
Unterbaum & Toggle-Pfeil .nk-tree-children
Kinder rücken unter einer Führungslinie ein. .collapsed klappt sie weg, .open am Pfeil dreht ihn um 90°. Beides sind reine Zustandsklassen – das Umschalten übernimmst du.
Auf kleinem Schirm:Unverändert; die Einrückung bleibt bei 14px, damit tiefe Bäume in eine schmale Leiste passen.
.nk-tree-children.collapsed.nk-toggle-arrow.open
Tastatur-Hinweis .nk-kbd
nk-kbd-hint schiebt ein Kürzel an den rechten Rand einer Zeile; nk-kbd ist die Taste selbst. Bewusst präfixiert – eine nackte kbd-Regel würde in die Host-Seite lecken.
Auf kleinem Schirm:Kann bleiben, trägt aber nicht: Touch-Geräte haben dieses Kürzel nicht.
.nk-kbd-hint.nk-kbd
Seiten-Shell & Dokument
PRD 5.3
Seitenspalte .nk-page
Die Dokumentspalte: max-width: 760px mit Auto-Rändern, nie eine feste Breite. Das Icon zieht sich per negativem Rand über das Cover; der Titel ist contenteditable-fähig.
🚀
Produkt-Roadmap
👤 Ada Lovelace📅 Erstellt am 12. Mai 2026
Ein kurzer Lead-Absatz führt in die Seite ein – ruhiger und etwas größer gesetzt als der Fließtext, der darunter beginnt.
html<divclass="nk-page-scroll" style="height:100%"><divclass="nk-cover" style="height:120px"></div><divclass="nk-page" style="padding-bottom:24px"><divclass="nk-page-icon">🚀</div><h1class="nk-page-title" contenteditable="true">Produkt-Roadmap</h1><divclass="nk-page-meta"><span>👤 Ada Lovelace</span><span>📅 Erstellt am 12. Mai 2026</span></div><pclass="lead">Ein kurzer Lead-Absatz führt in die Seite ein – ruhiger und etwas größer gesetzt als der Fließtext, der darunter beginnt.</p></div></div>
Auf kleinem Schirm:Der Seitenabstand fällt unter 860px von 64px auf 24px. Die 760px-Grenze greift dort schlicht nicht.
Ein 200px hohes Zierband über der Seite. Drei radiale Verläufe, gemischt aus den --nk-decor-*-Tokens über --nk-bg-callout. Für ein Foto den ganzen background ersetzen.
Auf kleinem Schirm:Feste 200px Höhe, randlos. Auf kurzen Schirmen bei Bedarf selbst reduzieren.
.nk-cover
Überschriften & Lead .nk-heading
nk-heading ist die Abschnitts-Überschrift im Dokument – eine flex-Zeile, damit ein Emoji ohne Zusatz-Markup auf der Grundlinie sitzt. p.lead ist der größere Einstiegsabsatz in nk-page.
✅ So funktioniert das
Ein kurzer Lead-Absatz führt in die Seite ein – ruhiger und etwas größer gesetzt als der Fließtext, der darunter beginnt.
html<divclass="nk-page" style="padding:0;max-width:none"><h2class="nk-heading">✅ So funktioniert das</h2><pclass="lead">Ein kurzer Lead-Absatz führt in die Seite ein – ruhiger und etwas größer gesetzt als der Fließtext, der darunter beginnt.</p></div>
Auf kleinem Schirm:Unverändert. Der Seitentitel bleibt 40px; bei Bedarf auf dem Handy selbst verkleinern.
.nk-heading.lead
Inhalts-Elemente
PRD 5.4
Callout .nk-callout
Ein getönter Block für den einen Gedanken, der nicht übersehen werden darf. Das Icon ist ein .c-icon-Kind und hat einen ::slotted()-Zwilling – <nk-callout> kann es später per Slot annehmen.
💡
Leitidee: Ein Callout trägt genau einen Gedanken, der nicht übersehen werden darf. Ein bis zwei Sätze reichen.
html<divclass="nk-callout"><spanclass="c-icon">💡</span><div><b>Leitidee:</b> Ein Callout trägt genau einen Gedanken, der nicht übersehen werden darf. Ein bis zwei Sätze reichen.</div></div>
Auf kleinem Schirm:Fließt natürlich; das Icon bleibt in der ersten Zeile, weil die Zeile align-items: flex-start nutzt.
.nk-callout.c-icon
To-do .nk-todo
Eine Checkbox mit eigenem Haken. Der Geschwister-Selektor input:checked + span streicht das Label durch – beide Hälften liegen in einer Komponente und überstehen den Umzug in einen Shadow Root.
Auf kleinem Schirm:Die 16px-Box liegt unter dem Touch-Minimum. In ein <label> packen, damit die ganze Zeile tippbar ist.
.nk-todo
Toggle .nk-toggle
Auf nativem <details>/<summary> gebaut – öffnet und schließt ohne eine Zeile JavaScript. Der Marker ist ein ::before, das sich bei [open] dreht.
Was ist nicht enthalten?
Der Text-Editor selbst. NotionKit liefert die optische Hülle; TipTap, BlockNote oder Novel hängst du hinein.
html<detailsclass="nk-toggle" open><summary>Was ist nicht enthalten?</summary><divclass="toggle-body">Der Text-Editor selbst. NotionKit liefert die optische Hülle; TipTap, BlockNote oder Novel hängst du hinein.</div></details>
Auf kleinem Schirm:Die Summary-Zeile ist bequem tippbar. Natives Verhalten auf allen Plattformen.
.nk-toggle.toggle-body
Zitat & Trenner .nk-quote
Ein Blockzitat mit durchgezogener linker Linie, dazu der waagerechte Trenner. nk-divider ist für ein <hr> gedacht und setzt dessen eigenen Rahmen zurück.
Design ist nicht, wie etwas aussieht. Design ist, wie es funktioniert.— Steve Jobs
html<blockquoteclass="nk-quote">Design ist nicht, wie etwas aussieht. Design ist, wie es funktioniert.<citeclass="q-cite">— Steve Jobs</cite></blockquote><hrclass="nk-divider">
Auf kleinem Schirm:Unverändert.
.nk-quote.q-cite.nk-divider
Inline-Erwähnungen .nk-mention
Drei Varianten im Fließtext: .person mit Mini-Avatar, .page haarfein unterstrichen, .date in der orangen Tag-Farbe. Alle sind inline-flex und brechen nie mitten in der Erwähnung.
Auf kleinem Schirm:white-space: nowrap hält jede Erwähnung zusammen; der Absatz bricht darum herum.
.nk-mention.person.page.date.mini-avatar
Code .nk-code
Ein Block mit Sprach-Badge in der Ecke und zwei Farb-Haken – .tag nimmt den Akzent, .attr die orange Tag-Farbe. nk-inline-code ist die Variante im Satz.
Auf kleinem Schirm:white-space: pre plus overflow-x: auto: Lange Zeilen scrollen im Block, statt die Seite zu verschieben.
.nk-code.lang.tag.attr.nk-inline-code
Datenbank-Views
PRD 5.5
View-Reiter .nk-db-tabs
Die Leiste über einer Datenbank. Der aktive Reiter wird durch eine 2px-Unterlinie in Textfarbe markiert, nicht durch eine Füllung. Das .badge-Kind trägt die Zeilenzahl.
Auf kleinem Schirm:Bei mehr als drei, vier Views overflow-x: auto an die Leiste geben.
.nk-database.nk-db-tabs.nk-db-tab.active.badge
Tabellen-Ansicht .nk-table
Kopfzellen sind ruhig und klickbar, Zeilen heben sich beim Hovern hervor, und jede Zelle ist white-space: nowrap, damit Spalten ihre Form behalten. .nk-new-row ist die Hinzufügen-Zeile unten (innerhalb von .nk-table funktioniert die Kurzform .new-row weiter).
Auf kleinem Schirm:Das ist der entscheidende Fall: nk-table-wrap scrollt horizontal, damit die Tabelle die Seite nie breiter macht. Die Tabelle immer einwickeln.
Vier semantische Farben, je ein Hintergrund/Text-Paar pro Theme. Die Paare sind für Hell und Dunkel getrennt abgestimmt, nicht per Deckkraft abgeleitet.
Auf kleinem Schirm:Feste 110px Breite, damit er in einer Tabellenzelle lesbar bleibt. Für volle Breite überschreiben.
.nk-progress.nk-progress-label
Board-Ansicht .nk-board
Feste 220px-Spalten in einer horizontal scrollenden Zeile. nk-board ist standardmäßig display:none, damit es neben einer Tabellen-Ansicht liegen kann; .active zeigt es.
Eine gemeinsame Form für alle drei. Der Fokusring ist color-mix(in srgb, var(--nk-accent) 25%, transparent) und färbt sich mit dem Akzent um. .wide füllt die Zeile.
html<divstyle="display:flex;flex-direction:column;gap:10px;max-width:340px"><inputclass="nk-input wide" value="Ada Lovelace"><selectclass="nk-select wide"><option>Hell</option><option>Dunkel</option><option>System</option></select><textareaclass="nk-textarea wide" placeholder="Ein paar Worte über dich …"></textarea></div>
Auf kleinem Schirm:min-width: 210px kann eine schmale Feldzeile sprengen – mit .wide kombinieren oder nk-field umbrechen lassen.
.nk-input.nk-textarea.nk-select.wide
Buttons .nk-btn
Fünf Varianten. Hover ist bei gefüllten Buttons eine Deckkraft-Änderung, bei umrandeten ein Hintergrund-Hauch – nie ein Farbwechsel. .small lässt sich mit jeder Variante kombinieren.
Funktioniert auf zwei Wegen: als <input type="checkbox"> über :checked oder als <button role="switch"> über aria-checked="true". Die Button-Form ist der barrierefreie Standard.
Kompakte Ansicht
Reduziert Abstände in Sidebar und Listen.
Animationen reduzieren
html<divstyle="max-width:420px"><divclass="nk-field"><div><divclass="f-label">Kompakte Ansicht</div><divclass="f-desc">Reduziert Abstände in Sidebar und Listen.</div></div><divclass="f-control"><buttonclass="nk-switch" role="switch" aria-checked="true"></button></div></div><divclass="nk-field"><div><divclass="f-label">Animationen reduzieren</div></div><divclass="f-control"><buttonclass="nk-switch" role="switch" aria-checked="false"></button></div></div></div>
Auf kleinem Schirm:34×20px – die Trefferfläche vergrößern, indem die ganze nk-field-Zeile klickbar wird.
.nk-switch.aria-checked
Checkbox & Radio .nk-check
Dieselbe 16px-Box für beides; die Radio-Variante wird über [type="radio"] erkannt und wird zum Kreis mit Punkt. Die Marken sind ::after-Inhalte, keine Bilder.
Auf kleinem Schirm:Das Label umschließt das Input, die ganze Zeile ist also die Trefferfläche.
.nk-check
Slider .nk-slider
Ein natives Range-Input, eingefärbt per accent-color: var(--nk-accent) – kein eigenes Schienen-Markup, also bleiben Tastatur und Screenreader nativ. nk-slider-value ist die Anzeige.
Auf kleinem Schirm:Die native Reglergröße liefert auf jeder Plattform eine bequeme Trefferfläche.
.nk-slider.nk-slider-value
Feld-Zeile .nk-field
Das Grundelement einer Einstellungszeile: Label und Beschreibung links, Bedienelement rechts, auseinandergeschoben per justify-content: space-between. Gestapelt ergeben sie ein ganzes Einstellungs-Pane.
Anzeigename
So wirst du im Workspace angezeigt.
E-Mail
html<divstyle="max-width:460px"><divclass="nk-field"><div><divclass="f-label">Anzeigename</div><divclass="f-desc">So wirst du im Workspace angezeigt.</div></div><divclass="f-control"><inputclass="nk-input" value="Ada Lovelace"></div></div><divclass="nk-field"><div><divclass="f-label">E-Mail</div></div><divclass="f-control"><inputclass="nk-input" value="ada@acme.com"></div></div></div>
Auf kleinem Schirm:Der 24px-Abstand hält beide Seiten getrennt; bei Bedarf selbst flex-wrap: wrap ergänzen, damit das Bedienelement eine eigene Zeile bekommt.
.nk-field.f-label.f-desc.f-control
Profil-Zeile .nk-profile-row
Ein 56px-Avatar mit zwei Aktionen daneben. Der Verlauf passt zu jedem anderen Avatar im System, weil alle dieselben zwei Decor-Tokens lesen.
Auf kleinem Schirm:Unverändert; auf sehr schmalen Schirmen rutschen die Buttons unter den Avatar.
.nk-profile-row.big-avatar
Modell-Karte .nk-model-card
Eine Radio-Gruppe als Karten. Die ausgewählte Karte mischt 6 % des Akzents in ihren Hintergrund und bekommt einen Akzent-Rahmen – beides abgeleitet und damit rebranding-fest.
Mona StandardEmpfohlen
Ausgewogenes Modell für den Arbeitsalltag. Schnell, ruhig, zuverlässig.
Mona Deep
Ausgewogenes Modell für den Arbeitsalltag. Schnell, ruhig, zuverlässig.
html<divstyle="max-width:460px"><divclass="nk-model-card selected"><divclass="m-radio"></div><div><divclass="m-name">Mona Standard<spanclass="nk-tag green">Empfohlen</span></div><divclass="m-desc">Ausgewogenes Modell für den Arbeitsalltag. Schnell, ruhig, zuverlässig.</div></div></div><divclass="nk-model-card"><divclass="m-radio"></div><div><divclass="m-name">Mona Deep</div><divclass="m-desc">Ausgewogenes Modell für den Arbeitsalltag. Schnell, ruhig, zuverlässig.</div></div></div></div>
Auf kleinem Schirm:Von Haus aus volle Breite; die Beschreibung bricht unter den Namen um.
.nk-model-card.selected.m-radio.m-name.m-desc
Gefahrenbereich .nk-danger-zone
Rahmen und Titel lesen --nk-danger; der Rahmen ist 40 % davon per color-mix() – es gibt kein zweites Rot, das synchron gehalten werden müsste.
⚠️ Gefahrenbereich
Löschen
Entfernt alle Seiten, Datenbanken und Mitglieder unwiderruflich.
html<divclass="nk-danger-zone" style="margin-top:0;max-width:460px"><divclass="dz-title">⚠️ Gefahrenbereich</div><divclass="nk-field" style="padding-top:0"><div><divclass="f-label">Löschen</div><divclass="f-desc">Entfernt alle Seiten, Datenbanken und Mitglieder unwiderruflich.</div></div><divclass="f-control"><buttonclass="nk-btn danger-solid small">Löschen</button></div></div></div>
Auf kleinem Schirm:Unverändert.
.nk-danger-zone.dz-title
Mitglieder-Zeilen .nk-member-row
Zeilen, getrennt durch eine Haarlinie. Die Regel „letzte Zeile ohne Rahmen“ hängt am Container nk-member-list und hat einen ::slotted()-Zwilling – sie funktioniert also weiter, wenn ein künftiges Element die Zeilen projiziert.
Auf kleinem Schirm:Das Rollen-Select wird per margin-left:auto nach rechts geschoben; in schmalen Zeilen umbrechen lassen.
.nk-member-list.nk-member-row.m-mail
Einstellungs-Modal
PRD 5.7
Einstellungs-Modal .nk-modal
Ein zweispaltiges Overlay: Navigation links, Panes rechts. Der Backdrop startet mit opacity: 0; pointer-events: none; .open blendet ihn ein und skaliert das Modal von 0.98 auf 1. Panes wechseln über .active. Das Modal bemisst sich selbst – min(960px, 92vw) mal min(640px, 86vh) – und braucht keine Inline-Maße.
Anzeigename
Anzeigename
So wirst du im Workspace angezeigt.
Kompakte Ansicht
html<divclass="nk-modal-backdrop open" style="position:absolute;border-radius:var(--nk-radius)"><divclass="nk-modal" style="width:96%;height:92%"><navclass="nk-settings-nav"><divclass="nk-settings-user"><divclass="avatar">AL</div><divclass="u-text"><divclass="name">Ada Lovelace</div><divclass="mail">ada@acme.com</div></div></div><divclass="nk-section-label">Einstellungen</div><divclass="nk-tree-item active"><spanclass="icon">👤</span><spanclass="label">Anzeigename</span></div><divclass="nk-tree-item"><spanclass="icon">🎨</span><spanclass="label">Hell/Dunkel</span></div><divclass="nk-tree-item"><spanclass="icon">🤖</span><spanclass="label">Mona</span></div></nav><divclass="nk-settings-content" style="padding:24px 28px"><divclass="nk-settings-pane active"><h2>Anzeigename</h2><divclass="nk-field"><div><divclass="f-label">Anzeigename</div><divclass="f-desc">So wirst du im Workspace angezeigt.</div></div><divclass="f-control"><inputclass="nk-input" value="Ada Lovelace"></div></div><divclass="nk-field"><div><divclass="f-label">Kompakte Ansicht</div></div><divclass="f-control"><buttonclass="nk-switch" role="switch" aria-checked="true"></button></div></div></div></div></div></div>
Auf kleinem Schirm:Unter 860px schrumpft die Navigation auf eine 60px-Icon-Leiste – Labels, Abschnitts-Label und der Name/Mail-Block des Nutzers (.u-text) verschwinden, das Inhalts-Padding fällt auf 24px.
Die gemeinsame Fläche unter jedem schwebenden Panel: Seitenhintergrund, 10px Radius, der dreilagige Menü-Schatten. Die Positionierung übernimmt der Consumer – die Klasse liefert nur die Fläche.
Auf kleinem Schirm:Feste 296px Breite. Auf dem Handy entweder verbreitern oder am Viewport-Rand verankern.
.nk-pop
Emoji-Picker .nk-emoji-grid
Ein achtspaltiges Raster in nk-pop, darüber ein Filterfeld, darunter eine ausgegraute Kategorieleiste. Kategorien leuchten beim Hovern oder mit .active auf.
Eine ⌘K-Palette: Eingabezeile, gruppierte Liste, Fußzeile mit Tastenhinweisen. Die per Tastatur hervorgehobene Zeile trägt .selected – diese Klasse verschiebt dein Pfeiltasten-Handler.
Auf kleinem Schirm:Das padding-top des Backdrops fällt von 14vh auf 6vh, und die Palette verbreitert sich auf min(560px, 96vw) – sie füllt den Handyschirm, statt mittig zu schweben.
Was die Liste zeigt, wenn der Filter nichts trifft. Die Eingabe zurückzitieren, damit sichtbar ist, wonach gesucht wurde.
🔍
Keine Ergebnisse für “xyzzy”
html<divclass="nk-cmdk" style="box-shadow:none;border:1px solid var(--nk-border);width:min(460px,100%)"><divclass="nk-cmdk-input-row"><span>🔍</span><inputvalue="xyzzy" placeholder="Suchen oder Befehl eingeben …"></div><divclass="nk-cmdk-list"><divclass="nk-cmdk-empty">Keine Ergebnisse für “xyzzy”</div></div></div>
Auf kleinem Schirm:Wie die Palette: volle Breite, reduziertes oberes Padding.
.nk-cmdk-empty
Toast .nk-toast
Unten mittig fixiert, invertiert (Textfarbe als Hintergrund). Er sitzt außerhalb des Bildes, bis .show ergänzt wird, und fährt dann hoch. pointer-events: none verhindert, dass er Klicks abfängt.
Auf kleinem Schirm:Per translateX(-50%) zentriert und bleibt es in jeder Breite.
.nk-toast.show
Galerie & Produktivität
PRD 5.9
Galerie-Raster .nk-gallery-grid
Ein fließendes repeat(auto-fit, minmax(min(280px, 100%), 1fr))-Raster. Bewusst ohne Breakpoint: Die Spaltenzahl folgt dem Container, nicht dem Viewport.
Auf kleinem Schirm:Fällt auf eine Spalte, sobald der Container unter ~600px rutscht – ganz ohne Media Query.
.nk-gallery-grid.nk-g-item
Reiter .nk-tabs
Reiter innerhalb der Seite, optisch das ruhigere Geschwister der Datenbank-Reiter. Das Ein- und Ausblenden der Panels übernimmst du; die Library stylt nur.
📝 Notizen
✅ Aufgaben
📎 Dateien
Der Panel-Inhalt folgt der Reiterleiste und erbt die ruhige Fließtext-Typografie.
html<div><divclass="nk-tabs"><divclass="nk-tab active">📝 Notizen</div><divclass="nk-tab">✅ Aufgaben</div><divclass="nk-tab">📎 Dateien</div></div><divclass="nk-tab-panel">Der Panel-Inhalt folgt der Reiterleiste und erbt die ruhige Fließtext-Typografie.</div></div>
Auf kleinem Schirm:Bei langer Leiste overflow-x: auto an nk-tabs geben.
.nk-tabs.nk-tab.active.nk-tab-panel
Template-Button .nk-template-btn
Ein linksbündiger Button über die volle Breite auf Callout-Hintergrund – die Geste „vorbereiteten Block einfügen“ im Dokument.
Auf kleinem Schirm:Von Haus aus volle Breite – nichts anzupassen.
.nk-template-btn
Statistik-Karten .nk-stats
Gleich breite Karten in einer flex-Zeile. .s-delta.up nimmt die grüne Tag-Farbe, .down nimmt --nk-danger – die Richtung ist eine Klasse, nie ein Inline-Style.
Aktive Seiten
128
▲ 12 diese Woche
KI-Anfragen
1 204
▲ 8 %
Offene Aufgaben
17
▼ 5 seit gestern
html<divclass="nk-stats"><divclass="nk-stat"><divclass="s-label">Aktive Seiten</div><divclass="s-value">128</div><divclass="s-delta up">▲ 12 diese Woche</div></div><divclass="nk-stat"><divclass="s-label">KI-Anfragen</div><divclass="s-value">1 204</div><divclass="s-delta up">▲ 8 %</div></div><divclass="nk-stat"><divclass="s-label">Offene Aufgaben</div><divclass="s-value">17</div><divclass="s-delta down">▼ 5 seit gestern</div></div></div>
Auf kleinem Schirm:Die Zeile bricht nicht von selbst um; der 860px-Breakpoint ergänzt flex-wrap: wrap, damit die Karten stapeln.
.nk-stats.nk-stat.s-label.s-value.s-delta.up.down
Synced-Block .nk-synced
Inhalt, der auf mehreren Seiten gespiegelt wird – markiert durch eine Kontur in Danger-Farbe und ein Badge, das in die Oberkante eingelassen ist. Der Rahmen sind 55 % von --nk-danger.
⟳ 3 Orte
Dieser Text erscheint identisch auf drei Seiten und wird zentral gepflegt.
html<divclass="nk-synced" style="max-width:420px"><spanclass="synced-badge">⟳ 3 Orte</span>
Dieser Text erscheint identisch auf drei Seiten und wird zentral gepflegt.
</div>
Auf kleinem Schirm:Das Badge ist oben rechts absolut positioniert und bleibt dort in jeder Breite.
.nk-synced.synced-badge
Segment-Auswahl .nk-segmented
Eine kleine Menge sich ausschließender Optionen. Das aktive Segment hebt sich mit dem Seitenhintergrund und einem Ein-Pixel-Schatten aus der Schiene.
Auf kleinem Schirm:inline-flex, es schrumpft also auf seinen Inhalt; bei drei, vier Segmenten bleiben.
.nk-segmented.active
Banner .nk-banner
Ein Hinweis über die volle Breite in drei semantischen Tönen, jeder nutzt ein Tag-Farbpaar wieder. .b-action schiebt eine unterstrichene Aktion an den rechten Rand.
ℹ️ Die Datenbank „Projektübersicht“ hat 2 überfällige Einträge.Ansehen
✅ Alle Änderungen wurden synchronisiert.
⚠️ Deine Testphase endet in 5 Tagen.Ansehen
html<divclass="nk-banner info">ℹ️ Die Datenbank „Projektübersicht“ hat 2 überfällige Einträge.<spanclass="b-action">Ansehen</span></div><divclass="nk-banner success">✅ Alle Änderungen wurden synchronisiert.</div><divclass="nk-banner warning">⚠️ Deine Testphase endet in 5 Tagen.<spanclass="b-action">Ansehen</span></div>
Auf kleinem Schirm:Die Aktion bleibt in derselben Zeile; bei Enge den Banner-Inhalt selbst umbrechen lassen.
.nk-banner.info.success.warning.b-action
Avatar-Gruppe .nk-avatar-group
Überlappende Avatare mit einem Ring in Seitenfarbe, damit sie als Stapel lesbar sind. Der :first-child-Reset liegt in der Gruppe und hat einen ::slotted()-Zwilling.
ALTWSL+2
5 Personen haben Zugriff
html<divstyle="display:flex;align-items:center;gap:10px"><divclass="nk-avatar-group"><spanclass="mini-avatar" style="background:var(--nk-decor-purple)">AL</span><spanclass="mini-avatar" style="background:var(--nk-decor-blue)">TW</span><spanclass="mini-avatar" style="background:var(--nk-tag-green-text)">SL</span><spanclass="mini-avatar more">+2</span></div><spanstyle="font-size:13px;color:var(--nk-text-tertiary)">5 Personen haben Zugriff</span></div>
Auf kleinem Schirm:Unverändert. Die Anzahl deckeln und den Rest über .more anzeigen.
.nk-avatar-group.mini-avatar.more
Skelett .nk-skeleton
Ein schimmernder Platzhalter. Breite und Höhe setzt du selbst. Unter prefers-reduced-motion: reduce steht die Animation still und es bleibt ein flacher Block in Callout-Farbe.
Auf kleinem Schirm:Prozentbreiten nutzen, damit der Platzhalter zum vertretenen Inhalt passt.
.nk-skeleton
Leerzustand .nk-empty
Ein gestrichelter Rahmen mit Icon, Titel und einer erklärenden Zeile. Gedacht für genau eine Aktion – den Weg aus dem Leerzustand heraus.
🗂️
Noch keine Einträge
Lege den ersten Eintrag an oder importiere vorhandene Daten.
html<divclass="nk-empty" style="max-width:420px"><divclass="e-icon">🗂️</div><divclass="e-title">Noch keine Einträge</div><divclass="e-desc">Lege den ersten Eintrag an oder importiere vorhandene Daten.</div><buttonclass="nk-btn secondary small">+ Neuer Eintrag</button></div>
Auf kleinem Schirm:Zentriert und fließend; das Padding folgt dem Container.
.nk-empty.e-icon.e-title.e-desc
Kollaboration & KI
PRD 5.10
Kommentar-Faden .nk-comments
Ein Faden an einer linken Linie, wie er neben einem Absatz stehen würde. Jeder Kommentar besteht aus Avatar, Kopf (Name und Zeit) und Rumpf.
SL
Sara Lindt · vor 1 Std.
Die Board-Ansicht fühlt sich schon sehr nah am Original an. 👍
html<divclass="nk-comments" style="max-width:420px"><divclass="nk-comment"><spanclass="mini-avatar" style="background:var(--nk-decor-purple)">SL</span><div><divclass="c-head"><b>Sara Lindt</b> · vor 1 Std.</div><divclass="c-body">Die Board-Ansicht fühlt sich schon sehr nah am Original an. 👍</div></div></div><divclass="nk-comment-input"><inputclass="nk-input" placeholder="Kommentieren …"><buttonclass="nk-btn primary small">Senden</button></div></div>
Auf kleinem Schirm:Die 18px-Einrückung bleibt; auf schmalen Schirmen den Faden unter den Absatz setzen statt daneben.
Ein Assistenten-Gespräch als Teil des Dokuments, kein schwebendes Widget. .user gibt der Nachricht den Verlauf-Avatar; der Assistent behält den neutralen Callout-Kreis. Die Eingabezeile leuchtet bei :focus-within auf.
AL
Du
Fasse die offenen Aufgaben dieses Projekts zusammen.
🤖
Mona · KI
Zwei Aufgaben sind offen: Die Tabellen-Ansicht steht bei 65 %, das Board mit Drag-and-Drop ist geplant.
html<divstyle="max-width:460px"><divclass="nk-ai-thread"><divclass="nk-ai-msg user"><spanclass="mini-avatar">AL</span><div><divclass="a-name">Du</div><divclass="a-body">Fasse die offenen Aufgaben dieses Projekts zusammen.</div></div></div><divclass="nk-ai-msg"><spanclass="mini-avatar">🤖</span><div><divclass="a-name">Mona <span>· KI</span></div><divclass="a-body">Zwei Aufgaben sind offen: Die Tabellen-Ansicht steht bei 65 %, das Board mit Drag-and-Drop ist geplant.</div><divclass="nk-ai-actions"><button>📋 Kopieren</button><button>↻ Neu formulieren</button></div></div></div></div><divclass="nk-ai-input-row"><inputplaceholder="Mona etwas fragen …"><buttonclass="nk-ai-send">↑</button></div></div>
Auf kleinem Schirm:Fließt natürlich. Die Eingabezeile ist eine flex-Zeile mit fixem 26px-Sendeknopf.
Die optische Hülle, in die ein Editor eingehängt wird. Sie liefert den Hover-Hauch, den Fokusring bei :focus-within, einen Platz für ein Drag-Handle links der Spalte und .nk-drop-target für Drag-Rückmeldung. Sie ist bewusst funktionsfrei.
Leitidee: Ein Callout trägt genau einen Gedanken, der nicht übersehen werden darf. Ein bis zwei Sätze reichen.
⠿
Tippe „/“ für Befehle …
Diese Vorschau ist nur die statische Hülle – die + / ⠿-Leiste hier tut nichts. Die funktionierende Fassung mit Slash-Menü, Drag & Drop und Blockmenü ist der Live-Editor in der Doku.
html<divstyle="padding-left:48px;max-width:460px"><divclass="nk-block-host"><divclass="nk-block-actions show" style="top:6px;left:-46px;pointer-events:none" aria-hidden="true"><buttontype="button" tabindex="-1">+</button><buttontype="button" class="drag" tabindex="-1">⠿</button></div><divstyle="padding:4px 2px;line-height:1.6">Leitidee: Ein Callout trägt genau einen Gedanken, der nicht übersehen werden darf. Ein bis zwei Sätze reichen.</div></div><divclass="nk-block-host nk-drop-target"><spanclass="nk-block-handle">⠿</span><divstyle="padding:4px 2px;color:var(--nk-text-tertiary)">Tippe „/“ für Befehle …</div></div></div>
Auf kleinem Schirm:Das Handle sitzt bei left: -26px, außerhalb der Spalte. Auf schmalen Schirmen ausblenden und stattdessen ein Long-Press-Menü nutzen.
Gib den schwebenden Containern deines Editors diese Klassen, und sie erben die NotionKit-Popover-Optik. Dieselben Regeln greifen in einem Block-Host auch auf .bn-suggestion-menu und .tippy-box – TipTap und BlockNote brauchen also kein Zusatz-Markup.
Basis-Blöcke
H1
Überschrift 1
Große Abschnitts-Überschrift
☑
To-do-Liste
Aufgaben mit Checkbox verfolgen
</>
Code-Block
Ein Snippet festhalten
Statisches Markup für die Optik. Die lebende, tastaturgesteuerte Fassung läuft im Doku-Editor – dort / tippen.