Skip to content

Commit c66b20d

Browse files
bzzz-codingLoTerencebennyv8
authored
Checkbox Component with Tailwind (#654)
* Created Checkbox Component with Tailwind * Deleted .scss file and refactored away old Checkbox component * Updated Checkbox * Installed tailwind-merge and implemented cn function * Updated Checkbox with twmerge * Update frontend/src/tw-components/Checkbox.tsx Co-authored-by: Terence Lo <[email protected]> * Update frontend/src/tw-components/Checkbox.tsx Co-authored-by: Terence Lo <[email protected]> * Update frontend/tests/components/Checkbox.test.tsx Co-authored-by: Terence Lo <[email protected]> * Feat/qualifier pages (#668) * update qualifier page 1 - aligned qualifier nav - use grid system instead of flex box for items * Refactor: update button styles for primary-dark theme * Feat: add ProgressIndicator component and integrate it into QualifierPage2 * Refactor: update border style in QualifierNav component * Refactor: dynamic grid layout in QualifierPage1 for responsive design * Feat: enhance RadioButtonForm to support skill selection callback * Feat: update RadioButtonForm dynamically render skill & experience levels * Add selectCOP and experience levels props to qualifiers * Feat: use context in QualiferPage2 to keep track of chosen experience level * Feat: integrate qualifiers context to manage selected COP in QualifierPage1 * Feat: refactor QualifierPage2 layout and improve skill selection handling * Refactor: - renamed experienceLevels to skills_matrix - refactored to use tw-components/Buttons.tsx & added second style - Ran npm run lint in frontend directory * update tech stack * feat: use new tw-button variant, fix merge --------- Co-authored-by: Terence Lo <[email protected]> * Fixed className syntax --------- Co-authored-by: Terence Lo <[email protected]> Co-authored-by: Benny <[email protected]>
1 parent 20155e2 commit c66b20d

File tree

9 files changed

+109
-178
lines changed

9 files changed

+109
-178
lines changed

frontend/src/components/Inputs/Checkbox.tsx

Lines changed: 0 additions & 108 deletions
This file was deleted.

frontend/src/components/Inputs/_Checkbox.scss

Lines changed: 0 additions & 51 deletions
This file was deleted.
Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
@forward "Calendar";
2-
@forward "Checkbox";
32
@forward "Chip";
43
@forward "Dropdown";
54
@forward "Textfield";

frontend/src/components/components.tsx

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import { Button } from "./Buttons/Button";
22
import { IconButton } from "./Buttons/IconButton";
33
import { ScrollCarousel } from "./Carousel/ScrollCarousel";
44
import { Calendar } from "./Inputs/Calendar";
5-
import { Checkbox } from "./Inputs/Checkbox";
65
import { Chip } from "./Inputs/Chip";
76
import { Dropdown, DropdownOption } from "./Inputs/Dropdown";
87
import { TextField } from "./Inputs/Textfield";
@@ -18,7 +17,6 @@ export {
1817
// Dialog
1918
// Inputs
2019
Calendar,
21-
Checkbox,
2220
Chip,
2321
Dropdown,
2422
DropdownOption,

frontend/src/pages/Demo/Demo.tsx

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import React, { Fragment, useState } from "react";
33

44
// Internal Imports
55
import {
6-
Checkbox,
76
Chip,
87
TextField,
98
Notification,
@@ -22,9 +21,6 @@ function Demo() {
2221
console.log(e.target.value);
2322
}
2423

25-
function checkboxOnChange(e: React.ChangeEvent<HTMLInputElement>) {
26-
console.log(e.target.checked);
27-
}
2824
return (
2925
<Fragment>
3026
<Notification closable fade>
@@ -121,17 +117,6 @@ function Demo() {
121117
);
122118
})}
123119
</div>
124-
<h2>Checkboxes</h2>
125-
<Checkbox label="Enabled selected" defaultChecked />
126-
<Checkbox label="Enabled unselected" />
127-
<Checkbox label="Disabled selected" defaultChecked disabled />
128-
<Checkbox label="Disabled unselected" disabled />
129-
<Checkbox
130-
label="Enabled selected"
131-
defaultChecked
132-
labelHidden={true}
133-
onChange={checkboxOnChange}
134-
/>
135120
<h2>Textfields</h2>
136121
<TextField
137122
type="email"

frontend/src/pages/Demo/DemoTailwind.tsx

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import React, { useState, useEffect } from "react";
22
import Typography from "tw-components/Typography";
33
import { Button, IconButton } from "tw-components/Buttons";
4+
import { Checkbox } from "tw-components/Checkbox";
45

56
const DemoTailwind = () => {
67
// Add a setDarkMode for testing dark mode styles
@@ -14,8 +15,25 @@ const DemoTailwind = () => {
1415
}
1516
}, [darkMode]);
1617

18+
function checkboxOnChange(e: React.ChangeEvent<HTMLInputElement>) {
19+
console.log(e.target.checked);
20+
}
21+
1722
return (
1823
<div className="min-h-screen bg-grey-light p-8">
24+
<div className="mx-auto max-w-4xl rounded-lg bg-white p-6 shadow-md transition-colors duration-300 dark:bg-[#030D2D]">
25+
<Typography.Title2 className="mb-4">Checkboxes</Typography.Title2>
26+
<Checkbox label="Enabled selected" defaultChecked />
27+
<Checkbox label="Enabled unselected" />
28+
<Checkbox label="Disabled selected" defaultChecked disabled />
29+
<Checkbox label="Disabled unselected" disabled />
30+
<Checkbox
31+
label="Enabled selected"
32+
defaultChecked
33+
labelHidden
34+
onChange={checkboxOnChange}
35+
/>
36+
</div>
1937
<div className="mx-auto max-w-4xl rounded-lg bg-white p-6 shadow-md transition-colors duration-300 dark:bg-[#030D2D]">
2038
<Typography.Title1 className="mb-4 text-blue-dark dark:text-white">
2139
Buttons
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
import React, { useId, useRef, useState, useEffect } from "react";
2+
import { IconCheckboxY, IconCheckboxN } from "assets/images/images";
3+
import { cn } from "lib/utils";
4+
5+
// Type declaration for props
6+
interface CheckboxProps {
7+
className?: string;
8+
defaultChecked?: boolean;
9+
disabled?: boolean;
10+
label: string;
11+
labelHidden?: boolean;
12+
onChange?: (e: React.ChangeEvent<HTMLInputElement>) => void;
13+
}
14+
15+
function Checkbox({
16+
defaultChecked = false,
17+
disabled = false,
18+
labelHidden = false,
19+
...props
20+
}: CheckboxProps) {
21+
const checkboxId = useId();
22+
const checkboxRef = useRef<HTMLInputElement>(null);
23+
const [isChecked, setIsChecked] = useState(defaultChecked);
24+
25+
useEffect(() => {
26+
if (checkboxRef.current) {
27+
checkboxRef.current.checked = isChecked;
28+
}
29+
}, [isChecked]);
30+
31+
function handleChange(e: React.ChangeEvent<HTMLInputElement>) {
32+
if (!disabled) {
33+
setIsChecked(e.target.checked);
34+
}
35+
if (props.onChange) {
36+
props.onChange(e);
37+
}
38+
}
39+
40+
return (
41+
<div className={cn("relative flex items-center", props.className)}>
42+
<input
43+
id={checkboxId}
44+
type="checkbox"
45+
defaultChecked={defaultChecked}
46+
disabled={disabled}
47+
ref={checkboxRef}
48+
onChange={handleChange}
49+
className="peer sr-only"
50+
/>
51+
52+
{/* Circle Effect */}
53+
<span className="absolute h-10 w-10 rounded-full opacity-0 peer-focus:bg-blue-dark peer-focus:opacity-[.16] peer-active:bg-blue-dark peer-active:opacity-[.32]"></span>
54+
55+
{/* Label & Checkbox Icon */}
56+
<label
57+
htmlFor={checkboxId}
58+
className={`relative flex select-none items-center ${
59+
disabled ? "cursor-not-allowed opacity-50" : "cursor-pointer"
60+
}`}
61+
>
62+
<span className="relative flex h-10 w-10 items-center justify-center">
63+
{isChecked ? (
64+
<IconCheckboxY
65+
height="24"
66+
width="24"
67+
fill={disabled ? "#C1C1C1" : "#3450A1"}
68+
stroke={disabled ? "#C1C1C1" : "#3450A1"}
69+
viewBox="0 0 24 24"
70+
aria-hidden="true"
71+
/>
72+
) : (
73+
<IconCheckboxN
74+
height="24"
75+
width="24"
76+
fill="#fff"
77+
stroke={disabled ? "#C1C1C1" : "#585858"}
78+
viewBox="0 0 24 24"
79+
aria-hidden="true"
80+
/>
81+
)}
82+
</span>
83+
<span className={labelHidden ? "sr-only" : "ml-1"}>{props.label}</span>
84+
</label>
85+
</div>
86+
);
87+
}
88+
89+
export { Checkbox };

frontend/src/tw-components/index.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,4 @@ export { default as TextField } from "./TextField";
66
export { default as Dialog } from "./Dialog";
77
export { default as Typography } from "./Typography";
88
export { CircleCard } from "./CircleCard";
9+
export { Checkbox } from "./Checkbox";

frontend/tests/components/Checkbox.test.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import "regenerator-runtime/runtime";
77
import { config } from "react-transition-group";
88

99
// Internal imports
10-
import { Checkbox } from "components/components";
10+
import { Checkbox } from "tw-components/Checkbox";
1111

1212
config.disabled = true;
1313

0 commit comments

Comments
 (0)