Skip to content
Cynosurev0.5.0
SearchStorybookGitHubnpmColour mode: System. Switch to Light

Guides

Build-tool adapters

Cynosure needs no plugin: import @arshad-shah/cynosure/styles.css (or per-component styles/<name>.css) and the components. For shadow roots use @arshad-shah/cynosure/styles.inline (css string or createStyleSheet()).

Which stylesheets a component needsLink to "Which stylesheets a component needs"

A component's CSS is not always in a file of its own name: Inline's rules are in stack.css, Sheet needs dialog.css, Accordion disclosure.css, IconButton tooltip.css, Button's loading state loading-dots.css, and every component needs base.css (which also holds shared rules such as .cy-visually-hidden). Do not keep that list by hand:

  • @arshad-shah/cynosure/styles/manifest.json maps each component to every file it needs, base first, worked out from the source imports at build time: { "Inline": ["base.css", "stack.css"], "Sheet": ["base.css", "icon.css", "button.css", "dialog.css", … ] }. Add styles/tokens.css (the default tokens) or your theme.
  • With the Vite or Astro adapter, styles: "imports" does it for you: every module that imports components from the package also imports the stylesheets they need.
  • A unit test fails when a component renders a styled class that its manifest entry does not bring.

Vite (@arshad-shah/cynosure/vite)Link to "Vite (@arshad-shah/cynosure/vite)"

ts
Copy
// vite.config.ts
import { cynosure } from "@arshad-shah/cynosure/vite";
export default { plugins: [cynosure({ theme: { accent: "#e8462e", scale: "compact" } })] };
ts
Copy
// app entry
import "@arshad-shah/cynosure/styles.css";
import "virtual:cynosure/theme.css"; // the product theme, built at compile time
// extension content script / shadow root:
import css from "virtual:cynosure/inline"; // all CSS + theme as a string

Options: theme (any createTheme input; invalid input fails the build), selector (default :root/:host), stylesheet (override the compiled CSS path), styles: "imports" (add only the stylesheets the imported components need, from styles/manifest.json, plus tokens.css when no theme is given; then import virtual:cynosure/theme.css for a theme instead of styles.css).

Astro (@arshad-shah/cynosure/astro)Link to "Astro (@arshad-shah/cynosure/astro)"

Astro renders on the server, where CynosureTheme target="document" never runs. The integration themes the page in the HTML itself: the product theme as CSS on :root, Cynosure's stylesheet on every page, and the saved-mode script inline in <head>.

js
Copy
// astro.config.mjs
import { cynosure } from "@arshad-shah/cynosure/astro";
export default {
  integrations: [cynosure({ theme: { accent: "#0f766e" }, initScript: { key: "nimaz-mode" } })],
};
astro
Copy
---
// src/layouts/Base.astro
import { htmlAttributes } from "@arshad-shah/cynosure/astro";
---
<html lang="en" {...htmlAttributes({ mode: "system" })}>

Options: everything the Vite adapter takes, plus styles (default true: add styles.css to every page; "imports": only what each page's components need) and initScript (default true; false for pages whose content security policy forbids inline scripts, or themeInitScript options, whose key must match ThemeToggle's storageKey). htmlAttributes({ mode, contrast }) gives <html> the data-cy-mode (default system) and data-cy-contrast attributes the stylesheet switches on. Components still render as React islands where they need script; the theme does not.

Contract for new adapters (esbuild/extforge…): one factory export in src/adapters/<tool>/, zero runtime cost in the product bundle, the same virtual ids, a unit test, and a section here.

Optional fontLink to "Optional font"

ts
Copy
import "@arshad-shah/cynosure/fonts/hanken.css"; // Hanken Grotesk, variable weight, Latin subset, self-hosted (OFL)

It registers the font face and points --cy-font-sans and --cy-font-display at it. Without it Cynosure uses the system font stack (zero bytes).

Getting started
Theming
Icons
Accessibility
Code editors and highlighters
Using Cynosure without React
Build-tool adapters
Components
Accordion
AppShell
AspectRatio
Breadcrumbs
Calendar
Card
Container
Disclosure
Divider
DocumentViewport
Grid
Inline
PageHeader
PanZoomCanvas
ScrollArea
SideNav
SortableList
SplitPane
Stack
StatusBar
Tabs
TitleBar
Toolbar
Tree
VirtualList
ZoomControls
Announcer
Avatar
Badge
CodeBlock
DescriptionList
EmptyState
ErrorBoundary
Field
Heading
IconTile
Image
Kbd
List
LoadingDots
Notice
ProgressBar
Prose
Skeleton
Stat
Steps
Table
Text
Button
Checkbox
Checklist
ColorField
ColorSwatches
Combobox
CompareSlider
CopyButton
DateField
FileDrop
IconButton
KeyValueEditor
Link
NumberField
Pagination
PathField
RadioGroup
SearchField
SegmentedControl
Select
SelectionFrame
SignaturePad
Slider
Switch
TagInput
TextArea
TextField
ThemeToggle
TimeField
ButtonBase
ChoiceBase
DialogBase
FileInputBase
HiddenValue
Icon
InputBase
LinkBase
LiveRegion
TextAreaBase
ChatMessage
Choice
DataGrid
DeviceFrame
HighlightedText
HotkeyField
ListRow
OptionList
OverlayFrame
QRCode
RowActions
Section
SiteFooter
SiteHeader
SkipLink
SortButton
VisuallyHidden
CommandPalette
ContextMenu
Dialog
FloatingToolbar
HoverCard
Menu
Menubar
Popover
ProgressOverlay
Sheet
Toast
Tooltip
Changelog