Dokumentation

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 --> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@jungherz-de/notionkit@1/notionkit.min.css"> <!-- local --> <link rel="stylesheet" href="notionkit.css"> <!-- your own theme, after the library --> <link rel="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:

html<html lang="de" data-theme="dark"> <body class="nk-body"> … </body> </html>

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.

TokenHellDunkelBedeutung
--nk-bg#ffffff#191919Seitenhintergrund
--nk-bg-sidebar#f9f8f7#202020Sidebar und Settings-Navigation
--nk-bg-hoverrgba(55,53,47,0.06)rgba(255,255,255,0.055)Hover-Hauch – eine Verdunkelung, nie ein Farbwechsel
--nk-bg-activergba(55,53,47,0.08)rgba(255,255,255,0.08)Aktive/ausgewählte Zeile
--nk-bg-callout#f0efed#252525Callouts, Badges, Tasten, Segment-Schiene
--nk-bg-code#f7f6f3#202020Hintergrund von Code-Blöcken
--nk-bg-card#ffffff#202020Board-Karten und weiße Buttons – getrennt von --nk-bg, damit Dark Mode sie abheben kann
--nk-bg-inputrgba(242,241,238,0.6)rgba(255,255,255,0.055)Die gefüllte Eingabefläche: Inputs, Selects, Textareas, die Emoji-Suche
--nk-text#2c2c2brgba(255,255,255,0.81)Fließtext. Nie reines Schwarz
--nk-text-secondary#7d7a75rgba(255,255,255,0.46)Sekundärtext, Tabellenköpfe, Beschreibungen
--nk-text-tertiary#91918ergba(255,255,255,0.32)Meta, Platzhalter, Abschnittslabels
--nk-text-sidebar#5f5e5brgba(255,255,255,0.62)Baum-Einträge, Breadcrumbs, Topbar-Buttons – eine Stufe dunkler als sekundär, wie in Notion
--nk-borderrgba(28,19,1,0.11)rgba(255,255,255,0.094)Haarlinien-Trenner, Tabellengitter, Input-Rahmen
--nk-border-strongrgba(27,21,0,0.19)rgba(255,255,255,0.16)Input-Hover, Scrollbar-Griffe, gestrichelte Rahmen, Checkboxen
--nk-accent#2383e2#529CCADie eine Markenfarbe. Alles Akzentuierte wird daraus gemischt
--nk-on-accent#ffffff—Text und Marken auf Akzent- oder Danger-Füllung
--nk-danger#cd3c3a#df5452Destruktive Aktionen, Inline-Code, negative Deltas
--nk-tag-gray-bg#e3e2e0#373737Tag-Fläche (Grau)
--nk-tag-gray-text#32302crgba(255,255,255,0.85)Tag-Text (Grau), fast schwarz auf der Fläche
--nk-tag-brown-bg#eee0da#603b2cTag-Fläche (Braun)
--nk-tag-brown-text#442a1ergba(255,255,255,0.85)Tag-Text (Braun), fast schwarz auf der Fläche
--nk-tag-orange-bg#fadec9#854c1dTag-Fläche (Orange)
--nk-tag-orange-text#49290ergba(255,255,255,0.85)Tag-Text (Orange), fast schwarz auf der Fläche
--nk-tag-yellow-bg#fdecc8#89632aTag-Fläche (Gelb)
--nk-tag-yellow-text#402c1brgba(255,255,255,0.85)Tag-Text (Gelb), fast schwarz auf der Fläche
--nk-tag-green-bg#dbeddb#2b593fTag-Fläche (Grün)
--nk-tag-green-text#1c3829rgba(255,255,255,0.85)Tag-Text (Grün), fast schwarz auf der Fläche
--nk-tag-blue-bg#d3e5ef#28456cTag-Fläche (Blau)
--nk-tag-blue-text#183347rgba(255,255,255,0.85)Tag-Text (Blau), fast schwarz auf der Fläche
--nk-tag-purple-bg#e8deee#492f64Tag-Fläche (Lila)
--nk-tag-purple-text#412454rgba(255,255,255,0.85)Tag-Text (Lila), fast schwarz auf der Fläche
--nk-tag-pink-bg#f5e0e9#69314cTag-Fläche (Pink)
--nk-tag-pink-text#4c2337rgba(255,255,255,0.85)Tag-Text (Pink), fast schwarz auf der Fläche
--nk-tag-red-bg#ffe2dd#6e3630Tag-Fläche (Rot)
--nk-tag-red-text#5d1715rgba(255,255,255,0.85)Tag-Text (Rot), fast schwarz auf der Fläche
--nk-tint-gray#f1f1ef#252525Weiche Grau-Fläche für Banner und getönte Blöcke
--nk-color-gray#787774#9b9b9bFarbiger Text und Marken (Grau)
--nk-tint-brown#f4eeee#2e2724Weiche Braun-Fläche für Banner und getönte Blöcke
--nk-color-brown#9f6b53#ba856fFarbiger Text und Marken (Braun)
--nk-tint-orange#fbecdd#36291fWeiche Orange-Fläche für Banner und getönte Blöcke
--nk-color-orange#d9730d#c77d48Farbiger Text und Marken (Orange) – zugleich Datums-Erwähnungen und Code-Attribute
--nk-tint-yellow#fbf3db#372e20Weiche Gelb-Fläche für Banner und getönte Blöcke
--nk-color-yellow#cb912f#ca8f3dFarbiger Text und Marken (Gelb)
--nk-tint-green#edf3ec#242b26Weiche Grün-Fläche für Banner und getönte Blöcke
--nk-color-green#448361#529e72Farbiger Text und Marken (Grün) – zugleich positives Delta
--nk-tint-blue#e7f3f8#1f282dWeiche Blau-Fläche für Banner und getönte Blöcke – zugleich Fortschritts-Schiene
--nk-color-blue#337ea9#5e87c9Farbiger Text und Marken (Blau) – zugleich Fortschritts-Füllung
--nk-tint-purple#f8f3fc#2a2430Weiche Lila-Fläche für Banner und getönte Blöcke
--nk-color-purple#9065b0#9d68d3Farbiger Text und Marken (Lila)
--nk-tint-pink#fcf1f6#2e2328Weiche Pink-Fläche für Banner und getönte Blöcke
--nk-color-pink#c14c8a#d15796Farbiger Text und Marken (Pink)
--nk-tint-red#fdebec#332523Weiche Rot-Fläche für Banner und getönte Blöcke
--nk-color-red#cd3c3a#df5452Farbiger Text und Marken (Rot)
--nk-decor-purple#9065b0—Avatar-Verlauf-Start und Cover. Bewusst in beiden Themes gleich
--nk-decor-blue#529cca—Avatar-Verlauf-Ende und Cover
--nk-decor-orange#d9730d—Cover-Akzent
--nk-scrimrgba(15,15,15,0.6)—Modal-Backdrop
--nk-scrim-softrgba(15,15,15,0.5)—Backdrop der Befehlspalette, eine Stufe heller
--nk-sidebar-width260px—Sidebar-Breite, zugleich ihre min-width (plus linker Safe-Area-Inset, falls vorhanden)
--nk-peek-width560px—Breite des Side Peeks; .pk-resize setzt es beim Ziehen auf :root
--nk-page-full-maxnone—Grenze einer .nk-page.full-Spalte – none: das ganze Fenster, 1080px für ein Dashboard ohne 1600px lange Zeilen
--nk-cover-height200px—Höhe des Cover-Bands der Seite – auf :root oder an einem Cover; Notion nimmt etwa 30vh
--nk-panel-cover-height64px—Höhe eines Covers im Panel, das Band einer Seitenkachel
--nk-tab-bar-height58px—Höhe der mobilen Tab-Bar ohne Safe-Area; der Platzhalter nutzt denselben Wert
--nk-radius6px—Radius für Bedienelemente. Karten und Modals nutzen direkt 8–12px
--nk-fontui-sans-serif, -apple-system, "Segoe UI", Inter, Helvetica, Arial, sans-serif—System-Schriftstapel
--nk-font-monoui-monospace, "SF Mono", Menlo, Consolas, monospace—Monospace-Stapel für Code
--nk-shadow-menurgba(15,15,15,0.05) 0px 0px 0px 1px, rgba(15,15,15,0.1) 0px 3px 6px, rgba(15,15,15,0.2) 0px 9px 24pxrgba(15,15,15,0.2) 0px 0px 0px 1px, rgba(15,15,15,0.4) 0px 3px 6px, rgba(15,15,15,0.6) 0px 9px 24pxDreilagiger Schatten für jede schwebende Fläche
--nk-shadow-card0 1px 2px rgba(0,0,0,0.04)noneAbheben der Board-Karte. Im Dark Mode `none`
--nk-shadow-btninset 0 0 0 1px rgba(15,15,15,0.1), 0 1px 2px rgba(15,15,15,0.1)inset 0 0 0 1px rgba(255,255,255,0.1), 0 1px 2px rgba(0,0,0,0.3)Die Kontur des weißen Buttons: 1px-Innenring plus 1px Schatten, kein Rahmen
--nk-shadow-knob0 1px 2px rgba(0,0,0,0.2)—Switch-Knopf
--nk-shadow-segment0 1px 2px rgba(0,0,0,0.08)—Aktives Segment

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<html data-theme="light"> <!-- default, the attribute may be omitted --> <html data-theme="dark">
htmldocument.documentElement.setAttribute('data-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.

KlasseGilt fürWirkung
[hidden][class*="nk-"] ::slotted(*)Blendet aus, immer – auch Komponenten mit eigenem display, die vor 1.5.2 die Browser-Regel schlugen. hidden="until-found" behält das Aufdecken per Seitensuche des Browsers.
.activenk-tree-item nk-db-tab nk-tab nk-tab-bar-item nk-settings-pane nk-segmented button nk-emoji-cats span nk-board nk-bubble-menu buttonMarkiert das aktuelle Element. Baum-Einträge und View-Reiter bekommen den Aktiv-Hintergrund, .nk-tab die Unterlinie, Panes werden sichtbar.
.opennk-modal-backdrop nk-cmdk-backdrop nk-sheet-backdrop nk-dialog-backdrop nk-peek-backdrop nk-pop.floating nk-tooltip nk-sidebar nk-sidebar-backdrop nk-toggle-arrowBlendet das Overlay ein und macht es bedienbar; schiebt den Side Peek von rechts herein; zeigt ein schwebendes Menü oder einen Tooltip; schiebt die Sidebar auf dem Telefon als Schublade herein; dreht den Toggle-Pfeil um 90°.
.peek-insetnk-appSolange der Side Peek offen ist: Die Hauptspalte bekommt rechts ein Padding so breit wie der Peek, die Seite rückt also zur Seite, statt darunter zu liegen. Nur auf dem Desktop.
.copiednk-copy-field .cf-btnDer Moment nach dem Kopieren: Die Aktion wird grün. Nach dem Schreiben in die Zwischenablage setzen und wieder abnehmen.
.squarenk-profile-row .big-avatarDas abgerundete Quadrat eines Workspace-Icons statt des Kreises einer Person.
.floatingnk-popEin Menü über der Seite: unsichtbar und inaktiv bis .open, dann blendet es ein und setzt sich aus 4px Höhe und 98 % ab, so wie die Palette öffnet.
.sheetnk-popUnter 860px wird das Popover zum Bottom Sheet – volle Breite, Griff, 40px-Zeilen, die Seite abgedunkelt –, eine Inline-Position wird übergangen.
.done / currentnk-stepEin erledigter Schritt auf dem grünen Tag mit Haken; der Schritt, auf dem man steht, im Akzent umrandet, mit aria-current="step".
.collapsednk-tree-children nk-sidebar nk-sidebar-toggleKlappt einen Unterbaum per display: none weg. An der Sidebar schiebt es sie auf dem Desktop nach links hinaus; am ☰ zeigt es den Button, der sie zurückholt.
.selectednk-cmdk-item nk-model-card nk-slash-item nk-calendar .cal-dayDie per Tastatur hervorgehobene oder gewählte Option – im Kalender der gewählte Tag, im Akzent. Anders als active: Auswahl ist flüchtig, active ist der Ort, an dem du bist.
.start / end / in-rangenk-calendar .cal-dayEin Zeitraum: erster und letzter Tag im Akzent, außen gerundet, die Tage dazwischen in der Tönung des Akzents. Ein Zeitraum von einem Tag ist start und end.
.today / off / outnk-calendar .cal-day nk-calendar-view .cv-dayHeute in Rot – in der Kalenderansicht eine rote Pille; ein Tag ohne Arbeit (Wochenende, Feiertag) gegraut bzw. hinterlegt; ein Tag des Monats davor oder danach ebenso.
.weeksnk-calendar nk-calendar-viewErgänzt die Spalte der ISO-Kalenderwochen vor den Tagen.
.stackednk-fieldLabel über einem vollbreiten Control statt daneben – Textareas, lange Beschreibungen.
.compactnk-field nk-tree-item nk-selectDie engere Variante: ein Feld mit kleinem tertiärem Label ohne Zeilen-Padding (in .nk-fields), eine 26px-Baumzeile, ein 120px-Select.
.scrollnk-segmentedScrollt die Segmente horizontal mit versteckter Scrollleiste, begrenzt auf die Elternbreite.
.wrapnk-segmented nk-table nk-table tdLässt die Segmente in weitere Zeilen umbrechen; auf einer Tabelle oder Zelle lässt es Zellentext umbrechen statt einzeilig zu bleiben.
.fixednk-tab-barHeftet die Tab-Bar an den unteren Viewport-Rand; ein folgender .nk-tab-bar-spacer hält ihre Höhe im Fluss frei.
:indeterminatenk-check input[type=checkbox]Gemischt: einige einer Gruppe gewählt – die Box füllt sich mit dem Akzent und zeigt einen Strich. Nur eine Eigenschaft, per Skript gesetzt; eine Radio-Gruppe ohne Wahl behält ihre leeren Kreise.
.coverednk-pageDie Seite folgt einem Cover: kein oberes Padding, das Icon überlappt die Cover-Unterkante. Klassen-Markup bekommt das über .nk-cover + .nk-page; setzt die Klasse.
.fullnk-pageSeitenoption „Volle Breite“: hebt die 760px-Grenze auf, die Spalte füllt das Fenster. Pro Seite, wie in Notions ⋯-Menü.
.smallnk-page nk-avatar nk-btnSeitenoption „Kleiner Text“: Dokumenttext 14px statt 16px; Überschrift, Lead, Prosa und Editor ziehen mit. An einem Avatar 20px, an einem Button 24px.
.widenk-progress nk-input nk-select nk-textareaFüllt seine Zeile. Ein breiter Fortschrittsbalken wächst in einer flex-Zeile ab 60px, sein Label bleibt also daneben.
.bubblenk-ai-msgDie Nachricht als graue Blase ohne Avatar und Namen; mit .user steht sie rechts, wie die eigene Frage in Notions KI-Chat.
.lastnk-list-item nk-member-rowNimmt der Zeile die untere Linie, wo die Liste das letzte Kind nicht sieht – eine Zeile, die in ihrem eigenen Shadow Root steht.
.alwaysnk-tab-barZeigt die Tab-Bar in jeder Breite, nicht nur unter 860px – für Vorschauen und Telefon-Rahmen.
.shownk-toastFä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.
:checkednk-todo input nk-check input nk-switch (input form)Nativer Zustand. Zeichnet Haken oder Punkt und streicht ein To-do-Label durch.
.nk-drop-targetnk-block-hostDrag-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.

PaarHellDunkelAA Fließtext
--nk-text / --nk-bg13.9811.78✓
--nk-text / --nk-bg-sidebar13.1811.06✓
--nk-text-sidebar / --nk-bg-sidebar6.117.03✓
--nk-text-secondary / --nk-bg4.274.63✗
--nk-text-tertiary / --nk-bg3.162.91—
--nk-accent / --nk-bg3.885.83—
--nk-on-accent / --nk-accent3.883.01✗
--nk-danger / --nk-bg4.884.63✓
tag gray10.179.10—
tag blue10.127.56—
tag green10.416.37—
tag orange10.185.49—
tag yellow11.304.42—
tag purple10.048.59—
tag red10.747.30—

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<div class="nk-block-host" id="editor"></div> <script type="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.

html<div class="nk-block-host"> <BlockNoteView editor={editor} theme="light" /> </div>

Novel – der Next.js-Weg

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.

html<div class="nk-block-host"> <EditorContent className="novel-editor" /> </div>

Live: TipTap in einem Block-Host

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.

html.nk-callout .c-icon, .nk-callout ::slotted(.c-icon) { font-size: 17px; }

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). Auf dem Desktop klappt die Sidebar wie in Notion ein: .nk-sidebar-head hält die Workspace-Zeile und das « .nk-sidebar-collapse, das erscheint, solange der Zeiger über der Sidebar ist; .collapsed an der Sidebar schiebt sie nach links hinaus – die Hauptspalte nimmt die Breite, die verborgene Sidebar nimmt keinen Fokus –, und .collapsed am .nk-sidebar-toggle der Topbar zeigt das ☰, das sie zurückholt. Notions Kürzel ist ⌘\.

📊 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<div class="nk-sidebar-backdrop open"></div>   <!-- phones: the drawer's scrim -->
<aside class="nk-sidebar open">…</aside>         <!-- slides in over the page -->
<button class="nk-topbar-btn nk-sidebar-toggle" aria-label="Menu">☰</button>
jscollapseBtn.addEventListener('click', () => {            // the « in .nk-sidebar-head
  sidebar.classList.add('collapsed');                      // slides out on the desktop
  sidebarToggle.classList.add('collapsed');                // das ☰ in der Topbar holt sie zurück
});
html<div class="nk-app" style="height:100%"> <aside class="nk-sidebar"> <div class="nk-sidebar-head"> <div class="nk-workspace"><div class="avatar">A</div>Acme GmbH<span class="chev">⌄</span></div> <button class="nk-sidebar-collapse" aria-label="Seitenleiste schließen"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="m18 17-5-5 5-5M11 17l-5-5 5-5"/></svg></button> </div> <div class="nk-sidebar-scroll"> <div class="nk-tree-item"><span class="icon">🔍</span><span class="label">Suche</span></div> <div class="nk-tree-item active"><span class="icon">🏠</span><span class="label">Start</span></div> <div class="nk-tree-item"><span class="icon">📥</span><span class="label">Posteingang</span></div> </div> <div class="nk-sidebar-footer"> <div class="nk-tree-item"><span class="icon">⚙️</span><span class="label">Einstellungen</span></div> </div> </aside> <main class="nk-main"> <header class="nk-topbar"> <button class="nk-topbar-btn nk-sidebar-toggle" aria-label="Menu">☰</button> <div class="nk-breadcrumb"><span class="crumb current">📊 Projektübersicht</span></div> <div class="nk-topbar-actions"><button class="nk-topbar-btn nk-share-btn">Teilen</button></div> </header> <div class="nk-page-scroll"><div class="nk-page" style="padding-top:16px"> <h1 class="nk-page-title" style="font-size:28px">Produkt-Roadmap</h1> <p class="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 tritt die Sidebar zur Seite, die Hauptspalte nimmt die volle Breite. .open holt sie als Off-Canvas-Schublade über die Seite zurück, mit einem .nk-sidebar-backdrop als Abdunklung: Sie gleitet herein und die Abdunklung blendet ein, nur mit CSS. Das ☰, das sie öffnet, ist ein .nk-topbar-btn.nk-sidebar-toggle am Anfang der Topbar, nur auf dem Telefon sichtbar; .open an Sidebar und Backdrop umschalten, schließen über den Backdrop, Escape und eine gewählte Seite. Die Höhe ist 100dvh mit 100vh-Fallback, damit eine Standalone-PWA auf iOS die Statusleiste nicht in die Shell einrechnet. Safe-Areas behandelt jede Fläche selbst, nicht nk-app: Topbar, Seite, Sidebar und Tab-Bar rücken ihren Inhalt um die linken/rechten Insets ein (Dynamic Island im Querformat), ihre Hintergründe laufen weiter bis zum Rand.
.nk-app.nk-sidebar.nk-sidebar-head.nk-sidebar-collapse.nk-sidebar-scroll.nk-sidebar-footer.nk-main.nk-sidebar-backdrop.nk-sidebar-toggle.open.collapsed

Workspace-Umschalter .nk-workspace

Sitzt ganz oben in der Sidebar. Der Avatar-Verlauf wird aus --nk-decor-purple und --nk-decor-blue gemischt und übersteht ein Rebranding unverändert.

A
Acme GmbH⌄
html<div class="nk-workspace" style="background:var(--nk-bg-sidebar);max-width:244px"> <div class="avatar">A</div>Acme GmbH<span class="chev">⌄</span> </div>
Auf kleinem Schirm:Verschwindet unter 860px zusammen mit der Sidebar.
.nk-workspace.avatar.chev

Topbar .nk-topbar

Eine 44px 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. Reiner Text zwischen den Aktionen – „Bearbeitet vor 2 Min.“ – ist nk-topbar-meta. nk-theme-glyph umschließt die Glyphe eines Theme-Knopfs: ein Emoji für ein festes Theme, mit auto Sonne und Mond diagonal für den Modus, der dem System folgt.

📊 Projektübersicht/🚀 Roadmap
Zuletzt bearbeitet: vor 2 Min.
html<header class="nk-topbar" style="border:1px solid var(--nk-border);border-radius:var(--nk-radius)"> <div class="nk-breadcrumb"> <span class="crumb">📊 Projektübersicht</span><span class="sep">/</span><span class="crumb current">🚀 Roadmap</span> </div> <div class="nk-topbar-actions"> <span class="nk-topbar-meta">Zuletzt bearbeitet: vor 2 Min.</span> <button class="nk-topbar-btn">💬</button> <button class="nk-topbar-btn nk-share-btn">Teilen</button> <button class="nk-topbar-btn">⭐</button> <button class="nk-topbar-btn nk-theme-toggle">🌙</button> <button class="nk-topbar-btn nk-theme-toggle" title="Appearance: automatic"><span class="nk-theme-glyph auto"><span>☀️</span><span>🌙</span></span></button> <button class="nk-topbar-btn">⋯</button> </div> </header>
Auf kleinem Schirm:Unter 860px bleiben die Seite und ihre Aktionen, wie in Notions Mobil-App: Nur der letzte Crumb bleibt und endet mit Auslassungspunkten, nk-topbar-meta wird ausgeblendet.
.nk-topbar.nk-topbar-actions.nk-topbar-btn.nk-topbar-meta.nk-share-btn.nk-theme-toggle.nk-theme-glyph

Tab-Bar (mobil) .nk-tab-bar

Der daumenfreundliche Zwilling der Sidebar für Telefone und installierte PWAs: bis zu fünf Ziele in einer Reihe, jedes ein Icon über einer kurzen Beschriftung, das aktuelle in --nk-accent. Als letztes Kind von nk-main sitzt sie unter der scrollenden Seite und bewegt sich nie. In einem Dokument, das selbst scrollt, klebt sie am unteren Viewport-Rand. floating macht sie zur Kapsel; fixed heftet sie für Standalone-PWAs an den unteren Viewport-Rand, ein .nk-tab-bar-spacer direkt dahinter hält ihre Höhe (--nk-tab-bar-height plus Safe-Area) im Fluss frei. Der fünfte Eintrag öffnet meist die Sidebar als Schublade.

html<nav class="nk-tab-bar fixed">…</nav><div class="nk-tab-bar-spacer"></div>
html<div style="max-width:390px;border:1px solid var(--nk-border);border-radius:12px;overflow:hidden"> <nav class="nk-tab-bar always"> <button class="nk-tab-bar-item active"><span class="icon">🏠</span><span class="label">Start</span></button> <button class="nk-tab-bar-item"><span class="icon">📥</span><span class="label">Posteingang</span></button> <button class="nk-tab-bar-item"><span class="icon">🔍</span><span class="label">Suche</span></button> <button class="nk-tab-bar-item"><span class="icon">⚙️</span><span class="label">Einstellungen</span></button> <button class="nk-tab-bar-item"><span class="icon">☰</span><span class="label">Mehr</span></button> </nav> </div> <pre class="nk-code" style="margin-top:12px"><span class="lang">html</span>&lt;nav class="nk-tab-bar fixed"&gt;…&lt;/nav&gt;&lt;div class="nk-tab-bar-spacer"&gt;&lt;/div&gt;</pre>
Auf kleinem Schirm:Nur unter 860px sichtbar – darüber übernimmt die Sidebar, die Bar ist display: none. always zeigt sie in jeder Breite, wie in dieser Vorschau. Auf Telefonen mit Home-Indikator ist das untere Padding das Größere aus 6px und env(safe-area-inset-bottom), die Beschriftungen enden also dort, wo iOS seine eigene Tab-Bar enden lässt; im Querformat wächst das seitliche Padding auf die linken/rechten Insets (Dynamic Island), der Hintergrund läuft weiter bis zum Rand.
.nk-tab-bar.nk-tab-bar-item.nk-tab-bar-spacer.icon.label.active.always.fixed.floating

Breadcrumb .nk-breadcrumb

Jede Stufe ist ein .crumb; die letzte trägt .current und wechselt von sekundärer zu primärer Textfarbe. Trenner sind .sep.

📊 Projektübersicht/ 📚 Wissensdatenbank/ 🚀 Roadmap
html<div class="nk-breadcrumb"> <span class="crumb">📊 Projektübersicht</span><span class="sep">/</span> <span class="crumb">📚 Wissensdatenbank</span><span class="sep">/</span> <span class="crumb current">🚀 Roadmap</span> </div>
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.

📊Projektübersicht
html<div style="background:var(--nk-bg-sidebar);border-radius:var(--nk-radius);padding:4px 8px;max-width:244px"> <div class="nk-section-label">Favoriten<span class="plus">+</span></div> <div class="nk-tree-item"><span class="icon">📊</span><span class="label">Projektübersicht</span></div> </div>
Auf kleinem Schirm:In der Settings-Navigation unter 860px ausgeblendet, wo diese auf Icons zusammenschrumpft.
.nk-section-label.plus

Seiten-Shell & Dokument

PRD 5.3

Seitenspalte & Seitenoptionen .nk-page

Die Dokumentspalte: max-width: 760px mit Auto-Rändern, nie eine feste Breite. Nach einem Cover (.nk-cover + .nk-page oder .nk-page.covered) zieht sich das Icon per negativem Rand darüber und die Seite hat kein oberes Padding; ohne Cover behält die Seite 24px oberes Padding und das Icon sitzt darin, ganz sichtbar. Der Titel ist contenteditable-fähig. Notions zwei Seitenoptionen sind Klassen an der Seite: full hebt die 760px-Grenze auf, die Spalte füllt das Fenster, small setzt den Dokumenttext von 16px auf 14px, und Überschriften, Lead, Prosa und Editor ziehen mit, weil sie in em bemessen sind. Titel, Eigenschaften, Tabellen und Bedienelemente behalten ihre Größe. In Notion sind das Optionen der einzelnen Seite, in ihrem ⋯-Menü, keine App-Einstellungen. Das Token --nk-page-full-max begrenzt full – standardmäßig none; 1080px auf :root gibt einem Dashboard aus Tabellen Platz ohne 1600px lange Zeilen.

🚀

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<div class="nk-page-scroll" style="height:100%"> <div class="nk-cover" style="height:120px"></div> <div class="nk-page" style="padding-bottom:24px"> <div class="nk-page-icon">🚀</div> <h1 class="nk-page-title" contenteditable="true">Produkt-Roadmap</h1> <div class="nk-page-meta"><span>👤 Ada Lovelace</span><span>📅 Erstellt am 12. Mai 2026</span></div> <p class="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, full ändert dort also nichts; small schon.
.nk-page-scroll.nk-page.nk-page-icon.nk-page-title.nk-page-meta.covered.full.small

Seiteneigenschaften .nk-props

Die Eigenschaften unter dem Titel einer Datenbankseite – das Muster, für das Notion bekannt ist. Ein .nk-prop pro Zeile: der Name mit seinem Typ-Icon in einer 160px-Spalte, daneben der Wert, beide 34px hoch mit Hover-Hauch, weil in Notion jede Hälfte ihren eigenen Editor öffnet. Werte sind gewöhnliches Markup: Tags, ein Avatar mit Namen, ein Datum, ein .nk-progress.wide. Es ersetzt .nk-page-meta auf einer Seite, die eine Zeile ist. Als <dl>, <dt> und <dd> geschrieben ist es auch für assistive Technik eine Beschreibungsliste; schlichte <div>s funktionieren genauso. Ein Wert, der Text ist – ein Satz, eine Adresse, ein Modellname mit Etikett –, bekommt .text und fließt als Text, statt seine Teile untereinander zu setzen. Der Wert behält mindestens 220px: In einer Spalte unter 380px, etwa einer Seitenleiste, rutscht er unter seinen Namen. .flush nimmt den Außenabstand weg, für eine Liste in einem Panel oder einer Flex-Spalte mit eigenem Abstand.

◉Status
In Arbeit
👤Verantwortlich
ALAda Lovelace
📅Fällig
2. Juni 2026
✉️Adresse
support+design@notionkit.example.com · Bestätigt
🏷️Tags
Design-SystemCSS
▰Fortschritt
65 %
html<dl class="nk-props" style="max-width:520px"> <div class="nk-prop"><dt class="p-name"><span class="p-icon">◉</span>Status</dt><dd class="p-value"><span class="nk-tag blue">In Arbeit</span></dd></div> <div class="nk-prop"><dt class="p-name"><span class="p-icon">👤</span>Verantwortlich</dt><dd class="p-value"><span class="nk-avatar small purple">AL</span>Ada Lovelace</dd></div> <div class="nk-prop"><dt class="p-name"><span class="p-icon">📅</span>Fällig</dt><dd class="p-value">2. Juni 2026</dd></div> <div class="nk-prop"><dt class="p-name"><span class="p-icon">✉️</span>Adresse</dt><dd class="p-value text">support+design@notionkit.example.com · <span class="nk-tag green">Bestätigt</span></dd></div> <div class="nk-prop"><dt class="p-name"><span class="p-icon">🏷️</span>Tags</dt><dd class="p-value"><span class="nk-tag purple">Design-System</span><span class="nk-tag">CSS</span></dd></div> <div class="nk-prop"><dt class="p-name"><span class="p-icon">▰</span>Fortschritt</dt><dd class="p-value"><span class="nk-progress wide"><i style="width:65%"></i></span><span class="nk-progress-label">65 %</span></dd></div> </dl>
Auf kleinem Schirm:Unter 860px stapelt sich jede Eigenschaft: der Name über seinem Wert, beide linksbündig, damit der Wert die ganze Breite bekommt.
.nk-props.nk-prop.p-name.p-icon.p-value.text.flush

Cover .nk-cover

Ein Zierband über der Seite, 200px hoch – das Token --nk-cover-height, auf :root oder an einem Cover; Notions eigenes nimmt etwa 30vh, clamp(200px, 30vh, 300px) kommt nahe heran. Drei radiale Verläufe, gemischt aus den --nk-decor-*-Tokens über --nk-bg-callout. Für ein Bild ein <img> hineinsetzen: Es füllt das Band und wird beschnitten, nie verzerrt, und object-position verschiebt den Ausschnitt wie Notions „Neu positionieren“. Der Verlauf bleibt darunter, solange es lädt.

html<div class="nk-cover" style="border-radius:var(--nk-radius)"></div> <div class="nk-cover" style="height:120px;border-radius:var(--nk-radius);margin-top:12px"><img src="../covers/meadow.svg" alt=""></div>
Auf kleinem Schirm:Randlos, so hoch wie --nk-cover-height; das Token senken, wenn das Band zu viel eines kurzen Schirms frisst. Ohne Seiten-Icon behält die Seite ihren oberen Abstand unter dem Cover.
.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<div class="nk-page" style="padding:0;max-width:none"> <h2 class="nk-heading">✅ So funktioniert das</h2> <p class="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<div class="nk-callout"><span class="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

Bookmark .nk-bookmark

Notions Link-Block: .bm-title, zwei Zeilen .bm-desc und die .bm-url mit ihrem .bm-favicon links, das Vorschaubild in .bm-cover rechts – ein Drittel der Box, höchstens 240px, sodass ein og:image in 1200×630 fast ganz hineinpasst. Die ganze Box ist der Link, ein <a>; gefüllt aus og:title, og:description und og:image der Seite. Ohne Bild nimmt der Text die Breite, ohne Beschreibung wird die Box niedriger. Auch der Weg, zu zeigen, wie ein geteilter Link aussehen wird.

html<a class="nk-bookmark" href="https://notionkit.jungherz.com" target="_blank" rel="noopener" style="max-width:600px"> <span class="bm-text"> <span class="bm-title">NotionKit – der ruhige Workspace-Look als CSS</span> <span class="bm-desc">NotionKit ist eine reine CSS-Komponentenbibliothek im Notion-Look: Sidebar, Seitenbaum, Dokument-Shell, Datenbank-Views, Einstellungen und KI-Flächen.</span> <span class="bm-url"><img class="bm-favicon" src="../favicon.svg" alt=""><span>https://notionkit.jungherz.com</span></span> </span> <span class="bm-cover"><img src="../covers/notionkit-og.jpg" alt=""></span> </a>
Auf kleinem Schirm:Das Bild behält sein Drittel und wird mittig beschnitten; Titel und Adresse enden mit Auslassungspunkten, die Beschreibung nach zwei Zeilen.
.nk-bookmark.bm-text.bm-title.bm-desc.bm-url.bm-favicon.bm-cover

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.

html<div> <label class="nk-todo"><input type="checkbox" checked><span>Komponenten-Umfang skizzieren</span></label> <label class="nk-todo"><input type="checkbox" checked><span>Preview bauen</span></label> <label class="nk-todo"><input type="checkbox"><span>MVP-Umfang priorisieren</span></label> </div>
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<details class="nk-toggle" open> <summary>Was ist nicht enthalten?</summary> <div class="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<blockquote class="nk-quote">Design ist nicht, wie etwas aussieht. Design ist, wie es funktioniert.<cite class="q-cite">— Steve Jobs</cite></blockquote> <hr class="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.

SLSara Lindt 📄 Wissensdatenbank 📅 20. Mai

html<p style="line-height:1.9"> <span class="nk-mention person"><span class="nk-avatar purple">SL</span>Sara Lindt</span> <span class="nk-mention page">📄 Wissensdatenbank</span> <span class="nk-mention date">📅 20. Mai</span> </p>
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.

html<div class="nk-callout"> <span class="c-icon">💡</span> </div>

Inline: --nk-accent

html<div class="nk-code"><span class="lang">html</span><span class="tag">&lt;div</span> <span class="attr">class=</span>"nk-callout"<span class="tag">&gt;</span> <span class="tag">&lt;span</span> <span class="attr">class=</span>"c-icon"<span class="tag">&gt;</span>💡<span class="tag">&lt;/span&gt;</span> <span class="tag">&lt;/div&gt;</span></div> <p>Inline: <code class="nk-inline-code">--nk-accent</code></p>
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

Prosa .nk-prose

Text, den die App nicht Tag für Tag geschrieben hat – gerendertes Markdown, Hilfeseiten, das HTML, das ein Editor gespeichert hat – bekommt die Dokument-Optik von einer Klasse an seinem Container: Überschriften, Absätze, Listen, Aufgabenlisten, Links, Inline-Code, Code-Blöcke, Zitate, Trenner, Bilder und Tabellen. Es liest genau dieselben Regeln wie der Editor-Adapter, eine Seite zum Lesen und dieselbe Seite in TipTap decken sich also auf den Pixel. Die Größen sind in em und folgen dem, worin der Text steht: 16px auf einer Seite, 14px mit small oder in der App-Oberfläche. Kein äußerer Rand am ersten und letzten Block, es sitzt also bündig in einem Panel. Ein leerer Absatz behält seine Zeile, wie er sie im Editor hatte.

Versionshinweise

Gerendertes Markdown bekommt die Dokument-Optik von einer Klasse: Überschriften, Listen, Links, Code, Zitate und Tabellen.

  • Absätze und Listen halten Notions Abstände
  • Die Größen folgen der Seite – 16px, oder 14px mit small
Der Editor-Adapter liest dieselben Regeln.
KlasseFür
fullVolle Breite
smallKleiner Text

Bewusst nur als Klasse: ::slotted() erreicht den geslotteten Knoten, nie einen Absatz darin, ein <nk-prose>-Element könnte seinen Inhalt also nicht stylen. Die Klasse gehört an einen Container im Light DOM, auch in NotionKit Elements.

html<div class="nk-page" style="padding:0;max-width:560px;margin:0"><div class="nk-prose"> <h2>Versionshinweise</h2> <p>Gerendertes Markdown bekommt die Dokument-Optik von <strong>einer Klasse</strong>: Überschriften, Listen, <a href="#">Links</a>, <code>Code</code>, Zitate und Tabellen.</p> <ul><li>Absätze und Listen halten Notions Abstände</li><li>Die Größen folgen der Seite – 16px, oder 14px mit <code>small</code></li></ul> <blockquote>Der Editor-Adapter liest dieselben Regeln.</blockquote> <table><thead><tr><th>Klasse</th><th>Für</th></tr></thead><tbody><tr><td><code>full</code></td><td>Volle Breite</td></tr><tr><td><code>small</code></td><td>Kleiner Text</td></tr></tbody></table> </div></div>
Auf kleinem Schirm:Fließt mit der Spalte; eine breite Tabelle scrollt in ihrem eigenen Kasten, statt die Seite zu verbreitern.
.nk-prose

Datenbank-Views

PRD 5.5

View-Reiter .nk-db-tabs

Die Leiste über einer Datenbank. Die aktive View sitzt als Pille auf dem Aktiv-Hauch, die anderen sind schlichte Wörter – keine Unterlinie, keine Linie, wie in Notion seit 2025. Das .badge-Kind trägt die Zeilenzahl.

▦ Tabelle4
▤ Board
🖼 Galerie
html<div class="nk-database"> <div class="nk-db-tabs"> <div class="nk-db-tab active">▦ Tabelle<span class="badge">4</span></div> <div class="nk-db-tab">▤ Board</div> <div class="nk-db-tab">🖼 Galerie</div> </div> </div>
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

Werkzeugleiste & Filter-Pills .nk-db-toolbar

Der Datenbank-Kopf, wie Notion ihn anordnet: links die View-Reiter, rechts die Werkzeuge der Ansicht – .nk-db-tool-Knöpfe für Filter, Sortieren und Suche, dann „Neu“. Ein Werkzeug, das wirkt, bekommt .active, den Akzent. Darunter hält .nk-filter-row die wirkenden Filter als .nk-filter-pills – .active mit Akzent-Tönung – und am Ende eine ruhige .add-Pill. Eine Pill ist ein Knopf, oder ein Kasten mit dem Label-Knopf und einem .fp-remove-×, wenn sich ein Filter direkt entfernen lässt.

▦ Tabelle
▤ Board
☰ Liste
html<div class="nk-database" style="max-width:620px"> <div class="nk-db-toolbar"> <div class="nk-db-tabs"> <div class="nk-db-tab active">▦ Tabelle</div><div class="nk-db-tab">▤ Board</div><div class="nk-db-tab">☰ Liste</div> </div> <div class="tools"> <button class="nk-db-tool active">Filter</button><button class="nk-db-tool">Sortieren</button><button class="nk-db-tool" aria-label="Suche">🔍</button> <button class="nk-btn primary small">Neu</button> </div> </div> <div class="nk-filter-row"> <span class="nk-filter-pill active"><button>Status: Offen</button><button class="fp-remove" aria-label="Filter entfernen">×</button></span> <button class="nk-filter-pill">Verantwortlich: Marcel ▾</button> <button class="nk-filter-pill add">+ Filter</button> </div> </div>
Auf kleinem Schirm:Wird die Zeile schmal, scrollen die Reiter seitwärts; die Werkzeuge behalten ihren Platz. Die Pills brechen in weitere Zeilen um.
.nk-db-toolbar.tools.nk-db-tool.active.nk-filter-row.nk-filter-pill.add.fp-remove

Tabellen-Ansicht .nk-table

36px-Zeilen bei 14px, Haarlinien zwischen Zeilen und Spalten, Kopfzellen ruhig und klickbar – an einer echten Notion-Tabelle gemessen. Eine Auswahlspalte hat th.select-all als Kopf: eine Checkbox statt eines Namens – leer, ein Strich für einige Zeilen, ein Haken für alle –, die nichts sortiert; der Strich ist indeterminate, per Skript gesetzt. Jede Zelle ist white-space: nowrap, damit Spalten ihre Form behalten; .wrap auf der Tabelle oder einer Zelle lässt Text umbrechen, wie Notions „Spalte umbrechen“. .num an einer Zelle setzt eine Zahl rechtsbündig in gleich breiten Ziffern, wie Notion eine Zahl-Eigenschaft setzt; der Kopf bleibt links. .row-actions in einer Zelle setzt Knöpfe für die Zeile an ihren rechten Rand – „Erneut“, „Verwerfen“ –, und th.actions ist ein Kopf, der nichts sortiert. .td-text gibt einem Wert eine von Notions neun Textfarben – .orange für einen Fehler – und .td-desc eine leise zweite Zeile darunter; die Zeile wächst mit. .nk-new-row ist die Hinzufügen-Zeile unten (innerhalb von .nk-table funktioniert die Kurzform .new-row weiter).

📄Name◉Status 👤Verantwortlich📅Fällig 📊Fortschritt#Aufwand (h)
🚀 RoadmapDrei offene FragenFertig SLSara 12.05.2026 100 %6,0
🎨 Design-SystemIn Arbeit TWTom 20.05.2026 65 %12,5
📣 LaunchGeplant MKMia 02.06.2026 10 %3,25
+ Neue Seite
html<div class="nk-table-wrap"><table class="nk-table"> <thead><tr> <th class="select-all"><label class="nk-check"><input type="checkbox" aria-label="Alle auswählen"></label></th><th><span class="th-icon">📄</span>Name</th><th><span class="th-icon">◉</span>Status</th> <th><span class="th-icon">👤</span>Verantwortlich</th><th><span class="th-icon">📅</span>Fällig</th> <th><span class="th-icon">📊</span>Fortschritt</th><th><span class="th-icon">#</span>Aufwand (h)</th><th class="actions"></th> </tr></thead> <tbody> <tr><td><label class="nk-check"><input type="checkbox" checked></label></td><td><span class="row-title">🚀 Roadmap</span><span class="td-desc">Drei offene Fragen</span></td><td><span class="nk-tag green">Fertig</span></td> <td><span class="person-cell"><span class="nk-avatar small purple">SL</span>Sara</span></td> <td class="date-cell">12.05.2026</td> <td><span class="nk-progress"><i style="width:100%"></i></span><span class="nk-progress-label">100 %</span></td><td class="num">6,0</td> <td><span class="row-actions"><button class="nk-btn secondary small">Öffnen</button><button class="nk-btn danger small">Archivieren</button></span></td></tr> <tr><td><label class="nk-check"><input type="checkbox"></label></td><td><span class="row-title">🎨 Design-System</span></td><td><span class="nk-tag blue">In Arbeit</span></td> <td><span class="person-cell"><span class="nk-avatar small blue">TW</span>Tom</span></td> <td class="date-cell">20.05.2026</td> <td><span class="nk-progress"><i style="width:65%"></i></span><span class="nk-progress-label">65 %</span></td><td class="num">12,5</td> <td><span class="row-actions"><button class="nk-btn secondary small">Öffnen</button><button class="nk-btn danger small">Archivieren</button></span></td></tr> <tr><td><label class="nk-check"><input type="checkbox" checked></label></td><td><span class="row-title">📣 Launch</span></td><td><span class="nk-tag yellow">Geplant</span></td> <td><span class="person-cell"><span class="nk-avatar small orange">MK</span>Mia</span></td> <td class="date-cell"><span class="td-text red">02.06.2026</span></td> <td><span class="nk-progress"><i style="width:10%"></i></span><span class="nk-progress-label">10 %</span></td><td class="num">3,25</td> <td><span class="row-actions"><button class="nk-btn secondary small">Öffnen</button><button class="nk-btn danger small">Archivieren</button></span></td></tr> </tbody> </table> <div class="nk-new-row">+ Neue Seite</div></div> <script>document.currentScript.previousElementSibling.querySelector('th.select-all input').indeterminate = true</script>
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.
.nk-table-wrap.nk-table.wrap.th-icon.row-title.date-cell.person-cell.num.row-actions.actions.select-all.td-text.td-desc.nk-new-row

Tags .nk-tag

Die Select-Option, wie Notion sie zeichnet: 20px hoch, 3px Ecken, die 14px der Zelle, fast schwarzer Text auf gesättigter Fläche (≥ 10:1 im Hellmodus). Neun Farben, je ein Hintergrund/Text-Paar pro Theme; ohne Farbklasse ist es der graue Tag. Für farbigen Text die --nk-color-*-Mitteltöne nehmen, für eine weiche Fläche die --nk-tint-*-Hintergründe.

Nicht begonnen Archiv Geplant Review Fertig In Arbeit Design-System Idee Blockiert
html<span class="nk-tag">Nicht begonnen</span> <span class="nk-tag brown">Archiv</span> <span class="nk-tag orange">Geplant</span> <span class="nk-tag yellow">Review</span> <span class="nk-tag green">Fertig</span> <span class="nk-tag blue">In Arbeit</span> <span class="nk-tag purple">Design-System</span> <span class="nk-tag pink">Idee</span> <span class="nk-tag red">Blockiert</span>
Auf kleinem Schirm:Unverändert. Inline-flex mit Ellipse, eine lange Option wird also gekürzt statt die Spalte verbreitert.
.nk-tag.gray.brown.orange.yellow.green.blue.purple.pink.red

Fortschrittsbalken .nk-progress

Eine 6px-Schiene, deren Füllung ein <i> mit Prozentbreite ist. Schiene und Füllung nutzen Notions blaue Tönung und den blauen Mittelton und ziehen bei einem Theme-Wechsel mit. 110px breit in einer Zelle; wide füllt seine Zeile – ein Eigenschaftswert, ein Panel, eine Kursübersicht – und in einer flex-Zeile behält das Label seinen Platz daneben; in einer flex-Spalte bleibt er ein 6px-Balken. .nk-progress-row hält Balken und Label als eine Zeile – in einer flex-Spalte, einem Panel, stünden die beiden sonst untereinander: Das Label steht neben dem Balken, auf seiner Mitte, und ein breiter Balken füllt den Rest.

65 %

20 %
80 %

Fortschritt

40 %
html<span class="nk-progress"><i style="width:65%"></i></span><span class="nk-progress-label">65 %</span><br><br> <span class="nk-progress"><i style="width:20%"></i></span><span class="nk-progress-label">20 %</span> <div style="display:flex;align-items:center;max-width:360px;margin-top:14px"><span class="nk-progress wide"><i style="width:80%"></i></span><span class="nk-progress-label">80 %</span></div> <div class="nk-panel" style="max-width:360px;margin-top:14px"><h3>Fortschritt</h3><span class="nk-progress-row"><span class="nk-progress wide"><i style="width:40%"></i></span><span class="nk-progress-label">40 %</span></span></div>
Auf kleinem Schirm:Der 110px-Balken bleibt in einer Tabellenzelle lesbar; wide folgt seinem Container.
.nk-progress.nk-progress-label.wide.nk-progress-row

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.

Geplant1
🖥 Board-Ansicht
TW28.05.
In Arbeit1
🎨 Design-System
Fertig1
🚀 Roadmap
12.05.
html<div class="nk-board active"> <div class="nk-board-col"> <div class="nk-board-col-header"><span class="nk-tag orange">Geplant</span><span class="count">1</span></div> <div class="nk-card"><div class="card-title">🖥 Board-Ansicht</div><div class="card-meta"><span class="nk-avatar small blue">TW</span>28.05.</div></div> </div> <div class="nk-board-col"> <div class="nk-board-col-header"><span class="nk-tag blue">In Arbeit</span><span class="count">1</span></div> <div class="nk-card"><div class="card-title">🎨 Design-System</div><div class="card-meta"><span class="nk-progress" style="width:70px"><i style="width:65%"></i></span></div></div> </div> <div class="nk-board-col"> <div class="nk-board-col-header"><span class="nk-tag green">Fertig</span><span class="count">1</span></div> <div class="nk-card"><div class="card-title">🚀 Roadmap</div><div class="card-meta">12.05.</div></div> </div> </div>
Auf kleinem Schirm:Die Spalten scrollen horizontal, statt zu stapeln – das Board bleibt ein Board.
.nk-board.nk-board-col.nk-board-col-header.count.nk-card.card-title.card-meta

Listen-Ansicht .nk-list

Die dritte Datenbank-Ansicht: eine Zeile pro Eintrag – Icon, Titel und rechts ein paar Eigenschaften –, wie Notion eine Datenbank unter „Liste“ zeigt. Haarlinien zwischen den Zeilen und der Hover-Hauch über die ganze Zeile, wie eine Tabelle ohne Spalten; die letzte Zeile verliert ihre Linie. Als <a> ist jede Zeile ein echter Link. In .nk-database unter die View-Reiter setzen oder allein für jede Liste von Seiten nutzen. Eine Zeile, die selbst kein Ziel ist – eine Datei mit eigenem Entfernen-Knopf –, bekommt .static: keine Hand, kein Hover-Hauch.

html<div class="nk-list" style="max-width:520px"> <a class="nk-list-item" href="#"><span class="l-icon">🚀</span><span class="l-title">Roadmap</span><span class="l-meta">12.05.2026 <span class="nk-tag green">Fertig</span></span></a> <a class="nk-list-item" href="#"><span class="l-icon">🎨</span><span class="l-title">Design-System</span><span class="l-meta">20.05.2026 <span class="nk-tag blue">In Arbeit</span></span></a> <a class="nk-list-item" href="#"><span class="l-icon">📣</span><span class="l-title">Launch</span><span class="l-meta">02.06.2026 <span class="nk-tag orange">Geplant</span></span></a> </div>
Auf kleinem Schirm:Bleibt eine Zeile pro Eintrag: Der Titel gibt zuerst nach und endet mit Auslassungspunkten, die Eigenschaften behalten ihren Platz.
.nk-list.nk-list-item.l-icon.l-title.l-meta.last.static

Kalender-Ansicht .nk-calendar-view

Die Datenbank als Notions Monat, ein View-Reiter wie Tabelle, Board und Liste: ein Kopf mit dem Monat und den .cal-nav-Knöpfen der Datumsauswahl, die Wochentage und ein .cv-day je Tag mit seiner .cv-num oben rechts – die von heute auf einer roten Pille – und den an diesem Tag fälligen Zeilen als .cv-item-Karten. Tage des Monats davor und danach (.out) und Tage, an denen nicht gearbeitet wird (.off), sind hinterlegt. weeks ergänzt eine Spalte mit ISO-Kalenderwochen. Die Spalten teilen sich die Breite, sieben passen also immer; der Titel eines Eintrags endet mit Auslassungspunkten.

Mai 2026
KW
Mo
Di
Mi
Do
Fr
Sa
So
18
27
28
29
30
1
2
3
19
4
5
6
7
8
9
10
20
11
12
13
14
15
16
17
21
18
19
20
21
22
23
24
22
25
26
27
28
29
30
31
html<div class="nk-calendar-view weeks"> <div class="cv-head"><div class="cv-title">Mai 2026</div><button class="cal-nav">Heute</button><button class="cal-nav" aria-label="Voriger Monat"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M15 6l-6 6 6 6"/></svg></button><button class="cal-nav" aria-label="Nächster Monat"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M9 6l6 6-6 6"/></svg></button></div> <div class="cv-grid"> <div class="cv-wd">KW</div><div class="cv-wd">Mo</div><div class="cv-wd">Di</div><div class="cv-wd">Mi</div><div class="cv-wd">Do</div><div class="cv-wd">Fr</div><div class="cv-wd">Sa</div><div class="cv-wd">So</div> <div class="cv-week">18</div><div class="cv-day out"><span class="cv-num">27</span></div><div class="cv-day out"><span class="cv-num">28</span></div><div class="cv-day out"><span class="cv-num">29</span></div><div class="cv-day out"><span class="cv-num">30</span></div><div class="cv-day"><span class="cv-num">1</span></div><div class="cv-day"><span class="cv-num">2</span></div><div class="cv-day"><span class="cv-num">3</span></div> <div class="cv-week">19</div><div class="cv-day"><span class="cv-num">4</span></div><div class="cv-day"><span class="cv-num">5</span></div><div class="cv-day"><span class="cv-num">6</span></div><div class="cv-day"><span class="cv-num">7</span></div><div class="cv-day"><span class="cv-num">8</span><button class="cv-item">🧭 App-Shell & Sidebar</button></div><div class="cv-day"><span class="cv-num">9</span></div><div class="cv-day"><span class="cv-num">10</span><button class="cv-item">📄 Seiten-Shell</button></div> <div class="cv-week">20</div><div class="cv-day"><span class="cv-num">11</span></div><div class="cv-day"><span class="cv-num">12</span></div><div class="cv-day"><span class="cv-num">13</span></div><div class="cv-day"><span class="cv-num">14</span></div><div class="cv-day"><span class="cv-num">15</span></div><div class="cv-day"><span class="cv-num">16</span></div><div class="cv-day"><span class="cv-num">17</span></div> <div class="cv-week">21</div><div class="cv-day"><span class="cv-num">18</span></div><div class="cv-day"><span class="cv-num">19</span></div><div class="cv-day today"><span class="cv-num">20</span><button class="cv-item">🗃️ Datenbank-Tabelle</button><button class="cv-item">▤ Board-Ansicht</button></div><div class="cv-day"><span class="cv-num">21</span></div><div class="cv-day"><span class="cv-num">22</span></div><div class="cv-day"><span class="cv-num">23</span></div><div class="cv-day"><span class="cv-num">24</span></div> <div class="cv-week">22</div><div class="cv-day"><span class="cv-num">25</span></div><div class="cv-day"><span class="cv-num">26</span></div><div class="cv-day"><span class="cv-num">27</span></div><div class="cv-day"><span class="cv-num">28</span></div><div class="cv-day"><span class="cv-num">29</span></div><div class="cv-day"><span class="cv-num">30</span></div><div class="cv-day"><span class="cv-num">31</span></div> </div> </div>
Auf kleinem Schirm:Unter 860px werden die Tage niedriger (64px) und die Karten kleiner; sieben Spalten passen weiter.
.nk-calendar-view.weeks.cv-head.cv-title.cv-grid.cv-wd.cv-week.cv-day.out.off.today.cv-num.cv-item

Galerie-Ansicht .nk-gallery

Die fünfte Datenbank-Ansicht: die Einträge als Karten mit einem Bild oben, in einem Raster, das die Zeile füllt – Notions Galerie, für einen Kurskatalog oder eine Leseliste. Eine Karte ist die .nk-card des Boards mit .card-title und .card-meta; ein .nk-cover als erstes Kind läuft in 2:1 bis an die Ränder der Karte, ein Bild darin wird beschnitten – ohne Bild zeigt sich der Cover-Verlauf. .small und .large setzen die Kartengröße, Spalten ab 180px und 340px statt 260px; .fit zeigt ein Bild ganz, für Logos. Ein .nk-new-row am Ende wird zur Hinzufügen-Karte. Der Klick auf eine Karte ist dein Skript, wie bei einer Tabellenzeile. Eine Karte, die sich in einem neuen Tab öffnen und deren Adresse sich kopieren lassen soll, ist ein Link, <a class="nk-card" href>, in einem .card-item mit role="listitem" – der Link behält seine eigene Rolle –, und die Karte füllt es.

html<div class="nk-gallery" role="list"> <div class="nk-card" role="listitem" tabindex="0"><div class="nk-cover"><img src="../covers/aurora.svg" alt=""></div><div class="card-title">🚀 Roadmap</div><div class="card-meta"><span class="nk-tag green">Fertig</span><span>📅 12.05.2026</span></div></div> <div class="nk-card" role="listitem" tabindex="0"><div class="nk-cover"><img src="../covers/dunes.svg" alt=""></div><div class="card-title">🎨 Design-System</div><div class="card-meta"><span class="nk-tag blue">In Arbeit</span><span>📅 20.05.2026</span></div></div> <div class="card-item" role="listitem"><a class="nk-card" href="#nk-gallery"><div class="nk-cover"></div><div class="card-title">📣 Launch</div><div class="card-meta"><span class="nk-tag yellow">Geplant</span><span>📅 02.06.2026</span></div></a></div> <div class="nk-new-row" role="button" tabindex="0">+ Neue Seite</div> </div>
Auf kleinem Schirm:Das Raster verliert Spalten von selbst – auf dem Telefon eine Karte pro Zeile, ganz ohne Breakpoint.
.nk-gallery.small.large.fit.card-item

Formulare & Einstellungen

PRD 5.6

Inputs, Textarea, Select .nk-input

Eine gemeinsame Form für alle drei: gefüllt mit --nk-bg-input in einer Haarlinie, 32px hoch bei 14px – Notions Input, keine umrandete weiße Box. Der Fokusring wird aus dem Akzent gemischt und färbt sich mit ihm um. .wide füllt die Zeile. Jedes behält mindestens 210px, außer in einem Panel, wo es nie über den Rand einer schmalen Kachel hinausragt; eine Feldzeile behält die 210px auch dort.

html<div style="display:flex;flex-direction:column;gap:10px;max-width:340px"> <input class="nk-input wide" value="Ada Lovelace"> <select class="nk-select wide"><option>Hell</option><option>Dunkel</option><option>System</option></select> <textarea class="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

Kopierfeld .nk-copy-field

Ein Wert zum Mitnehmen – ein Link zum Teilen, eine Adresse, ein Schlüssel – in einem eigenen Feld, so hoch wie ein Eingabefeld, mit seinen Aktionen rechts darin. .cf-value hält den Text in einer Zeile mit Auslassungspunkten, ein Klick markiert ihn ganz; .cf-btns sind die leisen Aktionen – Kopieren und, bei einem Geheimnis, Zeigen. .copied an einem Button ist der Moment danach, in Grün; das Kopieren übernimmt dein Skript. mono für Adressen, Schlüssel und Code, wrap lässt einen langen Wert umbrechen, die Aktionen bleiben in der ersten Zeile, wide füllt die Zeile. Wie ein Input behält es mindestens 210px, außer in einem Panel. Ein Button kann neben seinem Wort in einem <span> ein <svg> tragen – zwei überlappende Quadrate für Kopieren, ein Auge für Zeigen, ein Haken für den Moment danach – und das Wort als aria-label: Auf dem Telefon und überall mit icons steht das Symbol für das Wort, wie in Notion, und ein verdeckter Schlüssel behält ein Dutzend Zeichen mehr.

https://monahilft.notionkit.app
ntn_••••••••••••••••••••
ntn_••••••••••••••••••••
jsbtn.addEventListener('click', async () => {
  await navigator.clipboard.writeText(field.querySelector('.cf-value').textContent);
  btn.classList.add('copied');   // kurz grün
  setTimeout(() => btn.classList.remove('copied'), 1500);
});
html<div class="nk-copy-field" style="max-width:340px"><span class="cf-value">https://monahilft.notionkit.app</span><button class="cf-btn">Kopieren</button></div> <div class="nk-copy-field mono" style="max-width:340px;margin-top:10px"><span class="cf-value">ntn_••••••••••••••••••••</span><button class="cf-btn">Zeigen</button><button class="cf-btn copied">✓ Kopiert</button></div> <div class="nk-copy-field mono icons" style="max-width:340px;margin-top:10px"><span class="cf-value">ntn_••••••••••••••••••••</span><button class="cf-btn" aria-label="Zeigen"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M2 12s3.5-7 10-7 10 7 10 7-3.5 7-10 7S2 12 2 12Z"/><circle cx="12" cy="12" r="3"/></svg><span>Zeigen</span></button><button class="cf-btn" aria-label="Kopieren"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M15 9V5a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v8a2 2 0 0 0 2 2h4"/><rect x="9" y="9" width="12" height="12" rx="2"/></svg><span>Kopieren</span></button><button class="cf-btn copied" aria-label="Kopiert"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M20 6 9 17l-5-5"/></svg><span>Kopiert</span></button></div>
Auf kleinem Schirm:Bleibt in seiner Spalte: Gekürzt wird der Wert, nie die Aktionen. Buttons mit einem Symbol zeigen es statt ihres Worts.
.nk-copy-field.cf-value.cf-btn.copied.mono.wrap.wide.icons

Datumsauswahl .nk-calendar

Notions Monatsblatt für ein Datum: ein Titel mit Heute und ‹ ›, die Wochentage, sechs Reihen .cal-day-Knöpfe. Der gewählte Tag ist .selected im Akzent, heute ist rot; ein Zeitraum läuft von .start bis .end über .in-range-Tage in der Tönung des Akzents. .off graut einen Tag, an dem nicht gearbeitet wird – ein Wochenende, ein Feiertag, mit seinem Namen als title –, .out einen Tag des Monats davor oder danach; aria-disabled="true" markiert einen außerhalb der Grenzen. .cal-marks hält bis zu drei Punkte in den neun Farben (i.blue, i.red …), für Fristen oder Meilensteine. weeks stellt jeder Reihe die ISO-Kalenderwoche voran, .cal-foot ein Zeitfeld oder Aktionen unter das Blatt. Die Zellen sind 36px, sieben und die Wochenspalte füllen also ein .nk-pop; in .nk-pop.floating.sheet ist es auf dem Desktop ein Popover und auf dem Telefon ein Sheet mit 44px-Zellen. Monat, Tasten und Wert sind dein Skript – oder <nk-calendar>.

Juni 2026
KWMoDiMiDoFrSaSo 23 24 25 26 27 28
Juni 2026
KWMoDiMiDoFrSaSo 23 24 25 26 27 28
html<div style="display:flex;gap:16px;flex-wrap:wrap;align-items:flex-start"> <div class="nk-pop"> <div class="nk-calendar weeks"> <div class="cal-head"><div class="cal-title">Juni 2026</div><button class="cal-nav">Heute</button><button class="cal-nav" aria-label="Voriger Monat"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M15 6l-6 6 6 6"/></svg></button><button class="cal-nav" aria-label="Nächster Monat"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M9 6l6 6-6 6"/></svg></button></div> <div class="cal-grid"> <span class="cal-wd">KW</span><span class="cal-wd">Mo</span><span class="cal-wd">Di</span><span class="cal-wd">Mi</span><span class="cal-wd">Do</span><span class="cal-wd">Fr</span><span class="cal-wd">Sa</span><span class="cal-wd">So</span> <span class="cal-week">23</span><button class="cal-day">1</button><button class="cal-day selected">2<span class="cal-marks"><i class="blue"></i></span></button><button class="cal-day">3</button><button class="cal-day off" title="Fronleichnam">4</button><button class="cal-day">5</button><button class="cal-day off">6</button><button class="cal-day off">7</button> <span class="cal-week">24</span><button class="cal-day">8</button><button class="cal-day">9</button><button class="cal-day">10</button><button class="cal-day">11<span class="cal-marks"><i class="orange"></i><i class="red"></i></span></button><button class="cal-day">12</button><button class="cal-day off">13</button><button class="cal-day off">14</button> <span class="cal-week">25</span><button class="cal-day">15</button><button class="cal-day">16</button><button class="cal-day today">17</button><button class="cal-day">18</button><button class="cal-day">19</button><button class="cal-day off">20</button><button class="cal-day off">21</button> <span class="cal-week">26</span><button class="cal-day">22</button><button class="cal-day">23</button><button class="cal-day">24<span class="cal-marks"><i class="green"></i></span></button><button class="cal-day">25</button><button class="cal-day">26</button><button class="cal-day off">27</button><button class="cal-day off">28</button> <span class="cal-week">27</span><button class="cal-day">29</button><button class="cal-day">30</button><button class="cal-day out">1</button><button class="cal-day out">2</button><button class="cal-day out">3</button><button class="cal-day out off">4</button><button class="cal-day out off">5</button> <span class="cal-week">28</span><button class="cal-day out">6</button><button class="cal-day out">7</button><button class="cal-day out">8</button><button class="cal-day out">9</button><button class="cal-day out">10</button><button class="cal-day out off">11</button><button class="cal-day out off">12</button> </div> </div> </div> <div class="nk-pop"> <div class="nk-calendar weeks"> <div class="cal-head"><div class="cal-title">Juni 2026</div><button class="cal-nav">Heute</button><button class="cal-nav" aria-label="Voriger Monat"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M15 6l-6 6 6 6"/></svg></button><button class="cal-nav" aria-label="Nächster Monat"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M9 6l6 6-6 6"/></svg></button></div> <div class="cal-grid"> <span class="cal-wd">KW</span><span class="cal-wd">Mo</span><span class="cal-wd">Di</span><span class="cal-wd">Mi</span><span class="cal-wd">Do</span><span class="cal-wd">Fr</span><span class="cal-wd">Sa</span><span class="cal-wd">So</span> <span class="cal-week">23</span><button class="cal-day">1</button><button class="cal-day">2</button><button class="cal-day">3</button><button class="cal-day off" title="Fronleichnam">4</button><button class="cal-day">5</button><button class="cal-day off">6</button><button class="cal-day off">7</button> <span class="cal-week">24</span><button class="cal-day start">8</button><button class="cal-day in-range">9</button><button class="cal-day in-range">10</button><button class="cal-day in-range">11</button><button class="cal-day end">12</button><button class="cal-day off">13</button><button class="cal-day off">14</button> <span class="cal-week">25</span><button class="cal-day">15</button><button class="cal-day">16</button><button class="cal-day today">17</button><button class="cal-day">18</button><button class="cal-day">19</button><button class="cal-day off">20</button><button class="cal-day off">21</button> <span class="cal-week">26</span><button class="cal-day">22</button><button class="cal-day">23</button><button class="cal-day">24</button><button class="cal-day">25</button><button class="cal-day">26</button><button class="cal-day off">27</button><button class="cal-day off">28</button> <span class="cal-week">27</span><button class="cal-day">29</button><button class="cal-day">30</button><button class="cal-day out">1</button><button class="cal-day out">2</button><button class="cal-day out">3</button><button class="cal-day out off">4</button><button class="cal-day out off">5</button> <span class="cal-week">28</span><button class="cal-day out">6</button><button class="cal-day out">7</button><button class="cal-day out">8</button><button class="cal-day out">9</button><button class="cal-day out">10</button><button class="cal-day out off">11</button><button class="cal-day out off">12</button> </div> <div class="cal-foot"><input class="nk-input" type="time" value="09:30" aria-label="Uhrzeit"><button class="cal-nav">Löschen</button></div> </div> </div> </div>
Auf kleinem Schirm:In einem Sheet wachsen die Zellen auf 44px, eine Daumenbreite; sieben und die Wochenspalte passen weiter auf einen 390px-Schirm.
.nk-calendar.weeks.cal-head.cal-title.cal-nav.cal-grid.cal-wd.cal-week.cal-day.out.off.today.start.end.in-range.cal-marks.cal-foot

Buttons .nk-btn

Fünf Varianten, 28px hoch bei 14px. .secondary und .danger sind Notions weißer Button: die Kontur ist --nk-shadow-btn, ein 1px-Innenring plus 1px Schatten, kein Rahmen. Hover ist bei gefüllten Buttons eine Deckkraft-Änderung, bei weißen ein Hauch – nie ein Farbwechsel. .small (24px) lässt sich mit jeder Variante kombinieren. Über eine Spalte gestreckt – ein Button über die volle Breite auf einer Anmeldeseite – bleibt seine Beschriftung mittig.

html<div style="display:flex;gap:8px;flex-wrap:wrap;align-items:center"> <button class="nk-btn primary">Änderungen speichern</button> <button class="nk-btn secondary">Verwerfen</button> <button class="nk-btn danger">Löschen</button> <button class="nk-btn danger-solid">Löschen</button> <button class="nk-btn secondary small">Entfernen</button> </div>
Auf kleinem Schirm:Die Höhe liegt bei 28px, unter dem 44px-Touch-Ziel. Für Touch-Oberflächen das Padding anheben.
.nk-btn.primary.secondary.danger.danger-solid.small

Switch .nk-switch

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. In einer Einstellungszeile benennt das nk-field-Label den Schalter; für mehrere Schalter nebeneinander bekommt jeder ein label.nk-switch-label mit sichtbarem Text – der Text gehört zur Trefferfläche.

Kompakte Ansicht
Reduziert Abstände in Sidebar und Listen.
Animationen reduzieren
html<div style="max-width:420px"> <div class="nk-field"><div><div class="f-label">Kompakte Ansicht</div><div class="f-desc">Reduziert Abstände in Sidebar und Listen.</div></div> <div class="f-control"><button class="nk-switch" role="switch" aria-checked="true"></button></div></div> <div class="nk-field"><div><div class="f-label">Animationen reduzieren</div></div> <div class="f-control"><button class="nk-switch" role="switch" aria-checked="false"></button></div></div> <div style="display:flex;gap:20px;flex-wrap:wrap;padding:9px 0"> <label class="nk-switch-label"><button class="nk-switch" role="switch" aria-checked="true"></button><span>Geplant</span></label> <label class="nk-switch-label"><button class="nk-switch" role="switch" aria-checked="false"></button><span>In Arbeit</span></label> <label class="nk-switch-label"><button class="nk-switch" role="switch" aria-checked="true"></button><span>Fertig</span></label> </div> </div>
Auf kleinem Schirm:34×20px – die Trefferfläche vergrößern, indem die ganze nk-field-Zeile klickbar wird.
.nk-switch.nk-switch-label.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; eine Checkbox, die indeterminate ist – nur eine Eigenschaft, per Skript gesetzt –, zeigt einen Strich, für eine teilweise gewählte Gruppe. Bricht ein Label um, bleibt die Box neben seiner ersten Zeile, wie in Notion.

html<div style="display:flex;gap:32px;flex-wrap:wrap"> <div> <label class="nk-check"><input type="checkbox">Alle</label><script>document.currentScript.previousElementSibling.querySelector('input').indeterminate = true</script> <label class="nk-check"><input type="checkbox" checked>Hell</label> <label class="nk-check"><input type="checkbox">Dunkel</label> </div> <div> <label class="nk-check"><input type="radio" name="nkdemo" checked>Hell</label> <label class="nk-check"><input type="radio" name="nkdemo">System</label> </div> <div style="max-width:260px"> <label class="nk-check"><input type="checkbox" checked>Produktneuheiten und Einladungen zu Beta-Programmen, höchstens einmal im Monat – mit einem Klick abbestellbar.</label> </div> </div>
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.

Textgröße: 100 %
html<div><input class="nk-slider" type="range" min="80" max="140" value="100"> <div class="nk-slider-value">Textgröße: 100 %</div></div>
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. stacked setzt das Label über ein vollbreites Control – für Textareas und lange Beschreibungen; compact verkleinert das Label auf 12px tertiären Text und nimmt das Zeilen-Padding weg. Für mehrere kurze Felder nebeneinander gibt es .nk-fields.

Anzeigename
So wirst du im Workspace angezeigt.
E-Mail
Über mich
html<div style="max-width:460px"> <div class="nk-field"><div><div class="f-label">Anzeigename</div><div class="f-desc">So wirst du im Workspace angezeigt.</div></div> <div class="f-control"><input class="nk-input" value="Ada Lovelace"></div></div> <div class="nk-field"><div><div class="f-label">E-Mail</div></div> <div class="f-control"><input class="nk-input" value="ada@acme.com"></div></div> <div class="nk-field stacked"><div><div class="f-label">Über mich</div></div> <div class="f-control"><textarea class="nk-textarea" rows="2" placeholder="Ein paar Worte über dich …"></textarea></div></div> </div>
Auf kleinem Schirm:Unter 860px bricht die Zeile um: Ein Control, das nicht neben sein Label passt, rückt darunter, und kein Control wird breiter als seine Spalte.
.nk-field.f-label.f-desc.f-control.stacked.compact

Feldraster .nk-fields

Mehrere kurze Felder in einer Zeile: ein Raster aus minmax(150px, 1fr)-Spalten, das umbricht, wie es die Breite erlaubt. Jedes direkte .nk-field-Kind wird von selbst gestapelt und kompakt – ein 12px-Label über einem vollbreiten Control –, damit nichts kollidiert. .fit lässt die Felder die Zeile stattdessen teilen – zwei Felder in einem 560px-Dialog sind zwei Hälften, nicht zwei Drittel und eine Lücke.

Name
E-Mail
Status
html<div class="nk-fields" style="max-width:520px"> <div class="nk-field"><div><div class="f-label">Name</div></div><div class="f-control"><input class="nk-input" value="Ada Lovelace"></div></div> <div class="nk-field"><div><div class="f-label">E-Mail</div></div><div class="f-control"><input class="nk-input" value="ada@acme.com"></div></div> <div class="nk-field"><div><div class="f-label">Status</div></div><div class="f-control"><select class="nk-select"><option>In Arbeit</option><option>Fertig</option></select></div></div> </div>
Auf kleinem Schirm:Bricht von selbst auf ein oder zwei Spalten um; kein Breakpoint nötig.
.nk-fields.fit

Profil-Zeile & Bild .nk-profile-row

Ein 56px-Avatar mit seinen Aktionen daneben, in .pr-actions – hochladen, ändern und das leise .pr-remove. Der Verlauf passt zu jedem anderen Avatar im System, weil alle dieselben zwei Decor-Tokens lesen; ein <img> in .big-avatar ist ein gewähltes Bild, auf den Kreis zugeschnitten. square macht daraus das abgerundete Quadrat eines Workspace-Icons. Die Datei zu wählen – ein verstecktes <input type="file">, vom Button geöffnet, EXIF-Drehung, Skalierung – übernimmt dein Skript oder <nk-image-picker>.

AL
html<div class="nk-profile-row"> <div class="big-avatar">AL</div> <div class="pr-actions"> <button class="nk-btn secondary small">Bild hochladen</button> </div> </div> <div class="nk-profile-row"> <div class="big-avatar square"><img src="../favicon.svg" alt=""></div> <div class="pr-actions"> <button class="nk-btn secondary small">Bild ändern</button> <button class="nk-btn secondary small pr-remove">Entfernen</button> </div> </div>
Auf kleinem Schirm:Unverändert; die Aktionen bleiben neben dem Avatar.
.nk-profile-row.big-avatar.square.pr-actions.pr-remove

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<div style="max-width:460px"> <div class="nk-model-card selected"><div class="m-radio"></div><div> <div class="m-name">Mona Standard<span class="nk-tag green">Empfohlen</span></div> <div class="m-desc">Ausgewogenes Modell für den Arbeitsalltag. Schnell, ruhig, zuverlässig.</div></div></div> <div class="nk-model-card"><div class="m-radio"></div><div> <div class="m-name">Mona Deep</div><div class="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<div class="nk-danger-zone" style="margin-top:0;max-width:460px"> <div class="dz-title">⚠️ Gefahrenbereich</div> <div class="nk-field" style="padding-top:0"> <div><div class="f-label">Löschen</div><div class="f-desc">Entfernt alle Seiten, Datenbanken und Mitglieder unwiderruflich.</div></div> <div class="f-control"><button class="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.

AL
Ada Lovelace
ada@acme.com
TW
Tom Weber
tom@acme.com
html<div class="nk-member-list" style="max-width:460px"> <div class="nk-member-row"><span class="nk-avatar purple">AL</span> <div><div>Ada Lovelace</div><div class="m-mail">ada@acme.com</div></div> <select class="nk-select"><option>Admin</option><option>Mitglied</option></select></div> <div class="nk-member-row"><span class="nk-avatar blue">TW</span> <div><div>Tom Weber</div><div class="m-mail">tom@acme.com</div></div> <select class="nk-select"><option>Mitglied</option></select></div> </div>
Auf kleinem Schirm:Die Namensspalte gibt zuerst nach: Eine lange Adresse endet mit Auslassungspunkten, die Rollen-Auswahl behält ihren Platz.
.nk-member-list.nk-member-row.m-mail

Overlays & Menüs

PRD 5.8

Popover-Basis .nk-pop

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.

Aktionen
✏️Umbenennen
html<div class="nk-pop" style="width:240px"> <div class="nk-menu-label">Aktionen</div> <div class="nk-menu-item"><span class="m-icon">✏️</span>Umbenennen</div> </div>
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.

🚀📊💡✅🎨📚🗂️🔍📥⚙️🧩🌙☀️📅👤💬
🕐😀🐶🍎⚽🚗💡
html<div class="nk-pop"> <input class="nk-emoji-search" placeholder="Suche …"> <div class="nk-emoji-grid"> <span>🚀</span><span>📊</span><span>💡</span><span>✅</span><span>🎨</span><span>📚</span><span>🗂️</span><span>🔍</span><span>📥</span><span>⚙️</span><span>🧩</span><span>🌙</span><span>☀️</span><span>📅</span><span>👤</span><span>💬</span> </div> <div class="nk-emoji-cats"><span class="active">🕐</span><span>😀</span><span>🐶</span><span>🍎</span><span>⚽</span><span>🚗</span><span>💡</span></div> </div>
Auf kleinem Schirm:Das Raster ist fließend; fix ist nur die 296px-Popover-Breite – also das Popover verbreitern, nicht das Raster.
.nk-emoji-search.nk-emoji-grid.nk-emoji-cats

Kontextmenü .nk-menu

nk-pop mit nk-menu kombinieren. Einträge nehmen links ein .m-icon und rechts ein .m-shortcut; .danger färbt einen Eintrag rot. Ein .nk-switch als letztes Kind eines Eintrags sitzt rechts, wie „Kleiner Text“ und „Volle Breite“ in Notions Seitenmenü. Ein Menü, das über der Seite schwebt, bekommt floating und öffnet und schließt über .open wie die Palette: Es blendet ein und setzt sich aus 4px Höhe und 98 % ab; geschlossen nimmt es weder Klicks noch Fokus an, und wo es sitzt, bestimmst du. sheet macht es auf dem Telefon zum Bottom Sheet, so wie Notions Mobil-App jedes Menü öffnet – dasselbe Markup, zwei Darstellungen. Ein schwebendes Menü wächst nie über das Fenster hinaus: Ein längeres scrollt in sich, und --_nk-float-max begrenzt es auf den Platz, den ein Skript unter oder über seinem Anker gefunden hat. Es liegt über Modal, Sheet und Dialog, ein Menü oder eine Datumsauswahl aus einem davon erscheint also darüber.

Seiten
✏️Umbenennen⌘⇧R
📄Duplizieren⌘D
🔗Link kopieren⌘L
🔡Kleiner Text
🗑In den Papierkorb
html<div class="nk-pop nk-menu floating sheet open" style="position:fixed; top:48px; right:12px">…</div>
html<div class="nk-pop nk-menu"> <div class="nk-menu-label">Seiten</div> <div class="nk-menu-item"><span class="m-icon">✏️</span>Umbenennen<span class="m-shortcut">⌘⇧R</span></div> <div class="nk-menu-item"><span class="m-icon">📄</span>Duplizieren<span class="m-shortcut">⌘D</span></div> <div class="nk-menu-item"><span class="m-icon">🔗</span>Link kopieren<span class="m-shortcut">⌘L</span></div> <div class="nk-menu-sep"></div> <div class="nk-menu-item"><span class="m-icon">🔡</span>Kleiner Text<button class="nk-switch" role="switch" aria-checked="true" aria-label="Kleiner Text"></button></div> <div class="nk-menu-sep"></div> <div class="nk-menu-item danger"><span class="m-icon">🗑</span>In den Papierkorb</div> </div> <pre class="nk-code" style="margin-top:12px"><span class="lang">html</span>&lt;div class="nk-pop nk-menu floating sheet open" style="position:fixed; top:48px; right:12px"&gt;…&lt;/div&gt;</pre>
Auf kleinem Schirm:Kürzel sind auf Touch bedeutungslos – die .m-shortcut-Spans dort ausblenden. Mit sheet wird das Menü unter 860px zum Bottom Sheet: volle Breite, ein Griff, 40px-Zeilen, die Seite dahinter abgedunkelt; eine Inline-Position wird übergangen.
.nk-menu.nk-menu-item.m-icon.m-shortcut.danger.nk-menu-sep.nk-menu-label.floating.sheet.open

Befehlspalette .nk-cmdk

Eine ⌘K-Palette: Eingabezeile, gruppierte Liste, Fußzeile mit Tastenhinweisen. Die per Tastatur hervorgehobene Zeile trägt .selected – diese Klasse verschiebt dein Pfeiltasten-Handler.

🔍
Seiten
📊Projektübersicht
📚Wissensdatenbank
Aktionen
+Neue Seite⌘N
⚙️Einstellungen öffnen⌘,
html<div class="nk-cmdk-backdrop open" style="position:absolute;padding-top:22px;border-radius:var(--nk-radius)"> <div class="nk-cmdk" style="width:min(460px, 92%)"> <div class="nk-cmdk-input-row"><span>🔍</span><input placeholder="Suchen oder Befehl eingeben …"></div> <div class="nk-cmdk-list"> <div class="nk-cmdk-group">Seiten</div> <div class="nk-cmdk-item selected"><span class="m-icon">📊</span>Projektübersicht</div> <div class="nk-cmdk-item"><span class="m-icon">📚</span>Wissensdatenbank</div> <div class="nk-cmdk-group">Aktionen</div> <div class="nk-cmdk-item"><span class="m-icon">+</span>Neue Seite<span class="m-shortcut">⌘N</span></div> <div class="nk-cmdk-item"><span class="m-icon">⚙️</span>Einstellungen öffnen<span class="m-shortcut">⌘,</span></div> </div> <div class="nk-cmdk-footer"> <span><kbd class="nk-kbd">↑</kbd><kbd class="nk-kbd">↓</kbd> navigieren</span> <span><kbd class="nk-kbd">↵</kbd> öffnen</span> <span><kbd class="nk-kbd">⌘</kbd><kbd class="nk-kbd">K</kbd> umschalten</span> </div> </div> </div>
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.
.nk-cmdk-backdrop.nk-cmdk.nk-cmdk-input-row.nk-cmdk-list.nk-cmdk-group.nk-cmdk-item.selected.nk-cmdk-empty.nk-cmdk-footer

Palette: keine Treffer .nk-cmdk-empty

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<div class="nk-cmdk" style="box-shadow:none;border:1px solid var(--nk-border);width:min(460px,100%)"> <div class="nk-cmdk-input-row"><span>🔍</span><input value="xyzzy" placeholder="Suchen oder Befehl eingeben …"></div> <div class="nk-cmdk-list"><div class="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

Sheet .nk-sheet

Notions Mobil-Fläche für Menüs, Eigenschaften und mehr: der Telefon-Zwilling des Modals. Der Backdrop blendet ein, das Panel steigt von der Unterkante auf, mit gerundeten oberen Ecken und einem .sh-grabber oben, und der Home-Indikator behält seinen Abstand. Es liegt über der Tab-Leiste. Wie das Modal startet es unsichtbar, .open zeigt es; geschlossen verlässt der Backdrop nach dem Ausblenden das Layout. Bis 640px breit, auf größeren Schirmen zentriert. Zeilen darin bekommen 40px, eine Daumenhöhe. Für ein Menü, das auf dem Desktop Popover und auf dem Telefon Sheet ist, stattdessen .nk-pop.sheet nehmen.

html<div class="nk-sheet-backdrop open" style="position:absolute;border-radius:var(--nk-radius)"> <div class="nk-sheet" role="dialog" aria-modal="true" aria-label="Seite"> <div class="sh-grabber"></div> <div class="sh-title">Seite</div> <div class="nk-menu-item"><span class="m-icon">🔡</span>Kleiner Text<button class="nk-switch" role="switch" aria-checked="true" aria-label="Kleiner Text"></button></div> <div class="nk-menu-item"><span class="m-icon">🔗</span>Link kopieren</div> <div class="nk-menu-item"><span class="m-icon">📄</span>Duplizieren</div> <div class="nk-menu-item danger"><span class="m-icon">🗑</span>In den Papierkorb</div> </div> </div>
Auf kleinem Schirm:Fürs Telefon gemacht: volle Breite, unteres Padding aus der Safe Area, der Inhalt scrollt im Sheet und bewegt nie die Seite.
.nk-sheet-backdrop.open.nk-sheet.sh-grabber.sh-title

Side Peek .nk-peek

Notions Side Peek: Eine Datenbankzeile öffnet sich in einem Panel am rechten Rand, in voller Höhe, neben der Tabelle, die sichtbar und bedienbar bleibt – es gibt keine Abdunklung, der Backdrop hält nur das Panel und lässt Klicks durch. .pk-bar trägt die Aktionen – Schließen mit », Als Seite öffnen –, .pk-body die Seite: Titel in 32px, Eigenschaften, Prosa, Kommentare. .open am Backdrop schiebt das Panel herein; geschlossen verlässt es das Layout, sobald es hinausgeglitten ist. Es liegt über Seite und Tab-Leiste und unter den schwebenden Menüs, sodass ein Menü aus dem Peek darüber erscheint. Das Schließen übernimmt dein Skript: », Escape, ein Klick daneben; ein Klick auf eine andere Zeile tauscht den Inhalt. Seine Breite ist das Token --nk-peek-width (560px): .pk-resize am linken Rand nimmt den Zeiger, um es breiter oder schmaler zu ziehen, wie in Notion – beim Ziehen das Token auf :root setzen; es zeigt eine Linie bei Hover, Fokus oder .active. .peek-inset an .nk-app gibt der Hauptspalte rechts ein Padding so breit wie der Peek, die Seite rückt also zur Seite, statt darunter zu liegen – für ein Gantt-Diagramm, dessen Balken sichtbar bleiben müssen.

jsrow.addEventListener('click', () => peek.classList.add('open'));        // eine Zeile öffnet sich neben der Tabelle
closeBtn.addEventListener('click', () => peek.classList.remove('open'));
document.addEventListener('keydown', e => { if (e.key === 'Escape') peek.classList.remove('open'); });
handle.addEventListener('pointermove', e =>                  // .pk-resize, with pointer capture
  document.documentElement.style.setProperty('--nk-peek-width', innerWidth - e.clientX + 'px'));
app.classList.toggle('peek-inset', open);                     // the page moves aside
html<div class="nk-peek-backdrop open" style="position:absolute;border-radius:var(--nk-radius);overflow:hidden"> <aside class="nk-peek" role="dialog" aria-label="Database Table-View" style="width:min(440px, 100%)"> <div class="pk-resize" role="separator" aria-orientation="vertical" aria-label="Breite ändern" tabindex="0"></div> <div class="pk-bar"> <button class="nk-topbar-btn" aria-label="Schließen"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="m6 17 5-5-5-5M13 17l5-5-5-5"/></svg></button> <button class="nk-topbar-btn" aria-label="Als Seite öffnen"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M15 3h6v6M9 21H3v-6M21 3l-7 7M3 21l7-7"/></svg></button> </div> <div class="pk-body"> <h1 class="nk-page-title">🗃️ Database Table-View</h1> <dl class="nk-props"> <div class="nk-prop"><dt class="p-name"><span class="p-icon">◉</span>Status</dt><dd class="p-value"><span class="nk-tag blue">In Arbeit</span></dd></div> <div class="nk-prop"><dt class="p-name"><span class="p-icon">📅</span>Fällig</dt><dd class="p-value">20.05.2026</dd></div> </dl> <div class="nk-prose"><p>Tabelle, Board und Liste lesen dieselben Zeilen; Filter und Sortierung wirken auf alle drei.</p></div> </div> </aside> </div>
Auf kleinem Schirm:Unter 860px steigt es als Sheet von der Unterkante über eine abgedunkelte Seite auf – volle Breite, ein Griff, der Titel in 28px –, und die abgedunkelte Seite nimmt den Tipp, der es schließt.
.nk-peek-backdrop.open.nk-peek.pk-resize.pk-bar.pk-body.active.peek-inset

Dialog .nk-dialog

Eine Frage oder ein kurzes Formular – „In den Papierkorb?“, der Name einer neuen Ansicht, die Verknüpfung zweier Vorgänge – in einer Karte von 440px, .wide 560px: .dl-title, .dl-body und .dl-actions rechts, der bestätigende Button zuletzt. Der Vertrag von Modal und Sheet: .open am Backdrop blendet ihn über einer Abdunklung ein, die Karte setzt sich wie die des Modals; geschlossen verlässt der Backdrop nach dem Ausblenden das Layout. Er liegt über Modal und Sheet, eine Frage kann also aus beiden kommen. Das Schließen übernimmt dein Skript: Escape (in der Capture-Phase, vor den Overlays dahinter), der Backdrop, die Buttons; Fokus hinein und wieder zurück. role="alertdialog" für eine Frage, role="dialog" für ein Formular.

„Produkt-Roadmap“ in den Papierkorb verschieben?
Die Seite und ihre Unterseiten lassen sich 30 Tage lang aus dem Papierkorb wiederherstellen.
html<div class="nk-dialog-backdrop open">
  <div class="nk-dialog wide" role="dialog" aria-modal="true" aria-labelledby="t">
    <div class="dl-title" id="t">Neue Ansicht</div>
    <div class="dl-body">
      <div class="nk-field stacked"><div><div class="f-label">Name</div></div><div class="f-control"><input class="nk-input"></div></div>
    </div>
    <div class="dl-actions"><button class="nk-btn secondary">Abbrechen</button><button class="nk-btn primary">Erstellen</button></div>
  </div>
</div>
html<div class="nk-dialog-backdrop open" style="position:absolute;border-radius:var(--nk-radius)"> <div class="nk-dialog" role="alertdialog" aria-modal="true" aria-label="In den Papierkorb"> <div class="dl-title">„Produkt-Roadmap“ in den Papierkorb verschieben?</div> <div class="dl-body">Die Seite und ihre Unterseiten lassen sich 30 Tage lang aus dem Papierkorb wiederherstellen.</div> <div class="dl-actions"><button class="nk-btn secondary">Abbrechen</button><button class="nk-btn danger-solid">In den Papierkorb</button></div> </div> </div>
Auf kleinem Schirm:Unter 860px steigt er als Sheet von der Unterkante auf – volle Breite, ein Griff, die Safe Area gewahrt –, und die Buttons stapeln sich über die Breite, der bestätigende oben.
.nk-dialog-backdrop.open.nk-dialog.wide.dl-title.dl-body.dl-actions

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. Mit einer Aktion ist er Notions „In den Papierkorb verschoben · Rückgängig“: ein .t-action-Button in den eigenen Farben des Toasts und ein .t-close-× – die einzigen Teile, die den Zeiger nehmen, und nur, solange der Toast steht. So einen Toast stehen lassen, bis einer davon benutzt wird; das Timing ist dein Skript.

✓ Einstellungen gespeichert
🗑️ In den Papierkorb verschoben
html<div class="nk-toast show" style="position:relative;bottom:auto;left:auto;transform:none;display:inline-flex;z-index:auto">✓ <span>Einstellungen gespeichert</span></div> <div class="nk-toast show" style="position:relative;bottom:auto;left:auto;transform:none;display:inline-flex;z-index:auto;margin-top:12px">🗑️ <span>In den Papierkorb verschoben</span><button class="t-action" type="button">Rückgängig</button><button class="t-close" type="button" aria-label="Schließen"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M18 6 6 18M6 6l12 12"/></svg></button></div>
Auf kleinem Schirm:Per translateX(-50%) zentriert und bleibt es in jeder Breite.
.nk-toast.show.t-action.t-close

Tooltip .nk-tooltip

Ein Hover-Hinweis in den Farben des Toasts: 12px, höchstens 260px breit, ein Kürzel in .tt-key, gedämpft. Unsichtbar und inaktiv, bis .open ihn einblendet; wo er sitzt, entscheidest du – fixed, top und left, 6px unter dem Button und zentriert, darüber, wo das Fenster endet. Er liegt über jedem Overlay und nimmt nie den Zeiger. Zeige ihn nach einem Moment unter dem Zeiger und sofort bei Tastaturfokus, blende ihn beim Verlassen, einem Druck und Escape aus; nenne ihn im aria-describedby des Buttons. Lange Wörter brechen um; .lines behält die Zeilenumbrüche seines Texts, für einen Hinweis über zwei, drei Zeilen.

html<div style="position:relative;height:84px"> <button class="nk-topbar-btn" style="position:absolute;left:61px;top:6px" aria-label="Stil, Export und mehr">⋯</button> <div class="nk-tooltip open" role="tooltip" style="position:absolute;left:8px;top:40px">Stil, Export und mehr</div> <button class="nk-sidebar-collapse" style="position:absolute;left:300px;top:6px;opacity:1" aria-label="Seitenleiste schließen"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="m18 17-5-5 5-5M11 17l-5-5 5-5"/></svg></button> <div class="nk-tooltip open" role="tooltip" style="position:absolute;left:255px;top:40px">Seitenleiste schließen<span class="tt-key">⌘\</span></div> </div>
Auf kleinem Schirm:Ein Telefon hat kein Hover: Tooltips dem Zeiger überlassen und bei Berührung nichts zeigen.
.nk-tooltip.open.tt-key.lines

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<div class="nk-comments" style="max-width:420px"> <div class="nk-comment"> <span class="nk-avatar green">SL</span> <div><div class="c-head"><b>Sara Lindt</b> · vor 1 Std.</div><div class="c-body">Die Board-Ansicht fühlt sich schon sehr nah am Original an. 👍</div></div> </div> <div class="nk-comment-input"> <input class="nk-input" placeholder="Kommentieren …"><button class="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.
.nk-comments.nk-comment.c-head.c-body.nk-comment-input

KI-Faden .nk-ai-thread

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. bubble setzt eine Nachricht als graue Blase ohne Avatar und Namen – mit .user rechts, so wie Notions KI-Chat die eigene Frage zeigt. Die Eingabezeile leuchtet bei :focus-within auf.

AL
Du
Fasse die offenen Aufgaben dieses Projekts zusammen.
Was ist auf dieser Seite noch offen?
🤖
Mona · KI
Zwei Aufgaben sind offen: Die Tabellen-Ansicht steht bei 65 %, das Board mit Drag-and-Drop ist geplant.
html<div style="max-width:460px"> <div class="nk-ai-thread"> <div class="nk-ai-msg user"> <span class="mini-avatar">AL</span> <div><div class="a-name">Du</div><div class="a-body">Fasse die offenen Aufgaben dieses Projekts zusammen.</div></div> </div> <div class="nk-ai-msg user bubble"><div class="a-body">Was ist auf dieser Seite noch offen?</div></div> <div class="nk-ai-msg"> <span class="mini-avatar">🤖</span> <div><div class="a-name">Mona <span>· KI</span></div> <div class="a-body">Zwei Aufgaben sind offen: Die Tabellen-Ansicht steht bei 65 %, das Board mit Drag-and-Drop ist geplant.</div> <div class="nk-ai-actions"><button>📋 Kopieren</button><button>↻ Neu formulieren</button></div></div> </div> </div> <div class="nk-ai-input-row"> <input placeholder="Mona etwas fragen …"><button class="nk-ai-send">↑</button> </div> </div>
Auf kleinem Schirm:Fließt natürlich. Die Eingabezeile ist eine flex-Zeile mit fixem 26px-Sendeknopf.
.nk-ai-thread.nk-ai-msg.user.bubble.a-name.a-body.nk-ai-actions.nk-ai-input-row.nk-ai-send

Editor-Adapter

PRD 5.11

Block-Host .nk-block-host

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<div style="padding-left:48px;max-width:460px"> <div class="nk-block-host"> <div class="nk-block-actions show" style="top:6px;left:-46px;pointer-events:none" aria-hidden="true"><button type="button" tabindex="-1">+</button><button type="button" class="drag" tabindex="-1">⠿</button></div> <div style="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> <div class="nk-block-host nk-drop-target"> <span class="nk-block-handle">⠿</span> <div style="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.
.nk-block-host.nk-block-handle.nk-block-actions.nk-drop-target

Slash-Menü & Bubble-Toolbar .nk-slash-menu

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.

html<div style="display:flex;gap:20px;flex-wrap:wrap;align-items:flex-start"> <div class="nk-slash-menu" style="box-shadow:none;border:1px solid var(--nk-border)"> <div class="nk-slash-menu-label">Basis-Blöcke</div> <div class="nk-slash-item selected"><span class="m-icon">H1</span><div><div>Überschrift 1</div><div class="m-desc">Große Abschnitts-Überschrift</div></div></div> <div class="nk-slash-item"><span class="m-icon">☑</span><div><div>To-do-Liste</div><div class="m-desc">Aufgaben mit Checkbox verfolgen</div></div></div> <div class="nk-slash-item"><span class="m-icon">&lt;/&gt;</span><div><div>Code-Block</div><div class="m-desc">Ein Snippet festhalten</div></div></div> </div> <div class="nk-bubble-menu" style="box-shadow:none;border:1px solid var(--nk-border)"> <button class="active"><b>B</b></button><button><i>I</i></button><button><s>S</s></button><button>&lt;/&gt;</button><button>🔗</button> </div> </div>
Auf kleinem Schirm:Feste 280px Breite. Auf dem Handy am Viewport-Rand verankern statt am Cursor.
.nk-slash-menu.nk-slash-menu-label.nk-slash-item.selected.nk-bubble-menu