79 lines
2.1 KiB
TypeScript
79 lines
2.1 KiB
TypeScript
// components/ui/LabeledSwitch.tsx
|
|
'use client'
|
|
|
|
import * as React from 'react'
|
|
import clsx from 'clsx'
|
|
import Switch, { type SwitchProps } from './Switch'
|
|
|
|
type Props = Omit<SwitchProps, 'ariaLabelledby' | 'ariaDescribedby' | 'ariaLabel'> & {
|
|
label: React.ReactNode
|
|
description?: React.ReactNode
|
|
|
|
/** "left" = Label links / Switch rechts (wie Beispiel) */
|
|
labelPosition?: 'left' | 'right'
|
|
/** Layout wrapper classes */
|
|
className?: string
|
|
}
|
|
|
|
export default function LabeledSwitch({
|
|
label,
|
|
description,
|
|
labelPosition = 'left',
|
|
id,
|
|
className,
|
|
...switchProps
|
|
}: Props) {
|
|
const reactId = React.useId()
|
|
const switchId = id ?? `sw-${reactId}`
|
|
const labelId = `${switchId}-label`
|
|
const descId = `${switchId}-desc`
|
|
|
|
if (labelPosition === 'right') {
|
|
// With right label Beispiel
|
|
return (
|
|
<div className={clsx('flex items-center justify-between gap-3', className)}>
|
|
<Switch
|
|
{...switchProps}
|
|
id={switchId}
|
|
ariaLabelledby={labelId}
|
|
ariaDescribedby={description ? descId : undefined}
|
|
/>
|
|
|
|
<div className="text-sm">
|
|
<label id={labelId} htmlFor={switchId} className="font-medium text-gray-900 dark:text-white">
|
|
{label}
|
|
</label>{' '}
|
|
{description ? (
|
|
<span id={descId} className="text-gray-500 dark:text-gray-400">
|
|
{description}
|
|
</span>
|
|
) : null}
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
// With left label and description Beispiel
|
|
return (
|
|
<div className={clsx('flex items-center justify-between', className)}>
|
|
<span className="flex grow flex-col">
|
|
<label id={labelId} htmlFor={switchId} className="text-sm/6 font-medium text-gray-900 dark:text-white">
|
|
{label}
|
|
</label>
|
|
{description ? (
|
|
<span id={descId} className="text-sm text-gray-500 dark:text-gray-400">
|
|
{description}
|
|
</span>
|
|
) : null}
|
|
</span>
|
|
|
|
<Switch
|
|
{...switchProps}
|
|
id={switchId}
|
|
ariaLabelledby={labelId}
|
|
ariaDescribedby={description ? descId : undefined}
|
|
/>
|
|
</div>
|
|
)
|
|
}
|