The project is in a healthy, maintained state
Color variables, light and dark mode, and component classes shared by keystone_ui and keystone_ui-react.
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
 Dependencies

Runtime

>= 7.0
 Project Readme

keystone_ui-styles

Shared CSS for keystone_ui and keystone_ui-react: keystone's color variables, its light and dark mode, and the classes for buttons, panels and form fields.

Host apps do not install this gem directly. keystone_ui depends on it and brings it into the host's Tailwind build.

Requirements

How a host gets it

keystone_ui imports keystone_ui-styles into the host's Tailwind build through the keystone_source.css file it writes at boot. A host imports nothing for keystone_ui-styles itself.

A gem that needs the file directly can read its path from KeystoneUi::Styles.tailwind_file.

Colors

--color-accent-50 to --color-accent-950 default to Tailwind's blue, and --color-surface-50 to --color-surface-950 default to zinc. keystone_ui-colors overrides these variables on the page, and every class below reads them.

Light and dark mode

A page follows the operating system's setting. Setting data-theme on the html element overrides it:

<html data-theme="dark">   <!-- always dark -->
<html data-theme="light">  <!-- always light -->
<html data-theme="custom"> <!-- drawn from a background and a text colour -->
<html>                     <!-- follows the operating system -->

The dark: variant in the host's own Tailwind classes follows the same rule, and a custom page never takes it.

Dark mode applies on screens only. A dark page prints in its light colours, so a printed page or a PDF always has dark text on white paper.

On a custom page, white is --color-custom-background, and every gray-* and zinc-* shade is a blend of --color-custom-text into that background, from 3% at shade 50 to 100% at shade 950. They default to white and #18181b, and keystone_ui-colors sets them from the colours a user picks.

Look variables

The classes below read these variables, so a host restyles every component that renders them by setting the variables in a plain :root rule in its own stylesheet. The defaults sit in Tailwind's base layer, so a :root rule outside any layer overrides them wherever it is imported.

Variable Sets Default
--ks-radius-control Button corner radius, and three quarters of it for inputs --radius-lg
--ks-radius-surface Card and panel corner radius, and three quarters of it for alerts --radius-lg
--ks-shadow-surface Panel shadow --shadow-sm
--ks-font-body Page body and button font family inherit, so the page and its buttons keep the font they have
--ks-font-heading Page, page header, section, card, modal and navbar title font family --ks-font-body
--ks-font-mono The theme's mono font, which no class reads: code takes its font from Tailwind's --default-mono-font-family, and keystone_ui-preferences' theme writer sets that from --ks-font-mono when a theme names a mono font The font list Tailwind gives code
--ks-letter-spacing Page body letter spacing normal
--ks-font-weight-strong Button label weight --font-weight-semibold
--ks-font-weight-heading Section, card and alert title weight, and one step heavier for page titles --font-weight-semibold
--ks-border-width-control Button border width 0px
--ks-spacing The unit every button, input, page, card, alert and panel padding is a multiple of --spacing
--ks-color-accent, --ks-color-accent-hover Primary button fill, and on hover --color-accent-600, --color-accent-500
--ks-color-neutral, --ks-color-neutral-hover Secondary button fill, and on hover --ks-color-surface, --ks-color-hover
--ks-color-neutral-border Secondary button outline, drawn inside its edge at --ks-border-width --ks-color-border-control
--ks-color-danger, --ks-color-danger-hover Danger button fill, and on hover --color-red-600, --color-red-500
--ks-color-on-fill The label colour the primary and danger button label colours default to --color-white
--ks-color-on-accent, --ks-color-on-danger Primary and danger button label --ks-color-on-fill
--ks-color-on-neutral Secondary button label --ks-color-text
--ks-color-surface Panel, card and input background --color-white, and --color-surface-900 on a dark page
--ks-color-border Panel and card border --color-surface-200
--ks-color-border-control Input border --color-gray-300
--ks-color-text Input text and page, section and card titles --color-surface-900
--ks-color-text-label Field labels --color-surface-700
--ks-color-text-muted Hints, subtitles and card summaries --color-surface-500
--ks-border-width Border and ring width of menus, dialogs, form controls and cards, doubled for radio and option cards and the file drop zone 1px
--ks-shadow-overlay Menu, dialog and colour picker shadow --shadow-lg
--ks-font-weight-medium Copy button, checkbox row and radio card label weight --font-weight-medium
--ks-color-overlay Dialog, action menu, copy button and colour picker background --color-white
--ks-color-on-overlay Dialog, action menu and colour picker text currentcolor, so each keeps the text colour it inherits
--ks-color-on-overlay-muted Radio card and stat card disclosure text --ks-color-text-secondary
--ks-color-on-surface Menu text currentcolor, so it keeps the text colour it inherits
--ks-color-backdrop The dimmed page behind a dialog Black at 60%
--ks-color-text-heading Dialog title --color-gray-900
--ks-color-close, --ks-color-close-hover Dialog close button, and on hover --color-gray-400, --color-gray-600
--ks-color-ring Action menu outline Black at 5%
--ks-color-hover Menu option on hover --color-gray-50
--ks-color-hover-raised Copy button on hover --color-gray-50
--ks-color-border-strong Copy button, menu checkbox, colour swatch and file drop zone border --color-gray-300
--ks-color-focus Checkbox focus ring --color-accent-500
--ks-color-border-choice Checkbox row box border --color-surface-300
--ks-color-text-choice, --ks-color-text-choice-muted Checkbox row label and hint --color-surface-900, --color-surface-500
--ks-color-selected-border, --ks-color-selected Chosen radio card, option card and active drop zone border, and the chosen radio card background --color-accent-500, --color-accent-50
--ks-color-text-option, --ks-color-text-option-muted Radio card label and hint --color-gray-900, --color-surface-500
--ks-color-drop-active File drop zone background while a file is dragged over it --color-accent-50
--ks-color-icon File upload icon --color-gray-400
--ks-color-text-secondary File upload prompt --color-gray-600
--ks-color-link, --ks-color-link-hover File upload browse link, and on hover --color-accent-600, --color-accent-500

| --ks-radius-pill | Progress bar, hero badge and swipe button corners | Fully rounded | | --ks-color-hover-border | Link card and feature card border on hover | Accent 500 at 50% | | --ks-color-tint, --ks-color-tint-border | Feature icon, hero badge, active tab and current table row background, and the hero badge border | Accent 500 at 10% and 20% | | --ks-color-border-subtle | Call to action, feature card, code, accordion and disclosure border | --color-surface-200 | | --ks-color-fill-muted | Call to action and code caption background | --color-surface-50 | | --ks-color-raised | Feature card background | --color-white | | --ks-color-text-display, --ks-color-text-display-muted | Marketing titles and values, and their subtitles | --color-surface-900, --color-surface-500 | | --ks-color-text-body | Accordion and disclosure body text | --color-surface-600 | | --ks-color-icon-soft | Disclosure icon | --color-surface-400 | | --ks-color-track, --ks-color-meter | Progress track, and the progress bar, funnel accent step and bucket fill | --color-surface-200, --color-accent-500 | | --ks-color-text-meter-label | Progress and funnel labels | --color-surface-700 | | --ks-color-funnel-accent, -sky, -violet, -amber, -rose | The five funnel step colours | The matching Tailwind 500 shade | | --ks-color-funnel-band, --ks-color-text-funnel-band | The joined funnel's band between steps and its percent | --color-surface-800, --color-white, and --color-surface-100, --color-surface-900 on a dark page | | --ks-color-chart-1 to --ks-color-chart-5 | The five chart series colours, for a chart to read | --color-accent-600, then teal, amber, violet and rose at Tailwind's 600 shade, and --color-accent-400, then the same four at Tailwind's 400 shade, on a dark page | | --ks-color-over-goal, --ks-color-over-goal-warning | Bucket fill over its goal | --color-green-500, --color-amber-500 | | --ks-color-table-head, --ks-color-table-body, --ks-color-divider | Table head and body background, and the line between rows | --color-gray-50, --color-white, --color-gray-200 | | --ks-shadow-surface-dark | Table shadow on a dark page | None | | --ks-color-code, --ks-color-text-code | Code block background and text | --color-surface-900, --color-surface-100 | | --ks-color-pipeline, --ks-color-pipeline-box, --ks-color-pipeline-border | Pipeline and box background, and their border | --color-surface-800, --color-surface-900, --color-surface-700 | | --ks-color-text-on-dark, --ks-color-pipeline-muted, --ks-color-pipeline-label, --ks-color-pipeline-amber | Pipeline title, subtitle, box label and amber count | --color-white, --color-surface-400, --color-surface-500, --color-amber-400 | | --ks-color-nav, --ks-color-nav-border | Bottom nav, desktop nav menu and sidebar background, and the bottom nav, nav menu, sidebar and open sidebar group border and the lines between their links | --base-bg-low, then --color-white; --base-border-tertiary, then --color-gray-200 | | --ks-color-nav-text, --ks-color-nav-text-hover | Bottom nav item and sidebar group label, and nav links on hover | --base-text-tertiary, then --color-gray-500; --base-text-secondary, then --color-gray-700 | | --ks-color-nav-link, --ks-color-nav-active, --ks-color-nav-indicator | Nav link and sidebar tab text, the current page's link or tab, and the underline under the current link on wide screens and the bar beside the current sidebar tab | --base-text, --text-primary and --border-primary, then --color-gray-900, --color-accent-600 and --color-accent-600 | | --ks-color-nav-menu-mobile, --ks-color-nav-hover | Nav menu background on small screens, a menu link on hover, and the current sidebar tab | --base-bg-base, then --color-white; --base-bg-hover, then --color-gray-50 | | --ks-shadow-menu | Desktop nav menu shadow | --shadow-md | | --ks-font-weight-normal | Mobile header subtitle weight | --font-weight-normal | | --ks-color-hover-soft | Settings link on hover | --color-gray-50 | | --ks-color-on-hover | Settings link and tab text on hover | --ks-color-text | | --ks-color-on-hover-muted | Menu option, menu move button and copy button text on hover | --ks-color-text-label | | --ks-color-focus | Input and checkbox focus border and ring | --color-accent-500, and --color-accent-400 on a dark page | | --ks-color-link-strong-hover | Section action and card link on hover | --color-accent-900, and --color-accent-300 on a dark page | | --ks-color-badge-neutral | Neutral badge background | --color-gray-100, and --color-zinc-700 on a dark page | | --ks-color-page, --ks-color-on-page | The html element background and text | transparent and CanvasText, the browser defaults, so a page keeps the colours it has, and the html element tells the browser the page's mode so those defaults turn dark on a dark page | Each colour variable in the table whose component changes on a dark page has a -dark partner, such as --ks-color-surface-dark, that it reads there.

The navigation colours read the --base-* variables keystone_ui's nav used before, when a host sets them, so a host that coloured its nav that way keeps its colours.

Many roles default to a base role, so setting the base role recolours all of them, and setting one of them on its own still overrides it:

Base role Roles that follow it
--ks-color-text text-display, text-heading, text-option, text-choice, nav-link, on-hover, on-neutral
--ks-color-text-muted text-display-muted, text-choice-muted, text-option-muted, nav-text
--ks-color-text-secondary text-body, on-overlay-muted
--ks-color-text-label text-meter-label, nav-text-hover, on-hover-muted
--ks-color-icon close, icon-soft
--ks-color-border border-subtle, track, divider, nav-border
--ks-color-border-strong border-control, border-choice
--ks-color-surface table-body, nav, nav-menu-mobile, neutral
--ks-color-overlay raised
--ks-color-hover fill-muted, hover-raised, hover-soft, table-head, nav-hover, neutral-hover
--ks-color-link nav-active, nav-indicator
--ks-color-on-fill on-accent, on-danger
--ks-color-border-control neutral-border

The base roles draw from the surface scale, which keystone_ui-colors sets per account. The nav roles read the old --base-* variables first when a host sets them.

Alerts and badges read a shade scale per status instead: --ks-color-success-*, --ks-color-warning-*, --ks-color-danger-* and --ks-color-info-*, each with shades 50, 100, 300, 400, 600, 700, 800 and 900, and 500 for danger. They default to Tailwind's green, yellow and red, and to the accent scale for info. An alert uses shades 50 and 800, and 900 and 300 on a dark page. A badge uses 100 and 700, and 900 and 400 on a dark page.

:root {
  --ks-radius-control: 9999px;
  --ks-font-weight-strong: 500;
  --ks-color-accent: #6200ee;
  --ks-color-accent-dark: #bb86fc;
}

Classes

Class Use
ks-button Every button
ks-button-primary, ks-button-secondary, ks-button-danger Button color
ks-button-sm, ks-button-md, ks-button-lg Button size
ks-panel Panel border and background
ks-panel-radius-md, ks-panel-radius-lg, ks-panel-radius-xl Panel corner radius
ks-panel-padding-sm, ks-panel-padding-md, ks-panel-padding-lg Panel padding
ks-panel-shadow Panel shadow
ks-input Text inputs, text areas and selects
ks-input-disabled A disabled input
ks-label Field label
ks-required Required field marker
ks-hint Field hint
ks-error Field error
ks-checkbox Checkbox
ks-page Page padding
ks-page-sm, ks-page-md, ks-page-lg, ks-page-xl Page maximum width, centered
ks-page-offset-sm, ks-page-offset-md, ks-page-offset-lg, ks-page-offset-xl Space above a page
ks-page-header, ks-page-header-title, ks-page-header-subtitle, ks-page-header-actions Page header and its parts
ks-section-sm, ks-section-md, ks-section-lg Space above a section
ks-section-header, ks-section-title, ks-section-subtitle, ks-section-action Section header and its parts
ks-heading Every heading
ks-heading-sm, ks-heading-md, ks-heading-lg Heading size
ks-heading-row, ks-heading-note A heading with a short note at the right end of its row
ks-caption Small uppercase text placed above a title or figure
ks-caption-link Beside ks-caption, a caption in the link colour with space under it, such as the label above a quiz question
ks-link A text link in the link colour
ks-text-button A button drawn as small, underlined, muted text
ks-fact, ks-facts A fact drawn as a small bordered box, and the row of facts holding it
ks-paragraph Running text
ks-value-list-row One row of a label and its value, with a line between rows
ks-value-list-label, ks-value-list-note, ks-value-list-value A row's label, the short note under it, and its value
ks-value-list-end On the list, pushes each value to the right end of its row
ks-value-list-total A row drawn with more weight, for a total
ks-bar-chart-bar, ks-bar-chart-bar-shaded A bar chart's bars, filled in the first chart colour, and a bar drawn faded
ks-bar-chart-grid A bar chart's grid lines
ks-bar-chart-text, ks-bar-chart-value A bar chart's axis and bar labels, and the value shown on a bar
ks-metric-plain A stat drawn as a plain figure, padded with no card border or background
ks-stat-card-note, ks-stat-card-fallback A stat's note under its value, and the muted fallback shown when its value is missing
ks-card, ks-card-edge Card, and a card that runs edge to edge on small screens
ks-card-body, ks-card-title, ks-card-summary, ks-card-cta, ks-card-link Card parts
ks-alert Every alert
ks-alert-info, ks-alert-success, ks-alert-warning, ks-alert-error Alert color
ks-alert-body, ks-alert-content, ks-alert-title, ks-alert-message, ks-alert-message-titled, ks-alert-dismiss Alert parts
ks-badge Every badge
ks-badge-neutral, ks-badge-success, ks-badge-danger, ks-badge-warning, ks-badge-info Badge color
ks-modal-backdrop, ks-modal-panel, ks-modal-header, ks-modal-title, ks-modal-close Dialog and its parts
ks-action-menu, ks-action-menu-button Mobile action menu and the button that opens it
ks-menu, ks-menu-trigger, ks-menu-option, ks-menu-checkbox, ks-menu-option-hidden, ks-menu-move Column picker and multi select menu and their parts
ks-copy-button Copy button
ks-theme-toggle-option Theme toggle button, filled when pressed
ks-checkbox-row, ks-checkbox-row-input, ks-checkbox-row-label, ks-checkbox-row-hint Checkbox row and its parts
ks-radio-card, ks-radio-card-highlight, ks-radio-card-label, ks-radio-card-hint Radio card and its parts
ks-radio-card-value, ks-radio-card-block An answer's value shown on a radio card, and a full-width radio card that holds one beside its label
ks-option-card, ks-option-card-selected Option card, and a chosen one
ks-file-upload, ks-file-upload-drop-zone, ks-file-upload-drop-zone-active, ks-file-upload-inner, ks-file-upload-icon, ks-file-upload-prompt, ks-file-upload-browse, ks-file-upload-hint, ks-file-upload-file-name File upload and its parts
ks-color-swatch, ks-color-picker-panel Colour picker swatch and its panel
ks-metric-card Stat card and chart card
ks-stat-card-header, ks-stat-card-label, ks-stat-card-value, ks-stat-card-suffix, ks-stat-card-disclosure, ks-stat-card-emphasis, ks-stat-card-change, ks-stat-card-info Stat card parts
ks-tone-neutral, ks-tone-muted, ks-tone-success, ks-tone-danger, ks-tone-warning, ks-tone-info Stat card value and change colour
ks-chart-card-title Chart card title
ks-link-card, ks-link-card-shadow, ks-link-card-padding-sm, ks-link-card-padding-md, ks-link-card-padding-lg Card link, its shadow and its padding
ks-cta-banner, ks-cta-banner-title, ks-cta-banner-subtitle, ks-cta-banner-actions Call to action banner and its parts
ks-feature-grid, ks-feature-grid-title, ks-feature-grid-subtitle, ks-feature-card, ks-feature-card-icon, ks-feature-card-title, ks-feature-card-description Feature grid and its cards
ks-hero, ks-hero-inner, ks-hero-content, ks-hero-split, ks-hero-title, ks-hero-subtitle, ks-hero-badge, ks-hero-actions Hero and its parts
ks-table, ks-table-head, ks-table-body, ks-table-header, ks-table-header-first, ks-table-header-middle, ks-table-header-last, ks-table-cell-first, ks-table-cell-middle, ks-table-cell-last, ks-table-phone-list-cell, ks-table-header-locked, ks-table-cell-locked, ks-table-toolbar, ks-table-sort-link, ks-table-sort-icon, ks-table-sort-icon-active Data table and its parts
ks-code, ks-code-caption, ks-code-block Code block and its caption
ks-accordion, ks-accordion-item, ks-accordion-button, ks-accordion-answer Accordion and its parts
ks-disclosure, ks-disclosure-summary, ks-disclosure-body, ks-disclosure-icon Disclosure and its parts
ks-tab-bar, ks-tab, ks-tab-active Tab switcher, a tab, and the active tab
ks-progress-track, ks-progress-bar, ks-meter-label Progress bar and its label
ks-funnel, ks-funnel-layer, ks-funnel-row, ks-funnel-label, ks-funnel-value, ks-funnel-bar, ks-funnel-transition, ks-funnel-bar-accent, ks-funnel-bar-sky, ks-funnel-bar-violet, ks-funnel-bar-amber, ks-funnel-bar-rose, ks-funnel-joined, ks-funnel-band, ks-funnel-band-label Funnel and its parts
ks-bucket, ks-bucket-series, ks-bucket-label, ks-bucket-goal, ks-bucket-percent, ks-bucket-tank, ks-bucket-actual, ks-bucket-fill, ks-bucket-fill-over, ks-bucket-fill-over-warning Bucket and its parts
ks-pipeline, ks-pipeline-header, ks-pipeline-title, ks-pipeline-subtitle, ks-pipeline-track, ks-pipeline-box, ks-pipeline-box-label, ks-pipeline-count, ks-pipeline-link-healthy, ks-pipeline-link-broken, ks-pipeline-count-amber, ks-pipeline-count-emerald, ks-pipeline-count-danger, ks-pipeline-count-muted Pipeline and its parts
ks-empty-state Empty state, shown where a list or section has nothing in it
ks-swipe-card, ks-swipe-empty, ks-swipe-empty-title, ks-swipe-empty-message, ks-swipe-actions, ks-swipe-button, ks-swipe-button-reject, ks-swipe-button-accept Swipe deck and its parts
ks-bottom-nav, ks-bottom-nav-item, ks-bottom-nav-label Bottom nav bar, fixed to the bottom of small screens, and its items
ks-nav-dropdown, ks-nav-dropdown-trigger, ks-nav-dropdown-caret, ks-nav-dropdown-menu Nav dropdown and its parts, including the links inside the menu
ks-nav-item A nav link
ks-navbar-title Navbar title on small screens
ks-sidebar, ks-sidebar-logo, ks-sidebar-group-label, ks-sidebar-group-tabs, ks-sidebar-tab Vertical navigation panel, its logo, its group labels, the bordered container around an open group's tabs, and its tabs, with active marking the current tab
ks-mobile-header-title, ks-mobile-header-back, ks-mobile-header-subtitle Mobile header parts
ks-page-back, ks-breadcrumbs Space under a page's desktop Back link and breadcrumbs, with the Back link kept close above the breadcrumbs
ks-settings-link, ks-settings-link-label Settings link and its label
ks-grid-gap-sm, ks-grid-gap-md, ks-grid-gap-lg, ks-grid-gap-xl, and the same with -x- and -y- Grid gaps, both ways, across or down
ks-form, ks-form-field, ks-form-field-checkbox Space between a form's fields, inside a field, and beside a checkbox
ks-theme-toggle Space between the theme toggle's buttons
ks-color-picker-label Space under the colour picker's label
ks-settings-link-chevron Settings link arrow colour
ks-page-title Form page and show page title

On small screens the page's main element is padded to clear the bottom nav, and a page inside Hotwire Native hides the bottom nav and drops that padding.

<button class="ks-button ks-button-primary ks-button-md">Save</button>

License

MIT