Island Button
npx @vyui/cli add island-buttonOverview
VyIslandButton is a pill-shaped action designed for VyIsland. Inside an island it can declaratively select a value, switch the row mode, toggle an expanded panel, or reset the mode. It also works as a standalone button.
Usage
Use icon, label, or both. Buttons inherit their size from the nearest VyIsland.
<script setup lang="ts">
import { VyIsland, VyIslandButton } from '@vyui/kit'
</script>
<template>
<VyIsland layer="inline" size="lg">
<VyIslandButton icon="i-lucide-plus" label="New issue" />
<VyIslandButton icon="i-lucide-settings" accessibility-label="Settings" />
</VyIsland>
</template>
With no label and no default slot content, the button uses a square icon-only footprint. Supplying a label or default slot creates a wider pill.
Selected values
Set value to connect the button to its parent island's v-model:value. Matching buttons become active automatically.
<script setup lang="ts">
import { ref } from 'vue'
import { VyIsland, VyIslandButton } from '@vyui/kit'
const active = ref<string | number | null>('inbox')
</script>
<template>
<VyIsland v-model:value="active" layer="inline">
<VyIslandButton value="inbox" icon="i-lucide-inbox" label="Inbox" />
<VyIslandButton value="saved" icon="i-lucide-bookmark" label="Saved" />
</VyIsland>
</template>
The explicit active prop can force active styling independently of the parent's value.
Mode and expansion controls
Declarative behavior props can be combined. On tap, the button applies value, then mode, then expand, then reset, before emitting its own tap event.
<script setup lang="ts">
import { VyIsland, VyIslandButton } from '@vyui/kit'
</script>
<template>
<VyIsland layer="inline">
<VyIslandButton mode="search" icon="i-lucide-search" />
<VyIslandButton expand icon="i-lucide-menu" />
<template #search>
<VyIslandButton
reset
icon="i-lucide-search"
label="Search…"
:style="{ flexGrow: 1 }"
/>
<VyIslandButton reset icon="i-lucide-x" />
</template>
<template #expanded>
<VyIslandButton expand icon="i-lucide-settings" label="Settings" />
<VyIslandButton expand icon="i-lucide-circle-help" label="Help" />
</template>
</VyIsland>
</template>
mode, expand, and reset do nothing when the button has no parent island context; the normal tap event still fires.
Custom content
The leading slot replaces the built-in icon. The default slot replaces the built-in label while retaining the leading icon.
<VyIslandButton icon="i-lucide-bell">
<view class="flex flex-row items-center gap-1">
<text>Notifications</text>
<text class="rounded-full bg-red-500 px-1.5 text-xs text-white">3</text>
</view>
</VyIslandButton>
When rendering a custom SVG icon in leading, pass an explicit color because Lynx SVG does not inherit text color.
Features and behavior
valuesets the parent island's selected value and automatically participates in active-state matching.modesets the parent island's free-form row mode.expandtoggles the parent island's open state.resetsets the parent mode to'default'.- Behavior props may be combined and run in the fixed order
value→mode→expand→reset. - Disabled buttons do not update island state and do not emit
tap. activealways enables active styling. Otherwise, a definedvalueis active when it strictly equals the parent value.- An explicit
sizeoverrides the inherited island size. Standalone buttons default tomd. - Built-in icon sizes are 16, 20, 24, and 28 pixels for
sm,md,lg, andxl.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
icon | string | undefined | Leading Iconify icon name. |
label | string | undefined | Built-in label text. Its presence creates a label-pill footprint. |
active | boolean | false | Forces active styling. Parent value matching can also activate the button. |
disabled | boolean | false | Prevents state changes and tap emission. |
value | string | number | undefined | Value written to the parent island on tap and used for automatic active state. |
mode | string | undefined | Free-form row mode written to the parent island on tap. |
expand | boolean | false | Toggles the parent island's open state on tap. |
reset | boolean | false | Resets the parent island's mode to 'default' on tap. |
size | 'sm' | 'md' | 'lg' | 'xl' | Parent size / 'md' | Explicit size override. |
class | any | undefined | Classes merged onto the button base. |
ui | Partial<Record<IslandButtonSlot, any>> | undefined | Per-instance theme slot overrides. |
Emits
| Event | Payload | Description |
|---|---|---|
tap | none | Emitted after enabled declarative parent updates have run. |
Slots
| Slot | Description |
|---|---|
default | Replaces the built-in label. The built-in leading icon remains. |
leading | Replaces the built-in icon area entirely. |
Slot content does not receive scoped props.
Styling and theming
Override globally through appConfig.ui.islandButton or locally with ui.
| UI slot | Purpose |
|---|---|
base | Button layout, target size, spacing, surface states, and rounding. |
leadingIcon | Built-in icon size and foreground color. |
label | Built-in label size, truncation, and foreground color. |
The theme combines size, resolved active state, and automatic iconOnly detection.
| Size | Target | Icon |
|---|---|---|
sm | 40px | 16px |
md | 44px | 20px |
lg | 56px | 24px |
xl | 64px | 28px |
Inactive buttons are transparent with slate foregrounds and a pressed background. Active buttons use a subtle dark surface and stronger foreground. Disabled buttons reduce opacity. The default theme is light-mode-oriented.
Accessibility
The underlying @vyui/core button exposes native Lynx button semantics, blocks interaction when disabled, and announces disabled state. Pass accessibility-label for every icon-only button; attributes fall through to the underlying button root.
The active visual state does not currently add a pressed, selected, or current accessibility state. Use visible labels where possible, provide surrounding context for navigation state, and test value-driven island navigation with VoiceOver and TalkBack. Custom default content should retain a concise accessible name.
Platform notes
- Interaction uses Lynx
tap, exposed as Vue's@tap, rather than relying on a DOM click event. - Lynx SVG does not inherit
currentColor. The built-in icon resolves supportedtext-{color}-{shade},text-white, andtext-blackclasses into an explicit icon color. - Arbitrary foreground classes such as
text-[#abc]cannot be inferred for the built-in SVG; use a customleadingslot and explicit icon color when needed. - Foreground classes live on
leadingIconandlabel, not only onbase, because CSS inheritance is disabled in the Lynx build.
Related components
Islandfor parent state, sizing, row modes, and expandable panels.Island Groupfor arranging companion islands.Buttonfor a general-purpose action outside island layouts.Togglewhen the pressed state itself is the control's value.