gökberk. design system

Get started

Import a component's registration module and use its tag — that's the whole setup. Load the token CSS once, then each element you import registers itself.

1. Install the package
npm install @gokberknur/design-system
2. Load the tokens, then register the elements you need
import '@gokberknur/design-system/standalone.css';
import '@gokberknur/design-system/gok-button';
3. Use them as ordinary HTML
<gok-button>Get started</gok-button>
<gok-button variant="secondary">Secondary</gok-button>

Actions

Button

Primary for the main action, secondary for the supporting one, negative for a destructive one — in three sizes (s · m · l).

Primary Secondary Delete Disabled
<gok-button>Primary</gok-button>
<gok-button variant="secondary">Secondary</gok-button>
<gok-button variant="negative">Delete</gok-button>
<gok-button disabled>Disabled</gok-button>

Link

A navigation link in the accent colour, underlined so it reads beyond colour. For navigation, not actions.

Read the docs Open example.com
<gok-link href="/docs">Read the docs</gok-link>
<gok-link href="https://example.com" target="_blank">Open example.com</gok-link>

Tag

A hairline pill chip for filters and keywords. Selectable chips are clickable toggles (aria-pressed) — a multi-select filter set, so wrap them in a labelled group; tags can also be removable. Monochrome at rest; the one accent appears only on the selected state. Try clicking the chips below.

All Open now Favorites
Research
<div role="group" aria-label="Filter by">
  <gok-tag selectable selected dot>All</gok-tag>
  <gok-tag selectable>Open now</gok-tag>
  <gok-tag selectable>Favorites</gok-tag>
</div>
<gok-tag removable>Research</gok-tag>

Forms

Input

The workhorse text field: a hairline frame, ring-led focus, an optional helper, and a reserved message line so an error swaps in without shifting the row.

<gok-input label="Email" placeholder="ada@studio.co"></gok-input>
<gok-input label="Helper" helper="We'll only use this to contact you."></gok-input>
<gok-input label="Error" value="ada@studio" error="Enter a valid email address."></gok-input>

Textarea

The multi-line sibling of the input — same frame and reserved message line, plus auto-grow and an optional character count. For prose: a support ticket, a dispute note, a claim description.

<gok-textarea label="Message" placeholder="Tell us what happened…"></gok-textarea>
<gok-textarea label="Dispute note" auto-grow max-rows="8" rows="2"></gok-textarea>
<gok-textarea label="Claim description" show-count maxlength="280"></gok-textarea>

Money

A currency amount field whose canonical value is always integer minor units — no float ever touches a stored amount. A leading symbol affix, tabular figures, group-on-blur, decimals derived from the currency (2 for USD/EUR, 0 for JPY), and reward-early/punish-late bounds.

<gok-money label="Amount" currency="USD" value="123450"></gok-money>
<!-- value is integer minor units (cents): 123450 → $1,234.50 -->
<gok-money label="Yen" currency="JPY" value="5000"></gok-money>

OTP

A one-time-code input — a row of single-character boxes for a 2FA / verification code. Type-to-advance, backspace-to-retreat, arrow nav, and paste-to-fill the whole code. The canonical value is the joined string; the first box offers the platform SMS code.

<gok-otp label="Verification code" length="6"></gok-otp>
<!-- value is the joined string; "complete" fires at value.length === length -->
<gok-otp label="Coupon" type="alphanumeric"></gok-otp>

Date picker

A date field pairing unambiguous ISO text entry (YYYY-MM-DD, in and out) with a calendar popover for pointing. The canonical value is always an ISO string; min/max bound it, with out-of-range days disabled and a full APG date-grid keyboard model.

<gok-date-picker label="Statement date" value="2026-06-15"></gok-date-picker>
<gok-date-picker label="Within June" value="2026-06-15"
  min="2026-06-01" max="2026-06-30"></gok-date-picker>

Date range

The two-field sibling of the date picker — a start + end ISO pair with one calendar that highlights the span between them. Two-click selection (start, then end; an earlier pick re-anchors the start), shared min/max, the same APG date-grid keyboard model. Form-associated (both bounds under name).

<gok-date-range label="Statement period"
  value-start="2026-06-08" value-end="2026-06-21"></gok-date-range>

Combobox

A text field that filters a list and binds the chosen value to a form — the WAI-ARIA combobox pattern, where focus stays in the input and the highlighted option tracks aria-activedescendant. Data-driven via the options property; select-only (free text reverts on dismiss).

<gok-combobox label="Settlement currency"></gok-combobox>
<script>
  combobox.options = [{ value: 'usd', label: 'US Dollar (USD)' }, …];
</script>

Multi-select

The multi-value sibling of the combobox — pick several options from a filtered list, each shown as a removable chip. Same data-driven options contract and combobox machinery, but choosing toggles membership and keeps the list open; Backspace on an empty query drops the last chip. Form-associated (each value under name).

<gok-multi-select label="Account tags"></gok-multi-select>
<script>
  multiSelect.options = [{ value: 'savings', label: 'Savings' }, …];
  multiSelect.values = ['savings'];
</script>

Slider

A token-themed range control — one thumb, or two for a range band. Flat track, accent fill, hairline-framed thumb; full APG keyboard model (arrows, Page, Home/End) and pointer drag. Form-associated.

<gok-slider label="Volume" show-value value="40"></gok-slider>
<gok-slider label="Price range" range value-start="20" value-end="70"></gok-slider>

File upload

A drop-or-browse field with a reviewable file list (name, size, optional per-file progress, remove). The selection + validation surface — it emits the chosen files; the consumer uploads and feeds progress back. Validates accept + max-size; form-associated.

<gok-file-upload label="Statement" accept=".pdf"></gok-file-upload>
<gok-file-upload label="Evidence" multiple accept="image/*,.pdf"></gok-file-upload>

Checkbox

A binary choice; checked fills the box forest green. Also supports an indeterminate and a disabled state.

Checked Unchecked Indeterminate Disabled
<gok-checkbox checked>Checked</gok-checkbox>
<gok-checkbox>Unchecked</gok-checkbox>
<gok-checkbox indeterminate>Indeterminate</gok-checkbox>
<gok-checkbox disabled>Disabled</gok-checkbox>

Radio

One of many. The group is a single Tab stop; arrow keys move and select. Set orientation="horizontal" for a row.

All activity Only @mentions Nothing
<gok-radio-group label="Notifications" name="notify" value="all">
  <gok-radio value="all">All activity</gok-radio>
  <gok-radio value="mentions">Only @mentions</gok-radio>
  <gok-radio value="none">Nothing</gok-radio>
</gok-radio-group>

Switch

For a setting that takes effect immediately. On fills the track forest green and slides the thumb; the position carries the state beyond colour.

Wi-Fi Bluetooth Airplane mode
<gok-switch checked>Wi-Fi</gok-switch>
<gok-switch>Bluetooth</gok-switch>
<gok-switch disabled>Airplane mode</gok-switch>

Select

A custom single-select in the input family that opens an anchored listbox. It submits, validates, and resets in a form. Put gok-options in the default slot.

Free Pro Team Custom (contact us)
<gok-select label="Plan" name="plan" value="pro" helper="Billed monthly.">
  <gok-option value="free">Free</gok-option>
  <gok-option value="pro">Pro</gok-option>
  <gok-option value="team">Team</gok-option>
</gok-select>

Segmented

A compact one-of-many switch for a view or mode — segments merge on one hairline rule, the selected one carrying the accent.

List Board Calendar
<gok-segmented label="View" value="list">
  <gok-segmented-item value="list">List</gok-segmented-item>
  <gok-segmented-item value="board">Board</gok-segmented-item>
  <gok-segmented-item value="calendar">Calendar</gok-segmented-item>
</gok-segmented>

Theme switch

A dedicated Light / Dark switch — the studio top-bar pill. It owns theming: applies <html data-theme>, persists to localStorage, and stays in sync across tabs. The one live in the top bar is the same element. (Flip it to re-theme this whole page.)

<gok-theme-switch label="Theme"></gok-theme-switch>

Navigation

Navbar

The persistent global header — a flat, frosted, sticky bar. A brand slot, mono-uppercase nav links (the active page on a 2px accent underline), and a trailing actions cluster. The layout is yours: ::part(brand|links|actions) are exposed, so ::part(links){margin-inline:auto} centres the links the studio-topbar way. Scroll the frame to watch content pass under the frost.

gökberk. Foundations Components Concepts Tokens Storybook ↗

Whitespace is a material. Near-white paper, near-black ink, and a neutral grey ramp do almost all the work.

The forest-green accent appears rarely — for the one thing that matters on a screen.

Everything is driven by design tokens: flip the theme above to watch the page re-resolve from one attribute.

Motion you feel, not see — precise to enter, dynamic to exit, never a bounce.

<style> gok-navbar::part(links) { margin-inline: auto } </style>

<gok-navbar accessible-label="Primary" collapse-at="m">
  <span slot="brand">gökberk</span>
  <gok-navbar-item href="/" selected>Foundations</gok-navbar-item>
  <gok-navbar-item href="/components">Components</gok-navbar-item>
  <gok-navbar-item href="/tokens">Tokens</gok-navbar-item>
  <a slot="actions" href="/storybook">Storybook ↗</a>
</gok-navbar>

Tabs

One tablist, one panel at a time. The selected tab sits on the accent rule; arrow keys move along the list and reveal as they go.

Overview Pricing FAQ A quiet, editorial overview of the thing. Three plans, no surprises. Answers to the usual questions.
<gok-tabs label="Sections" value="overview">
  <gok-tab slot="tab" value="overview">Overview</gok-tab>
  <gok-tab slot="tab" value="pricing">Pricing</gok-tab>
  <gok-tab-panel value="overview">A quiet, editorial overview.</gok-tab-panel>
  <gok-tab-panel value="pricing">Three plans, no surprises.</gok-tab-panel>
</gok-tabs>

Breadcrumb

A trail back up the tree — links joined by hairline chevrons, the current page in full ink. The last item (no href) is the current page.

Home Projects Studio site Settings
<gok-breadcrumb>
  <gok-breadcrumb-item href="/">Home</gok-breadcrumb-item>
  <gok-breadcrumb-item href="/projects">Projects</gok-breadcrumb-item>
  <gok-breadcrumb-item>Settings</gok-breadcrumb-item>
</gok-breadcrumb>

Sidenav

The persistent app-navigation rail — a <nav> landmark in the editorial register. Grouped gok-sidenav-sections (mono-eyebrow headings, collapsible) hold gok-sidenav-items — single-select with keyboard roving and built-in list semantics; items can nest (multilevel). The current item sits on a 2px leading accent rule; collapsed swaps to the icon-rail. (The numbered "in this issue" rail is now its own gok-toc, below.)

Installation Tokens Input Checkbox Radio Tabs Breadcrumb Input Checkbox Radio Tabs
<gok-sidenav accessible-label="Components">
  <gok-sidenav-section label="Forms">
    <gok-sidenav-item href="/input" selected>Input</gok-sidenav-item>
    <gok-sidenav-item href="/checkbox">Checkbox</gok-sidenav-item>
  </gok-sidenav-section>
  <gok-sidenav-section label="Navigation" collapsible>
    <gok-sidenav-item href="/tabs">Tabs</gok-sidenav-item>
  </gok-sidenav-section>
</gok-sidenav>

Table of contents

The numbered "in this issue" rail — a <nav> of in-page anchors in the editorial numbered-ledger register. The current row carries the accent numeral + a 2px leading rule. Set spy to let an IntersectionObserver mark the in-view section as you scroll (aria only — it never moves focus).

Overview Foundations Components Patterns
<gok-toc spy accessible-label="In this issue">
  <gok-toc-item href="#overview">Overview</gok-toc-item>
  <gok-toc-item href="#components">Components</gok-toc-item>
</gok-toc>

Pagination

Across pages of a collection. The current page is marked by a 2px accent underline; long ranges truncate with an ellipsis. Roving focus (one Tab stop, arrow keys move).

<gok-pagination total="20" page="6"></gok-pagination>

Menu

A menu button: a trigger opens an anchored list of commands. Arrow keys rove, type to jump, Escape closes. Put the button in the trigger slot.

Actions Open in new tab⌘↵ Duplicate⌘D Rename
Delete⌘⌫
<gok-menu accessible-label="Actions">
  <gok-button slot="trigger" variant="secondary">Actions<gok-icon slot="icon-end" name="chevron-down"></gok-icon></gok-button>
  <gok-menu-item value="open">Open in new tab</gok-menu-item>
  <gok-menu-item value="duplicate">Duplicate</gok-menu-item>
  <hr />
  <gok-menu-item value="delete" destructive>Delete</gok-menu-item>
</gok-menu>

Data display

Card

A flat surface that groups content — hairline frame, generous inset, structure from a rule and space, never a shadow. Variants: outlined · filled · ruled.

Case study

Orchard rebrand

A monochrome identity for a regional cider maker — one earned green, set in Geist.

Read
<gok-card>
  <span slot="header" class="gok-eyebrow">Case study</span>
  <h3 slot="header" class="gok-headline-5">Orchard rebrand</h3>
  <p>A monochrome identity for a regional cider maker.</p>
  <gok-button slot="footer">Read</gok-button>
</gok-card>

Page header

The standard page-title band — a mono uppercase eyebrow over a display title, an optional caption, and a right-aligned actions slot. Stacks on mobile; title and actions share a row on wider viewports. The one intentional uppercase.

Export
<gok-page-header
  eyebrow="Mortgages"
  heading="Mortgage calculator"
  caption="Model a monthly payment across rate and term.">
  <gok-button slot="actions" variant="secondary">Export</gok-button>
</gok-page-header>

Badge

Status shrunk to a label — a near-neutral chip whose meaning is carried by a 2px rule and a mono label, never by colour alone. Display-only.

Neutral Info Success Warning Error
<gok-badge>Neutral</gok-badge>
<gok-badge variant="info">Info</gok-badge>
<gok-badge variant="success">Success</gok-badge>
<gok-badge variant="warning">Warning</gok-badge>
<gok-badge variant="error">Error</gok-badge>

Divider

A thin neutral rule that separates content. A strong weight opens a major division; a label makes a section or "or" separator; orientation="vertical" groups controls on a row.

Account Notifications or
<gok-divider></gok-divider>
<gok-divider weight="strong"></gok-divider>
<gok-divider>or</gok-divider>
<gok-divider orientation="vertical"></gok-divider>

Icon

A small on-brand glyph set drawn from Geist. Pass a name; the glyph inherits currentColor and is sized s · m · l. Decorative by default; give it a label to announce it.

<gok-icon name="search"></gok-icon>
<gok-icon name="settings" size="l"></gok-icon>
<gok-icon name="arrow-right" label="Next"></gok-icon>

Accordion

A vertical set of disclosure sections — structure carried by hairline rules and space alone. Exclusive by default; set multiple to allow several open at once.

Billing & invoices

Invoices are issued on the first of each month and charged to your default card.

Notifications

Choose which events reach you by email and which stay in-app.

Data export

Export your records as CSV or JSON. Large exports run in the background.

<gok-accordion>
  <gok-accordion-item open>
    <span slot="summary">Billing &amp; invoices</span>
    <p>Invoices are issued on the first of each month.</p>
  </gok-accordion-item>
  <gok-accordion-item>
    <span slot="summary">Notifications</span>
    <p>Choose which events reach you by email.</p>
  </gok-accordion-item>
</gok-accordion>

Empty state

A centred, restrained placeholder for when there's nothing to show — an empty list, no results, or a first run. An optional glyph, a message, and one or two actions. Variants: default · compact.

No results found

Try a different search term or clear your filters.

Clear filters
<gok-empty-state>
  <gok-icon slot="media" name="search"></gok-icon>
  <h3 class="gok-headline-5">No results found</h3>
  <p>Try a different search term or clear your filters.</p>
  <gok-button slot="actions" variant="primary">Clear filters</gok-button>
</gok-empty-state>

Table

A property-driven data grid — sortable, selectable, resizable and freezable columns, density-aware rows with tabular numerals, and opt-in virtualization for thousands of rows. Hairline rules and one earned accent (the selected row, the active sort); the engine is TanStack Table, headless, behind a gök-only API.

Accounts
const t = document.querySelector('gok-table');
t.columns = [
  { key: 'name',   label: 'Name',   sortable: true },
  { key: 'status', label: 'Status', sortable: true },
  { key: 'amount', label: 'Amount', numeric: true, sortable: true },
];
t.rows = [{ name: 'Orchard', status: 'Active', amount: 1204.5 }, …];
t.selectionMode = 'multiple';
t.addEventListener('gok-selection-change', e => …);

Sparkline

A word-sized trend line — for a table cell, a stat strip, or inline beside a figure. Pure SVG, theme-adaptive; the trend is the one earned accent, or a status foreground via tone. Display-only, self-labelling. For a full chart the consumer brings their own engine.

<gok-sparkline points="4,6,5,8,7,10,9,12" tone="positive" area></gok-sparkline>
<!-- or set the .values property from JS -->

Feedback & overlay

Command menu

A global search + command menu — a search-bar button that opens a command palette just below it (a card with its own search field + grouped results) over a dimmed page. It lets people search anywhere in the app or run any action, fully keyboard-driven so anything is a few keystrokes away. Filters as you type, groups by section, drills into nested commands, and runs the chosen one. Opens on a global hotkey (⌘K / Ctrl K); ↑/↓ navigate, ↵ runs, Esc closes.

<gok-command-menu id="cmdk"></gok-command-menu>
<script>
  cmdk.commands = [
    { id: 'new', title: 'New file', section: 'File',
      icon: 'plus', shortcut: '$mod+KeyN', action: () => {} },
    { id: 'theme', title: 'Change theme…', section: 'General', icon: 'moon' },
    { id: 'light', title: 'Light', parent: 'theme', icon: 'sun' },
  ];
  // the trigger button is always visible; click it, press ⌘K, or call cmdk.show()
</script>

Alert

A block-level status message — a neutral surface with a leading icon and an inline-start status bar, never a saturated fill. Optional title, actions, and a dismiss.

Deploy finishedThe build passed all checks and is live on production. 2 records need reviewThey were imported with missing fields. Review them before the next sync.
<gok-alert status="success">
  <span slot="title">Deploy finished</span>
  The build passed all checks and is live.
</gok-alert>
<gok-alert status="warning" dismissible>
  <span slot="title">2 records need review</span>
  They were imported with missing fields.
</gok-alert>

Toast

A transient, auto-dismissing notice that floats on a shadow with a depleting countdown. Usually fired imperatively with the toaster helper.

success error with action
import { toaster } from '@gokberknur/design-system/toaster';

toaster.success('Changes saved.');
toaster.error("Couldn't reach the server.");
toaster.neutral('Item moved to archive', {
  action: { label: 'Undo', onClick: () => restore() },
});

Tooltip

A transient hint revealed on hover or focus and dismissed on leave, blur, or Escape. Wrap a focusable trigger; put the hint in the content slot.

Hover or focus me On the top
<gok-tooltip placement="top">
  <gok-button variant="secondary">Hover or focus me</gok-button>
  <span slot="content">On the top</span>
</gok-tooltip>

Popover

A click-opened, non-modal floating panel holding interactive content, anchored to a trigger. Dismisses on outside-click or Escape, returning focus to the trigger.

Share Share this project

Anyone with the link can view the result.

Copy link
<gok-popover placement="bottom">
  <gok-button variant="secondary">Share</gok-button>
  <span slot="heading">Share this project</span>
  <div slot="content">
    <p>Anyone with the link can view the result.</p>
    <gok-button size="s">Copy link</gok-button>
  </div>
</gok-popover>

Dialog

A modal surface for one focused task — a centred panel over a scrim that traps focus until you act. Renders in the top layer; Escape and a scrim click dismiss. Set tone="danger" for a destructive decision.

Publish…

The current build replaces the live site.

Cancel Publish
<gok-button onclick="dlg.open = true">Publish…</gok-button>
<gok-dialog id="dlg" heading="Publish">
  <p>The current build replaces the live site.</p>
  <gok-button slot="footer" variant="secondary">Cancel</gok-button>
  <gok-button slot="footer" variant="primary">Publish</gok-button>
</gok-dialog>

Drawer

A modal off-canvas panel pinned to a screen edge — for a filter rail, a detail inspector, or a cart. Slides in from the end (default), start, or bottom; traps focus, and Escape or a scrim click dismiss. Renders in the top layer.

Open filters…
In stock On sale Free shipping
Clear Apply
<gok-button onclick="drw.open = true">Open filters…</gok-button>
<gok-drawer id="drw" heading="Filters">
  <gok-checkbox>In stock</gok-checkbox>
  <gok-button slot="footer" variant="secondary">Clear</gok-button>
  <gok-button slot="footer" variant="primary">Apply</gok-button>
</gok-drawer>

Spinner

An indeterminate loader — a neutral hairline track with the accent on a single sweeping arc. Sizes s · m · l; carries role="status" and stops under reduced motion.

<gok-spinner size="s"></gok-spinner>
<gok-spinner size="m" accessible-label="Loading results"></gok-spinner>
<gok-spinner size="l"></gok-spinner>

Progress

A determinate bar — an ultra-thin track with the accent on the fill, a mono label and a tabular readout above it. On complete the fill shifts to the success role.

<gok-progress label="Upload" value="33"></gok-progress>
<gok-progress label="Upload" value="100"></gok-progress>
<gok-progress label="Steps" format="fraction" value="3" max="4"></gok-progress>

Skeleton

A monochrome loading placeholder with a quiet shimmer sweep. Shapes text · block · circle; a lines count for multi-line text.

<gok-skeleton shape="circle"></gok-skeleton>
<gok-skeleton shape="text" lines="2"></gok-skeleton>
<gok-skeleton shape="block"></gok-skeleton>