Skip to content

added radio and checkbox #12

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 2 additions & 22 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

42 changes: 42 additions & 0 deletions src/components/checkbox/Checkbox.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import React, { FC, useEffect, useState } from 'react';
import './checkbox.css';

export interface CheckboxProps {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should also let you specify name

checked?: boolean;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we also add defaultChecked

disabled?: boolean;
mode?: 'light' | 'dark';
label?: string;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should this be ReactNode? that way you can add formatting to the labels. it should also be required i think since you already wrap the checkbox in a <label>

onChange?: (event: React.ChangeEvent<HTMLInputElement>) => void;
}

export const Checkbox: FC<CheckboxProps> = ({
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<HTMLInputElement>) => {
setIsChecked(e.target.checked);
onChange?.(e);
};

return (
<label className={['storybook-checkbox', modeClass].join(' ')}>
<input
type="checkbox"
checked={isChecked}
disabled={disabled}
onChange={handleChange}
/>
{label && <span className="storybook-checkbox__label">{label}</span>}
</label>
);
};
142 changes: 142 additions & 0 deletions src/components/checkbox/checkbox.css
Original file line number Diff line number Diff line change
@@ -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;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

checkbox shouldn't have cursor: pointer when disabled

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;
}
1 change: 1 addition & 0 deletions src/components/page/Page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ export const Page = () => {
</a>
.
</p>

<div className="tip-wrapper">
<span className="tip">Tip</span> Adjust the width of the canvas with the{' '}
<svg width="10" height="10" viewBox="0 0 12 12" xmlns="http://www.w3.org/2000/svg">
Expand Down
38 changes: 38 additions & 0 deletions src/components/radio/Radio.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import React, { FC } from 'react';
import './radio.css';

export interface RadioProps {
name: string;
value: string;
defaultChecked?: boolean;
disabled?: boolean;
mode?: 'light' | 'dark';
label?: string;
onChange?: (event: React.ChangeEvent<HTMLInputElement>) => void;
}

export const Radio: FC<RadioProps> = ({
name,
value,
defaultChecked = false,
disabled = false,
mode = 'light',
label,
onChange,
}) => {
const modeClass = mode === 'dark' ? 'storybook-radio--dark' : 'storybook-radio--light';

return (
<label className={['storybook-radio', modeClass].join(' ')}>
<input
type="radio"
name={name}
value={value}
defaultChecked={defaultChecked}
disabled={disabled}
onChange={onChange}
/>
{label && <span className="storybook-radio__label">{label}</span>}
</label>
);
};
Loading