Link
Inline interactive text for navigation or a JS-driven action.
kuiLink is a directive on a native a or button. It composes kuiText internally, so you never add kuiText yourself.
import { KuiLink } from '@kikita-labs/ui';Tone sets the rest colour only. Hover, focus and active change the underline thickness and the focus ring, never the colour.
<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>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.
<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.
iconStart and iconEnd take an icon name and stay decorative. external defaults to target being _blank.
<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 anyrelyou set. - The library's own external-link glyph fills the
iconEndslot unless you pass an expliciticonEnd. It is a structural icon: synchronous icon data drawn as inline SVG. Replace it withdefaults.link.externalIconor theexternalLinkrole. - A visually hidden suffix, the
link.opensInNewTabmessage ((opens in a new tab)by default), is appended to the accessible name.
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.
<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>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).
| Name | Type | Default | Description |
|---|---|---|---|
| tone | 'default' | 'muted' | 'primary' | 'success' | 'warning' | 'danger' | — | Default tone. |
| underline | 'always' | 'hover' | 'none' | — | When the link is underlined. |
| externalIcon | KuiIconGlyph | — | Icon after an external link. Takes precedence over defaults.icons.externalLink. See Structural Icons. |
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.
| Name | Type | Default | Description |
|---|---|---|---|
| opensInNewTab | string | — | Hidden suffix for links that open a new tab. Default (opens in a new tab). |
Inputs verified against @kikita-labs/ui v2.0.0 public typings.
| Name | Type | Default | Description |
|---|---|---|---|
| tone | 'default' | 'muted' | 'primary' | 'success' | 'warning' | 'danger' | undefined | undefined | Rest colour only; hover, focus and active never change it. Falls back to defaults.link.tone, then primary. |
| underline | 'always' | 'hover' | 'none' | undefined | undefined | When 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 / iconEnd | string | undefined | undefined | Decorative icon name rendered through kui-icon before or after the content. An explicit iconEnd replaces the external-link glyph. |
| target / rel | string | undefined | undefined | Reflected onto the host as native attributes. rel is merged with noopener noreferrer for external links. |
| external | boolean | undefined | target() === "_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. |
| disabled | boolean | false | A 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 / -disabled | CSS custom properties | - | Rest colour per tone and the disabled colour. |
| --kui-link-focus-ring / -radius-focus | CSS custom properties | - | Focus ring shadow and its corner radius. |
| --kui-link-decoration-thickness-rest / -active | CSS custom properties | - | Underline thickness at rest and on hover, focus and active. |
| --kui-link-gap | CSS custom property | - | Gap between the icons and the text. |
| KuiLinkOptions | interface | - | Shape of defaults.link: tone, underline and externalIcon. |
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-visibleshows 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
buttonhost.
Deliberate omissions of the installed package.
- There is no
visitedtone or state; add a--kui-link-color-visitedtoken yourself if a product needs it. - There is no distinct active appearance from hover; both use the thicker underline.