Link
A styled anchor component for navigation with built-in icon support
Usage
import { Link } from '@hareui/vue'<script setup lang="ts">import { Link } from '@hareui/vue'</script><template> <Link href="#" icon> Call to action </Link></template>Anatomy
<template>
<!-- `icon` shows HeroUI's external-link arrow (Link.Icon); `#icon` replaces it -->
<Link href="#" icon>
Call to action
</Link>
</template>Examples
Icon Placement
<script setup lang="ts">import { Link } from '@hareui/vue'</script><template> <div class="flex flex-col gap-3"> <Link href="#" icon> Icon at end (default) </Link> <Link class="gap-1" href="#" icon icon-placement="start"> Icon at start </Link> </div></template>Text Decoration with Tailwind CSS
Link is underlined on hover by default. Use Tailwind CSS text-decoration utilities to make the underline always visible, remove it entirely, or customize its color, style, thickness, and offset.
Default hover underline
Hover to see the underlineAlways visible underline
Underline always visibleNo underline
Link without any underlineChanging the underline offset
<script setup lang="ts">import { Link } from '@hareui/vue'</script><template> <div class="flex flex-col gap-6"> <div class="flex flex-col gap-2"> <p class="text-sm font-medium text-muted"> Default hover underline </p> <Link href="#" icon> Hover to see the underline </Link> </div> <div class="flex flex-col gap-2"> <p class="text-sm font-medium text-muted"> Always visible underline </p> <Link class="underline" href="#" icon> Underline always visible </Link> </div> <div class="flex flex-col gap-2"> <p class="text-sm font-medium text-muted"> No underline </p> <Link class="no-underline" href="#" icon> Link without any underline </Link> </div> <div class="flex flex-col gap-2"> <p class="text-sm font-medium text-muted"> Changing the underline offset </p> <div class="flex flex-col gap-3"> <Link class="underline-offset-1" href="#" icon> Offset 1 (1px space) </Link> <Link class="underline-offset-2" href="#" icon> Offset 2 (2px space) </Link> <Link class="underline-offset-3" href="#" icon> Offset 3 (3px space) </Link> <Link class="underline-offset-4" href="#" icon> Offset 4 (4px space) </Link> </div> </div> </div></template>Text Decoration Line:
underline- Always visible underlineno-underline- Remove underline- default
Linkstyles - Underline appears on hover
Text Decoration Color:
decoration-accent,decoration-muted, etc. - Set underline color using theme colorsdecoration-muted/50- Use opacity modifiers for semi-transparent underlines
Text Decoration Style:
decoration-solid- Solid line (default)decoration-double- Double linedecoration-dotted- Dotted linedecoration-dashed- Dashed linedecoration-wavy- Wavy line
Text Decoration Thickness:
decoration-1,decoration-2,decoration-4, etc. - Control underline thickness
Underline Offset:
underline-offset-1,underline-offset-2,underline-offset-4, etc. - Adjust spacing between text and underline
For more details, see the Tailwind CSS documentation:
- text-decoration-line
- text-decoration-color
- text-decoration-style
- text-decoration-thickness
- text-underline-offset
Custom Icon
<script setup lang="ts">import { Icon } from '@iconify/vue'import { Link } from '@hareui/vue'</script><template> <div class="flex flex-col gap-3"> <Link href="#" :ui="{ icon: 'ms-1.5 size-3' }"> External link <template #icon> <Icon icon="gravity-ui:arrow-up-right-from-square" /> </template> </Link> <Link class="gap-1" href="#" :ui="{ icon: 'size-3' }"> Go to page <template #icon> <Icon icon="gravity-ui:link" /> </template> </Link> </div></template>Render Function
<script setup lang="ts">import { Link } from '@hareui/vue'import { defineComponent, h } from 'vue'const CustomSpan = defineComponent((_, { attrs, slots }) => () => h('span', { ...attrs, 'data-custom': 'foo' }, slots.default?.()))</script><template> <Link :as="CustomSpan" href="#" icon> Call to action </Link></template>Customization
Tailwind CSS
<script setup lang="ts">import { Link } from '@hareui/vue'</script><template> <Link class="font-medium text-neutral-700 underline decoration-neutral-300/80 underline-offset-4 transition-colors hover:text-neutral-900 dark:text-neutral-300 dark:decoration-neutral-600/80 dark:hover:text-neutral-100" href="#" icon > Call to action </Link></template>Global theme override
app.use(createHareUI({
ui: {
link: {
slots: {
base: 'font-semibold',
icon: 'opacity-100',
},
},
},
}))Styling Reference
Slots
base→[data-slot="link"]– Base link styles with hover underlineicon→[data-slot="link-icon"]– Link icon wrapper (data-default-icon="true"while it shows the built-in arrow)
Interactive States
- Focus:
:focus-visible - Hover:
:hover - Pressed:
:active - Disabled:
[aria-disabled="true"]
API Reference
Props
| Prop | Type | Default | Description |
|---|---|---|---|
as | AsTag | Component | "a" | The element or component to render as, e.g. a router link component. |
href | string | - | The URL the link points to. |
disabled | boolean | - | Whether the link is disabled: sets aria-disabled and blocks navigation. |
icon | boolean | false | Show the icon (HeroUI's Link.Icon). Defaults to the external-link arrow; fill #icon to replace it. |
iconPlacement | "start" | "end" | "end" | Which side of the text the icon goes on. |
ui | ComponentSlots<{ slots: { base: string; icon: string; }; }> | - | Per-slot class overrides. |
Slots
| Slot | Props | Description |
|---|---|---|
default | any | The link text. |
icon | any | Custom icon content; renders the icon wrapper even when icon is not set. |
Using with Routing Libraries
Pass a router link component to as; the Link styles and icon stay the same:
<script setup lang="ts">
import { Link } from '@hareui/vue'
import { RouterLink } from 'vue-router'
</script>
<template>
<Link :as="RouterLink" to="/about">
About Page
</Link>
</template>


