From 43bab9580998ea935bebfcc6a58c7a1c58b3aeb7 Mon Sep 17 00:00:00 2001 From: june Date: Fri, 31 Jan 2025 22:29:21 +0900 Subject: [PATCH 1/2] =?UTF-8?q?feat:=20JCL-73=20=ED=83=80=EC=9E=84?= =?UTF-8?q?=EB=B3=B4=EB=93=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../molecules/TimeBoard/index.module.scss | 28 ++++++++ .../molecules/TimeBoard/index.stories.tsx | 29 ++++++++ src/components/molecules/TimeBoard/index.tsx | 68 +++++++++++++++++++ src/components/molecules/index.tsx | 1 + src/styles/_global.scss | 9 +++ 5 files changed, 135 insertions(+) create mode 100644 src/components/molecules/TimeBoard/index.module.scss create mode 100644 src/components/molecules/TimeBoard/index.stories.tsx create mode 100644 src/components/molecules/TimeBoard/index.tsx diff --git a/src/components/molecules/TimeBoard/index.module.scss b/src/components/molecules/TimeBoard/index.module.scss new file mode 100644 index 0000000..35cea77 --- /dev/null +++ b/src/components/molecules/TimeBoard/index.module.scss @@ -0,0 +1,28 @@ +@use "src/styles/libs" as *; + +.time-board { + display: flex; + justify-content: center; + gap: 3px; + width: 240px; + height: 245px; + padding: 3px; + list-style: none; + background-color: $BLUISH-GRAY-100; + border: 1px $BLUE-400 solid; + border-radius: 3px; + + &_buttons { + height: 100%; + display: flex; + flex-direction: column; + align-items: center; + overflow-y: auto; + gap: 3px; + padding-right: 10px; + } + + &_button { + width: 90px; + } +} diff --git a/src/components/molecules/TimeBoard/index.stories.tsx b/src/components/molecules/TimeBoard/index.stories.tsx new file mode 100644 index 0000000..562367c --- /dev/null +++ b/src/components/molecules/TimeBoard/index.stories.tsx @@ -0,0 +1,29 @@ +/* eslint-disable react-hooks/rules-of-hooks */ +import { TimeBoard } from "@/index"; +import type { Meta, StoryObj } from "@storybook/react"; +import { useState } from "react"; + +const meta: Meta = { + title: "molecules/TimeBoard", + component: TimeBoard, + decorators: [(Story) => ], + tags: ["autodocs"], +}; + +export default meta; +type Story = StoryObj; + +export const Default: Story = { + render: () => { + const [value, setValue] = useState({ hour: 0, minute: 0 }); + return ( +
+ setValue(value)} /> + +
+ {JSON.stringify(value)} +
+
+ ); + }, +}; diff --git a/src/components/molecules/TimeBoard/index.tsx b/src/components/molecules/TimeBoard/index.tsx new file mode 100644 index 0000000..33a3e43 --- /dev/null +++ b/src/components/molecules/TimeBoard/index.tsx @@ -0,0 +1,68 @@ +import { Button } from "@/components/atoms"; +import styles from "./index.module.scss"; +import { useState } from "react"; + +const HOURS = Array.from({ length: 24 }, (_, i) => i + 1); +const MINUTES = Array.from({ length: 60 }, (_, i) => i + 1); + +export interface TimeBoardProps { + value?: { + hour: number; + minute: number; + }; + onChange?: (value: { hour: number; minute: number }) => void; +} + +export const TimeBoard = ({ value, onChange }: TimeBoardProps) => { + const [selectedHour, setSelectedHour] = useState( + new Date().getHours(), + ); + const [selectedMinute, setSelectedMinute] = useState( + new Date().getMinutes(), + ); + + const handleChangeHour = (hour: number) => { + setSelectedHour(hour); + value && onChange && onChange({ ...value, hour }); + }; + + const handleChangeMinute = (minute: number) => { + setSelectedMinute(minute); + value && onChange && onChange({ ...value, minute }); + }; + return ( +
+
    + {HOURS.map((hour, i) => ( +
  • + +
  • + ))} +
+ +
    + {MINUTES.map((minute, i) => ( +
  • + +
  • + ))} +
+
+ ); +}; diff --git a/src/components/molecules/index.tsx b/src/components/molecules/index.tsx index 9b42339..b14e413 100644 --- a/src/components/molecules/index.tsx +++ b/src/components/molecules/index.tsx @@ -9,3 +9,4 @@ export * from "./Modal"; export * from "./Table"; export * from "./Options"; export * from "./Checkbox"; +export * from "./TimeBoard"; diff --git a/src/styles/_global.scss b/src/styles/_global.scss index fca9c24..475e916 100644 --- a/src/styles/_global.scss +++ b/src/styles/_global.scss @@ -13,6 +13,15 @@ body { color: libs.$BLUISH-GRAY-800; } +ul { + list-style: none; +} +button { + &:hover { + cursor: pointer; + } +} + html { font-size: 16px; } From a0ea8ba32e457609cea4a2de8f6f384da20cee5d Mon Sep 17 00:00:00 2001 From: june Date: Fri, 31 Jan 2025 22:29:40 +0900 Subject: [PATCH 2/2] =?UTF-8?q?feat:=20JCL-73=20=EB=B2=84=ED=8A=BC?= =?UTF-8?q?=EC=97=90=20selected=20=EC=83=81=ED=83=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/atoms/Button/index.module.scss | 5 +++++ src/components/atoms/Button/index.stories.tsx | 9 +++++++++ src/components/atoms/Button/index.tsx | 3 +++ 3 files changed, 17 insertions(+) diff --git a/src/components/atoms/Button/index.module.scss b/src/components/atoms/Button/index.module.scss index afa1103..71b57e8 100644 --- a/src/components/atoms/Button/index.module.scss +++ b/src/components/atoms/Button/index.module.scss @@ -68,4 +68,9 @@ @include spinner-rotation; } } + + &.selected { + color: $GRAY-50; + background-color: $BLUE-300; + } } diff --git a/src/components/atoms/Button/index.stories.tsx b/src/components/atoms/Button/index.stories.tsx index 9e8f33e..284f296 100644 --- a/src/components/atoms/Button/index.stories.tsx +++ b/src/components/atoms/Button/index.stories.tsx @@ -85,3 +85,12 @@ export const Loading: Story = { isLoading: true, }, }; + +export const Selected: Story = { + args: { + size: "normal", + border: true, + children: "Button", + isSelected: true, + }, +}; diff --git a/src/components/atoms/Button/index.tsx b/src/components/atoms/Button/index.tsx index 3e03285..7e0d51d 100644 --- a/src/components/atoms/Button/index.tsx +++ b/src/components/atoms/Button/index.tsx @@ -17,6 +17,7 @@ export interface ButtonProps extends HtmlButtonProps { fontSize?: FontSizeType; fontWeight?: FontWeightType; isLoading?: boolean; + isSelected?: boolean; } export const Button = ({ @@ -28,6 +29,7 @@ export const Button = ({ fontWeight = 400, isLoading = false, disabled, + isSelected, ...props }: ButtonProps) => { return ( @@ -40,6 +42,7 @@ export const Button = ({ ${styles[`font-size-${fontSize}`]} ${styles[`font-weight-${fontWeight}`]} ${styles[isLoading ? "loading" : ""]} + ${styles[isSelected ? "selected" : ""]} ${className}`, )} {...props}