Skip to content

Link

Anchor primitive with token-driven styling, underline behaviour, and safe defaults for external destinations.

  • stable
  • since v0.1.0
  • 3.88 kB
  • typography
  • navigation

Renders a native <a>; external adds rel="noopener noreferrer" and target="_blank" plus an aria-hidden indicator icon so screen readers aren't double-announced.

Preview
Open
tsx

Three visual variants tune emphasis without changing semantics: default, subtle (for muted body links), and emphasis (for hero or callout links).

Preview
Open
tsx

underline controls underline behaviour — hover (default), always, or none. Pick the option that matches how prominent the link should look in flow.

Preview
Open
tsx

Pass external to automatically set target="_blank", append rel="noopener noreferrer", and render a decorative indicator icon. Caller-provided rel and target merge cleanly with the safe defaults.

Preview
Open
tsx

Drop a Link inside a Text to keep paragraph flow while remaining keyboard accessible.

Preview
Open
tsx

disabled cancels navigation, sets aria-disabled, and applies the muted style — use sparingly since disabled links are easy to miss.

Preview
Open
tsx
PropTypeDefaultDescription
variant
"default"|"subtle"|"emphasis"
"default"
Visual emphasis: `default` for primary links, `subtle` for tertiary navigation, `emphasis` for headline / hero CTAs.
underline
"always"|"hover"|"none"
"hover"
When the underline is drawn — `always`, only on `hover`, or `none`.
external
boolean
—
Marks the link as external: forces `rel="noopener noreferrer"`, `target="_blank"`, and appends a decorative arrow icon. The icon is `aria-hidden` so screen readers aren't double-announced.
disabled
boolean
—
Visually mutes the link and blocks `onClick`. Adds `aria-disabled`.
className
string
—
Additional class names appended after Cynosure's base classes.
style
CSSProperties
—
Inline style overrides merged last.
children
ReactNode
—
Link content.
padding
—
Padding on all four sides. Token from the spacing scale.
paddingX
—
Horizontal padding (left + right). Overrides `padding` on the X axis.
paddingY
—
Vertical padding (top + bottom). Overrides `padding` on the Y axis.
paddingTop
—
Padding on the top edge. Beats `padding` / `paddingY`.
paddingRight
—
Padding on the right (inline-end in RTL) edge.
paddingBottom
—
Padding on the bottom edge.
paddingLeft
—
Padding on the left (inline-start in RTL) edge.
margin
—
Margin on all four sides. Accepts the spacing scale or `"auto"`.
marginX
—
Horizontal margin (left + right). Use `"auto"` to centre.
marginY
—
Vertical margin (top + bottom).
marginTop
—
Margin on the top edge.
marginRight
—
Margin on the right edge.
marginBottom
—
Margin on the bottom edge.
marginLeft
—
Margin on the left edge.
width
—
Element width. Accepts a `SpaceToken`, `LengthValue`, or named alias.
height
—
Element height. Accepts a `SpaceToken`, `LengthValue`, or named alias.
minWidth
—
Minimum width — useful for preventing flex children from collapsing.
maxWidth
—
Maximum width — `"prose"` caps to a comfortable reading measure.
minHeight
—
Minimum height.
maxHeight
—
Maximum height.
background
—
Background colour. Use a `ColorToken` like `"bg.surface"` for theme awareness.
color
—
Text colour. Inherits unless set.
borderColor
—
Border colour. Pair with `borderWidth` to make the border visible.
borderWidth
—
Border thickness in scale steps.
borderStyle
—
Border line style.
borderRadius
—
Corner rounding token.
boxShadow
—
Drop-shadow token from the elevation scale.
opacity
Responsive<number | `${number}`>
—
Opacity 0–1. Use sparingly — prefer surface tokens over translucency.
overflow
—
How content that exceeds the box is handled.
overflowX
—
Horizontal-axis overflow control. Overrides `overflow` for the X axis.
overflowY
—
Vertical-axis overflow control.
display
—
CSS `display` value. `"contents"` removes the element's box from layout.
position
—
CSS `position`. Pair with `top`/`right`/`bottom`/`left` for placement.
top
—
Top inset (when positioned). Accepts a `SpaceToken`, `"auto"`, `"0"`, or `LengthValue`.
right
—
Right inset (when positioned).
bottom
—
Bottom inset (when positioned).
left
—
Left inset (when positioned).
zIndex
—
Stacking-context layer token (`"modal"`, `"tooltip"`, …).
gridColumn
Responsive<string>
—
Grid-column shorthand (e.g. `"1 / 3"`, `"span 2"`).
gridRow
Responsive<string>
—
Grid-row shorthand.
gridArea
Responsive<string>
—
Named grid area.
flex
Responsive<"none" | "1" | "auto" | "initial" | (string & {})>
—
Shorthand: `1 | auto | none | initial | <css>`. Resolves to `flex` on the child.
flexGrow
Responsive<number | `${number}`>
—
Grow factor inside a flex container.
flexShrink
Responsive<number | `${number}`>
—
Shrink factor inside a flex container.
flexBasis
Responsive<"content" | SizeValue>
—
Initial main-axis size before grow/shrink.
alignSelf
—
Override `align-items` for a single child.
justifySelf
—
Override `justify-items` for a single child (grid).
order
Responsive<number | `${number}`>
—
Flex/grid child reorder index.
asChild
boolean
—
When `true`, renders the primitive's single React child via `Slot`, forwarding className/style/ref/event handlers onto it.
  • Always write link text that stands on its own — avoid bare “click here” or “read more” copy.
  • external adds rel="noopener noreferrer" automatically so target="_blank" never leaks window.opener.
  • The external indicator icon is aria-hidden; the link text alone carries meaning for screen readers.
  • disabled sets aria-disabled="true" and blocks the click handler, but the anchor remains in the tab order — prefer hiding or replacing the link when it has no destination.
  • Underline + colour together carry the link signal so colour-blind users aren’t dependent on hue alone.
  • Use underline="always" for body links that must stand out against long-form prose.
  • Drop Link asChild over a framework router link to inherit Cynosure styling without losing client-side navigation: <Link asChild><NextLink href="/next">Next</NextLink></Link>.
  • Combine variant="subtle" with breadcrumbs or footer rows where many links sit close together.
  • Pair external with descriptive copy (“View on GitHub”) so the destination is obvious before the click.