Files
WRNexusJS/packages/ui/components/ButtonGroup.wrn
T

124 lines
3.7 KiB
Plaintext

component ButtonGroup {
outputs {
click(payload: { sourceEvent?: Event; [key: string]: string | number | boolean | null | object })
select(payload: { value: string | number | boolean | null | object; previousValue: string | number | boolean | null | object; item: string | number | boolean | null | object; index: number })
change(payload: { value: string | number | boolean | null | object; previousValue: string | number | boolean | null | object; item: string | number | boolean | null | object; index: number })
}
props {
items: unknown[] = []
value: string = ""
size: string = "md"
color: string = "primary"
variant: string = "default"
orientation: string = "horizontal"
responsive: boolean = false
attached: boolean = true
selectable: boolean = false
toolbar: boolean = false
disabled: boolean = false
ariaLabel: string = "Button group"
class: string = ""
}
state selectedValue = value
functions {
shared function itemValue(item, index) {
return item.value || item.label || String(index)
}
client function selectItem(item, index) {
previousValue = selectedValue
nextValue = itemValue(item, index)
output.select({
value: nextValue,
previousValue: previousValue,
item: item,
index: index
})
if (selectable && previousValue !== nextValue) {
selectedValue = nextValue
output.change({
value: nextValue,
previousValue: previousValue,
item: item,
index: index
})
}
}
}
view {
<div
{...attrs}
class="wire-next wire-next--button-group {class}"
role="{toolbar ? 'toolbar' : 'group'}"
aria-label="{ariaLabel}"
aria-orientation="{orientation}"
data-size="{size}"
data-color="{color}"
data-variant="{variant}"
data-orientation="{orientation}"
data-responsive="{responsive}"
data-attached="{attached}"
data-selectable="{selectable}"
data-disabled="{disabled}"
>
{#if items}
{#each items as item, index}
<button
type="{item.type || 'button'}"
class="wire-btn wire-btn--variant-{item.variant || variant} wire-btn--color-{item.color || color} wire-btn--size-{item.size || size}"
disabled="{disabled || item.disabled}"
aria-label="{item.ariaLabel || item.label}"
aria-pressed="{selectable ? (selectedValue === (item.value || item.label || String(index)) ? 'true' : 'false') : ''}"
data-value="{item.value || item.label || String(index)}"
data-selected="{selectable && selectedValue === (item.value || item.label || String(index)) ? 'true' : 'false'}"
@click="selectItem(item, index)"
>
{#if item.icon}
<span class="wire-btn__icon {item.icon}" aria-hidden="true"></span>
{/if}
<span class="wire-btn__label">{item.label}</span>
</button>
{/each}
{/if}
<slot />
</div>
}
style {
.wire-next--button-group {
display: inline-flex;
align-items: stretch;
width: fit-content;
max-width: 100%;
isolation: isolate;
}
.wire-next--button-group[data-orientation="vertical"] {
flex-direction: column;
}
.wire-next--button-group[data-attached="false"] {
gap: 0.5rem;
}
.wire-next--button-group[data-disabled="true"] {
cursor: not-allowed;
opacity: 0.6;
}
@media (max-width: 480px) {
.wire-next--button-group[data-responsive="true"] {
display: flex;
width: 100%;
flex-direction: column;
}
}
}
}