Buttons and inputs
Every control a Twilight Moon screen uses to collect a value from the player or staff: buttons, text fields, selects, toggles, sliders, pickers, knobs and faders. All of them use v-model and follow the server's theme.
KButton
The standard button, with seven variants, four sizes, optional icons and a built in busy state.
A button with no label and no default slot content renders as a square icon button.
| Prop | Type | Default | Description |
|---|---|---|---|
label | string | none | Button text. The default slot replaces it. |
icon | string | none | Icon before the text, for example lucide:save. |
iconRight | string | none | Icon after the text. |
variant | 'primary' | 'secondary' | 'ghost' | 'danger' | 'success' | 'warning' | 'subtle-danger' | 'secondary' | Visual style. |
size | 'xs' | 'sm' | 'md' | 'lg' | 'md' | Height and text size. |
block | boolean | false | Stretch to the full width of the parent. |
align | 'center' | 'start' | 'center' | Content alignment. start only applies together with block. |
disabled | boolean | false | Blocks clicks and dims the button. |
loading | boolean | false | Shows a spinner and blocks clicks. |
active | boolean | false | Shows the pressed look, for toggle style buttons. |
title | string | none | Native tooltip, useful on icon only buttons. |
action | () => unknown | none | Async handler. The button shows a spinner and ignores clicks until the returned promise settles. When set, the click event is not emitted. |
Events: click (the mouse event). Slots: default (replaces label).
<KButton variant="primary" icon="lucide:save" label="Save" @click="save" />
<KButton :action="submitReport" label="Submit" />
<KButton icon="lucide:x" title="Close" variant="ghost" @click="close" />KInput
A single line text, number or password field with label, hint, error text and optional icon, prefix and suffix.
| Prop | Type | Default | Description |
|---|---|---|---|
modelValue | string | number | null | none | The value. Number inputs emit null when empty. |
label | string | none | Label above the field. |
hint | string | none | Help text under the field. |
error | string | none | Error text under the field, with a red ring. |
invalid | boolean | false | Red ring without a message, for compact rows (pair it with a KTooltip). |
placeholder | string | none | Placeholder text. |
type | 'text' | 'number' | 'password' | 'text' | Input type. |
autocomplete | string | none | Passed to the input element. |
icon | string | none | Icon inside the field. |
prefix | string | none | Fixed text before the value. |
suffix | string | none | Fixed text after the value. |
min | number | none | Minimum, for number inputs. |
max | number | none | Maximum, for number inputs. |
step | number | string | none | Step, for number inputs. |
size | 'sm' | 'md' | 'md' | Field height. |
clearable | boolean | false | Shows a clear button when the field has a value. |
disabled | boolean | false | Disables the field. |
required | boolean | false | Marks the field as required. |
autofocus | boolean | false | Focuses the field when it mounts. |
mono | boolean | false | Monospace font, for codes and plates. |
Events: update:modelValue, enter (Enter key pressed). Exposed: focus().
<KInput v-model="name" label="Full name" icon="lucide:user" clearable @enter="submit" />
<KInput v-model="amount" type="number" prefix="$" :min="0" :step="50" />KTextarea
A multi line text field with label, hint and error text.
| Prop | Type | Default | Description |
|---|---|---|---|
modelValue | string | null | none | The text. |
label | string | none | Label above the field. |
hint | string | none | Help text under the field. |
error | string | none | Error text under the field. |
placeholder | string | none | Placeholder text. |
rows | number | 3 | Visible rows. |
mono | boolean | false | Monospace font. |
disabled | boolean | false | Disables the field. |
readonly | boolean | false | Shows the text but blocks edits. |
Events: update:modelValue.
<KTextarea v-model="notes" label="Case notes" :rows="4" />KSelect
A dropdown for picking one option. It gets a search box automatically when there are more than 8 options.
The SelectOption type is exported from the kit:
interface SelectOption {
label: string
value: string | number
icon?: string
description?: string
disabled?: boolean
}| Prop | Type | Default | Description |
|---|---|---|---|
modelValue | string | number | null | none | The selected option's value. |
options | SelectOption[] | required | The choices. |
label | string | none | Label above the field. |
hint | string | none | Help text under the field. |
placeholder | string | none | Text shown when nothing is selected. |
emptyText | string | none | Text shown when a search matches nothing. |
clearable | boolean | false | Adds an option to clear the selection. |
searchable | boolean | automatic | Show the search box. On by default when there are more than 8 options. |
disabled | boolean | false | Disables the select. |
size | 'sm' | 'md' | 'md' | Field height. |
Events: update:modelValue, change (fires with the new value when the player picks an option).
<script setup lang="ts">
import { KSelect, type SelectOption } from '@/kit'
const options: SelectOption[] = [
{ label: 'Police', value: 'police', icon: 'lucide:shield' },
{ label: 'Mechanic', value: 'mechanic', icon: 'lucide:wrench' }
]
</script>
<template>
<KSelect v-model="job" :options="options" label="Job" clearable @change="onJob" />
</template>KCheckbox
A small checkbox for table rows, bulk selection and permission grids. For a labeled on/off setting use KToggle instead.
| Prop | Type | Default | Description |
|---|---|---|---|
modelValue | boolean | required | Checked state. |
indeterminate | boolean | false | Shows a dash while the box is off, for a "some selected" header box. |
disabled | boolean | false | Disables the box. |
Events: update:modelValue. Clicks do not bubble, so a checkbox can sit inside a clickable row.
<KCheckbox :model-value="allSelected" :indeterminate="someSelected" @update:model-value="selectAll" />
<KCheckbox v-model="row.selected" />KToggle
A switch for an on/off setting, with an optional label and description.
| Prop | Type | Default | Description |
|---|---|---|---|
modelValue | boolean | required | On or off. |
label | string | none | Text next to the switch. |
description | string | none | Smaller help text under the label. |
disabled | boolean | false | Disables the switch. |
boxed | boolean | false | Wraps the switch in a bordered card. |
Events: update:modelValue.
<KToggle v-model="duty" label="On duty" description="Appear in the dispatch list" />KSlider
A range slider with a colored fill track and a live value readout.
Tones are neutral, blue, green, red, amber, violet and teal.
| Prop | Type | Default | Description |
|---|---|---|---|
modelValue | number | required | Current value. |
min | number | 0 | Lowest value. |
max | number | 100 | Highest value. |
step | number | 1 | Increment. Decimals in the step set the readout precision. |
label | string | none | Label above the track. |
icon | string | none | Icon next to the label. |
hint | string | none | Help text under the track. |
suffix | string | none | Unit appended to the readout, for example %. |
origin | number | none | Fill from this value instead of the left end (for a slider that runs from -1 to 1, fill from 0). |
tone | Tone | 'blue' | Fill color. |
disabled | boolean | false | Disables the slider. |
showValue | boolean | true | Show the numeric readout. |
Events: update:modelValue (fires on every change while dragging).
<KSlider v-model="volume" label="Volume" icon="lucide:volume-2" suffix="%" />
<KSlider v-model="balance" :min="-1" :max="1" :step="0.1" :origin="0" />KSegmented
A row of buttons where exactly one option is selected, for short lists like view modes or tabs inside a form.
| Prop | Type | Default | Description |
|---|---|---|---|
modelValue | string | number | boolean | null | required | The selected option's value. |
options | Array<{ label: string, value: string | number | boolean, icon?: string, disabled?: boolean }> | required | The choices. |
label | string | none | Label above the control. |
hint | string | none | Help text under the control. |
size | 'sm' | 'md' | 'md' | Control height. |
block | boolean | false | Stretch to the full width of the parent. |
disabled | boolean | false | Disables every option. |
Events: update:modelValue.
<KSegmented
v-model="view"
:options="[
{ label: 'Grid', value: 'grid', icon: 'lucide:layout-grid' },
{ label: 'List', value: 'list', icon: 'lucide:list' }
]"
/>KChips
A set of toggleable chips for picking several values. It adds All and None buttons, and a filter box when there are more than 12 options.
| Prop | Type | Default | Description |
|---|---|---|---|
modelValue | Array<string | number> | required | The selected values. |
options | Array<{ label: string, value: string | number, icon?: string }> | required | The available chips. |
label | string | none | Label above the chips. |
hint | string | none | Help text under the chips. |
disabled | boolean | false | Disables every chip. |
searchable | boolean | automatic | Show the filter box. On by default when there are more than 12 options. |
Events: update:modelValue. All and None act only on the chips currently visible, so a filter narrows them.
<KChips v-model="days" :options="dayOptions" label="Active days" />KDatePicker
A calendar popup that edits a plain YYYY-MM-DD string. It draws its own calendar because the browser's native date popup does not open reliably in the game's interface.
| Prop | Type | Default | Description |
|---|---|---|---|
modelValue | string | '' | The date as YYYY-MM-DD, or an empty string. |
label | string | none | Label above the field. |
hint | string | none | Help text under the field. |
error | string | none | Error text under the field. |
placeholder | string | none | Text shown when empty. |
clearable | boolean | false | Adds a clear button. |
disabled | boolean | false | Disables the field. |
size | 'sm' | 'md' | 'md' | Field height. |
min | string | none | Earliest pickable day, YYYY-MM-DD. |
max | string | none | Latest pickable day, YYYY-MM-DD. |
weekStart | 0 | 1 | 0 | First day of the week: 0 is Sunday, 1 is Monday. |
Events: update:modelValue, change (both fire with the new date string).
<KDatePicker v-model="born" label="Date of birth" :week-start="1" max="2026-12-31" clearable />KColorPicker
A color field with a saturation pad, hue slider, hex and RGB entry, quick swatches and optional opacity.
| Prop | Type | Default | Description |
|---|---|---|---|
modelValue | string | null | none | #rrggbb, or #rrggbbaa when alpha is on. Anything else counts as no color. |
label | string | none | Label above the field. |
hint | string | none | Help text under the field. |
placeholder | string | none | Text shown when there is no color. |
alpha | boolean | false | Adds an opacity slider. The value gains two digits while opacity is below 100%. |
swatches | string[] | 12 common colors | Quick pick colors under the pad. |
clearable | boolean | false | Adds a clear button. |
disabled | boolean | false | Disables the field. |
size | 'sm' | 'md' | 'md' | Field height. |
Events: update:modelValue (fires live while dragging), change (fires once when a pick is committed, so bind to it for anything expensive), clear.
<KColorPicker v-model="accent" label="Accent color" alpha clearable @change="saveColor" />KKnob
A rotary knob. Drag up or down (hold Shift for fine steps), use the mouse wheel or arrow keys, and double click to reset.
| Prop | Type | Default | Description |
|---|---|---|---|
modelValue | number | required | Current value. |
min | number | 0 | Lowest value. |
max | number | 100 | Highest value. |
step | number | 1 | Increment. |
origin | number | min | Where the arc starts. A bipolar knob fills out from its center. |
defaultValue | number | origin | Value restored by double click and the Home key. |
label | string | none | Label under the knob. |
suffix | string | none | Unit appended to the readout. |
display | string | none | Replaces the value readout (for example KILL). |
tone | Tone | 'violet' | Arc color. |
size | 'sm' | 'md' | 'lg' | 'md' | Knob size. |
disabled | boolean | false | Disables the knob. |
showValue | boolean | true | Show the readout. |
sensitivity | number | 170 | Pixels of drag for the full range. |
Events: update:modelValue (fires on every change while dragging, so debounce upstream when each change costs a network message).
<KKnob v-model="pan" label="Pan" :min="-50" :max="50" :origin="0" tone="teal" />KFader
A vertical or horizontal fader for volume, pitch or a crossfader. Drag or click the track, use the mouse wheel or arrow keys, and double click to reset.
| Prop | Type | Default | Description |
|---|---|---|---|
modelValue | number | required | Current value. |
min | number | 0 | Lowest value. |
max | number | 100 | Highest value. |
step | number | 1 | Increment. |
orientation | 'vertical' | 'horizontal' | 'vertical' | Direction of the track. |
length | number | 130 | Track length in pixels. |
origin | number | min | Where the fill starts. |
detent | boolean | false | Draw a tick at origin, for a bipolar fader. |
invert | boolean | false | Vertical only: puts max at the bottom instead of the top (a pitch fader with plus at the bottom). |
defaultValue | number | origin | Value restored by double click and the Home key. |
label | string | none | Label next to the fader. |
suffix | string | none | Unit appended to the readout. |
display | string | none | Replaces the value readout. |
tone | Tone | 'violet' | Fill color. |
disabled | boolean | false | Disables the fader. |
showValue | boolean | true | Show the readout. |
Events: update:modelValue (fires on every change while dragging, so debounce upstream when each change costs a network message).
<KFader v-model="level" label="Level" suffix="%" />
<KFader v-model="cross" orientation="horizontal" :min="-100" :max="100" :origin="0" detent :length="260" />