96 lines
		
	
	
		
			2.8 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			96 lines
		
	
	
		
			2.8 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
| import { Signal, useSignal } from "@preact/signals";
 | |
| import { useId, useState } from "preact/hooks";
 | |
| 
 | |
| interface CheckboxProps {
 | |
|   label: string;
 | |
|   isChecked?: boolean;
 | |
|   onChange: (isChecked: boolean) => void;
 | |
| }
 | |
| 
 | |
| const Checkbox2: preact.FunctionalComponent<CheckboxProps> = (
 | |
|   { label, isChecked = false, onChange },
 | |
| ) => {
 | |
|   const [checked, setChecked] = useState(isChecked);
 | |
| 
 | |
|   const toggleCheckbox = () => {
 | |
|     const newChecked = !checked;
 | |
|     setChecked(newChecked);
 | |
|     onChange(newChecked);
 | |
|   };
 | |
| 
 | |
|   return (
 | |
|     <div
 | |
|       class="flex items-center rounded-xl p-1 pl-4"
 | |
|       style={{ background: "var(--background)", color: "var(--foreground)" }}
 | |
|     >
 | |
|       <span>
 | |
|         {label}
 | |
|       </span>
 | |
|       <label
 | |
|         class="relative flex cursor-pointer items-center rounded-full p-3"
 | |
|         for="checkbox"
 | |
|         data-ripple-dark="true"
 | |
|       >
 | |
|         <input
 | |
|           type="checkbox"
 | |
|           class="before:content[''] peer relative h-5 w-5 cursor-pointer appearance-none rounded-md border border-blue-gray-200 transition-all before:absolute before:top-2/4 before:left-2/4 before:block before:h-12 before:w-12 before:-translate-y-2/4 before:-translate-x-2/4 before:rounded-full before:bg-blue-gray-500 before:opacity-0 before:transition-opacity  hover:before:opacity-10"
 | |
|           id="checkbox"
 | |
|           checked
 | |
|         />
 | |
|         <div
 | |
|           class={`pointer-events-none absolute top-2/4 left-2/4 -translate-y-2/4 -translate-x-2/4 text-white opacity-${
 | |
|             checked ? 100 : 0
 | |
|           } transition-opacity`}
 | |
|         >
 | |
|           <svg
 | |
|             xmlns="http://www.w3.org/2000/svg"
 | |
|             class="h-3.5 w-3.5"
 | |
|             viewBox="0 0 20 20"
 | |
|             fill="white"
 | |
|             stroke="currentColor"
 | |
|             stroke-width="1"
 | |
|           >
 | |
|             <path
 | |
|               fill-rule="evenodd"
 | |
|               d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z"
 | |
|               clip-rule="evenodd"
 | |
|             >
 | |
|             </path>
 | |
|           </svg>
 | |
|         </div>
 | |
|       </label>
 | |
|     </div>
 | |
|   );
 | |
| };
 | |
| 
 | |
| const Checkbox = (
 | |
|   { label, checked = useSignal(false) }: {
 | |
|     label: string;
 | |
|     checked?: Signal<boolean>;
 | |
|   },
 | |
| ) => {
 | |
|   const _id = useId();
 | |
|   const id = `checkbox-${_id}`;
 | |
|   return (
 | |
|     <label
 | |
|       className="flex items-center py-3 px-4 rounded-2xl"
 | |
|       style={{ color: "var(--foreground)", background: "var(--background)" }}
 | |
|     >
 | |
|       <input
 | |
|         type="checkbox"
 | |
|         checked={checked.value}
 | |
|         name="checkbox-one"
 | |
|         id={id}
 | |
|         onChange={(ev) => {
 | |
|           checked.value = ev.currentTarget.checked;
 | |
|         }}
 | |
|         class="bg-gray-200 hover:bg-gray-300 cursor-pointer 
 | |
|     w-5 h-5 border-3 border-amber-500 focus:outline-none rounded-lg"
 | |
|       />
 | |
|       <span class="ml-3">{label}</span>
 | |
|     </label>
 | |
|   );
 | |
| };
 | |
| 
 | |
| export default Checkbox;
 |