diff --git a/src/components/ui/boolean-toggle.tsx b/src/components/ui/boolean-toggle.tsx
new file mode 100644
index 0000000..369b2b8
--- /dev/null
+++ b/src/components/ui/boolean-toggle.tsx
@@ -0,0 +1,77 @@
+"use client";
+
+import { useId, useState } from "react";
+import { cn } from "@/lib/utils";
+
+interface BooleanToggleProps {
+ id?: string;
+ name?: string;
+ value?: boolean;
+ defaultValue?: boolean;
+ onChange?: (value: boolean) => void;
+ trueLabel?: string;
+ falseLabel?: string;
+ ariaLabel?: string;
+ className?: string;
+ disabled?: boolean;
+}
+
+export function BooleanToggle({
+ id,
+ name,
+ value,
+ defaultValue = false,
+ onChange,
+ trueLabel = "开启",
+ falseLabel = "关闭",
+ ariaLabel,
+ className,
+ disabled = false,
+}: BooleanToggleProps) {
+ const generatedId = useId();
+ const inputId = id ?? generatedId;
+ const controlled = value != null;
+ const [internalValue, setInternalValue] = useState(defaultValue);
+ const currentValue = controlled ? value : internalValue;
+
+ function select(nextValue: boolean) {
+ if (disabled) return;
+ if (!controlled) setInternalValue(nextValue);
+ onChange?.(nextValue);
+ }
+
+ return (
+
+ {name &&
}
+
+ {[
+ { value: true, label: trueLabel },
+ { value: false, label: falseLabel },
+ ].map((option) => {
+ const active = currentValue === option.value;
+ return (
+
+ );
+ })}
+
+
+ );
+}
diff --git a/src/components/ui/switch.tsx b/src/components/ui/switch.tsx
deleted file mode 100644
index 9b8b44b..0000000
--- a/src/components/ui/switch.tsx
+++ /dev/null
@@ -1,32 +0,0 @@
-"use client"
-
-import { Switch as SwitchPrimitive } from "@base-ui/react/switch"
-
-import { cn } from "@/lib/utils"
-
-function Switch({
- className,
- size = "default",
- ...props
-}: SwitchPrimitive.Root.Props & {
- size?: "sm" | "default"
-}) {
- return (
-
-
-
- )
-}
-
-export { Switch }