{"slug":"link","name":"Link","packageName":"@liquidify/react","category":"controls","maturity":"experimental","summary":"A control that opens a URL — the SwiftUI Link .","importPath":"@liquidify/react/link","sourcePath":"packages/@liquidify/react/src/components/link/link.tsx","specPath":"packages/@liquidify/react/src/components/link/spec.md","docsPath":"../liquidify-page/content/component-source/link.md","documentationStatus":"draft","storyIds":["controls-link--default"],"additionalExports":["ButtonSize","ButtonVariant","LinkActionProps","LinkNavigationProps","LinkTarget","LinkVariant","LiquidColor"],"anatomy":[{"name":"Inline surface (variant=\"inline\", the default): a bare","description":"Inline surface (variant=\"inline\", the default): a bare"},{"name":"Glass navigation surface (any other variant, with an href): Link","description":"Glass navigation surface (any other variant, with an href): Link"},{"name":"Glass action surface (any other variant, no href): a share/command","description":"Glass action surface (any other variant, no href): a share/command"}],"props":[{"name":"aria-label","type":"string | undefined","required":false,"description":"Accessible name override — required when {@link LinkCommonProps.children} is icon-only.","declaredIn":"packages/@liquidify/react/src/components/link/link.tsx"},{"name":"children","type":"ReactNode","required":false,"description":"The visible content and accessible-name source — SwiftUI `Link(_ title:, destination:)` (a string title) or the `Link(destination:)` label-closure form (an arbitrary node). An icon-only glass trigger (no visible text, only `leadingIcon` / `trailingIcon`) **requires** an explicit {@link LinkCommonProps. \"aria-label\" | aria-label} (WCAG 2.1 SC 1.1.1). children role: `label` (token parity — Link's text renders through Button; no `labelProps` seam, per ADR-0028 rule 3 / charter §2 rule 5).","declaredIn":"packages/@liquidify/react/src/components/link/link.tsx"},{"name":"className","type":"string | undefined","required":false,"description":"Optional additional CSS class merged into the glass surface class. The supported per-instance customisation seam: override any `--lq-*` custom property from this class's CSS — the token cascade the engine reads (ADR-0004). No raw inline style is involved, so this stays ADR-0003 clean.","declaredIn":"packages/@liquidify/react/src/liquid-component-props.ts"},{"name":"disabled","type":"boolean | undefined","required":false,"description":"Disables the control. Shape N (action `<button>`): native `disabled` + `data-disabled`, no `aria-disabled`. Shape A (any `<a>` mode — inline, or a glass variant with `href`): `aria-disabled=\"true\"` + `data-disabled` + hard suppression (navigation prevented, `onClick` / `onPress` suppressed, hover / press motion suppressed via `[data-disabled] { pointer-events: none }`) — the element **stays focusable** so assistive tech can perceive it (`docs/api-conventions.md` §3).","declaredIn":"packages/@liquidify/react/src/components/link/link.tsx"},{"name":"href","type":"string | undefined","required":false,"description":"The destination URL — SwiftUI `Link(destination:)`. Rendered as the anchor's native `href`. Absent in action mode — an action has no destination.","declaredIn":"packages/@liquidify/react/src/components/link/link.tsx"},{"name":"leadingIcon","type":"ReactNode","required":false,"description":"Leading glyph rendered before the label. **Glass variants only.**","declaredIn":"packages/@liquidify/react/src/components/link/link.tsx"},{"name":"onClick","type":"((event: MouseEvent<HTMLAnchorElement>) => void) | ((event: MouseEvent<HTMLButtonElement>) => void) | undefined","required":false,"description":"Low-level native passthrough; prefer `onPress`. Fires FIRST, before `onPress` — call `event.preventDefault()` here to suppress `onPress` and the default navigation (charter §1 rules 2–3). Low-level native passthrough; prefer `onPress`. Fires FIRST, before `onPress` — call `event.preventDefault()` here to suppress `onPress` (charter §1 rules 2–3).","declaredIn":"packages/@liquidify/react/src/components/link/link.tsx"},{"name":"onPress","type":"(() => void) | undefined","required":false,"description":"Semantic activation — the SwiftUI `Button(action:)` / environment `openURL` closure Link's action opens `destination` through. Payload-free, fires at most once per interaction, and only AFTER the {@link onClick } escape hatch on any surface where it fired without cancelling (charter §1 rules 1–3). Disabled emits nothing on every surface (audit §8).","declaredIn":"packages/@liquidify/react/src/components/link/link.tsx"},{"name":"ref","type":"((instance: HTMLButtonElement | null) => void | (() => VoidOrUndefinedOnly) | DO_NOT_USE_OR_YOU_WILL_BE_FIRED_CALLBACK_REF_RETURN_VALUES[keyof DO_NOT_USE_OR_YOU_WILL_BE_FIRED_CALLBACK_REF_RETURN_VALUES]) | RefObject<HTMLButtonElement | null> | ((instance: HTMLAnchorElement | null) => void | (() => VoidOrUndefinedOnly) | DO_NOT_USE_OR_YOU_WILL_BE_FIRED_CALLBACK_REF_RETURN_VALUES[keyof DO_NOT_USE_OR_YOU_WILL_BE_FIRED_CALLBACK_REF_RETURN_VALUES]) | RefObject<HTMLAnchorElement | null> | null | undefined","required":false,"description":"Forwarded ref to the rendered element — the component's native root (or the merged child element on a component that opts into {@link SlottableProps}). Generic over `E` (charter `docs/api-conventions.md` §4 rule 1, default `HTMLElement`) so a component with a polymorphic root (Link's navigation / action mode union, Text's `as`) can instantiate the concrete element per variant instead of leaving every consumer with a widened `Ref<HTMLElement>`. A component that does not narrow simply inherits the `HTMLElement` default — source-compatible with every pre-existing non-generic `extends ControlProps`.","declaredIn":"packages/@liquidify/react/src/liquid-component-props.ts"},{"name":"size","type":"ButtonSize | undefined","required":false,"description":"Control size — the `small · regular · large` subset, forwarded to {@link Button}. **Glass variants only**; ignored on the `\"inline\"` surface, which inherits the surrounding text size. Narrows the inherited {@link SizedControlProps} `size` axis to the three sizes the glass surface ships — the truthful `ButtonSize` re-export (charter §7 rule 4, the composition-wrapper exception: Link may not mint its own `Extract`). Control size — the `small · regular · large` subset, forwarded to {@link Button}. Narrows the inherited {@link SizedControlProps} `size` axis to the three sizes the glass surface ships — the truthful `ButtonSize` re-export (charter §7 rule 4).","defaultValue":"Button's own default (`\"regular\"`).","declaredIn":"packages/@liquidify/react/src/components/link/link.tsx"},{"name":"target","type":"LinkTarget | undefined","required":false,"description":"New-tab vs same-tab navigation (web-only; SwiftUI's `openURL` has no \"new window\" concept). `\"_blank\"` opens a new browsing context, auto-adds `rel=\"noopener noreferrer\"` (never independently settable), and appends a visually-hidden `\" (opens in new tab)\"` suffix to the accessible name. Absent in action mode — `target` is an anchor-only axis.","defaultValue":"same-tab (no `target` attribute)","declaredIn":"packages/@liquidify/react/src/components/link/link.tsx"},{"name":"tint","type":"LiquidTintValue | undefined","required":false,"description":"System-accent of the control — drawn from the RESTRICTED {@link LIQUID_COLORS} palette (the thirteen Apple system colours). **Orthogonal to a component's `variant`**: it recolours the accent the surface draws from (focus ring, tinted fill, selection) without changing its variant. Resolved via `data-tint` attribute selectors in CSS (tokens-only, ADR-0003).","declaredIn":"packages/@liquidify/react/src/liquid-component-props.ts"},{"name":"trailingIcon","type":"ReactNode","required":false,"description":"Trailing glyph rendered after the label. **Glass variants only.**","declaredIn":"packages/@liquidify/react/src/components/link/link.tsx"},{"name":"variant","type":"LinkVariant | undefined","required":false,"description":"The surface — SwiftUI `buttonStyle`. `\"inline\"` (default) is the Text-like inline link; the glass variants render the composed {@link Button}'s surface. Orthogonal to the root element, which follows the `href` discriminant (an `<a>` to navigate, a `<button>` to act).","defaultValue":"`\"inline\"`","declaredIn":"packages/@liquidify/react/src/components/link/link.tsx"}],"swiftUIMap":[{"swiftUI":"`destination: URL`","react":"`href`","notes":"The URL to open — the anchor's native `href`. Optional: an action-only glass trigger (e.g. ShareLink) may omit it and drive the control via `onClick` / `onPress` — Link then renders a native `<button>` instead of an `<a>`.","relationship":"direct"},{"swiftUI":"`Link(_ title:, destination:)` / `Link(_ titleKey:, destination:)`","react":"`children` (string)","notes":"Title-as-text form (demo: `plain`, `bordered`, `Visit`).","relationship":"direct"},{"swiftUI":"`Link(destination:) { Label(...) }`","react":"`children` (node) + `leadingIcon` / `trailingIcon`","notes":"Slot form — the label node, plus explicit glyph slots (glass variants only).","relationship":"direct"},{"swiftUI":"`.buttonStyle(_:)`","react":"`variant`","notes":"`\"inline\" | ButtonVariant`. `\"inline\"` (default) = text link; the rest = glass surface.","relationship":"direct"},{"swiftUI":"`.controlSize(_:)`","react":"`size`","notes":"`small | regular | large`, forwarded to Button. **Glass variants only** — the inline surface inherits the ambient text size.","relationship":"direct"},{"swiftUI":"`.disabled(_:)`","react":"`disabled`","notes":"A native anchor has no `disabled`; Link marks the `<a>` `aria-disabled` and prevents its default navigation + handlers.","relationship":"direct"},{"swiftUI":"`.tint(color)`","react":"`tint`","notes":"Restricted `LiquidColor` (13 system colours) — recolours the inline text / the glass capsule wash.","relationship":"direct"},{"swiftUI":"*(web-only, no SwiftUI analogue)*","react":"`target`","notes":"New-tab (`\"_blank\"`) vs same-tab (default).","relationship":"web-only"},{"swiftUI":"*(web-only, derived — not a prop)*","react":"`rel`","notes":"Auto-computed `\"noopener noreferrer\"` whenever `target=\"_blank\"`; never settable directly (security-critical, ADR-0017).","relationship":"web-only"},{"swiftUI":"`Link` action semantics (environment `openURL`)","react":"`onPress?: () => void`","notes":"Payload-free semantic activation — the SwiftUI action-closure analogue (charter §1 rule 1). Fires at most once per interaction, after `onClick` when it did not cancel.","relationship":"direct"},{"swiftUI":"*(web-only)*","react":"`onClick?: (event) => void`","notes":"Low-level native passthrough; prefer `onPress`. Typed to the concrete element per mode (`MouseEvent<HTMLAnchorElement>` navigation, `MouseEvent<HTMLButtonElement>` action). Fires FIRST; `event.preventDefault()` there suppresses `onPress` **and** the default navigation (charter §1 rules 2–3).","relationship":"web-only"}],"tokens":["--lq-color-accent","--lq-color-action-primary","--lq-duration-fast","--lq-easing-standard","--lq-focus-ring-color","--lq-font-size-","--lq-glass-","--lq-glass-fill-0","--lq-hit-target-","--lq-motion-","--lq-opacity-disabled","--lq-radius","--lq-radius-pill","--lq-space-","--lq-space-2","--lq-tint-current"],"keyboard":[{"key":"Keyboard","action":"Keyboard: a navigating is native — Tab focuses, Enter activates; anchors do not respond to Space. An action trigger (no href) is a native — Tab focuses, Enter and Space activate — all native, no custom key handler."}],"variants":["automatic","bordered","borderedProminent","borderless","glass","glassProminent","inline","plain","translucent"],"variantPages":[]}