fix: prevent deselecting active option in booker layout toggle (#27748)

* fix: prevent deselecting active option in ToggleGroup

Radix UI's single-type ToggleGroup allows deselection by default,
calling onValueChange("") when the active item is clicked.

Fix by converting to controlled mode with proper dual-mode support:
- Controlled (value prop): parent owns state, component just filters
  empty values from onValueChange. Parent can still reject changes.
- Uncontrolled (defaultValue prop): internal useState prevents
  deselection by only updating state for non-empty values.

* Update ToggleGroup.tsx

---------

Co-authored-by: Sahitya Chandra <sahityajb@gmail.com>
Co-authored-by: Eunjae Lee <hey@eunjae.dev>
This commit is contained in:
Ahmad Yasser
2026-02-20 10:41:54 +00:00
committed by GitHub
co-authored by Sahitya Chandra Eunjae Lee
parent 14c151be76
commit a2b25fa615
@@ -1,5 +1,6 @@
import * as RadixToggleGroup from "@radix-ui/react-toggle-group";
import type { ReactNode } from "react";
import { useState } from "react";
import classNames from "@calcom/ui/classNames";
@@ -42,15 +43,26 @@ export const ToggleGroup = ({
isFullWidth,
orientation = "horizontal",
customClassNames,
defaultValue,
...props
}: ToggleGroupProps & { customClassNames?: string }) => {
const isControlled = props.value !== undefined;
const [uncontrolledValue, setUncontrolledValue] = useState(defaultValue ?? "");
return (
<>
<RadixToggleGroup.Root
type="single"
{...props}
{...(isControlled ? { value: props.value } : { value: uncontrolledValue })}
orientation={orientation}
onValueChange={onValueChange}
onValueChange={(value) => {
if (!value) return;
if (!isControlled) {
setUncontrolledValue(value);
}
onValueChange?.(value);
}}
style={{
// @ts-expect-error --toggle-group-shadow is not a valid CSS property but can be a variable
"--toggle-group-shadow":