Link
The Link component provides styled links for navigation within and outside the application. It offers two size options and distinguishes between internal and external links with appropriate visual indicator. The component ensures consistent styling while maintaining accessibility standards.
Installation
import { Link } from '@harnessio/ui/components'
// ...
return ( <Link to="/your-url-here">Username</Link>)Anatomy
Link renders an anchor whose underlying element depends on whether it’s internal or external.
<Link to="/settings">Settings</Link><Link external href="https://harness.io">Harness</Link>- Internal vs. external — the
externalprop is a discriminated union. By default (externalunset/false) the component renders the app router’s link and takes atoprop. Withexternal, it renders a plain<a>and takes anhrefplus any standard anchor attributes. - Variants and size —
variant(default/secondary) andsize(md/sm) map tocn-link-*classes on the basecn-linkelement. - Icons —
prefixIconandsuffixIconaccepttrueor an icon name. Whentrue, they render the defaults:nav-arrow-left(prefix) andarrow-up-right(suffix), both as anIconV2at size2xs. Pass a name to override. - Disabled —
disableddoesn’t change the element; it setsdata-disabled/aria-disabledand intercepts clicks (callingpreventDefault/stopPropagationsoonClicknever fires). - Underline —
noHoverUnderlineopts out of the hover underline.
Best practices
Do
- Use an internal
Link(to) for in-app navigation andexternal(href) for links that leave the app. - Add a
suffixIconto external links so users can see the link leaves the current context. - Keep link text descriptive of its destination — it doubles as the accessible name.
Don’t
- Don’t use a
Linkto trigger an action with no navigation; use a Button for that. - Don’t write “click here” — the link text should make sense on its own.
Content
- Write link text that names the destination (“View pipeline settings”), not the mechanic (“click here”).
- Keep links short; if the surrounding sentence already explains the target, link just the key phrase.
Accessibility
Keyboard
- Links are focusable and activate with Enter, matching native anchor behavior.
Labeling
- The link’s text content is its accessible name — make it meaningful out of context. For an external link, consider indicating that it opens elsewhere.
Focus & states
disabledsetsaria-disabledand blocks activation, but the anchor remains in the DOM. Where a disabled link shouldn’t be reachable at all, also remove it from the tab order or render it as non-interactive text.
Known limitations
- External links don’t auto-set
target/relor add an external-link icon. Passtarget/relyourself when opening a new tab, and usesuffixIconto signal the link leaves the app.
Properties
Internal link
The default. Renders the app router link and accepts its props.
Prop | Required | Default | Type |
|---|---|---|---|
| to | true | string | |
| external | false | false |
External link
Set external to render a plain <a> and accept standard anchor attributes (target, rel, …).
Prop | Required | Default | Type |
|---|---|---|---|
| external | true | true | |
| href | true | string |
Common props
Shared by both variants.
Prop | Required | Default | Type |
|---|---|---|---|
| variant | false | 'default' | 'default' | 'secondary' |
| size | false | 'md' | 'md' | 'sm' |
| prefixIcon | false | 'nav-arrow-left' (when true) | boolean | IconPropsV2['name'] |
| suffixIcon | false | 'arrow-up-right' (when true) | boolean | IconPropsV2['name'] |
| disabled | false | false | boolean |
| noHoverUnderline | false | false | boolean |
| className | false | string |