Browse Source

Add Basic Style Management To Checkbox Component

Gamaranto 4 years ago
parent
commit
c2099e6b7d

+ 92 - 0
packages/components/src/components/Checkbox/Checkbox.style.tsx

@@ -0,0 +1,92 @@
+import { css } from "@emotion/core"
+import { colors } from "../../theme"
+
+type CheckboxState = "error" | "selected" | "unselected"
+
+export type CheckboxStyleProps = {
+	labelPosition?: "end" | "start" | "top" | "bottom"
+	caption?: string
+	state?: CheckboxState
+	pressed?: boolean
+	disabled?: boolean
+}
+
+let colorFromState = (state: CheckboxState, disabled: boolean) => {
+	switch (state) {
+		case "error": {
+			return {
+				border: colors.error.second,
+				shadow: "transparent",
+				fill: colors.error.second
+			}
+		}
+		case "selected": {
+			return {
+				shadow: disabled ? "transparent" : colors.blue[900],
+				border: disabled ? colors.gray[700] : colors.blue[500],
+				fill: disabled ? colors.gray[700] : colors.blue[500]
+			}
+		}
+		case "unselected": {
+			return {
+				border: disabled ? colors.gray[400] : colors.gray[300],
+				fill: "transparent",
+				shadow: disabled ? "transparent" : colors.gray[800]
+			}
+		}
+	}
+}
+
+export let makeStyles = ({ labelPosition, caption, state = "selected", pressed, disabled }: CheckboxStyleProps) => {
+	let { fill, border, shadow } = colorFromState(state, disabled)
+	return {
+		outerContainer: css`
+			border-radius: 999px;
+			color: ${disabled ? colors.gray[400] : colors.white};
+			max-width: 2rem;
+			max-height: 2rem;
+			width: 2rem;
+			height: 2rem;
+			display: flex;
+			justify-content: center;
+			align-items: center;
+
+			&:focus-within {
+				background-color: ${shadow};
+			}
+			&:hover {
+				${disabled ? "" : `background-color: ${shadow}`}
+			}
+		`,
+		innerContainer: css`
+			position: relative;
+			border-color: ${border};
+			border-width: 1px;
+			border-style: solid;
+			background-color: ${pressed ? fill : "transparent"};
+			width: 1.065rem;
+			height: 1.065rem;
+			max-height: 1.065rem;
+			max-width: 1.065rem;
+			text-align: center;
+
+			& > input[type="checkbox"]:checked {
+				border-color: ${state === "unselected" ? colors.white : border};
+				background-color: ${fill};
+			}
+		`,
+		input: css`
+			position: absolute;
+			top: 0;
+			bottom: 0;
+			left: 0;
+			right: 0;
+			opacity: 0;
+			width: 100%;
+			height: 100%;
+			padding: unset;
+			border: unset;
+			margin: unset;
+		`
+	}
+}

+ 41 - 0
packages/components/src/components/Checkbox/Checkbox.tsx

@@ -0,0 +1,41 @@
+import React, { useState } from "react"
+import { makeStyles, CheckboxStyleProps } from "./Checkbox.style"
+import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"
+import { faCheck, faGripHorizontal } from "@fortawesome/free-solid-svg-icons"
+
+type CheckboxProps = {
+	label?: string
+	disabled?: boolean
+	icon?: "check" | "dash"
+	onChange?: (e: React.ChangeEvent) => void
+} & CheckboxStyleProps
+
+export default function Checkbox({
+	label = "",
+	disabled = false,
+	icon = "check",
+	onChange = () => {},
+	...styleProps
+}: CheckboxProps) {
+	const [pressed, setPressed] = useState(false)
+	const styles = makeStyles({ ...styleProps, pressed, disabled })
+	return (
+		<div css={styles.outerContainer}>
+			<div css={styles.innerContainer}>
+				<input
+					css={styles.input}
+					type="checkbox"
+					checked={pressed}
+					disabled={disabled}
+					onChange={e => {
+						onChange(e)
+						setPressed(!pressed)
+					}}
+				/>
+				{pressed && styleProps.state !== "unselected" && (
+					<FontAwesomeIcon icon={icon === "check" ? faCheck : faGripHorizontal} />
+				)}
+			</div>
+		</div>
+	)
+}

+ 3 - 0
packages/components/src/components/Checkbox/index.ts

@@ -0,0 +1,3 @@
+//import { memo } from "react";
+import Checkbox from "./Checkbox"
+export default Checkbox

+ 1 - 0
packages/components/src/index.ts

@@ -4,5 +4,6 @@ export { default as TagButton } from "./components/TagButton"
 export { default as Header } from "./components/Header"
 export { default as Tag } from "./components/Tag"
 export { default as TextField } from "./components/TextField"
+export { default as Checkbox } from "./components/Checkbox"
 export { default as Typography } from "./components/Typography"
 export { default as Grid } from "./components/Grid"

+ 26 - 26
packages/components/src/theme/colors.ts

@@ -1,28 +1,28 @@
 export default {
-  white: "#FFFFFF",
-  black: "#000000",
-  gray: {
-    900: "#0B0C0F",
-    800: "#181C20",
-    700: "#272D33",
-    600: "#343D44",
-    500: "#424E57",
-    400: "#52616B",
-    300: "#7B8A95",
-    200: "#B5C1C9",
-    100: "#DAE2EB",
-    50: "#F4F6F8"
-  },
-  blue: {
-    900: "#030041",
-    700: "#261EE4",
-    600: "#2F2FF4",
-    500: "#4038FF",
-    400: "#5252FF",
-    300: "#6C6CFF",
-    100: "#B4BBFF",
-    50: "#E0E1FF"
-  },
-  success: "#B00020",
-  error: "#1CCB00"
+	white: "#FFFFFF",
+	black: "#000000",
+	gray: {
+		900: "#0B0C0F",
+		800: "#181C20",
+		700: "#272D33",
+		600: "#343D44",
+		500: "#424E57",
+		400: "#52616B",
+		300: "#7B8A95",
+		200: "#B5C1C9",
+		100: "#DAE2EB",
+		50: "#F4F6F8"
+	},
+	blue: {
+		900: "#030041",
+		700: "#261EE4",
+		600: "#2F2FF4",
+		500: "#4038FF",
+		400: "#5252FF",
+		300: "#6C6CFF",
+		100: "#B4BBFF",
+		50: "#E0E1FF"
+	},
+	success: "#B00020",
+	error: { first: "#1CCB00", second: "#FF3861" }
 }

+ 37 - 0
packages/components/stories/07-Checkbox.stories.tsx

@@ -0,0 +1,37 @@
+import React from "react"
+import { Checkbox } from "../src"
+
+export default {
+	title: "Checkbox",
+	component: Checkbox
+}
+
+export const Unselected = () => (
+	<div style={{ background: "black", padding: "4rem", display: "flex", justifyContent: "space-around" }}>
+		<Checkbox state="unselected" />
+		<Checkbox state="unselected" icon="dash" />
+		<Checkbox state="unselected" />
+	</div>
+)
+export const Selected = () => (
+	<div style={{ background: "black", padding: "4rem", display: "flex", justifyContent: "space-around" }}>
+		<Checkbox state="selected" />
+		<Checkbox state="selected" icon="dash" />
+		<Checkbox state="selected" />
+	</div>
+)
+export const Error = () => (
+	<div style={{ background: "black", padding: "4rem", display: "flex", justifyContent: "space-around" }}>
+		<Checkbox state="error" />
+		<Checkbox state="error" />
+		<Checkbox state="error" />
+	</div>
+)
+
+export const Disabled = () => (
+	<div style={{ background: "black", padding: "4rem", display: "flex", justifyContent: "space-around" }}>
+		<Checkbox disabled state="error" />
+		<Checkbox disabled state="selected" pressed />
+		<Checkbox disabled state="unselected" />
+	</div>
+)