jedmund-svelte/src/lib/components/admin/SegmentedControlField.svelte
Justin Edmund 05ddafcdea refactor: merge FormField and FormFieldWrapper components
- Add children prop to FormField to support wrapper mode
- Update components using FormFieldWrapper to use FormField
- Remove redundant FormFieldWrapper component
- Maintain all existing functionality with unified API

This reduces code duplication and simplifies the form component hierarchy.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-06-25 22:14:10 -04:00

110 lines
2 KiB
Svelte

<script lang="ts">
import FormField from './FormField.svelte'
interface Option {
value: string
label: string
}
interface Props {
label: string
options: Option[]
value?: string
required?: boolean
helpText?: string
error?: string
fullWidth?: boolean
}
let {
label,
options,
value = $bindable(),
required = false,
helpText,
error,
fullWidth = true
}: Props = $props()
function handleChange(newValue: string) {
value = newValue
}
</script>
<FormField {label} {required} {helpText} {error}>
{#snippet children()}
<div class="segmented-control-wrapper" class:full-width={fullWidth}>
<div class="segmented-control">
{#each options as option}
<button
type="button"
class="segment"
class:active={value === option.value}
onclick={() => handleChange(option.value)}
>
{option.label}
</button>
{/each}
</div>
</div>
{/snippet}
</FormField>
<style lang="scss">
.segmented-control-wrapper {
&.full-width {
width: 100%;
}
}
.segmented-control {
display: inline-flex;
background-color: $input-background-color;
border-radius: $corner-radius-full;
padding: 3px;
gap: 2px;
width: 100%;
// Match medium input height: padding (12px * 2) + font line-height (~20px) + padding for container (3px * 2)
height: 50px;
box-sizing: border-box;
}
.segment {
flex: 1;
padding: 0 $unit-2x;
background: transparent;
border: none;
border-radius: $corner-radius-full;
font-size: 1rem;
font-weight: 500;
color: $input-text-color;
cursor: pointer;
transition: all 0.15s ease;
white-space: nowrap;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
&:hover:not(.active) {
color: $input-text-color-hover;
background-color: rgba(0, 0, 0, 0.03);
}
&.active {
background-color: white;
color: $gray-10;
box-shadow:
0 1px 3px rgba(0, 0, 0, 0.08),
0 1px 2px rgba(0, 0, 0, 0.04);
}
&:focus {
outline: none;
}
&:focus-visible {
box-shadow: 0 0 0 2px $primary-color;
}
}
</style>