feat: add ToggleGroup support for labeled boolean widgets

This commit is contained in:
Csongor Czezar
2025-12-30 14:52:38 -08:00
parent 795962f3c3
commit 035a0f250c
10 changed files with 411 additions and 118 deletions

View File

@@ -1,13 +1,30 @@
<template>
<WidgetLayoutField :widget>
<div v-if="currentLabel" class="ml-auto flex items-center gap-2">
<ToggleSwitch
v-model="modelValue"
v-bind="filteredProps"
:aria-label="widget.name"
/>
<span class="text-sm">{{ currentLabel }}</span>
</div>
<WidgetLayoutField :widget="widgetWithStyle">
<!-- Use ToggleGroup when explicit labels are provided -->
<ToggleGroup
v-if="hasLabels"
type="single"
:model-value="toggleGroupValue"
class="ml-auto gap-0 bg-node-component-surface"
@update:model-value="handleToggleGroupChange"
>
<ToggleGroupItem
value="off"
:aria-label="`${widget.name}: ${labelOff}`"
class="rounded-l-md rounded-r-none border-0 bg-transparent text-node-component-text data-[state=on]:!bg-white data-[state=on]:!text-black hover:bg-node-component-border/20 cursor-pointer"
>
{{ labelOff }}
</ToggleGroupItem>
<ToggleGroupItem
value="on"
:aria-label="`${widget.name}: ${labelOn}`"
class="rounded-l-none rounded-r-md border-0 bg-transparent text-node-component-text data-[state=on]:!bg-white data-[state=on]:!text-black hover:bg-node-component-border/20 cursor-pointer"
>
{{ labelOn }}
</ToggleGroupItem>
</ToggleGroup>
<!-- Use ToggleSwitch for implicit boolean states -->
<ToggleSwitch
v-else
v-model="modelValue"
@@ -22,6 +39,7 @@
import ToggleSwitch from 'primevue/toggleswitch'
import { computed } from 'vue'
import { ToggleGroup, ToggleGroupItem } from '@/components/ui/toggle-group'
import type { SimplifiedWidget } from '@/types/simplifiedWidget'
import {
STANDARD_EXCLUDED_PROPS,
@@ -33,7 +51,7 @@ import WidgetLayoutField from './layout/WidgetLayoutField.vue'
interface BooleanWidgetOptions {
on?: string
off?: string
[key: string]: any
[key: string]: unknown
}
const { widget } = defineProps<{
@@ -46,9 +64,30 @@ const filteredProps = computed(() =>
filterWidgetProps(widget.options, STANDARD_EXCLUDED_PROPS)
)
const currentLabel = computed(() => {
return modelValue.value
? (widget.options?.on ?? (widget.options?.off ? 'true' : undefined))
: (widget.options?.off ?? (widget.options?.on ? 'false' : undefined))
const hasLabels = computed(() => {
return !!(widget.options?.on || widget.options?.off)
})
const labelOn = computed(() => widget.options?.on ?? 'true')
const labelOff = computed(() => widget.options?.off ?? 'false')
const toggleGroupValue = computed(() => {
return modelValue.value ? 'on' : 'off'
})
const handleToggleGroupChange = (value: unknown) => {
if (value === 'on') {
modelValue.value = true
} else if (value === 'off') {
modelValue.value = false
}
}
// Override WidgetLayoutField styling when using ToggleGroup
const widgetWithStyle = computed(() => ({
...widget,
borderStyle: hasLabels.value
? 'focus-within:!ring-0 !bg-transparent !rounded-none focus-within:!outline-none'
: undefined
}))
</script>