1. Kikita UI
  2. Components
  3. Actions
  4. Link
Skip to content
Kikita UI
  • Installation
  • Theming
  • Tokens
  • Typography
  • Density
  • Accessibility
  • Migrating to 2.0
  • Internationalization
  • Defaults
  • Structural icons
  • Auto Focus
  • Forms
  • AI Support
  • Package Smoke
  • Button
  • Link
  • Icon Button
  • Menu
  • Command Palette
  • Field
  • Input
  • Color Input
  • Select
  • Combobox
  • Date Picker
  • Time Picker
  • Calendar
  • Calendar Range
  • File Upload
  • Segmented
  • Slider
  • Number Input
  • OTP Input
  • Textarea
  • Checkbox
  • Switch
  • Radio
  • Group
  • Badge
  • Loader
  • Skeleton
  • Tooltip
  • Toast
  • Empty State
  • Alert
  • Progress
  • Card
  • Tabs
  • Accordion
  • Breadcrumbs
  • Popover
  • Dialog
  • Media Viewer
  • Drawer
  • Splitter
  • Dropdown
  • Separator
  • Stepper
  • Icon
  • Avatar
  • Table
  • Pagination
  • Line Chart
  • Bar Chart
  • Scatter Chart
  • Donut Chart
  • Carousel
  • Chip
  • Scrollbar
  • Tree
  • Import
  • Usage
  • Underline and sizes
  • Icons and external links
  • Actions and disabled
  • API
  • Accessibility
  • Not included
  • Provider defaults
  • Messages

Actions

Stable - @kikita-labs/ui v2.0.0

Link

Inline interactive text for navigation or a JS-driven action.

Import

kuiLink is a directive on a native a or button. It composes kuiText internally, so you never add kuiText yourself.

link.ts
import { KuiLink } from '@kikita-labs/ui';

Usage

Open in Playground

Tone sets the rest colour only. Hover, focus and active change the underline thickness and the focus ring, never the colour.

SettingsArchiveDocs (default)UpgradeResolve billing issueDelete account
<div class="link-example">
  <a kuiLink tone="default" href="#settings">Settings</a>
  <a kuiLink tone="muted" href="#archive">Archive</a>
  <a kuiLink tone="primary" href="#docs">Docs (default)</a>
  <a kuiLink tone="success" href="#billing">Upgrade</a>
  <a kuiLink tone="warning" href="#past-due">Resolve billing issue</a>
  <a kuiLink tone="danger" href="#delete">Delete account</a>
</div>

Underline and sizes

Use always for a link inside running text, since colour alone is not a sufficient signal. hover (default) suits a link that already stands apart. variant picks an inline text role of the composed kuiText.

Inline linkStandalone link (default)No underlinebody-lgbody-smcaption
<div class="link-example">
  <a kuiLink underline="always" href="#inline">Inline link</a>
  <a kuiLink underline="hover" href="#standalone">Standalone link (default)</a>
  <a kuiLink underline="none" href="#plain">No underline</a>
  <a kuiLink variant="body-lg" href="#lg">body-lg</a>
  <a kuiLink variant="body-sm" href="#sm">body-sm</a>
  <a kuiLink variant="caption" href="#caption">caption</a>
</div>

A link acting as a heading goes inside an h1 to h6, not the other way round, so heading semantics never depend on the text being a link. Font size, weight and line height follow the selected --kui-type-<variant>-* tokens.

Icons and external links

iconStart and iconEnd take an icon name and stay decorative. external defaults to target being _blank.

Download reportAll updatesExternal docs
<div class="link-example">
  <a kuiLink iconStart="download" href="#report">Download report</a>
  <a kuiLink iconEnd="arrow-right" href="#updates">All updates</a>
  <a kuiLink href="https://example.com" target="_blank">External docs</a>
</div>
  • An external link gets rel="noopener noreferrer" merged with any rel you set.
  • The library's own external-link glyph fills the iconEnd slot unless you pass an explicit iconEnd. It is a structural icon: synchronous icon data drawn as inline SVG. Replace it with defaults.link.externalIcon or the externalLink role.
  • A visually hidden suffix, the link.opensInNewTab message ((opens in a new tab) by default), is appended to the accessible name.

Actions and disabled

A link without a real href is a button, not an anchor. A disabled anchor is blocked by aria-disabled, tabindex -1 and a click handler.

Download (unavailable)
<div class="link-example">
  <button kuiLink type="button" (click)="copy()">Copy link ({{ copied() }})</button>
  <a kuiLink href="#report" disabled>Download (unavailable)</a>
  <button kuiLink type="button" disabled>Copy link</button>
</div>

Provider defaults

Set defaults.link once for the application or for a subtree. Each option resolves as local input > defaults.link.<option> > built-in default.

import { provideKikitaUi } from '@kikita-labs/ui';

export const appConfig: ApplicationConfig = {
  providers: [
    provideKikitaUi({
      defaults: {
        link: {
          /* options below */
        },
      },
    }),
  ],
};

kuiLink composes kuiText for its role class but ignores defaults.typography, because a link owns its text colour (defaults.link.tone).

NameTypeDefaultDescription
tone'default' | 'muted' | 'primary' | 'success' | 'warning' | 'danger' — Default tone.
underline'always' | 'hover' | 'none' — When the link is underlined.
externalIconKuiIconGlyph — Icon after an external link. Takes precedence over defaults.icons.externalLink. See Structural Icons.

Messages

Every text the component owns (accessible names, visible words, announcements) is a typed message with an English default. Override it for the application with provideKikitaUi({ messages }), or for a subtree with provideKuiMessages.

NameTypeDefaultDescription
opensInNewTabstring — Hidden suffix for links that open a new tab. Default (opens in a new tab).

API

Inputs verified against @kikita-labs/ui v2.0.0 public typings.

NameTypeDefaultDescription
tone'default' | 'muted' | 'primary' | 'success' | 'warning' | 'danger' | undefinedundefinedRest colour only; hover, focus and active never change it. Falls back to defaults.link.tone, then primary.
underline'always' | 'hover' | 'none' | undefinedundefinedWhen the link is underlined (defaults.link.underline, then hover). Use always inside running text; hover also underlines on focus-visible and active.
variant'body-lg' | 'body' | 'body-sm' | 'caption''body'Forwarded to the composed kuiText directive. The link has no typography scale of its own and ignores defaults.typography.
iconStart / iconEndstring | undefinedundefinedDecorative icon name rendered through kui-icon before or after the content. An explicit iconEnd replaces the external-link glyph.
target / relstring | undefinedundefinedReflected onto the host as native attributes. rel is merged with noopener noreferrer for external links.
externalboolean | undefinedtarget() === "_blank"Marks the link as leaving the app: adds rel="noopener noreferrer", the external-link glyph (unless iconEnd is set) and a hidden "(opens in a new tab)" suffix to the name.
disabledbooleanfalseA disabled anchor gets aria-disabled, tabindex -1 and a blocked click; a button also gets the native disabled attribute.
href, type, (click)native attributes-Plain bindings on the host a or button. There is no as input: use a button without a real href for a JS-driven action.
--kui-link-color-default / -muted / -primary / -success / -warning / -danger / -disabledCSS custom properties-Rest colour per tone and the disabled colour.
--kui-link-focus-ring / -radius-focusCSS custom properties-Focus ring shadow and its corner radius.
--kui-link-decoration-thickness-rest / -activeCSS custom properties-Underline thickness at rest and on hover, focus and active.
--kui-link-gapCSS custom property-Gap between the icons and the text.
KuiLinkOptionsinterface-Shape of defaults.link: tone, underline and externalIcon.

Accessibility

The host is a native a or button with no custom role.

  • The visible text is the accessible name; icons are decorative and never the only meaning.
  • :focus-visible shows an explicit ring (--kui-link-focus-ring).
  • Colour is never the only signal: default, hover, focus and active differ by underline thickness and, for focus, the ring. Avoid underline="none" inside running text.
  • Disabled links are excluded from the tab order.
  • Enter activates a link or button; Space activates only a button host.

Not included

Deliberate omissions of the installed package.

  • There is no visited tone or state; add a --kui-link-color-visited token yourself if a product needs it.
  • There is no distinct active appearance from hover; both use the thicker underline.

On this page