nsfwapp/frontend/src/components/ui/LabeledSwitch.tsx
2025-12-19 23:06:40 +01:00

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>
)
}