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.