From cb340c53a39917722137a8ee05b779af04a1203d Mon Sep 17 00:00:00 2001 From: MAZE Date: Thu, 13 Feb 2025 19:47:54 +0330 Subject: [PATCH] feat: add custom checkbox --- package-lock.json | 198 ++++++++++++++++++ package.json | 1 + src/components/checkbox/checkbox.module.css | 23 ++ src/components/checkbox/checkbox.tsx | 38 ++++ src/components/checkbox/index.ts | 1 + .../toolbox/todo/todos/todo/todo.module.css | 2 +- .../toolbox/todo/todos/todo/todo.tsx | 13 +- 7 files changed, 268 insertions(+), 8 deletions(-) create mode 100644 src/components/checkbox/checkbox.module.css create mode 100644 src/components/checkbox/checkbox.tsx create mode 100644 src/components/checkbox/index.ts diff --git a/package-lock.json b/package-lock.json index 4562c4a..1d68ec4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,6 +11,7 @@ "@astrojs/react": "3.6.0", "@floating-ui/react": "0.26.0", "@formkit/auto-animate": "0.8.2", + "@radix-ui/react-checkbox": "1.1.4", "@radix-ui/react-dropdown-menu": "2.0.6", "@radix-ui/react-slider": "1.2.3", "@radix-ui/react-tooltip": "1.0.7", @@ -4398,6 +4399,203 @@ } } }, + "node_modules/@radix-ui/react-checkbox": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-checkbox/-/react-checkbox-1.1.4.tgz", + "integrity": "sha512-wP0CPAHq+P5I4INKe3hJrIa1WoNqqrejzW+zoU0rOvo1b9gDEJJFl2rYfO1PYJUQCc2H1WZxIJmyv9BS8i5fLw==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.1", + "@radix-ui/react-compose-refs": "1.1.1", + "@radix-ui/react-context": "1.1.1", + "@radix-ui/react-presence": "1.1.2", + "@radix-ui/react-primitive": "2.0.2", + "@radix-ui/react-use-controllable-state": "1.1.0", + "@radix-ui/react-use-previous": "1.1.0", + "@radix-ui/react-use-size": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-checkbox/node_modules/@radix-ui/primitive": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.1.tgz", + "integrity": "sha512-SJ31y+Q/zAyShtXJc8x83i9TYdbAfHZ++tUZnvjJJqFjzsdUnKsxPL6IEtBlxKkU7yzer//GQtZSV4GbldL3YA==", + "license": "MIT" + }, + "node_modules/@radix-ui/react-checkbox/node_modules/@radix-ui/react-compose-refs": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.1.tgz", + "integrity": "sha512-Y9VzoRDSJtgFMUCoiZBDVo084VQ5hfpXxVE+NgkdNsjiDBByiImMZKKhxMwCbdHvhlENG6a833CbFkOQvTricw==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-checkbox/node_modules/@radix-ui/react-context": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.1.tgz", + "integrity": "sha512-UASk9zi+crv9WteK/NU4PLvOoL3OuE6BWVKNF6hPRBtYBDXQ2u5iu3O59zUlJiTVvkyuycnqrztsHVJwcK9K+Q==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-checkbox/node_modules/@radix-ui/react-presence": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.2.tgz", + "integrity": "sha512-18TFr80t5EVgL9x1SwF/YGtfG+l0BS0PRAlCWBDoBEiDQjeKgnNZRVJp/oVBl24sr3Gbfwc/Qpj4OcWTQMsAEg==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.1", + "@radix-ui/react-use-layout-effect": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-checkbox/node_modules/@radix-ui/react-primitive": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.0.2.tgz", + "integrity": "sha512-Ec/0d38EIuvDF+GZjcMU/Ze6MxntVJYO/fRlCPhCaVUyPY9WTalHJw54tp9sXeJo3tlShWpy41vQRgLRGOuz+w==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-checkbox/node_modules/@radix-ui/react-slot": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.2.tgz", + "integrity": "sha512-YAKxaiGsSQJ38VzKH86/BPRC4rh+b1Jpa+JneA5LRE7skmLPNAyeG8kPJj/oo4STLvlrs8vkf/iYyc3A5stYCQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-checkbox/node_modules/@radix-ui/react-use-callback-ref": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.0.tgz", + "integrity": "sha512-CasTfvsy+frcFkbXtSJ2Zu9JHpN8TYKxkgJGWbjiZhFivxaeW7rMeZt7QELGVLaYVfFMsKHjb7Ak0nMEe+2Vfw==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-checkbox/node_modules/@radix-ui/react-use-controllable-state": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.1.0.tgz", + "integrity": "sha512-MtfMVJiSr2NjzS0Aa90NPTnvTSg6C/JLCV7ma0W6+OMV78vd8OyRpID+Ng9LxzsPbLeuBnWBA1Nq30AtBIDChw==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-use-callback-ref": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-checkbox/node_modules/@radix-ui/react-use-layout-effect": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.0.tgz", + "integrity": "sha512-+FPE0rOdziWSrH9athwI1R0HDVbWlEhd+FR+aSDk4uWGmSJ9Z54sdZVDQPZAinJhJXwfT+qnj969mCsT2gfm5w==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-checkbox/node_modules/@radix-ui/react-use-size": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-size/-/react-use-size-1.1.0.tgz", + "integrity": "sha512-XW3/vWuIXHa+2Uwcc2ABSfcCledmXhhQPlGbfcRXbiUQI5Icjcg19BGCZVKKInYbvUCut/ufbbLLPFC5cbb1hw==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-use-layout-effect": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-collection": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.0.3.tgz", diff --git a/package.json b/package.json index 1254018..2f13c33 100644 --- a/package.json +++ b/package.json @@ -27,6 +27,7 @@ "@astrojs/react": "3.6.0", "@floating-ui/react": "0.26.0", "@formkit/auto-animate": "0.8.2", + "@radix-ui/react-checkbox": "1.1.4", "@radix-ui/react-dropdown-menu": "2.0.6", "@radix-ui/react-slider": "1.2.3", "@radix-ui/react-tooltip": "1.0.7", diff --git a/src/components/checkbox/checkbox.module.css b/src/components/checkbox/checkbox.module.css new file mode 100644 index 0000000..d9fc365 --- /dev/null +++ b/src/components/checkbox/checkbox.module.css @@ -0,0 +1,23 @@ +.checkboxRoot { + display: flex; + align-items: center; + justify-content: center; + width: 16px; + height: 16px; + cursor: pointer; + background: var(--color-neutral-100); + border: 2px solid var(--color-neutral-300); + border-radius: 4px; + transition: 0.2s; +} + +.checkboxRoot[data-state='checked'] { + background: var(--color-neutral-950); + border: 2px solid var(--color-neutral-950); +} + +.checkboxIndicator { + font-size: var(--font-2xsm); + color: var(--color-neutral-50); + transform: translateY(2px); +} diff --git a/src/components/checkbox/checkbox.tsx b/src/components/checkbox/checkbox.tsx new file mode 100644 index 0000000..0cfe771 --- /dev/null +++ b/src/components/checkbox/checkbox.tsx @@ -0,0 +1,38 @@ +import * as RadixCheckbox from '@radix-ui/react-checkbox'; +import { FaCheck } from 'react-icons/fa6/index'; + +import styles from './checkbox.module.css'; + +type CheckboxInputProps = { + checked?: boolean; + className?: string; + defaultChecked?: boolean; + disabled?: boolean; + onChange?: (checked: boolean) => void; +}; + +export function Checkbox({ + checked, + className, + defaultChecked = false, + disabled = false, + onChange, +}: CheckboxInputProps) { + const handleCheckedChange = (checked: boolean) => { + if (onChange) onChange(checked); + }; + + return ( + + + + + + ); +} diff --git a/src/components/checkbox/index.ts b/src/components/checkbox/index.ts new file mode 100644 index 0000000..83a0ba1 --- /dev/null +++ b/src/components/checkbox/index.ts @@ -0,0 +1 @@ +export { Checkbox } from './checkbox'; diff --git a/src/components/toolbox/todo/todos/todo/todo.module.css b/src/components/toolbox/todo/todos/todo/todo.module.css index b239bcd..2489d3a 100644 --- a/src/components/toolbox/todo/todos/todo/todo.module.css +++ b/src/components/toolbox/todo/todos/todo/todo.module.css @@ -30,7 +30,7 @@ } } - & button { + & .delete { display: flex; align-items: center; justify-content: center; diff --git a/src/components/toolbox/todo/todos/todo/todo.tsx b/src/components/toolbox/todo/todos/todo/todo.tsx index 3861d7f..bba2513 100644 --- a/src/components/toolbox/todo/todos/todo/todo.tsx +++ b/src/components/toolbox/todo/todos/todo/todo.tsx @@ -1,5 +1,7 @@ import { FaRegTrashAlt } from 'react-icons/fa/index'; +import { Checkbox } from '@/components/checkbox'; + import { useTodoStore } from '@/stores/todo'; import { cn } from '@/helpers/styles'; @@ -21,19 +23,16 @@ export function Todo({ done, id, todo }: TodoProps) { return (
- +
+ +
editTodo(id, e.target.value)} /> -