From f2acfc1a19930ae0a6a59e225d04712626d94fab Mon Sep 17 00:00:00 2001 From: ss0526100 Date: Wed, 7 Aug 2024 12:25:38 +0900 Subject: [PATCH 1/7] =?UTF-8?q?feat:=20=EC=9C=A0=ED=8B=B8=20=ED=83=80?= =?UTF-8?q?=EC=9E=85=20(entries)=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/common/theme/coloredTypography.ts | 20 +++ frontend/src/common/theme/semantic.ts | 2 +- frontend/src/common/theme/theme.type.ts | 25 ++++ .../src/components/Button/Button.stories.tsx | 14 ++ .../src/components/Button/Button.style.ts | 122 ++++++++++++++---- frontend/src/components/Button/Button.tsx | 21 ++- frontend/src/types/index.d.ts | 4 + 7 files changed, 175 insertions(+), 33 deletions(-) create mode 100644 frontend/src/common/theme/coloredTypography.ts create mode 100644 frontend/src/components/Button/Button.stories.tsx diff --git a/frontend/src/common/theme/coloredTypography.ts b/frontend/src/common/theme/coloredTypography.ts new file mode 100644 index 000000000..986ba61e8 --- /dev/null +++ b/frontend/src/common/theme/coloredTypography.ts @@ -0,0 +1,20 @@ +import { ColoredTypography, Typography } from './theme.type'; + +import { Entries } from '@_types/index'; +import { css } from '@emotion/react'; +import typography from './typography'; + +const coloredTypography: ColoredTypography = ( + Object.entries(typography) as Entries +).reduce((object, [key, style]) => { + object[key] = (fontColor: string) => { + return css` + ${style} + color:${fontColor}; + `; + }; + + return object; +}, {} as ColoredTypography); + +export default coloredTypography; diff --git a/frontend/src/common/theme/semantic.ts b/frontend/src/common/theme/semantic.ts index a11bfc8c4..878ea7bfd 100644 --- a/frontend/src/common/theme/semantic.ts +++ b/frontend/src/common/theme/semantic.ts @@ -1,7 +1,7 @@ import colorPalette from './colorPalette'; const semantic = { - primary: colorPalette.orange[400], + primary: colorPalette.orange[300], secondary: colorPalette.orange[50], disabled: colorPalette.grey[300], }; diff --git a/frontend/src/common/theme/theme.type.ts b/frontend/src/common/theme/theme.type.ts index 1fe9ebcae..9970743c2 100644 --- a/frontend/src/common/theme/theme.type.ts +++ b/frontend/src/common/theme/theme.type.ts @@ -42,6 +42,31 @@ export interface Typography { tag: SerializedStyles; } +export interface ColoredTypography { + h1: (fontColor: string) => SerializedStyles; + h2: (fontColor: string) => SerializedStyles; + h3: (fontColor: string) => SerializedStyles; + h4: (fontColor: string) => SerializedStyles; + h5: (fontColor: string) => SerializedStyles; + s1: (fontColor: string) => SerializedStyles; + s2: (fontColor: string) => SerializedStyles; + b1: (fontColor: string) => SerializedStyles; + b2: (fontColor: string) => SerializedStyles; + b3: (fontColor: string) => SerializedStyles; + b4: (fontColor: string) => SerializedStyles; + c1: (fontColor: string) => SerializedStyles; + c2: (fontColor: string) => SerializedStyles; + c3: (fontColor: string) => SerializedStyles; + label: (fontColor: string) => SerializedStyles; + ButtonFont: (fontColor: string) => SerializedStyles; + Typeface: (fontColor: string) => SerializedStyles; + Giant: (fontColor: string) => SerializedStyles; + Large: (fontColor: string) => SerializedStyles; + Medium: (fontColor: string) => SerializedStyles; + small: (fontColor: string) => SerializedStyles; + Tiny: (fontColor: string) => SerializedStyles; + tag: (fontColor: string) => SerializedStyles; +} export interface Layout { default: SerializedStyles; } diff --git a/frontend/src/components/Button/Button.stories.tsx b/frontend/src/components/Button/Button.stories.tsx new file mode 100644 index 000000000..9a8b75724 --- /dev/null +++ b/frontend/src/components/Button/Button.stories.tsx @@ -0,0 +1,14 @@ +import type { Meta, StoryObj } from '@storybook/react'; + +import Button from './Button'; + +const meta: Meta = { + component: Button, +}; + +export default meta; +type Story = StoryObj; + +export const Default: Story = { + args: {}, +}; diff --git a/frontend/src/components/Button/Button.style.ts b/frontend/src/components/Button/Button.style.ts index 025dfbe55..a3d4e94b9 100644 --- a/frontend/src/components/Button/Button.style.ts +++ b/frontend/src/components/Button/Button.style.ts @@ -1,6 +1,8 @@ -import { css, Theme } from '@emotion/react'; +import { Theme, css } from '@emotion/react'; -const font = css` +import { ButtonProps } from './Button'; + +const defaultFont = css` font-size: 1.6rem; font-weight: 700; font-style: normal; @@ -8,33 +10,83 @@ const font = css` color: #fff; letter-spacing: -0.032rem; `; -export const shapes = ( - shape: 'circle' | 'bar', - disabled: boolean, - theme: Theme, -) => { - if (shape === 'circle') { + +type themeStyleArgs = Pick< + ButtonProps, + 'disabled' | 'primary' | 'secondary' | 'reversePrimary' +> & { theme: Theme }; + +const themeStyle = ({ + theme, + disabled, + primary, + secondary, + reversePrimary, +}: themeStyleArgs) => { + if (disabled) { return css` - ${font}; - flex-shrink: 0; + pointer-events: none; + color: ${theme.colorPalette.white[100]}; + background-color: ${theme.semantic.disabled}; + `; + } + if (primary) { + return css` + color: ${theme.colorPalette.white[100]}; + background-color: ${theme.semantic.primary}; - background: ${disabled - ? theme.colorPalette.grey[300] - : theme.colorPalette.white[100]}; - border: none; - border-radius: 50%; - box-shadow: 0 0 3px #444; + &:active { + background-color: ${theme.colorPalette.orange[900]}; + } + `; + } + if (secondary) { + return css` + color: ${theme.colorPalette.white[100]}; + background-color: ${theme.semantic.secondary}; &:active { - background-color: #868e96; + background-color: ${theme.colorPalette.yellow[300]}; } `; } + + if (reversePrimary) { + return css` + color: ${theme.semantic.primary}; + background-color: ${theme.colorPalette.white[100]}; + border: solid 1px ${theme.semantic.primary}; + + &:active { + background-color: ${theme.colorPalette.grey[300]}; + } + `; + } + + // default:primary + return css` + color: ${theme.colorPalette.white}; + background-color: ${theme.semantic.primary}; + + &:active { + background-color: ${theme.colorPalette.orange[500]}; + } + `; +}; + +type shapeStyleArgs = Pick; + +const shapeStyle = ({ shape }: shapeStyleArgs) => { + if (shape === 'circle') { + return css` + border: none; + border-radius: 50%; + box-shadow: 0 0 3px #444; + `; + } if (shape === 'bar') { return css` - ${font} display: flex; - flex-shrink: 0; gap: 1rem; align-items: center; justify-content: center; @@ -43,17 +95,31 @@ export const shapes = ( height: 6.4rem; padding: 1.6rem 5.9rem; - background: ${disabled - ? theme.colorPalette.grey[300] - : theme.colorPalette.orange[300]}; border: none; border-radius: 3rem; - - &:active { - background-color: ${disabled - ? theme.colorPalette.grey[400] - : theme.colorPalette.orange[400]}; - } `; } }; + +type ShapeArgs = ButtonProps & { theme: Theme }; +export const shapes = ({ + theme, + shape, + + disabled, + primary, + reversePrimary, + + secondary, +}: ShapeArgs) => { + const defaultStyle = css` + user-select: none; + flex-shrink: 0; + `; + return [ + defaultStyle, + defaultFont, + shapeStyle({ shape }), + themeStyle({ theme, disabled, primary, secondary, reversePrimary }), + ]; +}; diff --git a/frontend/src/components/Button/Button.tsx b/frontend/src/components/Button/Button.tsx index bba51813d..baf189cd6 100644 --- a/frontend/src/components/Button/Button.tsx +++ b/frontend/src/components/Button/Button.tsx @@ -1,20 +1,33 @@ +import { + Interpolation, + SerializedStyles, + Theme, + useTheme, +} from '@emotion/react'; + import { ReactNode } from 'react'; import { shapes } from '@_components/Button/Button.style'; import { useTheme } from '@emotion/react'; -interface ButtonProps { +export interface ButtonProps { shape: 'circle' | 'bar'; onClick?: () => void; - disabled: boolean; + disabled?: boolean; + primary?: boolean; + secondary?: boolean; + reversePrimary?: boolean; + hasBorder?: boolean; + + font?: SerializedStyles | Interpolation; children: ReactNode; } export default function Button(props: ButtonProps) { - const { shape, onClick, disabled, children } = props; + const { onClick, disabled, children, font } = props; const theme = useTheme(); return (