[WEB-4687] feat: propel switch (#7629)

* feat: added switch

* fix: lint

* fix: lock file

* fix: improve accessibility and refactor switch component styles

* feat: add switch component to propel package

* fix: update imports in command component for consistency

* refactor: styles
This commit is contained in:
Jayash Tripathy 2025-08-23 00:27:31 +05:30 committed by GitHub
parent d3b26996dd
commit cf8eeee03a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 189 additions and 51 deletions

View file

@ -22,7 +22,8 @@
"./command": "./src/command/index.ts",
"./combobox": "./src/combobox/index.ts",
"./tooltip": "./src/tooltip/index.ts",
"./styles/fonts": "./src/styles/fonts/index.css"
"./styles/fonts": "./src/styles/fonts/index.css",
"./switch": "./src/switch/index.ts"
},
"dependencies": {
"@base-ui-components/react": "^1.0.0-beta.2",

View file

@ -1,7 +1,7 @@
import * as React from "react";
import { cn } from "@plane/utils";
import { Command } from "../command/command";
import { Popover } from "../popover/root";
import { cn } from "@plane/utils";
export interface ComboboxOption {
value: unknown;

View file

@ -1,7 +1,7 @@
import { Command as CommandPrimitive } from "cmdk";
import { SearchIcon } from "lucide-react";
import * as React from "react";
import { cn } from "@plane/ui";
import { cn } from "@plane/utils";
function CommandComponent({ className, ...props }: React.ComponentProps<typeof CommandPrimitive>) {
return <CommandPrimitive data-slot="command" className={cn("", className)} {...props} />;

View file

@ -0,0 +1 @@
export * from "./root";

View file

@ -0,0 +1,57 @@
import * as React from "react";
import { Switch as BaseSwitch } from "@base-ui-components/react/switch";
import { cn } from "@plane/utils";
interface IToggleSwitchProps {
value: boolean;
onChange: (value: boolean) => void;
label?: string;
size?: "sm" | "md" | "lg";
disabled?: boolean;
className?: string;
}
const Switch: React.FC<IToggleSwitchProps> = ({ value, onChange, label, size = "sm", disabled, className }) => (
<BaseSwitch.Root
checked={value}
disabled={disabled}
onCheckedChange={onChange}
aria-label={label}
className={cn(
"relative inline-flex flex-shrink-0 cursor-pointer rounded-full border border-custom-border-200 transition-colors duration-200 ease-in-out focus:outline-none",
// size
size === "sm" ? "h-4 w-6" : size === "md" ? "h-5 w-8" : "h-6 w-10",
// state
disabled
? "cursor-not-allowed bg-custom-background-80"
: value
? "cursor-pointer bg-custom-primary-100"
: "cursor-pointer bg-custom-background-90",
className
)}
>
{label && <span className="sr-only">{label}</span>}
<BaseSwitch.Thumb
aria-hidden="true"
className={cn(
"inline-block self-center rounded-full shadow ring-0 transition-transform duration-200 ease-in-out",
// size
size === "sm" ? "h-3 w-3" : size === "md" ? "h-4 w-4" : "h-5 w-5",
// position + color by state
value
? size === "sm"
? "translate-x-3 bg-white"
: size === "md"
? "translate-x-4 bg-white"
: "translate-x-5 bg-white"
: "translate-x-0.5 bg-custom-background-90",
// disabled
disabled && "cursor-not-allowed bg-custom-background-90"
)}
/>
</BaseSwitch.Root>
);
Switch.displayName = "plane-ui-switch";
export { Switch };