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

Guides

Icons

Cynosure ships two kinds of icon, both drawn by the same Icon component.

  • Facet icons (@arshad-shah/cynosure/icons): Cynosure's own set, 274 icons in 17 categories.
  • Brand marks (@arshad-shah/cynosure/brands): the official logos of 98 companies and projects, exactly as their owners publish them.

Facet iconsLink to "Facet icons"

One grammar: a 24 grid, a 1.75 round stroke, softened-square geometry, strokes only. The categories (ICON_CATEGORIES) are arrows, navigation, actions, editing, files, data, media, communication, status, time, security, people, devices, design, layout, maths and faith. Search them at the top of the Icons page, or browse them in Storybook: Foundations → Icon → Gallery (hover a tile to see its motion).

tsx
Copy
import { Icon } from "@arshad-shah/cynosure";
import { search } from "@arshad-shah/cynosure/icons";

<Icon icon={search} />                              // decorative (hidden from screen readers)
<Icon icon={search} label="Search" />               // role="img" with a name
<Icon icon={search} size="lg" tone="accent" />      // sm 14 · md 16 · lg 20 · or a number of px
<Icon icon={search} color="#14b8a6" />              // a one-off colour

ICON_KEYWORDS (from the same entry) maps each icon's name to other words it is found by (trash: delete, remove, bin), for building your own icon picker. Import icons by name so unused ones are left out of your bundle. Names are camelCase versions of the icon's kebab-case name (arrow-up-right → arrowUpRight); reserved words get an Icon suffix (packageIcon).

By nameLink to "By name"

When all you have is a name as a string (a plugin manifest that says icon: "database", a setting saved as text), look the icon up on its own entry:

tsx
Copy
import { Icon } from "@arshad-shah/cynosure";
import { iconByName, type IconName, icons } from "@arshad-shah/cynosure/icons/by-name";
import { puzzle } from "@arshad-shah/cynosure/icons";

<Icon icon={iconByName(plugin.icon) ?? puzzle} />;
  • iconByName(name) takes the icon's kebab-case name ("arrow-up-right", as in the gallery), and answers undefined for anything else (a camelCase export name, another set's name, "toString"), so keep a fallback.
  • icons is the frozen record behind it, keyed by name (IconName is the union of the names), for listing or validating names up front.
  • This entry brings every icon with it (about 13.5 kB gzipped once bundled), which is why it is separate: the main entry and @arshad-shah/cynosure/icons never import it, so importing icons one by one stays tree-shaken. Use it only where names arrive at run time.

Adding one: draw it on a 24 grid with strokes only, export the SVG, then run pnpm cy new icon <name> --from icon.svg --category <category>. In the generated file, set motion and mark the moving part animate: true. See src/icons/AGENTS.md. The by-name entry's budget is measured as one bundle by tools/icons-size.ts, which pnpm size runs after size-limit (size-limit's file plugin gzips each module on its own and overstated it about five times): when new icons push it over, raise ICONS_BY_NAME_BUDGET there to what it prints.

Brand marksLink to "Brand marks"

tsx
Copy
import { Icon } from "@arshad-shah/cynosure";
import { github, npm } from "@arshad-shah/cynosure/brands";

<Icon icon={github} label="GitHub" />                    // in the text colour (a one-colour mark)
<Icon icon={npm} label="npm" color="brand" size="lg" />  // in npm's own colour

Brands let their logos be used only as they publish them, so these are never redrawn in Facet's style:

  • Don't change a mark's shape, proportions or colours (other than one colour throughout, or color="brand").
  • Don't combine a mark with other shapes, or use it to suggest the brand endorses your product.
  • Do read the brand's own guidelines when you use its mark prominently. Each mark carries brand.guidelines (where published) and brand.source.

The marks come from Simple Icons (opens in new tab) (CC0). The trademarks remain their owners'. The list is tools/brands.json; regenerate with node --import tsx tools/brands.ts <unpacked simple-icons package>.

Not included, at the owners' request: some companies ask icon sets not to carry their marks. Use their own brand kits instead:

Without ReactLink to "Without React"

iconToSvg returns the same markup as Icon, as a string, for Astro components, static HTML or plain TypeScript. Load @arshad-shah/cynosure/styles/icon.css (or the full styles.css) so it sizes and colours the same way.

ts
Copy
import { iconToSvg, search } from "@arshad-shah/cynosure/icons";
import { github } from "@arshad-shah/cynosure/brands";

element.innerHTML = iconToSvg(search, { label: "Search" });
const mark = iconToSvg(github, { size: 20, color: "brand", label: "GitHub" });

Options: size (sm, md, lg or px), label (gives role="img"; omit for decorative icons), color (any CSS colour, or brand) and className. Labels and classes are escaped.

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