From 458c312753daa6392114fe82c472d33189071df2 Mon Sep 17 00:00:00 2001
From: =
Date: Mon, 5 May 2025 14:43:13 -0700
Subject: [PATCH 1/4] added radio and checkbox
---
package-lock.json | 24 +----
src/components/checkbox/Checkbox.tsx | 42 ++++++++
src/components/checkbox/checkbox.css | 142 +++++++++++++++++++++++++
src/components/page/Page.tsx | 1 +
src/components/radio/radio.css | 149 +++++++++++++++++++++++++++
src/components/radio/radio.tsx | 38 +++++++
src/index.ts | 4 +-
src/stories/Checkbox.stories.ts | 123 ++++++++++++++++++++++
src/stories/Radio.stories.ts | 123 ++++++++++++++++++++++
9 files changed, 623 insertions(+), 23 deletions(-)
create mode 100644 src/components/checkbox/Checkbox.tsx
create mode 100644 src/components/checkbox/checkbox.css
create mode 100644 src/components/radio/radio.css
create mode 100644 src/components/radio/radio.tsx
create mode 100644 src/stories/Checkbox.stories.ts
create mode 100644 src/stories/Radio.stories.ts
diff --git a/package-lock.json b/package-lock.json
index 941ec43..adfd6f1 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "@acmucsd/components",
- "version": "1.0.9",
+ "version": "1.0.10",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "@acmucsd/components",
- "version": "1.0.9",
+ "version": "1.0.10",
"license": "ISC",
"devDependencies": {
"@chromatic-com/storybook": "^3.2.3",
@@ -9686,19 +9686,6 @@
"typescript": ">= 4.3.x"
}
},
- "node_modules/react-dom": {
- "version": "19.0.0",
- "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.0.0.tgz",
- "integrity": "sha512-4GV5sHFG0e/0AD4X+ySy6UJd3jVl1iNsNHdpad0qhABJ11twS3TTBnseqsKurKcsNqCEFeGL3uLpVChpIO3QfQ==",
- "dev": true,
- "peer": true,
- "dependencies": {
- "scheduler": "^0.25.0"
- },
- "peerDependencies": {
- "react": "^19.0.0"
- }
- },
"node_modules/react-is": {
"version": "17.0.2",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz",
@@ -10276,13 +10263,6 @@
}
}
},
- "node_modules/scheduler": {
- "version": "0.25.0",
- "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.25.0.tgz",
- "integrity": "sha512-xFVuu11jh+xcO7JOAGJNOXld8/TcEHK/4CituBUeUb5hqxJLj9YuemAEuvm9gQ/+pgXYfbQuqAkiYu+u7YEsNA==",
- "dev": true,
- "peer": true
- },
"node_modules/schema-utils": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.0.tgz",
diff --git a/src/components/checkbox/Checkbox.tsx b/src/components/checkbox/Checkbox.tsx
new file mode 100644
index 0000000..6949a9a
--- /dev/null
+++ b/src/components/checkbox/Checkbox.tsx
@@ -0,0 +1,42 @@
+import React, { FC, useEffect, useState } from 'react';
+import './checkbox.css';
+
+export interface CheckboxProps {
+ checked?: boolean;
+ disabled?: boolean;
+ mode?: 'light' | 'dark';
+ label?: string;
+ onChange?: (event: React.ChangeEvent) => void;
+}
+
+export const Checkbox: FC = ({
+ checked = false,
+ disabled = false,
+ mode = 'light',
+ label,
+ onChange,
+}) => {
+ const modeClass = mode === 'dark' ? 'storybook-checkbox--dark' : 'storybook-checkbox--light';
+ const [isChecked, setIsChecked] = useState(checked);
+
+ useEffect(() => {
+ setIsChecked(checked);
+ }, [checked]);
+
+ const handleChange = (e: React.ChangeEvent) => {
+ setIsChecked(e.target.checked);
+ onChange?.(e);
+ };
+
+ return (
+
+ );
+};
diff --git a/src/components/checkbox/checkbox.css b/src/components/checkbox/checkbox.css
new file mode 100644
index 0000000..670ca6f
--- /dev/null
+++ b/src/components/checkbox/checkbox.css
@@ -0,0 +1,142 @@
+.storybook-checkbox {
+ display: inline-flex;
+ align-items: center;
+ cursor: pointer;
+ user-select: none;
+ font-family: 'DM Sans', sans-serif;
+ margin: 8px;
+}
+
+.storybook-checkbox input[type="checkbox"] {
+ cursor: pointer;
+ appearance: none;
+ width: 24px;
+ height: 24px;
+ border-radius: 4px;
+ border: 2px solid #000000;
+ background-color: #ffffff;
+ position: relative;
+ outline: none;
+}
+
+/* Label spacing */
+.storybook-checkbox__label {
+ margin-left: 8px;
+ font-size: 16px;
+}
+
+/* ——————————————————————
+ Light mode – Checked
+ —————————————————————— */
+.storybook-checkbox--light input[type="checkbox"]:checked {
+ border-color: #0073e6;
+ background-color: #0073e6;
+}
+
+.storybook-checkbox--light input[type="checkbox"]:checked::before {
+ content: "";
+ position: absolute;
+ left: 6px;
+ width: 6px;
+ height: 14px;
+ border: solid #fff;
+ border-width: 0 2px 2px 0;
+ transform: rotate(45deg);
+}
+
+.storybook-checkbox--light input[type="checkbox"]:checked:hover {
+ background-color: #005cb8;
+}
+
+.storybook-checkbox--light input[type="checkbox"]:checked:active {
+ background-color: #00458a;
+}
+
+.storybook-checkbox--light input[type="checkbox"]:checked:disabled {
+ background-color: #979797;
+}
+
+/* ——————————————————————
+ Light mode – Unchecked
+ —————————————————————— */
+.storybook-checkbox--light input[type="checkbox"] {
+ border-color: #000000;
+}
+
+.storybook-checkbox--light input[type="checkbox"]:hover {
+ border-color: #005cb8;
+}
+
+.storybook-checkbox--light input[type="checkbox"]:focus-visible {
+ outline: 2px solid #0073e6;
+}
+
+.storybook-checkbox--light input[type="checkbox"]:active {
+ border-color: #00458a;
+}
+
+.storybook-checkbox--light input[type="checkbox"]:disabled {
+ border-color: #979797;
+}
+
+/* ——————————————————————
+ Dark mode – Base color
+ —————————————————————— */
+.storybook-checkbox--dark {
+ color: #ffffff;
+}
+
+/* ——————————————————————
+ Dark mode – Checked
+ —————————————————————— */
+.storybook-checkbox--dark input[type="checkbox"]:checked {
+ border-color: #0073E6;
+ background-color: #0073E6;
+}
+
+.storybook-checkbox--dark input[type="checkbox"]:checked::before {
+ content: "";
+ position: absolute;
+ left: 6px;
+ width: 6px;
+ height: 14px;
+ border: solid #fff;
+ border-width: 0 2px 2px 0;
+ transform: rotate(45deg);
+}
+
+.storybook-checkbox--dark input[type="checkbox"]:checked:hover {
+ background-color: #57abff;
+}
+
+.storybook-checkbox--dark input[type="checkbox"]:checked:active {
+ background-color: #8fc7ff;
+}
+
+.storybook-checkbox--dark input[type="checkbox"]:checked:disabled {
+ background-color: #797c8b;
+}
+
+/* ——————————————————————
+ Dark mode – Unchecked
+ —————————————————————— */
+.storybook-checkbox--dark input[type="checkbox"] {
+ border-color: #ffffff;
+ background-color: transparent;
+}
+
+.storybook-checkbox--dark input[type="checkbox"]:hover {
+ border-color: #57abff;
+}
+
+.storybook-checkbox--dark input[type="checkbox"]:focus-visible {
+ outline: 2px solid #1f8fff;
+}
+
+.storybook-checkbox--dark input[type="checkbox"]:active {
+ border-color: #8fc7ff;
+}
+
+.storybook-checkbox--dark input[type="checkbox"]:disabled {
+ border-color: #797c8b;
+}
\ No newline at end of file
diff --git a/src/components/page/Page.tsx b/src/components/page/Page.tsx
index 990749c..4652e34 100644
--- a/src/components/page/Page.tsx
+++ b/src/components/page/Page.tsx
@@ -49,6 +49,7 @@ export const Page = () => {
.
+
Tip Adjust the width of the canvas with the{' '}