Button
Atomic button element
Default
With no variant or color, HLButton renders a secondary gray button.
<template>
<HLButton id="default-blue">Click me</HLButton>
</template>
<script setup lang="ts">
import { HLButton } from '@platform-ui/highrise'
</script>Primary
Set variant="primary" for a solid, high-emphasis button. Pair it with color, and use loading or disabled to reflect state.
<template>
<HLSpace justify="space-around" size="lg">
<HLButton id="primary-blue" color="blue" variant="primary">Click me</HLButton>
<HLButton id="primary-green" color="green" variant="primary">Click me</HLButton>
<HLButton id="primary-gray" color="gray" variant="primary">Click me</HLButton>
<HLButton id="primary-orange" color="orange" variant="primary">Click me</HLButton>
<HLButton id="primary-red" color="red" variant="primary">Click me</HLButton>
</HLSpace>
</template>
<script setup lang="ts">
import { HLButton, HLSpace } from '@platform-ui/highrise'
</script><template>
<HLSpace justify="space-around" size="lg">
<HLButton id="primary-blue" color="blue" variant="primary" loading>Click me</HLButton>
<HLButton id="primary-green" color="green" variant="primary" loading>Click me</HLButton>
<HLButton id="primary-gray" color="gray" variant="primary" loading>Click me</HLButton>
<HLButton id="primary-orange" color="orange" variant="primary" loading>Click me</HLButton>
<HLButton id="primary-red" color="red" variant="primary" loading>Click me</HLButton>
</HLSpace>
</template>
<script setup lang="ts">
import { HLButton, HLSpace } from '@platform-ui/highrise'
</script><template>
<HLSpace justify="space-around" size="lg">
<HLButton id="primary-blue" color="blue" variant="primary" disabled>Click me</HLButton>
<HLButton id="primary-green" color="green" variant="primary" disabled>Click me</HLButton>
<HLButton id="primary-gray" color="gray" variant="primary" disabled>Click me</HLButton>
<HLButton id="primary-orange" color="orange" variant="primary" disabled>Click me</HLButton>
<HLButton id="primary-red" color="red" variant="primary" disabled>Click me</HLButton>
</HLSpace>
</template>
<script setup lang="ts">
import { HLButton, HLSpace } from '@platform-ui/highrise'
</script>Secondary
secondary is the default variant — an outlined button for medium-emphasis actions alongside a primary one.
<template>
<HLSpace justify="space-around" size="lg">
<HLButton id="secondary-blue" color="blue">Click me</HLButton>
<HLButton id="secondary-green" color="green">Click me</HLButton>
<HLButton id="secondary-gray" color="gray">Click me</HLButton>
<HLButton id="secondary-orange" color="orange">Click me</HLButton>
<HLButton id="secondary-red" color="red">Click me</HLButton>
</HLSpace>
</template>
<script setup lang="ts">
import { HLButton, HLSpace } from '@platform-ui/highrise'
</script><template>
<HLSpace justify="space-around" size="lg">
<HLButton id="secondary-blue" color="blue" loading>Click me</HLButton>
<HLButton id="secondary-green" color="green" loading>Click me</HLButton>
<HLButton id="secondary-gray" color="gray" loading>Click me</HLButton>
<HLButton id="secondary-orange" color="orange" loading>Click me</HLButton>
<HLButton id="secondary-red" color="red" loading>Click me</HLButton>
</HLSpace>
</template>
<script setup lang="ts">
import { HLButton, HLSpace } from '@platform-ui/highrise'
</script><template>
<HLSpace justify="space-around" size="lg">
<HLButton id="secondary-blue" color="blue" disabled>Click me</HLButton>
<HLButton id="secondary-green" color="green" disabled>Click me</HLButton>
<HLButton id="secondary-gray" color="gray" disabled>Click me</HLButton>
<HLButton id="secondary-orange" color="orange" disabled>Click me</HLButton>
<HLButton id="secondary-red" color="red" disabled>Click me</HLButton>
</HLSpace>
</template>
<script setup lang="ts">
import { HLButton, HLSpace } from '@platform-ui/highrise'
</script>Tertiary
Set variant="tertiary" for a tinted, low-emphasis button — lighter than secondary but still filled.
<template>
<HLSpace justify="space-around" size="lg">
<HLButton id="tertiary-blue" color="blue" variant="tertiary">Click me</HLButton>
<HLButton id="tertiary-green" color="green" variant="tertiary">Click me</HLButton>
<HLButton id="tertiary-gray" color="gray" variant="tertiary">Click me</HLButton>
<HLButton id="tertiary-orange" color="orange" variant="tertiary">Click me</HLButton>
<HLButton id="tertiary-red" color="red" variant="tertiary">Click me</HLButton>
</HLSpace>
</template>
<script setup lang="ts">
import { HLButton, HLSpace } from '@platform-ui/highrise'
</script><template>
<HLSpace justify="space-around" size="lg">
<HLButton id="tertiary-blue" color="blue" variant="tertiary" loading>Click me</HLButton>
<HLButton id="tertiary-green" color="green" variant="tertiary" loading>Click me</HLButton>
<HLButton id="tertiary-gray" color="gray" variant="tertiary" loading>Click me</HLButton>
<HLButton id="tertiary-orange" color="orange" variant="tertiary" loading>Click me</HLButton>
<HLButton id="tertiary-red" color="red" variant="tertiary" loading>Click me</HLButton>
</HLSpace>
</template>
<script setup lang="ts">
import { HLButton, HLSpace } from '@platform-ui/highrise'
</script><template>
<HLSpace justify="space-around" size="lg">
<HLButton id="tertiary-blue" color="blue" variant="tertiary" disabled>Click me</HLButton>
<HLButton id="tertiary-green" color="green" variant="tertiary" disabled>Click me</HLButton>
<HLButton id="tertiary-gray" color="gray" variant="tertiary" disabled>Click me</HLButton>
<HLButton id="tertiary-orange" color="orange" variant="tertiary" disabled>Click me</HLButton>
<HLButton id="tertiary-red" color="red" variant="tertiary" disabled>Click me</HLButton>
</HLSpace>
</template>
<script setup lang="ts">
import { HLButton, HLSpace } from '@platform-ui/highrise'
</script>Ghost
Set variant="ghost" for a transparent button that only shows its background on hover — for the lowest-emphasis actions.
<template>
<HLSpace justify="space-around" size="lg">
<HLButton id="ghost-blue" color="blue" variant="ghost">Click me</HLButton>
<HLButton id="ghost-green" color="green" variant="ghost">Click me</HLButton>
<HLButton id="ghost-gray" color="gray" variant="ghost">Click me</HLButton>
<HLButton id="ghost-orange" color="orange" variant="ghost">Click me</HLButton>
<HLButton id="ghost-red" color="red" variant="ghost">Click me</HLButton>
</HLSpace>
</template>
<script setup lang="ts">
import { HLButton, HLSpace } from '@platform-ui/highrise'
</script><template>
<HLSpace justify="space-around" size="lg">
<HLButton id="ghost-blue" color="blue" variant="ghost" loading>Click me</HLButton>
<HLButton id="ghost-green" color="green" variant="ghost" loading>Click me</HLButton>
<HLButton id="ghost-gray" color="gray" variant="ghost" loading>Click me</HLButton>
<HLButton id="ghost-orange" color="orange" variant="ghost" loading>Click me</HLButton>
<HLButton id="ghost-red" color="red" variant="ghost" loading>Click me</HLButton>
</HLSpace>
</template>
<script setup lang="ts">
import { HLButton, HLSpace } from '@platform-ui/highrise'
</script><template>
<HLSpace justify="space-around" size="lg">
<HLButton id="ghost-blue" color="blue" variant="ghost" disabled>Click me</HLButton>
<HLButton id="ghost-green" color="green" variant="ghost" disabled>Click me</HLButton>
<HLButton id="ghost-gray" color="gray" variant="ghost" disabled>Click me</HLButton>
<HLButton id="ghost-orange" color="orange" variant="ghost" disabled>Click me</HLButton>
<HLButton id="ghost-red" color="red" variant="ghost" disabled>Click me</HLButton>
</HLSpace>
</template>
<script setup lang="ts">
import { HLButton, HLSpace } from '@platform-ui/highrise'
</script>Text
Set variant="text" for a button with no fill or border — just colored text. Add link to give it an underline on hover.
<template>
<HLSpace justify="space-around" size="lg">
<HLButton id="text-blue" color="blue" variant="text" link>Click me</HLButton>
<HLButton id="text-green" color="green" variant="text">Click me</HLButton>
<HLButton id="text-gray" color="gray" variant="text">Click me</HLButton>
<HLButton id="text-orange" color="orange" variant="text">Click me</HLButton>
<HLButton id="text-red" color="red" variant="text">Click me</HLButton>
</HLSpace>
</template>
<script setup lang="ts">
import { HLButton, HLSpace } from '@platform-ui/highrise'
</script><template>
<HLSpace justify="space-around" size="lg">
<HLButton id="text-blue" color="blue" variant="text" loading>Click me</HLButton>
<HLButton id="text-green" color="green" variant="text" loading>Click me</HLButton>
<HLButton id="text-gray" color="gray" variant="text" loading>Click me</HLButton>
<HLButton id="text-orange" color="orange" variant="text" loading>Click me</HLButton>
<HLButton id="text-red" color="red" variant="text" loading>Click me</HLButton>
</HLSpace>
</template>
<script setup lang="ts">
import { HLButton, HLSpace } from '@platform-ui/highrise'
</script><template>
<HLSpace justify="space-around" size="lg">
<HLButton id="text-blue" color="blue" variant="text" disabled>Click me</HLButton>
<HLButton id="text-green" color="green" variant="text" disabled>Click me</HLButton>
<HLButton id="text-gray" color="gray" variant="text" disabled>Click me</HLButton>
<HLButton id="text-orange" color="orange" variant="text" disabled>Click me</HLButton>
<HLButton id="text-red" color="red" variant="text" disabled>Click me</HLButton>
</HLSpace>
</template>
<script setup lang="ts">
import { HLButton, HLSpace } from '@platform-ui/highrise'
</script>All Sizes
Use size to scale a button from 3xs up to 2xl.
<template>
<HLSpace align="center">
<HLButton id="size-2xl-blue" size="2xl" color="blue">2XL Button</HLButton>
<HLButton id="size-xl-blue" size="xl" color="blue">XL Button</HLButton>
<HLButton id="size-lg-blue" size="lg" color="blue">LG Button</HLButton>
<HLButton id="size-md-blue" size="md" color="blue">MD Button</HLButton>
<HLButton id="size-sm-blue" size="sm" color="blue">SM Button</HLButton>
<HLButton id="size-xs-blue" size="xs" color="blue">XS Button</HLButton>
<HLButton id="size-2xs-blue" size="2xs" color="blue">2XS Button</HLButton>
<HLButton id="size-3xs-blue" size="3xs" color="blue">3XS Button</HLButton>
</HLSpace>
</template>
<script setup lang="ts">
import { HLButton, HLSpace } from '@platform-ui/highrise'
</script>Full Width Button
Add fullWidth to make the button fill its container. Wrap long labels in HLEllipsis to truncate instead of wrapping.
<template>
<div style="width: 240px; border: 1px solid #e0e0e0;" class="p-4">
<HLButton id="full-width-blue" color="blue" variant="primary" fullWidth>Full Width Button</HLButton>
</div>
<div style="width: 240px; border: 1px solid #e0e0e0;" class="p-4 mt-2">
<HLButton id="full-width-blue-ellipsis" color="blue" variant="primary" fullWidth>
<HLEllipsis>Full Width Button with Ellipsis</HLEllipsis>
</HLButton>
</div>
</template>
<script setup lang="ts">
import { HLButton, HLEllipsis } from '@platform-ui/highrise'
</script>Text Only Buttons
The text variant scales across every size just like the filled variants.
<template>
<HLSpace align="center">
<HLButton id="size-2xl-text" size="2xl" variant="text">2XL Button</HLButton>
<HLButton id="size-xl-text" size="xl" variant="text">XL Button</HLButton>
<HLButton id="size-lg-text" size="lg" variant="text">LG Button</HLButton>
<HLButton id="size-md-text" size="md" variant="text">MD Button</HLButton>
<HLButton id="size-sm-text" size="sm" variant="text">SM Button</HLButton>
<HLButton id="size-xs-text" size="xs" variant="text">XS Button</HLButton>
<HLButton id="size-2xs-text" size="2xs" variant="text">2XS Button</HLButton>
<HLButton id="size-3xs-text" size="3xs" variant="text">3XS Button</HLButton>
</HLSpace>
</template>
<script setup lang="ts">
import { HLButton, HLSpace } from '@platform-ui/highrise'
</script>Text with Link
Combine variant="text" with link to render an underlined-on-hover link styled as a button, available at every size.
<template>
<HLSpace align="center">
<HLButton id="size-2xl-link" size="2xl" color="blue" variant="text" :link="true">2XL Button</HLButton>
<HLButton id="size-xl-link" size="xl" color="blue" variant="text" :link="true">XL Button</HLButton>
<HLButton id="size-lg-link" size="lg" color="blue" variant="text" :link="true">LG Button</HLButton>
<HLButton id="size-md-link" size="md" color="blue" variant="text" :link="true">MD Button</HLButton>
<HLButton id="size-sm-link" size="sm" color="blue" variant="text" :link="true">SM Button</HLButton>
<HLButton id="size-xs-link" size="xs" color="blue" variant="text" :link="true">XS Button</HLButton>
<HLButton id="size-2xs-link" size="2xs" color="blue" variant="text" :link="true">2XS Button</HLButton>
<HLButton id="size-3xs-link" size="3xs" color="blue" variant="text" :link="true">3XS Button</HLButton>
</HLSpace>
</template>
<script setup lang="ts">
import { HLButton, HLSpace } from '@platform-ui/highrise'
</script>Icon Buttons
Fill the #iconLeft or #iconRight slot to place an icon beside the label.
<template>
<HLSpace align="center">
<HLButton id="size-2xl-icon-blue" size="2xl" color="blue">
2XL Button
<template #iconLeft><UserPlus01Icon class="w-3" /></template>
</HLButton>
<HLButton id="size-xl-icon-blue" size="xl" color="blue">
XL Button
<template #iconLeft><UserPlus01Icon class="w-3" /></template>
</HLButton>
<HLButton id="size-lg-icon-blue" size="lg" color="blue">
LG Button
<template #iconLeft><UserPlus01Icon class="w-3" /></template>
</HLButton>
<HLButton id="size-md-icon" size="md" color="blue">
MD Button
<template #iconLeft><UserPlus01Icon class="w-3" /></template>
</HLButton>
<HLButton id="size-sm-icon" size="sm" color="blue">
SM Button
<template #iconLeft><UserPlus01Icon class="w-3" /></template>
</HLButton>
<HLButton id="size-xs-icon" size="xs" color="blue">
XS Button
<template #iconRight><UserPlus01Icon class="w-3" /></template>
</HLButton>
<HLButton id="size-2xs-icon" size="2xs" color="blue">
2XS Button
<template #iconRight><UserPlus01Icon class="w-3" /></template>
</HLButton>
<HLButton id="size-3xs-icon" size="3xs" color="blue">
3XS Button
<template #iconRight><UserPlus01Icon class="w-3" /></template>
</HLButton>
</HLSpace>
</template>
<script setup lang="ts">
import { HLButton, HLSpace } from '@platform-ui/highrise'
import { UserPlus01Icon } from '@gohighlevel/ghl-icons/24/outline'
</script>Icon Only Buttons
Fill the #icon slot (with no label) for a square, icon-only button.
Accessibility Requirements
Icon-only buttons must include an accessible name to comply with WCAG 2.1 AA standards (button-name rule). Use one of these approaches:
aria-labelattribute (recommended)aria-labelledbypointing to descriptive text (Optional: The examplesr-onlyclass given below visually hides content while keeping it accessible to screen readers)iconLabelsprop to provide accessibility labels for icons inicon,iconLeft, andiconRightslots
HLButton forwards only class, aria-*, data-*, and role attributes to the underlying element — a plain title attribute is not passed through, so use aria-label / aria-labelledby / iconLabels instead.
<!-- Using aria-label for accessibility (recommended) -->
<template>
<HLButton id="icon-only-lg" size="lg" color="blue" aria-label="Add user">
<template #icon>
<UserPlus01Icon />
</template>
</HLButton>
</template>
<script setup lang="ts">
import { HLButton } from '@platform-ui/highrise'
import { UserPlus01Icon } from '@gohighlevel/ghl-icons/24/outline'
</script><!-- Using aria-labelledby for accessibility -->
<!-- Note: the sample `sr-only` class visually hides the text but keeps it accessible to screen readers -->
<template>
<div class="button-container" style="position: relative">
<div id="add-user-label-visual" class="sr-only">Add user</div>
<HLButton id="icon-only-sm" size="sm" color="blue" aria-labelledby="add-user-label-visual">
<template #icon>
<UserPlus01Icon />
</template>
</HLButton>
</div>
</template>
<script setup lang="ts">
import { HLButton } from '@platform-ui/highrise'
import { UserPlus01Icon } from '@gohighlevel/ghl-icons/24/outline'
</script>
<style>
.sr-only {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border: 0;
}
</style><!-- Using the iconLabels prop: labels each icon slot by its position. -->
<!-- The `default` key labels the `#icon` slot; `left` / `right` label `#iconLeft` / `#iconRight`. -->
<template>
<HLButton id="icon-only-2xs" size="2xs" color="blue" :iconLabels="{ default: 'Add user' }">
<template #icon>
<UserPlus01Icon />
</template>
</HLButton>
</template>
<script setup lang="ts">
import { HLButton } from '@platform-ui/highrise'
import { UserPlus01Icon } from '@gohighlevel/ghl-icons/24/outline'
</script>Button as Link
Set href (and optionally target) to render the button as an <a> tag while keeping its styling.
<template>
<HLButton id="link-lg" size="lg" color="blue" href="https://www.google.com" target="_blank">
LG Link
<template #iconRight>
<LinkExternal02Icon class="w-3" />
</template>
</HLButton>
</template>
<script setup lang="ts">
import { HLButton } from '@platform-ui/highrise'
import { LinkExternal02Icon } from '@gohighlevel/ghl-icons/24/outline'
</script>Button Type
HLButton always renders a native <button type="button"> (unless href is set, in which case it renders an <a>). This means it will not submit a surrounding <form> on click.
There is no type prop, and a plain type="submit" attribute is not forwarded to the underlying element — only class, aria-*, data-*, and role pass through. To submit a form, handle the click and submit programmatically.
<template>
<form @submit.prevent="onSubmit">
<!-- ... form fields ... -->
<HLButton id="save" variant="primary" color="blue" @click="onSubmit">Save</HLButton>
</form>
</template>
<script setup lang="ts">
import { HLButton } from '@platform-ui/highrise'
const onSubmit = () => {
// run validation / submit here
}
</script>Custom Color Buttons
Pass any CSS color (HEX, RGB, HSL, or a named color) to color, and every variant derives its shades from it. Edit the input below to recolor all six.
<template>
<HLSpace align="center" justify="center">
<HLSpace align="center">
<HLButton id="custom-color-button-primary" :color="inputColorValue" variant="primary">Custom Color Primary</HLButton>
<HLButton id="custom-color-button-secondary" :color="inputColorValue" variant="secondary">Custom Color Secondary</HLButton>
<HLButton id="custom-color-button-tertiary" :color="inputColorValue" variant="tertiary">Custom Color Tertiary</HLButton>
</HLSpace>
<HLSpace align="center">
<HLButton id="custom-color-button-ghost" :color="inputColorValue" variant="ghost">Custom Color Ghost</HLButton>
<HLButton id="custom-color-button-text" :color="inputColorValue" variant="text">Custom Color Text</HLButton>
<HLButton id="custom-color-button-text-link" :color="inputColorValue" variant="text" link>Custom Color Link</HLButton>
</HLSpace>
</HLSpace>
<div class="my-4"></div>
<HLInput id="button-color-value-input" v-model:modelValue="inputColorValue" />
</template>
<script setup lang="ts">
import { ref } from 'vue'
import { HLButton, HLInput, HLSpace } from '@platform-ui/highrise'
const inputColorValue = ref('#26a6a6')
</script>Custom Text Size
Wrap the default slot in HLText to control the label's typography independently of the button size.
<template>
<HLSpace justify="space-around" size="lg">
<HLButton id="custom-text-blue" variant="primary" color="blue" size="3xs">
<HLText size="2xl" weight="semibold">Placeholder</HLText>
</HLButton>
<HLButton id="custom-text-green" variant="primary" color="green" size="3xs">
<HLText size="2xl" weight="semibold">Placeholder</HLText>
</HLButton>
<HLButton id="custom-text-gray" variant="primary" color="gray" size="3xs">
<HLText size="2xl" weight="semibold">Placeholder</HLText>
</HLButton>
<HLButton id="custom-text-orange" variant="primary" color="orange" size="3xs">
<HLText size="2xl" weight="semibold">Placeholder</HLText>
</HLButton>
<HLButton id="custom-text-red" variant="primary" color="red" size="3xs">
<HLText size="2xl" weight="semibold">Placeholder</HLText>
</HLButton>
</HLSpace>
</template>
<script setup lang="ts">
import { HLButton, HLText, HLSpace } from '@platform-ui/highrise'
</script>Imports
import { HLButton } from '@platform-ui/highrise'
import type { HLAllColorNamesKCase, HLButtonSize, HLButtonVariant } from '@platform-ui/highrise'Accessibility
HLButtonoutputs a semantic<button>(or<a>whenhrefis set), so route any helper copy througharia-describedbyif it sits outside the control.- Provide
iconLabelsoraria-labelwhenever the content is icon-only, and keep toggle buttons in sync witharia-pressed. - When the button opens menus, dialogs, or new tabs, pair it with
aria-haspopup/aria-controlsand describe the destination in the visible label.
Props
| Name | Type | Default | Description |
|---|---|---|---|
| id * | string | undefined | undefined | The id of the element |
| size | '2xl' | 'xl' |'lg' | 'md' | 'sm' | 'xs' | '2xs' | '3xs' as HLButtonSize | 'md' | The size of the button |
| color | 'blue' | 'gray' | 'red' | 'orange' | 'green' | HLAllColorNamesKCase | string | 'gray' | The color of the button. All valid HEX, RGB, HSL, HSB, and named CSS spec color values are accepted as a string |
| variant | 'primary' | 'secondary' | 'tertiary' | 'ghost' | 'text' as HLButtonVariant | 'secondary' | The variant of the button |
| disabled | boolean | false | Disabled state of the button |
| loading | boolean | false | Loading state of the button |
| fullWidth | boolean | false | Whether the button should take full width |
| iconLabels | Record<'left' | 'right' | 'default', string> | undefined | Accessibility labels for icons in icon, iconLeft, and iconRight slots |
| link | boolean | false | Link type of button |
| href | string | undefined | The href of the anchor tag |
| target | string | undefined | The target of the anchor tag |
Types
export type HLAllColorNamesKCase =
| 'blue-dark'
| 'blue-light'
| 'blue'
| 'cyan'
| 'error'
| 'fuchsia'
| 'gray-blue'
| 'gray-cool'
| 'gray-iron'
| 'gray-modern'
| 'gray-neutral'
| 'gray-true'
| 'gray-warm'
| 'gray'
| 'green-light'
| 'green'
| 'indigo'
| 'moss'
| 'orange-dark'
| 'orange'
| 'pink'
| 'primary'
| 'purple'
| 'rose'
| 'success'
| 'teal'
| 'violet'
| 'warning'
| 'yellow'Emits
| Name | Parameters | Description |
|---|---|---|
@click | (event: MouseEvent) | Emitted when the button is clicked. Receives the native click event. |
Slots
| Name | Parameters | Description |
|---|---|---|
| default | () | The default content slot |
| icon | () | The icon slot for button |
| iconLeft | () | The icon slot for left side of the button |
| iconRight | () | The icon slot for right side of the button |