a tool for shared writing and social publishing
1import { CheckboxChecked } from "./Icons/CheckboxChecked";
2import { CheckboxEmpty } from "./Icons/CheckboxEmpty";
3import { Props } from "./Icons/Props";
4import React, { forwardRef, type JSX } from "react";
5
6export function Checkbox(props: {
7 checked: boolean;
8 onChange: (e: React.ChangeEvent<HTMLInputElement>) => void;
9 children: React.ReactNode;
10 className?: string;
11 small?: boolean;
12}) {
13 return (
14 <label
15 className={`flex w-full gap-2 items-start cursor-pointer ${props.className} ${props.checked ? "text-primary font-bold " : " text-tertiary font-normal"} ${props.small && "text-sm"}`}
16 >
17 <input
18 type="checkbox"
19 checked={props.checked}
20 className="hidden"
21 onChange={(e) => props.onChange(e)}
22 />
23 {!props.checked ? (
24 <CheckboxEmpty
25 className={`shrink-0 text-tertiary ${props.small ? "mt-1" : "mt-[6px]"}`}
26 />
27 ) : (
28 <CheckboxChecked
29 className={`shrink-0 text-accent-contrast ${props.small ? "mt-1" : "mt-[6px]"}`}
30 />
31 )}
32 {props.children}
33 </label>
34 );
35}
36
37type RadioProps = Omit<JSX.IntrinsicElements["input"], "content">;
38
39export function Radio(
40 props: {
41 onChange: (e: React.ChangeEvent<HTMLInputElement>) => void;
42 children: React.ReactNode;
43 radioEmptyClassName?: string;
44 radioCheckedClassName?: string;
45 } & JSX.IntrinsicElements["input"],
46) {
47 return (
48 <label
49 htmlFor={props.id}
50 className={`flex gap-2 items-start cursor-pointer shrink-0 ${props.checked ? "text-primary font-bold " : " text-tertiary font-normal"}`}
51 >
52 <input
53 type="radio"
54 name={props.name}
55 id={props.id}
56 value={props.value}
57 checked={props.checked}
58 className="hidden"
59 onChange={(e) => props.onChange(e)}
60 />
61 {!props.checked ? (
62 <RadioEmpty
63 className={`shrink-0 mt-[6px] text-tertiary ${props.radioEmptyClassName}`}
64 />
65 ) : (
66 <RadioChecked
67 className={`shrink-0 mt-[6px] text-accent-contrast ${props.radioCheckedClassName}`}
68 />
69 )}
70 {props.children}
71 </label>
72 );
73}
74
75const RadioEmpty = (props: Props) => {
76 return (
77 <svg
78 width="12"
79 height="12"
80 viewBox="0 0 12 12"
81 fill="none"
82 xmlns="http://www.w3.org/2000/svg"
83 {...props}
84 >
85 <path
86 fillRule="evenodd"
87 clipRule="evenodd"
88 d="M6 11C8.76142 11 11 8.76142 11 6C11 3.23858 8.76142 1 6 1C3.23858 1 1 3.23858 1 6C1 8.76142 3.23858 11 6 11ZM6 12C9.31371 12 12 9.31371 12 6C12 2.68629 9.31371 0 6 0C2.68629 0 0 2.68629 0 6C0 9.31371 2.68629 12 6 12Z"
89 fill="currentColor"
90 />
91 </svg>
92 );
93};
94
95const RadioChecked = (props: Props) => {
96 return (
97 <svg
98 width="12"
99 height="12"
100 viewBox="0 0 12 12"
101 fill="none"
102 xmlns="http://www.w3.org/2000/svg"
103 {...props}
104 >
105 <path
106 fillRule="evenodd"
107 clipRule="evenodd"
108 d="M6 10.5C8.48528 10.5 10.5 8.48528 10.5 6C10.5 3.51472 8.48528 1.5 6 1.5C3.51472 1.5 1.5 3.51472 1.5 6C1.5 8.48528 3.51472 10.5 6 10.5ZM6 12C9.31371 12 12 9.31371 12 6C12 2.68629 9.31371 0 6 0C2.68629 0 0 2.68629 0 6C0 9.31371 2.68629 12 6 12Z"
109 fill="currentColor"
110 />
111 <path
112 d="M9 6C9 7.65685 7.65685 9 6 9C4.34315 9 3 7.65685 3 6C3 4.34315 4.34315 3 6 3C7.65685 3 9 4.34315 9 6Z"
113 fill="currentColor"
114 />
115 </svg>
116 );
117};