Wordmark
A typographic brand mark — a two-part word (serif italic + upright sans) followed by a small accent symbol. Useful as a header logo without packaging a separate SVG. The root element is polymorphic — render as a span, an h1/h2 heading landmark, or an a link.
craftbits
Customize
Scale
md
Tone
accent
Element
span
Installation
npx shadcn@latest add https://craftbits.dev/r/wordmark.jsonUsage
Drop a Wordmark anywhere you'd otherwise drop a logo. The default text is the two-part "craft" + "bits" split with a single asterisk accent.
import { Wordmark } from "@craft-bits/core";
<Wordmark />Override the text — accepts either a single string (no split) or a [serif, sans] tuple:
<Wordmark text={["after", "noon"]} />
<Wordmark text="Acme" />Swap the accent symbol — strings, SVGs, or null to omit:
<Wordmark accent="·" />
<Wordmark accent={<StarIcon />} accentColor="warning" />
<Wordmark accent={null} />Render as a heading landmark or a link:
<Wordmark as="h1" size="xl" />
<Wordmark as="a" href="/" />Understanding the component
- Polymorphic root. The as prop picks the rendered tag — span keeps the mark inline, h1 and h2 give it heading semantics, and a turns it into a link that accepts href. The accent glyph nudges with a subtle hover transition only when the root is an anchor.
- Split text by default. text defaults to ["craft", "bits"]. Passing a tuple styles the first half serif italic and the second half upright sans. Passing a single string skips the split — the whole word renders upright. Either form keeps the same family/size pairing so consumers can swap word without re-tuning typography.
- Accent as a slot. accent accepts any ReactNode. A plain asterisk (default) renders inline with the serif family — the same font as the rest of the wordmark, so it sits on the baseline. Pass a custom SVG for a star, sparkle, or icon glyph. Pass null for a clean text-only wordmark.
- Size scales as one unit. The size prop sets the root font-size; everything inside inherits 1em so the accent glyph stays optically proportional. Four steps — sm (0.875rem), md (1.375rem, default), lg (1.875rem), xl (2.5rem) — cover sidebar labels through hero-page splashes.
- Tone-coded accent. accentColor picks a semantic tone (accent / success / warning / error) keyed to the cb-* tokens. The default matches the library accent; the semantic tones let the mark double as a status badge in error / empty states.
- Font fallback safe. The serif half resolves to var(--cb-font-serif, ui-serif, Georgia, serif) — if a consumer hasn't defined a serif token, the system serif keeps the visual contrast.
- Data-attributes for nested styling. The root carries data-cb-wordmark, data-size, and data-accent-color, and each child renders data-cb-wordmark-part="serif|sans|accent" — so consumers can target the accent glyph (e.g. animate it externally) without re-deriving props.
Props
Wordmark
| Prop | Type | Default | Description |
|---|---|---|---|
text | string | [string, string] | ["craft", "bits"] | Either a single string (no split) or a [serif, sans] tuple. |
accent | ReactNode | "*" | Small accent symbol rendered after the text. Pass null to omit. |
accentColor | 'accent' | 'success' | 'warning' | 'error' | 'accent' | Tone of the accent glyph. |
size | 'sm' | 'md' | 'lg' | 'xl' | 'md' | Root font-size — the accent glyph inherits at 1em. |
as | 'span' | 'h1' | 'h2' | 'a' | 'span' | Root element. a accepts href and gets a hover nudge on the accent. |
href | string | — | Link target. Only used when as="a". |
className | string | — | Merged onto the rendered root via cn(). |
...rest | Omit<HTMLAttributes<HTMLElement>, 'title'> | — | Any other root attribute. |
Accessibility
- The accent glyph is decorative — it renders with aria-hidden="true" so screen readers announce only the wordmark text, not the asterisk / star / sparkle.
- When as="a", the link gets a visible :focus-visible outline keyed to --cb-accent and meets the 3:1 contrast bar against every default surface.
- When as="h1" or as="h2", the mark is a landmark heading — keep at most one h1 per page.
- Color contrast: the text uses --cb-fg; every accent tone passes WCAG AA against the default surfaces.
- Motion: the only animation is a 300ms rotation on the accent glyph when the link is hovered. It uses transition-transform (no transition-all) and is below the library's 300ms motion cap. The base span / heading variants ship zero motion.
Credits
- Extracted from:
craftingattention(app/src/components/ui/Wordmark.tsx). The original was a fixed two-mode (full / compact) sparkle SVG + sans-serif text pair with hardcoded --color-accent-500 / --color-ink-50 tokens. craft-bits drops the inline SVG, generalises the surface into a polymorphic, scalable, theme-aware primitive — text becomes a tuple slot, the accent becomes a ReactNode slot, color and size become tokens, and the root tag becomes polymorphic so the same primitive serves headers, headings, and links.