Skip to content

Commit

Permalink
refactor(component: switch): make Switch component self-dependent by …
Browse files Browse the repository at this point in the history
…removing @radix-ui/react-switch dependency

Fixes #63

Refactor the `Switch` component to be self-contained and remove dependency on `@radix-ui/react-switch`.

* **Switch Component**:
  - Remove import statement for `@radix-ui/react-switch`.
  - Update the `Switch` component to be self-contained with its own state management and event handling.
  - Update the `Switch` component's props to include `checked` and `onCheckedChange`.

* **Documentation**:
  - Update the documentation in `apps/www/content/docs/components/switch.mdx` to reference the self-contained `Switch` component.
  - Add a new props table to the documentation to reflect the updated `Switch` component's props.

* **Dependencies**:
  - Remove `@radix-ui/react-switch` from `packages/ui/package.json`.
  - Update `pnpm-lock.yaml` to remove references to `@radix-ui/react-switch`.

* **Registry**:
  - Update `apps/www/public/registry/index.json` and `apps/www/public/registry/components/switch.json` to remove the dependency on `@radix-ui/react-switch`.
  - Update `apps/www/registry/ui.ts` to remove the dependency on `@radix-ui/react-switch`.

---

For more details, open the [Copilot Workspace session](https://copilot-workspace.githubnext.com/ruru-m07/ruru-ui/issues/63?shareId=XXXX-XXXX-XXXX-XXXX).
  • Loading branch information
ruru-m07 committed Oct 20, 2024
1 parent 8c6833a commit 17fed7e
Show file tree
Hide file tree
Showing 7 changed files with 116 additions and 79 deletions.
27 changes: 13 additions & 14 deletions apps/www/content/docs/components/switch.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,7 @@ import SwiychEvent from "../../../components/SwitchEvent.tsx";
</Tab>
<Tab className={"-mt-8"} value="Code">
```tsx
// [!code word:Switch]
import { Switch } from "your-ui-library/components/switch";
import { Switch } from "ruru-ui/components/switch";

export function Demo() {
return <Switch />;
Expand All @@ -76,7 +75,7 @@ export function Demo() {
<Tab className={"-mt-8"} value="Code">
```tsx
// [!code word:disabled]
import { Switch } from "your-ui-library/components/switch";
import { Switch } from "ruru-ui/components/switch";

export function SwitchDemo() {
return <Switch disabled />;
Expand All @@ -86,13 +85,6 @@ export function SwitchDemo() {

</Tabs>

## Props

| Name | Type | Default | Description |
| ------------- | ------- | ------- | -------------------------------------- |
| **className** | **string** | `"" ` | Additional class names for the switch. |
| **disabled** | **boolean** | `false` | Flag to disable the switch. |

## Examples

### Switch with lables
Expand All @@ -107,9 +99,7 @@ export function SwitchDemo() {
<Tab className={"-mt-8"} value="Code">
```tsx
// [!code word:airplane-mode]
// [!code word:id]
// [!code word:htmlFor]
import { Switch } from "your-ui-library/components/switch";
import { Switch } from "ruru-ui/components/switch";

export function Demo() {
return (
Expand All @@ -134,7 +124,7 @@ export function Demo() {
<Tab className={"-mt-8"} value="Code">
```tsx
// [!code word:defaultChecked]
import { Switch } from "your-ui-library/components/switch";
import { Switch } from "ruru-ui/components/switch";

export function SwitchDemo() {
return <Switch defaultChecked />;
Expand Down Expand Up @@ -179,3 +169,12 @@ export default SwiychDemo;
</Tab>
</Tabs>

## Props

| Name | Type | Default | Description |
| ------------------- | ------------------------ | ----------- | ------------------------------------------------------------ |
| **className** | **string** | `"" ` | Additional class names for the switch. |
| **disabled** | **boolean** | `false` | Flag to disable the switch. |
| **id** | **string** | `""` | Id for the switch. |
| **defaultChecked** | **boolean** | `false` | Flag to set the switch to checked by default. |
| **onCheckedChange** | **(e: boolean) => void** | `undefined` | Callback function that is called when the switch is toggled. |
3 changes: 1 addition & 2 deletions apps/www/public/registry/components/switch.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
{
"name": "switch",
"dependencies": ["@radix-ui/react-switch"],
"files": [
{
"name": "switch.tsx",
"content": "import * as React from \"react\";\nimport * as SwitchPrimitives from \"@radix-ui/react-switch\";\n\nimport { cn } from \"@/utils/cn\";\n\nconst Switch = React.forwardRef<\n React.ElementRef<typeof SwitchPrimitives.Root>,\n React.ComponentPropsWithoutRef<typeof SwitchPrimitives.Root>\n>(({ className, ...props }, ref) => (\n <SwitchPrimitives.Root\n className={cn(\n \"peer inline-flex h-5 w-9 shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent shadow-sm transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary bg-accent data-[state=unchecked]:bg-input\",\n className,\n )}\n {...props}\n ref={ref}\n >\n <SwitchPrimitives.Thumb\n className={cn(\n \"pointer-events-none block h-4 w-4 rounded-full bg-background shadow-lg ring-0 transition-transform data-[state=checked]:translate-x-4 data-[state=unchecked]:translate-x-0\",\n )}\n />\n </SwitchPrimitives.Root>\n));\nSwitch.displayName = SwitchPrimitives.Root.displayName;\n\nexport { Switch };\n"
"content": "import * as React from \"react\";\nimport { cn } from \"@/utils/cn\";\n\ninterface SwitchProps extends React.ComponentPropsWithoutRef<\"button\"> {\n checked?: boolean;\n onCheckedChange?: (checked: boolean) => void;\n}\n\n\nconst Switch = React.forwardRef<HTMLButtonElement, SwitchProps>(\n ({ className, checked, onCheckedChange, ...props }, ref) => {\n const [isChecked, setIsChecked] = React.useState(checked || false);\n\n const handleClick = () => {\n const newChecked = !isChecked;\n setIsChecked(newChecked);\n if (onCheckedChange) {\n onCheckedChange(newChecked);\n }\n };\n\n return (\n <button\n type=\"button\"\n role=\"switch\"\n aria-checked={isChecked}\n className={cn(\n \"peer inline-flex h-5 w-9 shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent shadow-sm transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:cursor-not-allowed disabled:opacity-50\",\n isChecked ? \"bg-primary\" : \"bg-accent\",\n className\n )}\n onClick={handleClick}\n ref={ref}\n {...props}\n >\n <span\n className={cn(\n \"pointer-events-none block h-4 w-4 rounded-full bg-background shadow-lg ring-0 transition-transform\",\n isChecked ? \"translate-x-4\" : \"translate-x-0\"\n )}\n />\n </button>\n );\n }\n);\n\nSwitch.displayName = \"Switch\";\n\nexport { Switch };\n"
}
],
"type": "components:ui"
Expand Down
1 change: 0 additions & 1 deletion apps/www/public/registry/index.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@
},
{
"name": "switch",
"dependencies": ["@radix-ui/react-switch"],
"files": ["switch.tsx"],
"type": "components:ui"
},
Expand Down
1 change: 0 additions & 1 deletion apps/www/registry/ui.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@ export const ui: Registry = [
{
name: "switch",
type: "components:ui",
dependencies: ["@radix-ui/react-switch"],
files: ["switch.tsx"],
},
{
Expand Down
1 change: 0 additions & 1 deletion packages/ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,6 @@
"@radix-ui/react-icons": "^1.3.0",
"@radix-ui/react-select": "^2.1.1",
"@radix-ui/react-slot": "^1.1.0",
"@radix-ui/react-switch": "^1.1.0",
"@radix-ui/react-tabs": "^1.1.0",
"@radix-ui/react-tooltip": "^1.1.2",
"@swc/core": "^1.6.13",
Expand Down
70 changes: 47 additions & 23 deletions packages/ui/src/components/switch.tsx
Original file line number Diff line number Diff line change
@@ -1,38 +1,62 @@
import * as React from "react";
import * as SwitchPrimitives from "@radix-ui/react-switch";

import { cn } from "@/utils/cn";

interface SwitchProps extends React.ComponentPropsWithoutRef<"button"> {
checked?: boolean;
onCheckedChange?: (checked: boolean) => void;
}

/**
* Switch component
*
* @param {string} className - Additional class names for the switch.
* @param {React.Ref<React.ElementRef<typeof SwitchPrimitives.Root>>} ref - Forwarded ref.
* @param {boolean} checked - Whether the switch is checked.
* @param {(checked: boolean) => void} onCheckedChange - Callback when the switch is checked or unchecked.
* @param {React.Ref<HTMLButtonElement>} ref - Forwarded ref.
*
* @example
*
* ```tsx
* <Switch />
* ```
*/
const Switch = React.forwardRef<
React.ElementRef<typeof SwitchPrimitives.Root>,
React.ComponentPropsWithoutRef<typeof SwitchPrimitives.Root>
>(({ className, ...props }, ref) => (
<SwitchPrimitives.Root
className={cn(
"peer inline-flex h-5 w-9 shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent shadow-sm transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary bg-accent data-[state=unchecked]:bg-input",
className,
)}
{...props}
ref={ref}
>
<SwitchPrimitives.Thumb
className={cn(
"pointer-events-none block h-4 w-4 rounded-full bg-background shadow-lg ring-0 transition-transform data-[state=checked]:translate-x-4 data-[state=unchecked]:translate-x-0",
)}
/>
</SwitchPrimitives.Root>
));
Switch.displayName = SwitchPrimitives.Root.displayName;
const Switch = React.forwardRef<HTMLButtonElement, SwitchProps>(
({ className, checked, onCheckedChange, ...props }, ref) => {
const [isChecked, setIsChecked] = React.useState(checked || false);

const handleClick = () => {
const newChecked = !isChecked;
setIsChecked(newChecked);
if (onCheckedChange) {
onCheckedChange(newChecked);
}
};

return (
<button
type="button"
role="switch"
aria-checked={isChecked}
className={cn(
"peer inline-flex h-5 w-9 shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent shadow-sm transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:cursor-not-allowed disabled:opacity-50",
isChecked ? "bg-primary" : "bg-accent",
className
)}
onClick={handleClick}
ref={ref}
{...props}
>
<span
className={cn(
"pointer-events-none block h-4 w-4 rounded-full bg-background shadow-lg ring-0 transition-transform",
isChecked ? "translate-x-4" : "translate-x-0"
)}
/>
</button>
);
}
);

Switch.displayName = "Switch";

export { Switch };
Loading

0 comments on commit 17fed7e

Please sign in to comment.