Enhanced various settings components by adding 'min-w-0' class for better overflow handling and adjusting flex properties for improved alignment. Updated card and grid structures to ensure a cohesive user experience across the settings interface. Refined descriptions and layout in several settings tabs for better clarity and usability.
105 lines
2.6 KiB
TypeScript
105 lines
2.6 KiB
TypeScript
import { type ReactNode } from 'react'
|
|
|
|
import { cn } from '@evobgp/ui/lib/utils'
|
|
import {
|
|
Field,
|
|
FieldContent,
|
|
FieldDescription,
|
|
FieldLabel,
|
|
FieldSeparator,
|
|
FieldTitle,
|
|
} from '@evobgp/ui/components/field'
|
|
|
|
export interface SettingRowProps {
|
|
title: string
|
|
description?: ReactNode
|
|
children: ReactNode
|
|
last?: boolean
|
|
/** Opt-in FieldSeparator after the row (default off — ReUI settings use Frame+gap). */
|
|
separated?: boolean
|
|
compact?: boolean
|
|
stacked?: boolean
|
|
labelFor?: string
|
|
contentClassName?: string
|
|
className?: string
|
|
titleAddon?: ReactNode
|
|
}
|
|
|
|
/**
|
|
* Settings row — settings-3 / settings-16 DNA.
|
|
* Control is flex-1 + min-w-0 (never a fixed w-78) so label and input do not overlap.
|
|
* @see https://reui.io/preview/base/settings-3
|
|
* @see https://reui.io/preview/base/settings-16
|
|
*/
|
|
export function SettingRow({
|
|
title,
|
|
description,
|
|
children,
|
|
last,
|
|
separated = false,
|
|
compact,
|
|
stacked,
|
|
labelFor,
|
|
contentClassName,
|
|
className,
|
|
titleAddon,
|
|
}: SettingRowProps) {
|
|
return (
|
|
<>
|
|
<Field
|
|
orientation={stacked ? 'vertical' : 'responsive'}
|
|
className={cn(
|
|
'min-w-0 gap-4 px-5 py-3.5',
|
|
!stacked &&
|
|
'@md/field-group:items-start @md/field-group:*:min-w-0 @md/field-group:*:max-w-full',
|
|
!last && !separated && 'border-border/40 border-b',
|
|
className,
|
|
)}
|
|
>
|
|
<div
|
|
className={cn(
|
|
'flex min-w-0 flex-1 flex-col gap-0.5',
|
|
!stacked && '@md/field-group:max-w-sm',
|
|
)}
|
|
>
|
|
<div className="flex min-w-0 flex-wrap items-center gap-2">
|
|
{labelFor ? (
|
|
<FieldLabel htmlFor={labelFor}>{title}</FieldLabel>
|
|
) : (
|
|
<FieldTitle>{title}</FieldTitle>
|
|
)}
|
|
{titleAddon}
|
|
</div>
|
|
|
|
{description ? (
|
|
<FieldDescription className="text-sm break-words">{description}</FieldDescription>
|
|
) : null}
|
|
</div>
|
|
|
|
<FieldContent
|
|
className={cn(
|
|
'w-full min-w-0 @md/field-group:flex-1',
|
|
stacked
|
|
? 'max-w-none'
|
|
: compact
|
|
? '@md/field-group:max-w-[17rem] @md/field-group:shrink-0'
|
|
: '@md/field-group:max-w-[min(100%,34rem)]',
|
|
contentClassName,
|
|
)}
|
|
>
|
|
<div
|
|
className={cn(
|
|
'flex w-full min-w-0 justify-start',
|
|
stacked ? 'justify-start' : '@md/field-group:justify-end',
|
|
)}
|
|
>
|
|
{children}
|
|
</div>
|
|
</FieldContent>
|
|
</Field>
|
|
|
|
{separated && !last ? <FieldSeparator /> : null}
|
|
</>
|
|
)
|
|
}
|