Files
netbird/client/ui/frontend/src/components/switches/SwitchItemGroup.tsx
T
Eduard GertandEdward f5707c3485 [client] Add RTL layout support to the desktop UI (#8076)
* [client] Add RTL layout support to the desktop UI

<html dir> follows the active language, Radix primitives get the
matching dir, physical spacing/positioning uses logical utilities, and
directional icons, animations, arrow-key navigation and tooltip sides
flip in RTL.

* [client] Address RTL review feedback

Force LTR with isolation for monospace values, let truncated names
take their direction from their content, and keep the profile name
field in the UI direction.

* [client] Keep translated monospace labels in their own direction

The forced-LTR rule for monospace values now skips elements with an
explicit dir, translated development labels use dir=auto, and
monospace values rendered through TruncatedText opt into LTR.

---------

Co-authored-by: Edward <43848523+thomashacker@users.noreply.github.com>
2026-10-06 12:08:11 +02:00

64 lines
1.8 KiB
TypeScript

import * as RadioGroup from "@radix-ui/react-radio-group";
import { createContext, type ReactNode, useContext, useId, useMemo } from "react";
import { cn } from "@/lib/cn";
import { useDirection } from "@/hooks/useDirection";
type SwitchItemGroupContextValue = {
value: string;
layoutId: string;
};
const SwitchItemGroupContext = createContext<SwitchItemGroupContextValue | null>(null);
export const useSwitchItemGroup = () => {
const ctx = useContext(SwitchItemGroupContext);
if (!ctx) {
throw new Error("SwitchItem must be used inside a SwitchItemGroup");
}
return ctx;
};
type Props = {
value: string;
onChange: (value: string) => void;
children: ReactNode;
className?: string;
disabled?: boolean;
"aria-label"?: string;
"aria-labelledby"?: string;
};
export const SwitchItemGroup = ({
value,
onChange,
children,
className,
disabled = false,
"aria-label": ariaLabel,
"aria-labelledby": ariaLabelledBy,
}: Props) => {
const layoutId = useId();
const dir = useDirection();
const contextValue = useMemo(() => ({ value, layoutId }), [value, layoutId]);
return (
<SwitchItemGroupContext.Provider value={contextValue}>
<RadioGroup.Root
dir={dir}
value={value}
onValueChange={onChange}
disabled={disabled}
aria-label={ariaLabel}
aria-labelledby={ariaLabelledBy}
className={cn(
"flex shrink-0 overflow-hidden rounded-lg border border-nb-gray-800 bg-nb-gray-910 p-1 dark:border-nb-gray-850",
disabled && "pointer-events-none opacity-50",
className,
)}
>
{children}
</RadioGroup.Root>
</SwitchItemGroupContext.Provider>
);
};