diff --git a/.hintrc b/.hintrc new file mode 100644 index 0000000..2fa1a2e --- /dev/null +++ b/.hintrc @@ -0,0 +1,13 @@ +{ + "extends": [ + "development" + ], + "hints": { + "axe/forms": [ + "default", + { + "select-name": "off" + } + ] + } +} \ No newline at end of file diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml new file mode 100644 index 0000000..a55e7a1 --- /dev/null +++ b/.idea/codeStyles/codeStyleConfig.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/apps/team-styled/next-env.d.ts b/apps/team-styled/next-env.d.ts index 4f11a03..574313a 100644 --- a/apps/team-styled/next-env.d.ts +++ b/apps/team-styled/next-env.d.ts @@ -3,3 +3,11 @@ // NOTE: This file should not be edited // see https://nextjs.org/docs/basic-features/typescript for more information. + +declare module '*.svg' { + import React = require('react'); + + export const ReactComponent: REact.FC>; + const src: string; + export default src; +} diff --git a/apps/team-styled/public/mg.png b/apps/team-styled/public/mg.png new file mode 100644 index 0000000..4206275 Binary files /dev/null and b/apps/team-styled/public/mg.png differ diff --git a/packages/chakra-ui-styled/src/components/Tag/Tag.stories.tsx b/packages/chakra-ui-styled/src/components/Tag/Tag.stories.tsx new file mode 100644 index 0000000..01db43f --- /dev/null +++ b/packages/chakra-ui-styled/src/components/Tag/Tag.stories.tsx @@ -0,0 +1,95 @@ +import styled from 'styled-components'; +import Tag, { TagProps, colorSchemeType } from './Tag'; + +export default { + title: 'chakra-ui-styled/components/Tag', + component: Tag, + parameters: { controls: { expanded: true } }, + + argTypes: { + children: { control: { type: 'text' } }, + size: { control: { type: 'select' } }, + colorScheme: { control: { type: 'select' } }, + variant: { control: { type: 'radio' } } + }, + args: { + children: '태그 테스트', + size: 'md', + colorScheme: 'blue', + variant: 'solid', + removeButton: true + } +}; +const Wrapper = styled.div` + display: flex; + flex-direction: column; + gap: 20px; +`; +const TagWrap = styled.div` + display: flex; + gap: 45px; + align-items: center; + + & > div { + display: flex; + flex-direction: column; + gap: 12px; + align-items: center; + justify-content: flex-start; + } +`; + +export const TagIndex = (args: TagProps) => { + const tagText: string = 'Tag'; + const colorArr: colorSchemeType[] = ['gray', 'blue', 'teal', 'green', 'red', 'purple', 'pink', 'orange']; + return ( + + Tag + + Tag Demo + + + + + Tag Index + {colorArr.map((color) => ( + + + + {tagText} + + + {tagText} + + + {tagText} + + + + + {tagText} + + + {tagText} + + + {tagText} + + + + + {tagText} + + + {tagText} + + + {tagText} + + + + ))} + + ); +}; +TagIndex.storyName = 'Tag'; diff --git a/packages/chakra-ui-styled/src/components/Tag/Tag.styled.tsx b/packages/chakra-ui-styled/src/components/Tag/Tag.styled.tsx new file mode 100644 index 0000000..53f7784 --- /dev/null +++ b/packages/chakra-ui-styled/src/components/Tag/Tag.styled.tsx @@ -0,0 +1,83 @@ +import styled, { css } from 'styled-components'; +import { TagProps } from './Tag'; +import { StyleText } from '../../foundation/typography/Text.styled'; + +const tagSize = { + lg: css` + gap: 8px; + height: 32px; + padding: 0 ${({ theme }) => theme.spacing[3]}; + `, + md: css` + gap: 6px; + height: 24px; + padding: 0 ${({ theme }) => theme.spacing[2]}; + `, + sm: css` + gap: 6px; + height: 20px; + padding: 0 ${({ theme }) => theme.spacing[2]}; + ` +}; +const tagText = { + lg: css` + ${({ theme }) => theme.typo.text.md}; + font-weight: ${({ theme }) => theme.typo.fontWeight.medium}; + line-height: 1.5; + `, + md: css` + ${({ theme }) => theme.typo.text.sm}; + font-weight: ${({ theme }) => theme.typo.fontWeight.medium}; + line-height: 1.3; + `, + sm: css` + ${({ theme }) => theme.typo.text.xs}; + font-weight: ${({ theme }) => theme.typo.fontWeight.medium}; + ` +}; + +export const TagStyle = styled.div` + ${({ theme, variant, colorScheme }) => css` + display: inline-flex; + align-items: center; + align-self: flex-start; + justify-content: center; + justify-self: flex-start; + width: auto; + border-radius: ${theme.radii.md}rem; + ${variant === 'solid' + ? css` + color: ${theme.color.white.white}; + background-color: ${theme.color[colorScheme][500]}; + border: 1px solid ${theme.color[colorScheme][500]}; + ` + : variant === 'subtle' + ? css` + color: ${theme.color[colorScheme][800]}; + background-color: ${theme.color[colorScheme][200]}; + border: 1px solid ${theme.color[colorScheme][200]}; + ` + : variant === 'outline' + ? css` + color: ${theme.color[colorScheme][600]}; + background-color: transparent; + border: 1px solid ${theme.color[colorScheme][500]}; + ` + : null} + `} + & .tag-remove-btn { + display: flex; + align-items: center; + justify-content: center; + color: inherit; + background: transparent; + border: 0 none; + outline: none; + } + + & ${StyleText} { + ${({ size }) => tagText[size]} + } + + ${({ size }) => tagSize[size]} +`; diff --git a/packages/chakra-ui-styled/src/components/Tag/Tag.tsx b/packages/chakra-ui-styled/src/components/Tag/Tag.tsx new file mode 100644 index 0000000..42af231 --- /dev/null +++ b/packages/chakra-ui-styled/src/components/Tag/Tag.tsx @@ -0,0 +1,37 @@ +import { StyleText } from '../../foundation/typography/Text.styled'; +import { TagStyle } from './Tag.styled'; + +export type colorSchemeType = 'blue' | 'gray' | 'teal' | 'red' | 'orange' | 'yellow' | 'pink' | 'purple' | 'green'; + +export interface TagProps { + variant: 'solid' | 'subtle' | 'outline'; + size: 'lg' | 'md' | 'sm'; + colorScheme: colorSchemeType; + children: React.ReactNode; + removeButton?: boolean; +} +const RemoveIcon = () => { + return ( + + + + ); +}; +const Tag = ({ children, colorScheme, variant, removeButton, size }: TagProps) => { + return ( + + {children && {children}} + {removeButton && ( + + + + )} + + ); +}; + +export default Tag; diff --git a/packages/chakra-ui-styled/src/components/badge/Badge.stories.tsx b/packages/chakra-ui-styled/src/components/badge/Badge.stories.tsx new file mode 100644 index 0000000..be98cd5 --- /dev/null +++ b/packages/chakra-ui-styled/src/components/badge/Badge.stories.tsx @@ -0,0 +1,61 @@ +import styled from 'styled-components'; +import Badge, { BadgeProps, colorSchemeType } from './Badge'; + +export default { + title: 'chakra-ui-styled/components/Badge', + component: Badge, + parameters: { controls: { expanded: true } }, + + argTypes: { + variant: { control: { type: 'radio' } }, + colorScheme: { control: { type: 'select' } }, + children: { control: { type: 'text' } }, + }, + args: { + variant: 'solid', + colorScheme: 'blue', + children: '뱃지 테스트', + } +}; +const Wrapper = styled.div` + display: flex; + flex-direction: column; + gap: 20px; +`; +const BtnBox = styled.div` + display: flex; + gap: 16px; + align-items: center; +`; + +export const BadgeIndex = (args: BadgeProps) => { + const BadgeText: string = 'BADGE'; + const colorArr: colorSchemeType[] = ['gray', 'blue', 'teal', 'green', 'red', 'purple', 'pink', 'orange']; + return ( + + Badge + + Badge Demo + + + + + Badge Index + + {colorArr.map((color) => ( + + + {BadgeText} + + + {BadgeText} + + + {BadgeText} + + + ))} + + ); +}; +BadgeIndex.storyName = 'Badge'; diff --git a/packages/chakra-ui-styled/src/components/badge/Badge.styled.tsx b/packages/chakra-ui-styled/src/components/badge/Badge.styled.tsx new file mode 100644 index 0000000..728438a --- /dev/null +++ b/packages/chakra-ui-styled/src/components/badge/Badge.styled.tsx @@ -0,0 +1,35 @@ +import styled, { css } from 'styled-components'; +import { BadgeProps } from './Badge'; + +export const StyleBadge = styled.div` + ${({ theme, variant, colorScheme }) => css` + display: inline-flex; + align-items: center; + align-self: flex-start; + justify-content: center; + justify-self: flex-start; + width: auto; + height: 16px; + padding: 0 ${theme.spacing[1]}; + border-radius: ${theme.radii.sm}rem; + ${variant === 'solid' + ? css` + color: ${theme.color.white.white}; + background-color: ${theme.color[colorScheme][500]}; + border: 1px solid ${theme.color[colorScheme][500]}; + ` + : variant === 'subtle' + ? css` + color: ${theme.color[colorScheme][800]}; + background-color: ${theme.color[colorScheme][100]}; + border: 1px solid ${theme.color[colorScheme][100]}; + ` + : variant === 'outline' + ? css` + color: ${theme.color[colorScheme][600]}; + background-color: transparent; + border: 1px solid ${theme.color[colorScheme][500]}; + ` + : null} + `} +`; diff --git a/packages/chakra-ui-styled/src/components/badge/Badge.tsx b/packages/chakra-ui-styled/src/components/badge/Badge.tsx new file mode 100644 index 0000000..f22579a --- /dev/null +++ b/packages/chakra-ui-styled/src/components/badge/Badge.tsx @@ -0,0 +1,21 @@ +import { StyleText } from '../../foundation/typography/Text.styled'; +import { StyleBadge } from './Badge.styled'; + +export type colorSchemeType = 'blue' | 'gray' | 'teal' | 'red' | 'orange' | 'yellow' | 'pink' | 'purple' | 'green'; + +export interface BadgeProps { + colorScheme: colorSchemeType; + variant: 'solid' | 'subtle' | 'outline'; + children: React.ReactNode; +} + +const Badge = ({ variant = 'solid', colorScheme, children }: BadgeProps) => { + return ( + + + {children} + + + ); +}; +export default Badge; diff --git a/packages/chakra-ui-styled/src/components/date-display/card/Card.stories.tsx b/packages/chakra-ui-styled/src/components/date-display/card/Card.stories.tsx new file mode 100644 index 0000000..b1dff30 --- /dev/null +++ b/packages/chakra-ui-styled/src/components/date-display/card/Card.stories.tsx @@ -0,0 +1,32 @@ +import Card from './Card'; +import { ReactNode } from 'react'; + +export type CardType = { + variant: 'elevated' | 'filled' | 'outline'; + children?: ReactNode; +}; +export default { + title: 'chakra-ui-styled/components/date-display/card', + component: Card, + parameter: { controls: { expanded: true } }, + argTypes: {}, + arg: { + variant: 'outline' + } +}; + +export const TableIndex = (args: CardType) => { + return ( + <> + Demo + Demo test + + + + + + > + ); +}; + +TableIndex.storyName = 'Table'; diff --git a/packages/chakra-ui-styled/src/components/date-display/card/Card.tsx b/packages/chakra-ui-styled/src/components/date-display/card/Card.tsx new file mode 100644 index 0000000..a734f7d --- /dev/null +++ b/packages/chakra-ui-styled/src/components/date-display/card/Card.tsx @@ -0,0 +1,34 @@ +import styled, { css } from 'styled-components'; +import { CardType } from './Card.stories'; + +const Card = ({ children, variant }: CardType) => { + return ( + <> + {children} + > + ); +}; + +const Container = styled.article` + min-width: 350px; + padding: 20px; + border-radius: 8px; + ${({ variant }) => { + return variant === 'elevated' + ? css` + background-color: white; + box-shadow: + 0 1px 3px #0001, + 0 1px 2px #00000006; + ` + : variant === 'filled' + ? css` + background-color: #e2e8f0; + ` + : css` + border: 1px solid #e2e8f0; + `; + }}; +`; + +export default Card; diff --git a/packages/chakra-ui-styled/src/components/date-display/stats/Stats.stories.tsx b/packages/chakra-ui-styled/src/components/date-display/stats/Stats.stories.tsx new file mode 100644 index 0000000..87c6950 --- /dev/null +++ b/packages/chakra-ui-styled/src/components/date-display/stats/Stats.stories.tsx @@ -0,0 +1,30 @@ +import Stats from './Stats'; + +export type StatsType = { + label: string; + number: string; + text: string; + type: 'increase' | 'decrease' | 'none'; +}; +export default { + title: 'chakra-ui-styled/components/date-display/stat', + component: Stats, + parameter: { controls: { expanded: true } }, + argTypes: {}, + arg: {} +}; + +export const StatsIndex = (args: StatsType) => { + return ( + <> + Demo + + + + + + > + ); +}; + +StatsIndex.storyName = 'Stat'; diff --git a/packages/chakra-ui-styled/src/components/date-display/stats/Stats.tsx b/packages/chakra-ui-styled/src/components/date-display/stats/Stats.tsx new file mode 100644 index 0000000..8f10c0d --- /dev/null +++ b/packages/chakra-ui-styled/src/components/date-display/stats/Stats.tsx @@ -0,0 +1,63 @@ +import { createContext } from 'react'; +import styled, { css } from 'styled-components'; +import { StatsType } from './Stats.stories'; + +const Stats = ({ label, number, text, type = 'none' }: StatsType) => { + return ( + + {label} + {number} + {type === 'increase' && ( + + + + + {text} + + )} + {type === 'decrease' && ( + + + + + {text} + + )} + {type === 'none' && {text}} + + ); +}; + +const Container = styled.div` + display: flex; + flex-direction: column; + gap: 4px; +`; +const StatLabel = styled.p` + ${({ theme }) => css` + color: ${theme.color.gray['700']}; + + font-size: ${theme.typo.text['sm'].fontSize}; + font-weight: ${theme.typo.text['sm'].fontWeight}; + `} +`; +const StatNumber = styled.p` + ${({ theme }) => css` + color: ${theme.color.gray['700']}; + + font-size: ${theme.typo.text['2xl'].fontSize}; + font-weight: ${theme.typo.fontWeight.semibold}; + `} +`; +const StatText = styled.p` + ${({ theme }) => css` + display: flex; + align-items: center; + font-size: ${theme.typo.text['sm'].fontSize}; + font-weight: ${theme.typo.text['sm'].fontWeight}; + color: ${theme.color.gray['700']}; + opacity: 0.8; + `} +`; + +export default Stats; diff --git a/packages/chakra-ui-styled/src/components/date-display/stats/assets/icon-dec.svg b/packages/chakra-ui-styled/src/components/date-display/stats/assets/icon-dec.svg new file mode 100644 index 0000000..808fddc --- /dev/null +++ b/packages/chakra-ui-styled/src/components/date-display/stats/assets/icon-dec.svg @@ -0,0 +1,3 @@ + + + diff --git a/packages/chakra-ui-styled/src/components/date-display/stats/assets/icon-inc.svg b/packages/chakra-ui-styled/src/components/date-display/stats/assets/icon-inc.svg new file mode 100644 index 0000000..3f36884 --- /dev/null +++ b/packages/chakra-ui-styled/src/components/date-display/stats/assets/icon-inc.svg @@ -0,0 +1,3 @@ + + + diff --git a/packages/chakra-ui-styled/src/components/date-display/table/Table.stories.tsx b/packages/chakra-ui-styled/src/components/date-display/table/Table.stories.tsx new file mode 100644 index 0000000..f8c6689 --- /dev/null +++ b/packages/chakra-ui-styled/src/components/date-display/table/Table.stories.tsx @@ -0,0 +1,76 @@ +import Table from './Table'; +import { progressType } from '../../feedback/progress/Progress.stories'; +import styled from 'styled-components'; + +export type ColumnType = { field: string }; +export type RowType = { [key: string]: string }; +const columnDefs: ColumnType[] = [ + { + field: 'one' + }, + { + field: 'kName' + }, + { + field: 'name' + } +]; +const rowDatas: RowType[] = [ + { + one: 'one', + name: 'one', + kName: '하나' + }, + { + one: 'two', + name: 'two', + kName: '두' + }, + { + one: 'three', + name: 'three', + kName: '셋' + } +]; +export type TableType = { + rD?: RowType[]; + cD?: ColumnType[]; + variant: 'unstyled' | 'striped' | 'simple'; +}; +export default { + title: 'chakra-ui-styled/components/date-display/table', + component: Table, + parameter: { controls: { expanded: true } }, + argTypes: {}, + arg: { + columnDefs, + rowDatas, + variant: 'unstyled' + } +}; + +export const TableIndex = (args: TableType) => { + return ( + <> + + Demo + + + + + + + > + ); +}; + +const Container = styled.div` + width: 100%; + height: 100%; + background-color: #eee; + padding: 24px; + display: flex; + flex-direction: column; + gap: 24px; +`; +TableIndex.storyName = 'Table'; diff --git a/packages/chakra-ui-styled/src/components/date-display/table/Table.tsx b/packages/chakra-ui-styled/src/components/date-display/table/Table.tsx new file mode 100644 index 0000000..1a59e27 --- /dev/null +++ b/packages/chakra-ui-styled/src/components/date-display/table/Table.tsx @@ -0,0 +1,92 @@ +import styled, { css } from 'styled-components'; +import { useState } from 'react'; +import { ColumnType, RowType, TableType } from './Table.stories'; +import { theme } from '../../../styles/ChakraThemeProvider'; + +const Table = ({ rD, cD, variant }: TableType) => { + const [columnDefs, setColumnDefs] = useState(cD || []); + const [rowDatas, setRowData] = useState(rD || []); + + const titles: string[] = columnDefs.map((columnDef) => columnDef.field); + return ( + <> + + + {titles.map((title, index) => ( + {title} + ))} + + {rowDatas.map((rowData, rIndex) => ( + + {titles.map((title, cIndex) => ( + {rowData[title]} + ))} + + ))} + + > + ); +}; + +const Container = styled.article` + padding: 12px; + border-radius: 12px; + background-color: white; + border: 1px solid #e2e8f0; + font-size: ${({ theme }) => theme.typo.text.xs.fontSize}; + color: ${theme.color.gray[700]}; + + ${({ variant, theme }) => { + switch (variant) { + case 'unstyled': + return css` + border: none; + ${TableRow} { + border: none; + } + `; + case 'simple': + return css` + ${TableRow} { + border-bottom: 1px solid ${theme.color.gray['200']}; + &:last-child { + border: none; + } + } + `; + case 'striped': + return css` + ${TableRow}:nth-child(even) { + background-color: ${theme.color.gray['100']}; + } + `; + default: + return css``; + } + }} +`; +const HeadingRow = styled.section` + &:first-child { + font-weight: ${({ theme }) => theme.typo.fontWeight.bold}; + } + display: flex; +`; +const TableRow = styled.section` + display: flex; + padding: 16px 24px; +`; +const TitleColumn = styled.div` + flex: 1; + padding: 16px 24px; +`; + +const RowData = styled.div` + flex: 1; + font-size: ${({ theme }) => theme.typo.text.sm.fontSize}; + + &:first-child { + font-weight: ${({ theme }) => theme.typo.fontWeight.medium}; + } +`; +// accent : font medium : regular +export default Table; diff --git a/packages/chakra-ui-styled/src/components/disclosure/accordion/Accordion.stories.tsx b/packages/chakra-ui-styled/src/components/disclosure/accordion/Accordion.stories.tsx new file mode 100644 index 0000000..e8f4535 --- /dev/null +++ b/packages/chakra-ui-styled/src/components/disclosure/accordion/Accordion.stories.tsx @@ -0,0 +1,65 @@ +import Accordion from './Accordion'; +import styled from 'styled-components'; +import { ReactNode } from 'react'; + +export type accordionType = { + state: boolean; + title?: string; + text?: string; + children?: ReactNode; +}; + +export default { + title: 'chakra-ui-styled/components/disclosure/accordion', + component: Accordion, + parameter: { controls: { expanded: true } }, + argTypes: { + state: { + control: { + type: 'boolean', + title: 'Accordion Button', + text: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.' + } + } + } +}; + +const Container = styled.div``; +export const AccordionComponent = (args: accordionType) => { + return ( + <> + + Accordion Demo + + + + + + + + + + + + + + + + + + + + + > + ); +}; +AccordionComponent.storyName = 'Accordion'; diff --git a/packages/chakra-ui-styled/src/components/disclosure/accordion/Accordion.tsx b/packages/chakra-ui-styled/src/components/disclosure/accordion/Accordion.tsx new file mode 100644 index 0000000..6853063 --- /dev/null +++ b/packages/chakra-ui-styled/src/components/disclosure/accordion/Accordion.tsx @@ -0,0 +1,88 @@ +import { accordionType } from './Accordion.stories'; +import { createContext, ReactNode, useContext, useState } from 'react'; +import styled, { css } from 'styled-components'; + +const AccordionContext = createContext({ + isOpen: false, + setIsOpen: (value: boolean) => {} +}); + +const Accordion = ({ state, children }: accordionType) => { + const [isOpen, setIsOpen] = useState(state); + const providerValue = { + isOpen, + setIsOpen + }; + return ( + + {children} + + ); +}; + +const Toggle = ({ title, children }: { title: string; children?: ReactNode }) => { + const { isOpen, setIsOpen } = useContext(AccordionContext); + + return ( + setIsOpen(!isOpen)}> + + {title} + + + + + + + {children} + + ); +}; + +const Panel = ({ text }: { text: string }) => { + const { isOpen } = useContext(AccordionContext); + + return isOpen && {text}; +}; + +Accordion.Toggle = Toggle; +Accordion.Panel = Panel; + +export default Accordion; + +const TitleBox = styled.div<{ isOpen: boolean }>` + display: flex; + justify-content: space-between; + flex: 1; + width: inherit; + max-width: 345px; + user-select: none; + ${({ isOpen }) => + isOpen && + css` + div { + transform: rotate(180deg); + } + `} +`; +const TextBox = styled.div` + font-size: 16px; + font-weight: 400; +`; + +const Container = styled.article` + display: flex; + justify-content: space-between; + align-items: center; + width: 403px; + border-block: 1px solid #d0d0d0; + padding: 10px 12px; + h5 { + font-size: 16px; + font-weight: 400; + } + > div { + display: flex; + width: 100%; + flex-direction: column; + } +`; diff --git a/packages/chakra-ui-styled/src/components/disclosure/accordion/asset/AccordionIcon.svg b/packages/chakra-ui-styled/src/components/disclosure/accordion/asset/AccordionIcon.svg new file mode 100644 index 0000000..2b23fec --- /dev/null +++ b/packages/chakra-ui-styled/src/components/disclosure/accordion/asset/AccordionIcon.svg @@ -0,0 +1,3 @@ + + + diff --git a/packages/chakra-ui-styled/src/components/disclosure/tabs/Tabs.stories.tsx b/packages/chakra-ui-styled/src/components/disclosure/tabs/Tabs.stories.tsx new file mode 100644 index 0000000..3915295 --- /dev/null +++ b/packages/chakra-ui-styled/src/components/disclosure/tabs/Tabs.stories.tsx @@ -0,0 +1,77 @@ +import Tabs from './Tabs'; +import { tabType } from './tab/tab.types'; +import styled from 'styled-components'; + +export default { + title: 'chakra-ui-styled/components/disclosure/tabs', + component: Tabs, + parameter: { controls: { expanded: true } }, + argTypes: { + size: { + control: { + type: 'select' + } + }, + styleType: { + control: { + type: 'select' + } + }, + active: { + control: { + type: 'boolean' + } + }, + arg: { + size: 'lg', + styleType: 'unstyled', + active: 'true', + text: 'Tabs' + } + } +}; + +const Container = styled.div` + background-color: #eee; +`; + +export const TabsComponent = (args: tabType) => { + return ( + + Tabs Demo + + + unstyled + + + + + + line Tabs + + + + + + enclosed Tabs + + + + + + soft-rounded Tabs + + + + + + solid-rounded Tabs + + + + + + ); +}; + +TabsComponent.storyName = 'Tabs'; diff --git a/packages/chakra-ui-styled/src/components/tabs/Tabs.styles.tsx b/packages/chakra-ui-styled/src/components/disclosure/tabs/Tabs.styles.tsx similarity index 100% rename from packages/chakra-ui-styled/src/components/tabs/Tabs.styles.tsx rename to packages/chakra-ui-styled/src/components/disclosure/tabs/Tabs.styles.tsx diff --git a/packages/chakra-ui-styled/src/components/disclosure/tabs/Tabs.tsx b/packages/chakra-ui-styled/src/components/disclosure/tabs/Tabs.tsx new file mode 100644 index 0000000..b92a3eb --- /dev/null +++ b/packages/chakra-ui-styled/src/components/disclosure/tabs/Tabs.tsx @@ -0,0 +1,44 @@ +import styled, { css } from 'styled-components'; +import Tab from './tab/Tab'; +import { tabType } from './tab/tab.types'; + +const Container = styled.div` + ${({ theme }) => css` + display: flex; + > div { + border-bottom: 2px solid ${theme.color.gray[200]}; + } + h2 { + span { + font-weight: 400; + } + } + `} +`; +// active 를 기본값 null false, true 면 true; +const Tabs = ({ size, styleType, active, text }: tabType) => { + return ( + + + + + + ); +}; + +// tab atoms 종류 +// +// unstyled +// soft-rounded +// solid-rounded +// enclosed +// line +// +// tab 사이즈 +// +// lg +// md +// sm +// tabs 종류별 1묶음으로 크기 분류 + +export default Tabs; diff --git a/packages/chakra-ui-styled/src/components/disclosure/tabs/tab/Tab.stories.tsx b/packages/chakra-ui-styled/src/components/disclosure/tabs/tab/Tab.stories.tsx new file mode 100644 index 0000000..f1d0ed2 --- /dev/null +++ b/packages/chakra-ui-styled/src/components/disclosure/tabs/tab/Tab.stories.tsx @@ -0,0 +1,84 @@ +import Tab from './Tab'; +import { tabType } from './tab.types'; +import styled from 'styled-components'; +// import { TextComponent } from '../../../../foundation/typography/Text.styled'; + +export default { + title: 'chakra-ui-styled/components/tabs', + component: Tab, + parameter: { controls: { expanded: true } }, + argTypes: { + size: { + control: { + type: 'select' + } + }, + styleType: { + control: { + type: 'select' + } + }, + active: { + control: { + type: 'boolean' + } + }, + arg: { + size: 'lg', + styleType: 'unstyled', + active: 'true', + text: 'Tabs' + } + } +}; +const DemoContainer = styled.div` + padding: 2rem; + background-color: #ddd; +`; +const Container = styled.div` + display: flex; + flex-direction: column; + gap: 16px; + div { + display: flex; + gap: 16px; + } + background-color: #eee; + padding: 2rem; +`; +export const TabComponent = (args: tabType) => { + return ( + + Tab + + demo + + + + + + + + + + + + + + + + + + + + + + + + + + + ); +}; + +TabComponent.storyName = 'Tab'; diff --git a/packages/chakra-ui-styled/src/components/disclosure/tabs/tab/Tab.tsx b/packages/chakra-ui-styled/src/components/disclosure/tabs/tab/Tab.tsx new file mode 100644 index 0000000..599a27d --- /dev/null +++ b/packages/chakra-ui-styled/src/components/disclosure/tabs/tab/Tab.tsx @@ -0,0 +1,117 @@ +import styled, { css } from 'styled-components'; +import { tabType } from './tab.types'; +import { TextComponent } from '../../../../foundation/typography/Text'; +// +// export const sizeStyles = { +// sm: css` +// padding: ${({ theme }) => theme.spacing[4]} ${({ theme }) => theme.spacing[1]}; +// background-color: transparent; +// `, +// md: css` +// padding: ${({ theme }) => theme.spacing[4]} ${({ theme }) => theme.spacing[2]}; +// background-color: transparent; +// `, +// lg: css` +// padding: ${({ theme }) => theme.spacing[4]} ${({ theme }) => theme.spacing[3]}; +// background-color: transparent; +// ` +// }; +// +// export const tabStyle = { +// unstyled: css` +// background-color: transparent; +// border: none; +// `, +// line: css` +// color: ${({ theme }) => theme.color.blue[600]}; +// border-bottom: 2px solid ${({ theme }) => theme.color.blue[600]}; +// `, +// enclosed: css` +// color: ${({ theme }) => theme.color.blue[600]}; +// background-color: ${({ theme }) => theme.color.white.white}; +// border-top: ${({ theme }) => theme.spacing.px} solid ${({ theme }) => theme.color.gray[200]}; +// border-right: ${({ theme }) => theme.spacing.px} solid ${({ theme }) => theme.color.gray[200]}; +// border-left: ${({ theme }) => theme.spacing.px} solid ${({ theme }) => theme.color.gray[200]}; +// border-radius: ${({ theme }) => theme.radii.md} ${({ theme }) => theme.radii.md} 0 0; +// `, +// softRounded: css` +// color: ${({ theme }) => theme.color.blue[700]}; +// background-color: ${({ theme }) => theme.color.blue[100]}; +// border-radius: 999px; +// `, +// solidRounded: css` +// color: ${({ theme }) => theme.color.white.white}; +// background-color: ${({ theme }) => theme.color.blue[600]}; +// border-radius: 999px; +// ` +// }; + +const TabBtn = styled.div` + ${({ theme, size, active, styleType }) => { + const sizeStyles = { + sm: css` + padding: ${theme.spacing[1]} ${theme.spacing[4]}; + `, + md: css` + padding: ${theme.spacing[2]} ${theme.spacing[4]}; + `, + lg: css` + padding: ${theme.spacing[3]} ${theme.spacing[4]}; + ` + }; + const tabStyle = { + unstyled: css` + background-color: transparent !important; + border: none; + `, + line: css` + color: ${theme.color.blue[600]}; + background-color: transparent; + border-bottom: 2px solid ${theme.color.blue[600]}; + `, + enclosed: css` + color: ${theme.color.blue[600]}; + background-color: ${theme.color.white.white} !important; + border-top: ${theme.spacing.px} solid ${theme.color.gray[200]}; + border-right: ${theme.spacing.px} solid ${theme.color.gray[200]}; + border-left: ${theme.spacing.px} solid ${theme.color.gray[200]}; + border-radius: ${theme.radii.md} ${theme.radii.md} 0 0; + `, + softRounded: css` + color: ${theme.color.blue[700]}; + background-color: ${theme.color.blue[100]} !important; + border-radius: 999px; + `, + solidRounded: css` + color: ${theme.color.white.white}; + background-color: ${theme.color.blue[600]} !important; + border-radius: 999px; + ` + }; + return css` + ${active && tabStyle[styleType]} + ${sizeStyles[size]} + `; + }} +`; + +// TODO +// size = sm md lg 프롭스로 전달 후 +// {({size))=> size === 'sm' && } 식으로 작업하여 동적 작업하기. +const Tab = ({ size, styleType, active, text = 'Tabs' }: tabType) => { + //rounded = fsz semibold 그외 medium + + return ( + <> + + {/**/} + + {text} + + + + > + ); +}; + +export default Tab; diff --git a/packages/chakra-ui-styled/src/components/disclosure/tabs/tab/tab.types.ts b/packages/chakra-ui-styled/src/components/disclosure/tabs/tab/tab.types.ts new file mode 100644 index 0000000..adc2a0c --- /dev/null +++ b/packages/chakra-ui-styled/src/components/disclosure/tabs/tab/tab.types.ts @@ -0,0 +1,6 @@ +export interface tabType { + text?: string; + size: 'sm' | 'md' | 'lg'; + styleType: 'unstyled' | 'line' | 'enclosed' | 'softRounded' | 'solidRounded'; + active: boolean; +} diff --git a/packages/chakra-ui-styled/src/components/feedback/alert/Alert.stories.tsx b/packages/chakra-ui-styled/src/components/feedback/alert/Alert.stories.tsx new file mode 100644 index 0000000..007bc14 --- /dev/null +++ b/packages/chakra-ui-styled/src/components/feedback/alert/Alert.stories.tsx @@ -0,0 +1,89 @@ +import Alert from './Alert'; + +export type alertType = { + alertStyle: 'vanilla' | 'solid' | 'top-border' | 'left-border'; + variant: 'info' | 'warning' | 'error' | 'success'; + title?: string; + text?: string; +}; +export default { + title: 'chakra-ui-styled/components/feedback/alert', + component: Alert, + parameter: { controls: { expanded: true } }, + argTypes: { + alertStyle: { control: { type: 'select' } }, + variant: { control: { type: 'select' } }, + title: { control: { type: 'text' } }, + text: { control: { type: 'text' } } + }, + arg: { + variant: 'info', + alertStyle: 'vanilla', + title: 'Title', + text: 'This is a description.' + } +}; + +export const AlertIndex = (args: alertType) => { + return ( + <> + + Alert Demo + + + + Info + + + + + + + + + + + + + + warning + + + + + + + + + + + + error + + + + + + + + + + + + + success + + + + + + + + + + + + > + ); +}; +AlertIndex.storyName = 'Alert'; diff --git a/packages/chakra-ui-styled/src/components/feedback/alert/Alert.tsx b/packages/chakra-ui-styled/src/components/feedback/alert/Alert.tsx new file mode 100644 index 0000000..2797c36 --- /dev/null +++ b/packages/chakra-ui-styled/src/components/feedback/alert/Alert.tsx @@ -0,0 +1,97 @@ +import styled, { css } from 'styled-components'; +import Icon from './Icon'; +import { alertType } from './Alert.stories'; + +const demoTitle: alertType['title'] = 'Title'; +const demoText: alertType['text'] = 'This is a description.'; + +const Alert = ({ alertStyle, variant, title = demoTitle, text = demoText }: alertType) => { + return ( + + + + {title} + {text} + + + ); +}; + +const Container = styled.article` + display: flex; + align-items: center; + gap: 12px; + width: 400px; + height: 72px; + padding: 12px; + ${({ theme, variant }) => css` + background-color: ${variant === 'info' + ? theme.color.blue['100'] + : variant === 'warning' + ? theme.color.orange['100'] + : variant === 'error' + ? theme.color.red['100'] + : variant === 'success' + ? theme.color.green['100'] + : null}; + `}; + + ${({ variant, alertStyle, theme }) => css` + ${alertStyle === 'left-border' + ? css` + border-left-style: solid; + border-left-width: 4px; + border-left-color: ${variant === 'info' + ? theme.color.blue['500'] + : variant === 'warning' + ? theme.color.orange['500'] + : variant === 'error' + ? theme.color.red['500'] + : variant === 'success' + ? theme.color.green['500'] + : null}; + ` + : alertStyle === 'top-border' + ? css` + border-top-style: solid; + border-top-width: 4px; + border-top-color: ${variant === 'info' + ? theme.color.blue['500'] + : variant === 'warning' + ? theme.color.orange['500'] + : variant === 'error' + ? theme.color.red['500'] + : variant === 'success' + ? theme.color.green['500'] + : null}; + ` + : alertStyle === 'solid' + ? css` + color: ${theme.color.white.white}; + background-color: ${variant === 'info' + ? theme.color.blue['500'] + : variant === 'warning' + ? theme.color.orange['500'] + : variant === 'error' + ? theme.color.red['500'] + : variant === 'success' + ? theme.color.green['500'] + : null}; + ` + : null} + `} +`; +const TextBox = styled.div` + display: flex; + flex-direction: column; + h5 { + font-size: 17px; + font-weight: 700; + } + p { + font-size: 16px; + font-weight: 400; + } +`; + +export default Alert; diff --git a/packages/chakra-ui-styled/src/components/feedback/alert/Icon.tsx b/packages/chakra-ui-styled/src/components/feedback/alert/Icon.tsx new file mode 100644 index 0000000..36b5c89 --- /dev/null +++ b/packages/chakra-ui-styled/src/components/feedback/alert/Icon.tsx @@ -0,0 +1,60 @@ +import { alertType } from './Alert.stories'; + +type IconProps = { + alertStyle: alertType['alertStyle']; + variant: alertType['variant']; +}; +const Icon = ({ alertStyle, variant }: IconProps) => { + let color; + if (variant === 'info') { + color = alertStyle === 'solid' ? '#fff' : '#3182ce'; + return ( + <> + + + + > + ); + } else if (variant === 'error') { + color = alertStyle === 'solid' ? '#fff' : '#e53e3e'; + return ( + <> + + + + > + ); + } else if (variant === 'success') { + color = alertStyle === 'solid' ? '#fff' : '#38a169'; + return ( + <> + + + + > + ); + } else if (variant === 'warning') { + color = alertStyle === 'solid' ? '#fff' : '#dd6b20'; + return ( + <> + + + + > + ); + } +}; + +export default Icon; diff --git a/packages/chakra-ui-styled/src/components/feedback/alert/assets/errorIcon.svg b/packages/chakra-ui-styled/src/components/feedback/alert/assets/errorIcon.svg new file mode 100644 index 0000000..af22bd6 --- /dev/null +++ b/packages/chakra-ui-styled/src/components/feedback/alert/assets/errorIcon.svg @@ -0,0 +1,3 @@ + + + diff --git a/packages/chakra-ui-styled/src/components/feedback/alert/assets/infoIcon.svg b/packages/chakra-ui-styled/src/components/feedback/alert/assets/infoIcon.svg new file mode 100644 index 0000000..6f28670 --- /dev/null +++ b/packages/chakra-ui-styled/src/components/feedback/alert/assets/infoIcon.svg @@ -0,0 +1,3 @@ + + + diff --git a/packages/chakra-ui-styled/src/components/feedback/alert/assets/successIcon.svg b/packages/chakra-ui-styled/src/components/feedback/alert/assets/successIcon.svg new file mode 100644 index 0000000..2b54d8c --- /dev/null +++ b/packages/chakra-ui-styled/src/components/feedback/alert/assets/successIcon.svg @@ -0,0 +1,3 @@ + + + diff --git a/packages/chakra-ui-styled/src/components/feedback/alert/assets/warningIcon.svg b/packages/chakra-ui-styled/src/components/feedback/alert/assets/warningIcon.svg new file mode 100644 index 0000000..41da3e1 --- /dev/null +++ b/packages/chakra-ui-styled/src/components/feedback/alert/assets/warningIcon.svg @@ -0,0 +1,3 @@ + + + diff --git a/packages/chakra-ui-styled/src/components/feedback/progress/Progress.stories.tsx b/packages/chakra-ui-styled/src/components/feedback/progress/Progress.stories.tsx new file mode 100644 index 0000000..b5e9f21 --- /dev/null +++ b/packages/chakra-ui-styled/src/components/feedback/progress/Progress.stories.tsx @@ -0,0 +1,82 @@ +import Progress from './Progress'; + +export type progressType = { + progress: number; + size: 'xs' | 'sm' | 'md' | 'lg'; + color: string; +}; +export default { + title: 'chakra-ui-styled/components/feedback/progress', + component: Progress, + parameter: { controls: { expanded: true } }, + argTypes: { + progress: { + control: { + type: 'number' + } + }, + size: { + options: ['xs', 'sm', 'md', 'lg'], + control: { + type: 'select' + } + }, + color: { + options: ['green', 'blue', 'red', 'orange', 'pink', 'purple', 'teal'], + control: { + type: 'select' + } + } + }, + arg: { + progress: 10, + size: 'lg', + color: 'red' + } +}; + +export const ProgressIndex = (args: progressType) => { + console.log(args); + return ( + <> + + Progress Demo + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + > + ); +}; + +ProgressIndex.storyName = 'Progress'; diff --git a/packages/chakra-ui-styled/src/components/feedback/progress/Progress.tsx b/packages/chakra-ui-styled/src/components/feedback/progress/Progress.tsx new file mode 100644 index 0000000..63a0f8e --- /dev/null +++ b/packages/chakra-ui-styled/src/components/feedback/progress/Progress.tsx @@ -0,0 +1,302 @@ +import styled, { css } from 'styled-components'; +import { createContext, ReactNode, useContext, useEffect, useState } from 'react'; +import { progressType } from './Progress.stories'; + +export type contextType = progressType & { + children?: ReactNode; +}; + +const ProgressContext = createContext({ + color: 'green', + size: 'lg', + percent: 0, + setPercent: (value: number) => {} +}); + +const Progress = ({ color, size, progress, children }: contextType) => { + const [percent, setPercent] = useState(0); + const providerValue = { + color, + size, + percent, + setPercent + }; + + useEffect(() => { + setPercent(progress); + }, [progress]); + return ( + + {children} + + ); +}; + +const Inner = () => { + const { percent, size, color } = useContext(ProgressContext); + console.log('Inner context:', { percent, size, color }); + const height = size === 'xs' ? 4 : size === 'sm' ? 8 : size === 'md' ? 16 : 20; + return ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ); +}; + +const Track = () => { + return ; +}; +// height 4 8 12 16 color blue,orange,pink,purple,red,green,teal +const Container = styled.div<{ size: string }>` + width: 400px; + ${({ theme, size }) => { + if (size === 'xs') { + return css` + height: 4px; + `; + } else if (size === 'sm') { + return css` + height: 8px; + `; + } else if (size === 'md') { + return css` + height: 12px; + `; + } else if (size === 'lg') { + return css` + height: 16px; + `; + } + }} + display: flex; + overflow: hidden; +`; + +const Bar = styled.div<{ percent: number; color: string }>` + flex-shrink: 0; + position: relative; + ${({ percent, color }) => css` + width: ${percent}%; + background-color: ${color}; + `} + svg { + position: absolute; + top: 0; + left: 0; + } +`; +const Background = styled.div` + background-color: #edf2f7; + flex: 1; +`; +export default Progress; +Progress.Inner = Inner; +Progress.Track = Track; diff --git a/packages/chakra-ui-styled/src/components/feedback/progress/assets/progress-stripe.svg b/packages/chakra-ui-styled/src/components/feedback/progress/assets/progress-stripe.svg new file mode 100644 index 0000000..d5e86c9 --- /dev/null +++ b/packages/chakra-ui-styled/src/components/feedback/progress/assets/progress-stripe.svg @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/chakra-ui-styled/src/components/feedback/skeleton/Skeleton.stories.tsx b/packages/chakra-ui-styled/src/components/feedback/skeleton/Skeleton.stories.tsx new file mode 100644 index 0000000..7c73b7f --- /dev/null +++ b/packages/chakra-ui-styled/src/components/feedback/skeleton/Skeleton.stories.tsx @@ -0,0 +1,51 @@ +import Skeleton from './Skeleton'; +import { ReactNode } from 'react'; + +export type skeletonType = { + isLoading: boolean; + children?: ReactNode; +}; +export default { + title: 'chakra-ui-styled/components/feedback/skeleton', + component: Skeleton, + parameter: { controls: { expanded: true } }, + argTypes: { + isLoading: { + control: { + type: 'boolean' + } + } + }, + arg: { + isLoading: true + } +}; + +export const SkeletonIndex = (args: skeletonType) => { + return ( + <> + Demo + + + + + + + + + + .skeleton-text + + + + .skeleton-image + + + .skeleton-circle + + + > + ); +}; + +SkeletonIndex.storyName = 'Skeleton'; diff --git a/packages/chakra-ui-styled/src/components/feedback/skeleton/Skeleton.tsx b/packages/chakra-ui-styled/src/components/feedback/skeleton/Skeleton.tsx new file mode 100644 index 0000000..356b2b5 --- /dev/null +++ b/packages/chakra-ui-styled/src/components/feedback/skeleton/Skeleton.tsx @@ -0,0 +1,50 @@ +import styled from 'styled-components'; +import { skeletonType } from './Skeleton.stories'; + +const Skeleton = ({ isLoading, children }: skeletonType) => { + return isLoading && {children}; +}; + +const SkeletonTheme = styled.div` + @keyframes gradientShift { + 0% { + background-position: 0 51%; + } + 50% { + background-position: 100% 50%; + } + 100% { + background-position: 0 51%; + } + } + + & .skeleton-circle { + background: linear-gradient(270deg, #e2e8f0, #ffffff); + background-size: 400% 400%; + animation: gradientShift 4s ease infinite; + border-radius: 9999px; + width: 51px; + height: 51px; + margin: 16px 0; + } + & .skeleton-text { + background: linear-gradient(270deg, #e2e8f0, #ffffff); + background-size: 400% 400%; + animation: gradientShift 4s ease infinite; + width: 447px; + border-radius: 2px; + height: 8px; + align-self: stretch; + margin: 16px 0; + } + & .skeleton-image { + background: linear-gradient(270deg, #e2e8f0, #ffffff); + background-size: 400% 400%; + animation: gradientShift 4s ease infinite; + border-radius: 4px; + width: 447px; + height: 113px; + margin: 16px 0; + } +`; +export default Skeleton; diff --git a/packages/chakra-ui-styled/src/components/form/button/Button.stories.tsx b/packages/chakra-ui-styled/src/components/form/button/Button.stories.tsx index a855d04..3e11a13 100644 --- a/packages/chakra-ui-styled/src/components/form/button/Button.stories.tsx +++ b/packages/chakra-ui-styled/src/components/form/button/Button.stories.tsx @@ -1,13 +1,25 @@ import styled from 'styled-components'; import Button, { ButtonProps } from './Button'; +const IconDummy = () => { + return ( + + + + ); +}; + export default { title: 'chakra-ui-styled/components/form/button', component: Button, parameters: { controls: { expanded: true } }, argTypes: { - text: { control: { type: 'text' } }, + as: { control: { type: 'text' } }, + children: { control: { type: 'text' } }, size: { control: { type: 'select' } }, colorScheme: { control: { type: 'select' } }, variant: { control: { type: 'radio' } }, @@ -15,12 +27,12 @@ export default { rightIcon: { control: { type: 'text' } } }, args: { - text: '안녕', + children: '안녕', size: 'lg', - leftIcon: 'react', - rightIcon: 'react', colorScheme: 'blue', - variant: 'solid' + variant: 'solid', + leftIcon: , + rightIcon: } }; const Wrapper = styled.div` @@ -33,6 +45,7 @@ const BtnBox = styled.div` gap: 16px; align-items: center; `; + export const ButtonIndex = (args: ButtonProps) => { const btnText: string = 'Button'; return ( @@ -46,129 +59,273 @@ export const ButtonIndex = (args: ButtonProps) => { Button Index - - - - + } rightIcon={} size="lg" colorScheme="blue"> + {btnText} + + } rightIcon={} size="md" colorScheme="blue"> + {btnText} + + } rightIcon={} size="sm" colorScheme="blue"> + {btnText} + + } rightIcon={} size="xs" colorScheme="blue"> + {btnText} + - - - - + } rightIcon={} size="lg" variant="outline" colorScheme="blue"> + {btnText} + + } rightIcon={} size="md" variant="outline" colorScheme="blue"> + {btnText} + + } rightIcon={} size="sm" variant="outline" colorScheme="blue"> + {btnText} + + } rightIcon={} size="xs" variant="outline" colorScheme="blue"> + {btnText} + - - - - + } rightIcon={} size="lg" colorScheme="gray"> + {btnText} + + } rightIcon={} size="md" colorScheme="gray"> + {btnText} + + } rightIcon={} size="sm" colorScheme="gray"> + {btnText} + + } rightIcon={} size="xs" colorScheme="gray"> + {btnText} + - - - - + } rightIcon={} size="lg" variant="outline" colorScheme="gray"> + {btnText} + + } rightIcon={} size="md" variant="outline" colorScheme="gray"> + {btnText} + + } rightIcon={} size="sm" variant="outline" colorScheme="gray"> + {btnText} + + } rightIcon={} size="xs" variant="outline" colorScheme="gray"> + {btnText} + - - - - + } rightIcon={} size="lg" colorScheme="teal"> + {btnText} + + } rightIcon={} size="md" colorScheme="teal"> + {btnText} + + } rightIcon={} size="sm" colorScheme="teal"> + {btnText} + + } rightIcon={} size="xs" colorScheme="teal"> + {btnText} + - - - - + } rightIcon={} size="lg" variant="outline" colorScheme="teal"> + {btnText} + + } rightIcon={} size="md" variant="outline" colorScheme="teal"> + {btnText} + + } rightIcon={} size="sm" variant="outline" colorScheme="teal"> + {btnText} + + } rightIcon={} size="xs" variant="outline" colorScheme="teal"> + {btnText} + - - - - + } rightIcon={} size="lg" colorScheme="red"> + {btnText} + + } rightIcon={} size="md" colorScheme="red"> + {btnText} + + } rightIcon={} size="sm" colorScheme="red"> + {btnText} + + } rightIcon={} size="xs" colorScheme="red"> + {btnText} + - - - - + } rightIcon={} size="lg" variant="outline" colorScheme="red"> + {btnText} + + } rightIcon={} size="md" variant="outline" colorScheme="red"> + {btnText} + + } rightIcon={} size="sm" variant="outline" colorScheme="red"> + {btnText} + + } rightIcon={} size="xs" variant="outline" colorScheme="red"> + {btnText} + - - - - + } rightIcon={} size="lg" colorScheme="orange"> + {btnText} + + } rightIcon={} size="md" colorScheme="orange"> + {btnText} + + } rightIcon={} size="sm" colorScheme="orange"> + {btnText} + + } rightIcon={} size="xs" colorScheme="orange"> + {btnText} + - - - - + } rightIcon={} size="lg" variant="outline" colorScheme="orange"> + {btnText} + + } rightIcon={} size="md" variant="outline" colorScheme="orange"> + {btnText} + + } rightIcon={} size="sm" variant="outline" colorScheme="orange"> + {btnText} + + } rightIcon={} size="xs" variant="outline" colorScheme="orange"> + {btnText} + - - - - + } rightIcon={} size="lg" colorScheme="yellow"> + {btnText} + + } rightIcon={} size="md" colorScheme="yellow"> + {btnText} + + } rightIcon={} size="sm" colorScheme="yellow"> + {btnText} + + } rightIcon={} size="xs" colorScheme="yellow"> + {btnText} + - - - - + } rightIcon={} size="lg" variant="outline" colorScheme="yellow"> + {btnText} + + } rightIcon={} size="md" variant="outline" colorScheme="yellow"> + {btnText} + + } rightIcon={} size="sm" variant="outline" colorScheme="yellow"> + {btnText} + + } rightIcon={} size="xs" variant="outline" colorScheme="yellow"> + {btnText} + - - - - + } rightIcon={} size="lg" colorScheme="pink"> + {btnText} + + } rightIcon={} size="md" colorScheme="pink"> + {btnText} + + } rightIcon={} size="sm" colorScheme="pink"> + {btnText} + + } rightIcon={} size="xs" colorScheme="pink"> + {btnText} + - - - - + } rightIcon={} size="lg" variant="outline" colorScheme="pink"> + {btnText} + + } rightIcon={} size="md" variant="outline" colorScheme="pink"> + {btnText} + + } rightIcon={} size="sm" variant="outline" colorScheme="pink"> + {btnText} + + } rightIcon={} size="xs" variant="outline" colorScheme="pink"> + {btnText} + - - - - + } rightIcon={} size="lg" colorScheme="purple"> + {btnText} + + } rightIcon={} size="md" colorScheme="purple"> + {btnText} + + } rightIcon={} size="sm" colorScheme="purple"> + {btnText} + + } rightIcon={} size="xs" colorScheme="purple"> + {btnText} + - - - - + } rightIcon={} size="lg" variant="outline" colorScheme="purple"> + {btnText} + + } rightIcon={} size="md" variant="outline" colorScheme="purple"> + {btnText} + + } rightIcon={} size="sm" variant="outline" colorScheme="purple"> + {btnText} + + } rightIcon={} size="xs" variant="outline" colorScheme="purple"> + {btnText} + - - - - + } rightIcon={} size="lg" colorScheme="green"> + {btnText} + + } rightIcon={} size="md" colorScheme="green"> + {btnText} + + } rightIcon={} size="sm" colorScheme="green"> + {btnText} + + } rightIcon={} size="xs" colorScheme="green"> + {btnText} + - - - - + } rightIcon={} size="lg" variant="outline" colorScheme="green"> + {btnText} + + } rightIcon={} size="md" variant="outline" colorScheme="green"> + {btnText} + + } rightIcon={} size="sm" variant="outline" colorScheme="green"> + {btnText} + + } rightIcon={} size="xs" variant="outline" colorScheme="green"> + {btnText} + ); diff --git a/packages/chakra-ui-styled/src/components/form/button/Button.styled.tsx b/packages/chakra-ui-styled/src/components/form/button/Button.styled.tsx new file mode 100644 index 0000000..9f7f8b8 --- /dev/null +++ b/packages/chakra-ui-styled/src/components/form/button/Button.styled.tsx @@ -0,0 +1,180 @@ +import styled, { css } from 'styled-components'; +import { ButtonProps } from './Button'; + +const iconSize = { + lg: '16px', + md: '16px', + sm: '14px', + xs: '12px' +}; + +const buttonSize = { + lg: css` + height: 48px; + padding: 0 ${({ theme }) => theme.spacing[6]}; + `, + md: css` + height: 40px; + padding: 0 ${({ theme }) => theme.spacing[4]}; + `, + sm: css` + height: 32px; + padding: 0 ${({ theme }) => theme.spacing[3]}; + `, + xs: css` + height: 24px; + padding: 0 ${({ theme }) => theme.spacing[2]}; + ` +}; + +const buttonColor = { + blue: { + enabled: css` + ${({ theme }) => theme.color.blue[500]} + `, + hover: css` + ${({ theme }) => theme.color.blue[400]} + `, + active: css` + ${({ theme }) => theme.color.blue[600]} + ` + }, + gray: { + enabled: css` + ${({ theme }) => theme.color.gray[100]} + `, + hover: css` + ${({ theme }) => theme.color.gray[50]} + `, + active: css` + ${({ theme }) => theme.color.gray[200]} + ` + }, + teal: { + enabled: css` + ${({ theme }) => theme.color.teal[500]} + `, + hover: css` + ${({ theme }) => theme.color.teal[400]} + `, + active: css` + ${({ theme }) => theme.color.teal[600]} + ` + }, + red: { + enabled: css` + ${({ theme }) => theme.color.red[500]} + `, + hover: css` + ${({ theme }) => theme.color.red[400]} + `, + active: css` + ${({ theme }) => theme.color.red[600]} + ` + }, + orange: { + enabled: css` + ${({ theme }) => theme.color.orange[500]} + `, + hover: css` + ${({ theme }) => theme.color.orange[400]} + `, + active: css` + ${({ theme }) => theme.color.orange[600]} + ` + }, + yellow: { + enabled: css` + ${({ theme }) => theme.color.yellow[400]} + `, + hover: css` + ${({ theme }) => theme.color.yellow[300]} + `, + active: css` + ${({ theme }) => theme.color.yellow[500]} + ` + }, + pink: { + enabled: css` + ${({ theme }) => theme.color.pink[500]} + `, + hover: css` + ${({ theme }) => theme.color.pink[400]} + `, + active: css` + ${({ theme }) => theme.color.pink[600]} + ` + }, + purple: { + enabled: css` + ${({ theme }) => theme.color.purple[500]} + `, + hover: css` + ${({ theme }) => theme.color.purple[400]} + `, + active: css` + ${({ theme }) => theme.color.purple[600]} + ` + }, + green: { + enabled: css` + ${({ theme }) => theme.color.green[500]} + `, + hover: css` + ${({ theme }) => theme.color.green[400]} + `, + active: css` + ${({ theme }) => theme.color.green[600]} + ` + } +}; + +export const StyleButton = styled.button` + ${({ theme, variant, colorScheme }) => css` + display: flex; + column-gap: ${theme.spacing[2]}; + align-items: center; + justify-content: center; + border: 1px solid ${buttonColor[colorScheme].enabled}; + border-radius: ${theme.radii.md}rem; + + ${variant === 'outline' + ? css` + color: ${colorScheme === 'gray' ? theme.color.gray[800] : buttonColor[colorScheme].enabled}; + background-color: ${theme.color.white.white}; + + &:hover { + color: ${colorScheme === 'gray' ? theme.color.gray[800] : buttonColor[colorScheme].hover}; + border-color: ${buttonColor[colorScheme].hover}; + } + + &:active { + color: ${colorScheme === 'gray' ? theme.color.gray[800] : buttonColor[colorScheme].hover}; + border-color: ${buttonColor[colorScheme].active}; + } + ` + : variant === 'solid' + ? css` + color: ${colorScheme === 'gray' || colorScheme === 'yellow' + ? theme.color.gray[800] + : theme.color.white.white}; + background-color: ${buttonColor[colorScheme].enabled}; + + &:hover { + background-color: ${buttonColor[colorScheme].hover}; + border-color: ${buttonColor[colorScheme].hover}; + } + + &:active { + background-color: ${buttonColor[colorScheme].active}; + border-color: ${buttonColor[colorScheme].active}; + } + ` + : null} + `} + & .icon, & .icon svg { + width: ${({ size }) => iconSize[size]}; + height: ${({ size }) => iconSize[size]}; + } + ${({ size }) => buttonSize[size]} +`; diff --git a/packages/chakra-ui-styled/src/components/form/button/Button.tsx b/packages/chakra-ui-styled/src/components/form/button/Button.tsx index 57b12b9..565a242 100644 --- a/packages/chakra-ui-styled/src/components/form/button/Button.tsx +++ b/packages/chakra-ui-styled/src/components/form/button/Button.tsx @@ -1,242 +1,39 @@ -import styled, { css } from 'styled-components'; -import { TextComponent } from '../../../foundation/typography/Text.styled'; +import { StyleText } from '../../../foundation/typography/Text.styled'; +import { StyleButton } from './Button.styled'; export interface ButtonProps { + as?: React.ElementType; size: 'lg' | 'md' | 'sm' | 'xs'; colorScheme: 'blue' | 'gray' | 'teal' | 'red' | 'orange' | 'yellow' | 'pink' | 'purple' | 'green'; variant?: 'solid' | 'outline'; - leftIcon?: string; - rightIcon?: string; - text: string; + children?: string; + leftIcon?: React.ReactNode; + rightIcon?: React.ReactNode; + onClick?: () => void; } - -// @todo icon dummy 추후 수정 -interface IconBaseProps { - size: string; -} -const IconDummy = ({ size }: IconBaseProps) => { - return ( - - - - ); +const setIcon = (icon: React.ReactNode) => { + return {icon}; }; -const getColor = (colorScheme: string) => { - // css`${({ theme }) => { - switch (colorScheme) { - case 'blue': - return { - enabled: css` - ${({ theme }) => theme.color.blue[500]} - `, - hover: css` - ${({ theme }) => theme.color.blue[400]} - `, - active: css` - ${({ theme }) => theme.color.blue[600]} - ` - }; - case 'gray': - return { - enabled: css` - ${({ theme }) => theme.color.gray[100]} - `, - hover: css` - ${({ theme }) => theme.color.gray[50]} - `, - active: css` - ${({ theme }) => theme.color.gray[200]} - ` - }; - case 'teal': - return { - enabled: css` - ${({ theme }) => theme.color.teal[500]} - `, - hover: css` - ${({ theme }) => theme.color.teal[400]} - `, - active: css` - ${({ theme }) => theme.color.teal[600]} - ` - }; - case 'red': - return { - enabled: css` - ${({ theme }) => theme.color.red[500]} - `, - hover: css` - ${({ theme }) => theme.color.red[400]} - `, - active: css` - ${({ theme }) => theme.color.red[600]} - ` - }; - case 'orange': - return { - enabled: css` - ${({ theme }) => theme.color.orange[500]} - `, - hover: css` - ${({ theme }) => theme.color.orange[400]} - `, - active: css` - ${({ theme }) => theme.color.orange[600]} - ` - }; - case 'yellow': - return { - enabled: css` - ${({ theme }) => theme.color.yellow[400]} - `, - hover: css` - ${({ theme }) => theme.color.yellow[300]} - `, - active: css` - ${({ theme }) => theme.color.yellow[500]} - ` - }; - case 'pink': - return { - enabled: css` - ${({ theme }) => theme.color.pink[500]} - `, - hover: css` - ${({ theme }) => theme.color.pink[400]} - `, - active: css` - ${({ theme }) => theme.color.pink[600]} - ` - }; - case 'purple': - return { - enabled: css` - ${({ theme }) => theme.color.purple[500]} - `, - hover: css` - ${({ theme }) => theme.color.purple[400]} - `, - active: css` - ${({ theme }) => theme.color.purple[600]} - ` - }; - case 'green': - return { - enabled: css` - ${({ theme }) => theme.color.green[500]} - `, - hover: css` - ${({ theme }) => theme.color.green[400]} - `, - active: css` - ${({ theme }) => theme.color.green[600]} - ` - }; - default: - return { - enabled: css` - ${({ theme }) => theme.color.blue[500]} - `, - hover: css` - ${({ theme }) => theme.color.blue[400]} - `, - active: css` - ${({ theme }) => theme.color.blue[600]} - ` - }; - } -}; - -const getButtonSize = (size: string) => css` - ${({ theme }) => { - switch (size) { - case 'lg': - return css` - height: 48px; - padding: 0 ${theme.spacing[6]}; - `; - case 'md': - return css` - height: 40px; - padding: 0 ${theme.spacing[4]}; - `; - case 'sm': - return css` - height: 32px; - padding: 0 ${theme.spacing[3]}; - `; - case 'xs': - return css` - height: 24px; - padding: 0 ${theme.spacing[2]}; - `; - } - }} -`; - -const iconSize = { - lg: '16px', - md: '16px', - sm: '14px', - xs: '12px' -}; - -const StyleButton = styled.button` - ${({ theme, variant, colorScheme }) => css` - display: flex; - column-gap: ${theme.spacing[2]}; - align-items: center; - justify-content: center; - border: 1px solid ${getColor(colorScheme).enabled}; - border-radius: ${theme.radii.md}rem; - - ${variant === 'outline' - ? css` - color: ${colorScheme === 'gray' ? theme.color.gray[800] : getColor(colorScheme).enabled}; - background-color: ${theme.color.white.white}; - - &:hover { - color: ${colorScheme === 'gray' ? theme.color.gray[800] : getColor(colorScheme).hover}; - border-color: ${getColor(colorScheme).hover}; - } - - &:active { - color: ${colorScheme === 'gray' ? theme.color.gray[800] : getColor(colorScheme).hover}; - border-color: ${getColor(colorScheme).active}; - } - ` - : variant === 'solid' - ? css` - color: ${colorScheme === 'gray' || colorScheme === 'yellow' - ? theme.color.gray[800] - : theme.color.white.white}; - background-color: ${getColor(colorScheme).enabled}; - - &:hover { - background-color: ${getColor(colorScheme).hover}; - border-color: ${getColor(colorScheme).hover}; - } - - &:active { - background-color: ${getColor(colorScheme).active}; - border-color: ${getColor(colorScheme).active}; - } - ` - : null} - `} - ${({ size }) => getButtonSize(size)} -`; - -const Button = ({ size = 'md', variant = 'solid', colorScheme, leftIcon, rightIcon, text }: ButtonProps) => { +const Button = ({ + as = 'button', + size = 'md', + variant = 'solid', + colorScheme, + leftIcon, + rightIcon, + children, + onClick +}: ButtonProps) => { return ( - - {leftIcon && } - {text} - {rightIcon && } + + {leftIcon && setIcon(leftIcon)} + {children && ( + + {children} + + )} + {rightIcon && setIcon(rightIcon)} ); }; diff --git a/packages/chakra-ui-styled/src/components/form/checkbox/Checbok.stories.tsx b/packages/chakra-ui-styled/src/components/form/checkbox/Checbok.stories.tsx index 526f931..315bace 100644 --- a/packages/chakra-ui-styled/src/components/form/checkbox/Checbok.stories.tsx +++ b/packages/chakra-ui-styled/src/components/form/checkbox/Checbok.stories.tsx @@ -1,6 +1,5 @@ import styled from 'styled-components'; -import Checkbox, { CheckboxProps } from './Checkbox'; - +import Checkbox, { CheckboxProps, colorSchemeType } from './Checkbox'; export default { title: 'chakra-ui-styled/components/form/checkbox', @@ -15,7 +14,7 @@ export default { isDisabled: { control: { type: 'boolean' } }, }, args: { - text: '체크대상텍스트', + text: '선택대상', size: 'md', colorScheme: 'blue', isChecked: true, @@ -35,10 +34,9 @@ const CheckboxGroup = styled.div` flex: 1 1 30%; gap: 5px 0px; `; -const colorSchemeIndex = ['blue', 'teal', 'green', 'cyan', 'purple', 'pink'] - export const CheckboxIndex = (args: CheckboxProps) => { const chkText: string = 'Checkbox Label'; + const colorArr: colorSchemeType[] = ['blue', 'teal', 'green', 'cyan', 'purple', 'pink']; return ( Checkbox @@ -49,132 +47,29 @@ export const CheckboxIndex = (args: CheckboxProps) => { Checkbox Index - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + {colorArr.map((color) => ( + + + + + + + + + + + + + + + + + + + + + + ))} ); }; diff --git a/packages/chakra-ui-styled/src/components/form/checkbox/Checkbox.styled.tsx b/packages/chakra-ui-styled/src/components/form/checkbox/Checkbox.styled.tsx new file mode 100644 index 0000000..4e26016 --- /dev/null +++ b/packages/chakra-ui-styled/src/components/form/checkbox/Checkbox.styled.tsx @@ -0,0 +1,64 @@ +import styled, { css } from 'styled-components'; +import { CheckboxProps } from './Checkbox'; + +const checkboxSize = { sm: 12, md: 16, lg: 20, }; +const iconSize = { sm: 8, md: 12, lg: 16, }; +export const CheckboxForm = styled.input.attrs({ type: "checkbox" })` + position: absolute; + opacity: 0; + cursor: pointer; + width: 0; + height: 0; +`; +export const Label = styled.label` + flex: 1 1 30%; + display: flex; + align-items: center; + gap: 8px; + + & span { + width: ${({ size }) => checkboxSize[size]}px; + height: ${({ size }) => checkboxSize[size]}px; + border-radius: 2px; + display: flex; + justify-content: center; + align-items: center; + + &::after { + font-size: ${({ size }) => iconSize[size]}px; + line-height: 1; + } + ${({ isChecked, isDisabled, isIndeterminate, colorScheme, theme }) => css` + ${isDisabled // 비활성화 기준으로 잡아 잉여코드 제거 + ? css` // only 비활성o + background-color: ${theme.color.gray[200]}; + border: none; + ${isChecked && css` // 동시 체크o + &::after { + content: '✔'; + color: ${theme.color.gray[500]}; + } + `} + ` + : isChecked + ? css` // 비활성x, 동시 체크o + background-color: ${theme.color[colorScheme][500]}; + border: 1px solid ${theme.color[colorScheme][500]}; + &::after { + ${isIndeterminate + ? css` // 불확실o + content: '-'; + transform: translateY(-10%); + ` + : css` // 불확실x + content: '✔'; + `} + color: ${theme.color.white.white}; + }` + : css` // 비활성x, 동시 체크x + border: 2px solid ${theme.color.gray[200]}; + background: none; + `} + `} + } +`; \ No newline at end of file diff --git a/packages/chakra-ui-styled/src/components/form/checkbox/Checkbox.tsx b/packages/chakra-ui-styled/src/components/form/checkbox/Checkbox.tsx index 277fa00..ea1b0a3 100644 --- a/packages/chakra-ui-styled/src/components/form/checkbox/Checkbox.tsx +++ b/packages/chakra-ui-styled/src/components/form/checkbox/Checkbox.tsx @@ -1,137 +1,25 @@ -import styled, { css } from 'styled-components'; +import { StyleText } from '../../../foundation/typography/Text.styled'; +import { CheckboxForm, Label } from './Checkbox.styled'; + +export type colorSchemeType = 'blue' | 'teal' | 'green' | 'cyan' | 'purple' | 'pink'; export interface CheckboxProps { size: 'sm' | 'md' | 'lg'; - colorScheme: 'blue' | 'teal' | 'green' | 'cyan' | 'purple' | 'pink'; + colorScheme: colorSchemeType; isChecked?: boolean; isDisabled?: boolean; isIndeterminate?: boolean; - // Indeterminate는 체크를 했다는 전제조건에서만 나올 수 있음, isDisabled가 true이면 Indeterminate는 자동으로 해제, 우선 배제하고 작업진행 text: string; } -const checkboxSize = { sm: 12, md: 16, lg: 20, }; -const iconSize = { sm: 8, md: 12, lg: 16, }; -// 기본색상 -const getColor = (colorScheme: string) => css` - ${({ theme }) => { - switch (colorScheme) { - case 'blue': - return theme.color.blue[500]; - case 'teal': - return theme.color.teal[500]; - case 'green': - return theme.color.green[500]; - case 'cyan': - return theme.color.cyan[500]; - case 'purple': - return theme.color.purple[500]; - case 'pink': - return theme.color.pink[500]; - case 'gray': - return theme.color.gray[500]; - default: - return theme.color.blue[500]; - } - }} -`; -// label 사이즈 설정 했을 때 label의 왼쪽여백 조정 -const getLabelPadding = (size: string) => css` - ${({ theme }) => { - switch (size) { - case 'sm': - return theme.spacing[5]; - case 'md': - return theme.spacing[6]; - case 'lg': - return theme.spacing[7]; - default: - return theme.spacing[6]; - } - }} -`; -const CheckboxForm = styled.input.attrs({ type: "checkbox" })` - position: absolute; - opacity: 0; - cursor: pointer; - height: 0; - width: 0; - - &:checked:indeterminate ~ span::after { - display: flex; - } -`; -const Label = styled.label` - flex: 1 0 30%; - display: flex; - align-items: center; - position: relative; - padding: 0 0 0 ${({ size }) => getLabelPadding(size)}; - - & span { - box-sizing: border-box; - position: absolute; - top: 50%; - left: 0; - transform: translate(0, -50%); - width: ${({ size }) => checkboxSize[size]}px; - height: ${({ size }) => checkboxSize[size]}px; - border-radius: 2px; - text-align: center; - &::after { - position: absolute; - font-size: ${({ size }) => iconSize[size]}px; - width: inherit; - height: inherit; - top: inherit; - left: 50%; - transform: translate(-50%, -50%); - display: flex; - justify-content: center; - align-items: center; - } - // label에서 CheckboxProps적용시 - ${({ isChecked, isDisabled, isIndeterminate, colorScheme, theme }) => css` - ${isDisabled // 비활성화 기준으로 잡아 잉여코드 제거 - ? css` // only 비활성o - background-color: ${theme.color.gray[200]}; - border: none; - ${isChecked && css` // 동시 체크o - &::after { - content: '✔'; - color: ${theme.color.gray[500]}; - } - `} - ` - : isChecked - ? css` // 비활성x, 동시 체크o - background-color: ${getColor(colorScheme)}; - border: 1px solid ${getColor(colorScheme)}; - &::after { - ${isIndeterminate - ? css` // 불확실o - content: '-'; - transform: translate(-50%, -60%); - ` - : css` // 불확실x - content: '✔'; - `} - color: ${theme.color.white.white}; - transform: translate(-50%, -60%); - }` - : css` // 비활성x, 동시 체크x - border: 2px solid ${theme.color.gray[200]}; - background: none; - `} - `} - } -`; const Checkbox = ({ size = 'md', isChecked = true, isDisabled = false, isIndeterminate = true, colorScheme, text }: CheckboxProps) => { return ( - {text} + + {text} + ); }; diff --git a/packages/chakra-ui-styled/src/components/form/closebutton/CloseButton.stories.tsx b/packages/chakra-ui-styled/src/components/form/closebutton/CloseButton.stories.tsx new file mode 100644 index 0000000..2abece2 --- /dev/null +++ b/packages/chakra-ui-styled/src/components/form/closebutton/CloseButton.stories.tsx @@ -0,0 +1,41 @@ +import styled from 'styled-components'; +import CloseButton, { CloseButtonProps } from './CloseButton'; +import { CloseIconStyle } from './CloseButton.styled'; + +export default { + title: 'chakra-ui-styled/components/form/closebutton', + component: CloseButton, + parameters: { controls: { expanded: true } }, + + argTypes: { + size: { control: { type: 'select' } } + }, + args: { + size: 'sm', + icon: + } +}; +const Wrapper = styled.div` + display: flex; + flex-direction: column; + gap: 20px; +`; + +export const CloseButtonIndex = (args: CloseButtonProps) => { + return ( + + CloseButton + + CloseButton Demo + + + + + CloseButton Index + } /> + } /> + } /> + + ); +}; +CloseButtonIndex.storyName = 'CloseButton'; diff --git a/packages/chakra-ui-styled/src/components/form/closebutton/CloseButton.styled.tsx b/packages/chakra-ui-styled/src/components/form/closebutton/CloseButton.styled.tsx new file mode 100644 index 0000000..fab7117 --- /dev/null +++ b/packages/chakra-ui-styled/src/components/form/closebutton/CloseButton.styled.tsx @@ -0,0 +1,7 @@ +export const CloseIconStyle = () => { + return ( + + + + ); +}; diff --git a/packages/chakra-ui-styled/src/components/form/closebutton/CloseButton.tsx b/packages/chakra-ui-styled/src/components/form/closebutton/CloseButton.tsx new file mode 100644 index 0000000..c98a725 --- /dev/null +++ b/packages/chakra-ui-styled/src/components/form/closebutton/CloseButton.tsx @@ -0,0 +1,27 @@ +import styled from 'styled-components'; + +export interface CloseButtonProps { + size: 'sm' | 'md' | 'lg'; + icon?: React.ReactNode; + onClick?: () => void; + className?: string; +} +const ViewBoxSize = { sm: 24, md: 32, lg: 40 }; +const setIcon = (icon: React.ReactNode) => { + return {icon}; +}; +const CloseButtonStyle = styled.div` + width: ${({ size }) => ViewBoxSize[size]}px; + height: ${({ size }) => ViewBoxSize[size]}px; + aspect-ratio: 1; + cursor: pointer; +`; +const CloseButton = ({ size = 'sm', icon, className, onClick }: CloseButtonProps) => { + return ( + + {icon && setIcon(icon)} + + ) +}; + +export default CloseButton; diff --git a/packages/chakra-ui-styled/src/components/form/input/Input.stories.tsx b/packages/chakra-ui-styled/src/components/form/input/Input.stories.tsx new file mode 100644 index 0000000..5f08efe --- /dev/null +++ b/packages/chakra-ui-styled/src/components/form/input/Input.stories.tsx @@ -0,0 +1,144 @@ +import styled from 'styled-components'; +import { InputSize } from './InputGroup'; +import Input, { InputType } from './Input'; + +export default { + title: 'chakra-ui-styled/components/form/Input/Input', + component: Input, + parameters: { controls: { expanded: true } }, + + argTypes: { + $size: { control: { type: 'select' } }, + $variant: { control: { type: 'select' } }, + $isInvalid: { control: { type: 'boolean' } }, + disabled: { control: { type: 'boolean' } }, + readOnly: { control: { type: 'boolean' } } + }, + args: { + $size: 'xs', + $variant: 'outline', + $isInvalid: false, + disabled: false, + readOnly: false + } +}; +const Wrapper = styled.div` + display: flex; + flex-direction: column; + gap: 20px; +`; +const BtnBox = styled.div` + display: flex; + gap: 16px; + align-items: center; +`; + +export const InputIndex = (args: InputType) => { + const inputArr: InputSize[] = ['xs', 'sm', 'md', 'lg']; + return ( + + InputIndex + InputIndex Demo + + + + Input Index + {inputArr.map((size, idx) => ( + + + + + + ))} + + {inputArr.map((size, idx) => ( + + + + + + ))} + + {inputArr.map((size) => ( + + + + + + ))} + + ); +}; +InputIndex.storyName = 'Input'; diff --git a/packages/chakra-ui-styled/src/components/form/input/Input.styled.tsx b/packages/chakra-ui-styled/src/components/form/input/Input.styled.tsx new file mode 100644 index 0000000..7c4d810 --- /dev/null +++ b/packages/chakra-ui-styled/src/components/form/input/Input.styled.tsx @@ -0,0 +1,73 @@ +import styled, { css } from 'styled-components'; +import { InputStyleSize } from './InputGroup.styled'; +import { CommonInputType } from './InputGroup'; + +const getInputVariant = ($props: CommonInputType) => { + if ($props.$variant === 'outline' || $props.$variant === 'flushed') { + return css` + padding: 0 ${InputStyleSize[$props.$size]?.padding}; + ${$props.$isInvalid && !$props.disabled && !$props.readOnly + ? css` + border: 1px solid ${({ theme }) => theme.color.red[500]}; + box-shadow: ${({ theme }) => theme.color.red[500]} 0 0 0 1px; + ` + : css` + border: 1px solid ${$props.$variant === 'outline' ? ({ theme }) => theme.color.gray[200] : 'transparent'}; + `}; + + &:focus-visible { + ${!$props.$isInvalid && + !$props.disabled && + !$props.readOnly && + css` + border-color: ${({ theme }) => theme.color.blue[500]}; + box-shadow: ${({ theme }) => theme.color.blue[500]} 0 0 0 1px; + `}; + } + `; + } + if ($props.$variant === 'filled') { + return css` + border: 0 none; + border-radius: 0; + + ${$props.$isInvalid && !$props.disabled && !$props.readOnly + ? css` + border-bottom: 1px solid ${({ theme }) => theme.color.red[500]}; + box-shadow: ${({ theme }) => theme.color.red[500]} 0 1px 0 0; + ` + : css` + border-bottom: 1px solid ${({ theme }) => theme.color.gray[200]}; + `}; + &:focus-visible { + ${!$props.$isInvalid && + !$props.disabled && + !$props.readOnly && + css` + border-bottom: 1px solid ${({ theme }) => theme.color.blue[500]}; + box-shadow: ${({ theme }) => theme.color.blue[500]} 0 1px 0 0; + `}; + } + `; + } + return null; +}; + +export const InputStyle = styled.input<{ $props: CommonInputType }>` + ${({ theme, $props }) => css` + position: relative; + z-index: 1; + box-sizing: border-box; + display: flex; + flex: 1; + height: ${InputStyleSize[$props.$size]?.height}; + border-radius: ${InputStyleSize[$props.$size].radii}; + ${theme.typo.text[$props.$size]}; + ${($props.disabled || $props.readOnly) && { opacity: '0.4', backgroundColor: `${theme.color.gray[100]}` }}; + ${getInputVariant($props)} + + &:focus-visible { + outline: none; + } + `} +`; diff --git a/packages/chakra-ui-styled/src/components/form/input/Input.tsx b/packages/chakra-ui-styled/src/components/form/input/Input.tsx new file mode 100644 index 0000000..4e3d974 --- /dev/null +++ b/packages/chakra-ui-styled/src/components/form/input/Input.tsx @@ -0,0 +1,32 @@ +import { CommonInputType } from './InputGroup'; +import { InputStyle } from './Input.styled'; + +export type InputType = CommonInputType & { + type?: 'text' | 'email' | 'tel' | 'password'; + name: string; + id: string; + placeholder?: string; +}; + +// input +const Input = ({ + $size = 'xs', + $isInvalid = false, + $variant = 'filled', + readOnly = false, + disabled = false, + placeholder = 'placeholder', + ...rest +}: InputType) => { + return ( + + ); +}; + +export default Input; diff --git a/packages/chakra-ui-styled/src/components/form/input/InputAddon.tsx b/packages/chakra-ui-styled/src/components/form/input/InputAddon.tsx new file mode 100644 index 0000000..27b9667 --- /dev/null +++ b/packages/chakra-ui-styled/src/components/form/input/InputAddon.tsx @@ -0,0 +1,15 @@ +import styled, { css } from 'styled-components'; +import { colorType } from './InputGroup'; + +export type InputAddonType = { + $color?: colorType; + $bg?: colorType; + dataPosition?: 'left' | 'right'; + $element: React.ReactNode; +}; +export const AddonStyle = styled.figure` + ${({ $color, $bg, theme }) => css` + color: ${$color ? theme.color[$color][500] : theme.color.black.black}; + background-color: ${$bg ? theme.color[$bg][100] : 'transparent'}; + `} +`; diff --git a/packages/chakra-ui-styled/src/components/form/input/InputGroup.styled.tsx b/packages/chakra-ui-styled/src/components/form/input/InputGroup.styled.tsx new file mode 100644 index 0000000..c99316b --- /dev/null +++ b/packages/chakra-ui-styled/src/components/form/input/InputGroup.styled.tsx @@ -0,0 +1,155 @@ +import styled, { css } from 'styled-components'; + +import { InputGroupType } from './InputGroup'; + +import { AddonStyle } from './InputAddon'; +import { InputStyle } from './Input.styled'; + +export const InputStyleSize = { + xs: { + height: '24px', + padding: '8px', + iconSize: '12px', + radii: css` + ${({ theme }) => theme.radii.sm + 'rem'} + ` + }, + sm: { + height: '32px', + padding: '12px', + iconSize: '14px', + radii: css` + ${({ theme }) => theme.radii.base + 'rem'} + ` + }, + md: { + height: '40px', + padding: '12px', + iconSize: '16px', + radii: css` + ${({ theme }) => theme.radii.md + 'rem'} + ` + }, + lg: { + height: '48px', + padding: '16px', + iconSize: '18px', + radii: css` + ${({ theme }) => theme.radii.lg + 'rem'} + ` + } +}; + +const getInputRadii = ($props: InputGroupType) => { + //leftAddon만있을경우 + if (!$props.rightAddon && $props.leftAddon) { + return css` + border-top-right-radius: ${InputStyleSize[$props.$size].radii}; + border-bottom-right-radius: ${InputStyleSize[$props.$size].radii}; + `; + } + //rightAddon만있을경우 + if ($props.rightAddon && !$props.leftAddon) { + return css` + border-top-left-radius: ${InputStyleSize[$props.$size].radii}; + border-bottom-left-radius: ${InputStyleSize[$props.$size].radii}; + `; + } + //다 없을경우 + if (!$props.rightAddon && !$props.leftAddon) { + return css` + border-radius: ${InputStyleSize[$props.$size].radii}; + `; + } + if ($props.rightAddon && $props.leftAddon) { + return css` + border-radius: 0; + `; + } + return null; +}; + +const getAddonBorder = ($position: string) => { + let AddonPosition; + let borderPosition; + switch ($position) { + case 'left': + break; + case 'right': + css` + border-left: 0 none; + border-top-right-radius: ${InputStyleSize[$props.$size].radii}; + border-bottom-right-radius: ${InputStyleSize[$props.$size].radii}; + `; + break; + } +}; + +export const InputGroupStyle = styled.div<{ + $props: InputGroupType; +}>` + ${({ theme, $props }) => css` + box-sizing: border-box; + display: flex; + align-items: flex-start; + justify-content: space-between; + width: 100%; + + & ${InputStyle} { + flex-grow: 1; + padding-right: ${$props.rightAddon ? InputStyleSize[$props.$size].padding : 0}; + padding-left: ${$props.leftAddon ? InputStyleSize[$props.$size].padding : InputStyleSize[$props.$size].padding}; + border-radius: 0; + ${getInputRadii($props)}; + + // 왼쪽 요소만있고, 왼쪽요소의 백그라운드가 투명일때 + ${$props.leftAddon && + !$props.leftAddon.props.$bg && + css` + &:not(:focus-visible) { + border-left-color: transparent; + } + padding-left: 0; + `} + // 오른쪽 요소만있고, 오른쪽요소의 백그라운드가 투명일때 + ${$props.rightAddon && + !$props.rightAddon.props.$bg && + css` + &:not(:focus-visible) { + border-right-color: transparent; + } + `} + } + & ${AddonStyle} { + display: flex; + flex: none; + align-items: center; + justify-content: center; + min-width: ${InputStyleSize[$props.$size].height}; + height: ${InputStyleSize[$props.$size].height}; + ${theme.typo.text[$props.$size]}; + padding: 0 ${InputStyleSize[$props.$size].padding}; + border: 1px solid ${theme.color.gray[200]}; + ${InputStyleSize[$props.$size].padding}; + ${($props.readOnly || $props.disabled) && + css` + background-color: ${theme.color.gray[100]}; + opacity: 0.4; + `} + &[dataPosition='left'] { + border-right: 0 none; + border-top-left-radius: ${InputStyleSize[$props.$size].radii}; + border-bottom-left-radius: ${InputStyleSize[$props.$size].radii}; + } + + &[dataPosition='right'] { + border-left: 0 none; + border-top-right-radius: ${InputStyleSize[$props.$size].radii}; + border-bottom-right-radius: ${InputStyleSize[$props.$size].radii}; + } + } + & ${AddonStyle} svg { + width: ${InputStyleSize[$props.$size].iconSize}; + } + `} +`; diff --git a/packages/chakra-ui-styled/src/components/form/input/InputGroup.tsx b/packages/chakra-ui-styled/src/components/form/input/InputGroup.tsx new file mode 100644 index 0000000..2353889 --- /dev/null +++ b/packages/chakra-ui-styled/src/components/form/input/InputGroup.tsx @@ -0,0 +1,59 @@ +import React from 'react'; + +import Input, { InputType } from './Input'; +import { AddonStyle, InputAddonType } from './InputAddon'; +import { InputGroupStyle } from './InputGroup.styled'; + +export type InputSize = 'xs' | 'sm' | 'md' | 'lg'; +export type VariantType = 'outline' | 'filled' | 'flushed'; +export type colorType = 'blue' | 'gray' | 'teal' | 'red' | 'orange' | 'yellow' | 'pink' | 'purple' | 'green'; + +export type CommonInputType = { + $size: InputSize; + $variant?: VariantType; + $isInvalid: boolean; + disabled: boolean; + readOnly: boolean; +}; + +export type InputGroupType = CommonInputType & + InputType & { + leftAddon?: React.ReactElement; + rightAddon?: React.ReactElement; + }; + +export const InputAddon = ({ $color, $bg, $element, dataPosition }: InputAddonType) => { + return ( + + {$element} + + ); +}; + +// Root Provider +export const InputGroup = ({ + $size, + $isInvalid, + disabled, + readOnly, + leftAddon, + rightAddon, + ...rest +}: InputGroupType) => { + return ( + + {leftAddon && leftAddon} + + {rightAddon && rightAddon} + + ); +}; + +export default InputGroup; diff --git a/packages/chakra-ui-styled/src/components/form/input/InputGruop.stories.tsx b/packages/chakra-ui-styled/src/components/form/input/InputGruop.stories.tsx new file mode 100644 index 0000000..2b43e3c --- /dev/null +++ b/packages/chakra-ui-styled/src/components/form/input/InputGruop.stories.tsx @@ -0,0 +1,153 @@ +import styled from 'styled-components'; +import InputGroup, { InputAddon, InputGroupType, InputSize } from './InputGroup'; + +const IconDummy = () => { + return ( + + + + ); +}; + +export default { + title: 'chakra-ui-styled/components/form/Input/InputGroup', + component: InputGroup, + parameters: { controls: { expanded: true } }, + + argTypes: { + $size: { control: { type: 'select' } }, + $isInvalid: { control: { type: 'boolean' } }, + disabled: { control: { type: 'boolean' } }, + readOnly: { control: { type: 'boolean' } } + }, + args: { + $size: 'xs', + $isInvalid: false, + disabled: false, + readOnly: false, + leftAddon: } />, + rightAddon: } /> + } +}; +const Wrapper = styled.div` + display: flex; + flex-direction: column; + gap: 20px; +`; +const InputBox = styled.div` + display: flex; + flex-direction: column; + gap: 16px; + align-items: flex-start; + + & > div { + flex: 1; + } +`; +const BtnBox = styled.div` + display: flex; + gap: 16px; + align-items: flex-start; +`; + +export const InputGroupIndex = (args: InputGroupType) => { + const inputArr: InputSize[] = ['xs', 'sm', 'md', 'lg']; + return ( + + InputGroup + InputGroup Demo + + + + InputGroup Index + + {inputArr.map((size) => ( + + + } />} + rightAddon={} />} + /> + } />} + /> + } />} + /> + } />} + rightAddon={} />} + /> + } />} + /> + } />} + /> + + ))} + + + ); +}; +InputGroupIndex.storyName = 'InputGroup'; diff --git a/packages/chakra-ui-styled/src/components/form/numberinput/NumberInput.stories.tsx b/packages/chakra-ui-styled/src/components/form/numberinput/NumberInput.stories.tsx new file mode 100644 index 0000000..ab830c2 --- /dev/null +++ b/packages/chakra-ui-styled/src/components/form/numberinput/NumberInput.stories.tsx @@ -0,0 +1,98 @@ +import styled from 'styled-components'; +import NumberInput, { NumberInputProps, colorSchemeType } from './NumberInput'; +import { IncrementStepperIconStyle, DecrementStepperIconStyle } from './NumberInput.styled'; + +export default { + title: 'chakra-ui-styled/components/form/numberinput', + component: NumberInput, + parameters: { controls: { expanded: true } }, + + argTypes: { + size: { control: { type: 'select' } }, + colorScheme: { control: { type: 'select' } }, + value: { control: { type: 'number' } }, + disabled: { control: { type: 'boolean' } }, + readonly: { control: { type: 'boolean' } }, + isInvalid: { control: { type: 'boolean' } } + }, + args: { + size: 'sm', + colorScheme: 'blue', + incrementIcon: , + decrementIcon: , + value: 1, + disabled: false, + readonly: false, + isInvalid: false + } +}; +const Wrapper = styled.div` + display: flex; + flex-direction: column; + gap: 20px; +`; +const Stack = styled.div` + display: flex; + flex-flow: row wrap; + flex: 1 1 0; + gap: 10px; +`; +export const NumberInputIndex = (args: NumberInputProps) => { + const colorArr: colorSchemeType[] = ['whiteAlpha', 'blackAlpha', 'gray', 'red', 'orange', 'yellow', 'green', 'teal', 'blue', 'cyan', 'purple', 'pink']; + return ( + + NumberInput + + NumberInput Demo + + + + + NumberInput Index + {colorArr.map((color) => ( + + } decrementIcon={} + /> + } decrementIcon={} + /> + } decrementIcon={} + /> + + } decrementIcon={} + /> + } decrementIcon={} + /> + } decrementIcon={} + /> + + } decrementIcon={} + /> + } decrementIcon={} + /> + } decrementIcon={} + /> + + } decrementIcon={} + /> + } decrementIcon={} + /> + } decrementIcon={} + /> + + ))} + + ); +}; +NumberInputIndex.storyName = 'NumberInput'; diff --git a/packages/chakra-ui-styled/src/components/form/numberinput/NumberInput.styled.tsx b/packages/chakra-ui-styled/src/components/form/numberinput/NumberInput.styled.tsx new file mode 100644 index 0000000..e240fc5 --- /dev/null +++ b/packages/chakra-ui-styled/src/components/form/numberinput/NumberInput.styled.tsx @@ -0,0 +1,122 @@ +import styled, { css } from 'styled-components'; +import { NumberInputProps } from './NumberInput'; + +const numberInputSize = { + xs: css` + height: 24px; + border-radius: 2px; + padding: 0px 0px 0px 12px; + `, + sm: css` + height: 32px; + border-radius: 2px; + padding: 0px 0px 0px 12px; + `, + md: css` + height: 40px; + border-radius: 6px; + padding: 0px 0px 0px 16px; + `, + lg: css` + height: 48px; + border-radius: 6px; + padding: 0px 0px 0px 16px; + `, +}; +const fontSize = { + xs: css` + ${({ theme }) => theme.typo.text.xs} + `, + sm: css` + ${({ theme }) => theme.typo.text.sm} + `, + md: css` + ${({ theme }) => theme.typo.text.md} + `, + lg: css` + ${({ theme }) => theme.typo.text.lg} + `, +}; +export const StyleNumberInput = styled.div` + display: flex; + align-items: center; + flex: 1 1 30%; + ${({ size }) => numberInputSize[size]} + & input{ + ${({ size }) => fontSize[size]} + } + &:focus { + outline: 0; + } + ${({ disabled, readOnly, isInvalid, colorScheme, theme }) => css` + ${disabled || readOnly + ? css` + // 비활성o + opacity: 0.5; + border: 1px solid ${theme.color.gray[200]}; + pointer-events: none; + ` + : css` + // 기본 + border: 1px solid ${theme.color.gray[200]}; + &:focus-within { + outline: 1px solid ${theme.color[colorScheme][500]}; + } + // 기본 + min, max값이 넘었을경우 조건 충족 : 굵은아웃라인 들어와야함 + ${isInvalid && + css` + outline: 3px solid ${theme.color.red[500]}; + `} + `} + `} +`; +export const NumberInputField = styled.input.attrs({ type: "text" })` + flex: 1; + border: none; + &:focus{ + outline: 0; + } +`; +export const NumberInputStepper = styled.div` + width: 24px; + height: 100%; + display: flex; + flex-direction: column; +`; +export const IncrementStepperIconStyle = () => { + return ( + + + + ); +}; +export const DecrementStepperIconStyle = () => { + return ( + + + + ); +}; +export const NumberIncrementStepper = styled.div` + display: flex; + justify-content: center; + align-items: center; + flex: 1; + height: 50%; + cursor: pointer; + ${({ theme }) => css` + border-left: 1px solid ${theme.color.gray[200]}; + `} +`; +export const NumberDecrementStepper = styled.div` + display: flex; + justify-content: center; + align-items: center; + flex: 1; + height: 50%; + cursor: pointer; + ${({ theme }) => css` + border-left: 1px solid ${theme.color.gray[200]}; + border-top: 1px solid ${theme.color.gray[200]}; + `} +`; \ No newline at end of file diff --git a/packages/chakra-ui-styled/src/components/form/numberinput/NumberInput.tsx b/packages/chakra-ui-styled/src/components/form/numberinput/NumberInput.tsx new file mode 100644 index 0000000..dabe61e --- /dev/null +++ b/packages/chakra-ui-styled/src/components/form/numberinput/NumberInput.tsx @@ -0,0 +1,35 @@ +import { StyleNumberInput, NumberInputField, NumberInputStepper, NumberIncrementStepper, NumberDecrementStepper } from './NumberInput.styled'; +import { useState } from 'react' + +export type colorSchemeType = 'whiteAlpha' | 'blackAlpha' | 'gray' | 'red' | 'orange' | 'yellow' | 'green' | 'teal' | 'blue' | 'cyan' | 'purple' | 'pink' ; +export interface NumberInputProps { + size: "xs" | 'sm' | 'md' | 'lg'; + colorScheme: colorSchemeType; + isInvalid?: boolean; + disabled?: boolean; + readOnly?: boolean; + value: number; + incrementIcon?: React.ReactNode; + decrementIcon?: React.ReactNode; +} + +const setIcon = (incrementIcon: React.ReactNode) => { + return {incrementIcon}; +}; +const NumberInput = ({ size = 'md', colorScheme, value, incrementIcon, decrementIcon, disabled = false, readOnly = false, isInvalid = false }: NumberInputProps) => { + const [count, setCount] = useState(0) + return ( + + + + setCount((count) => count + 1)}> + {incrementIcon && setIcon(incrementIcon)} + + setCount((count) => count - 1)}> + {decrementIcon && setIcon(decrementIcon)} + + + + ); +}; +export default NumberInput; \ No newline at end of file diff --git a/packages/chakra-ui-styled/src/components/form/pininput/PinInput.stories.tsx b/packages/chakra-ui-styled/src/components/form/pininput/PinInput.stories.tsx new file mode 100644 index 0000000..55aaa96 --- /dev/null +++ b/packages/chakra-ui-styled/src/components/form/pininput/PinInput.stories.tsx @@ -0,0 +1,38 @@ +import styled from 'styled-components'; +import PinInput, { PinInputProps } from './PinInput'; + +export default { + title: 'chakra-ui-styled/components/form/pininput', + component: PinInput, + parameters: { controls: { expanded: true } }, + + argTypes: { + size: { control: { type: 'select' } }, + colorScheme: { control: { type: 'select' } }, + numOfInputs: { control: { type: 'number' } }, + }, + args: { + size: 'sm', + colorScheme: 'blue', + numOfInputs: 4, + } +}; +const Wrapper = styled.div` + display: flex; + flex-direction: column; + gap: 20px; +`; + +export const PinInputIndex = (args: PinInputProps) => { + return ( + + PinInput + + PinInput Demo + + + + + ); +}; +PinInputIndex.storyName = 'PinInput'; diff --git a/packages/chakra-ui-styled/src/components/form/pininput/PinInput.style.tsx b/packages/chakra-ui-styled/src/components/form/pininput/PinInput.style.tsx new file mode 100644 index 0000000..4060329 --- /dev/null +++ b/packages/chakra-ui-styled/src/components/form/pininput/PinInput.style.tsx @@ -0,0 +1,53 @@ +import styled, { css } from 'styled-components'; +import { PinInputProps } from './PinInput'; + +const PinInputSize = { + xs: css` + width: ${({ theme }) => theme.spacing[6]}; + border-radius: 2px; + ${({ theme }) => theme.typo.text.xs}; + `, + sm: css` + width: ${({ theme }) => theme.spacing[8]}; + border-radius: 4px; + ${({ theme }) => theme.typo.text.sm} + `, + md: css` + width: ${({ theme }) => theme.spacing[10]}; + border-radius: 4px; + ${({ theme }) => theme.typo.text.md} + `, + lg: css` + width: ${({ theme }) => theme.spacing[12]}; + border-radius: 6px; + ${({ theme }) => theme.typo.text.lg} + ` +}; +export const StylePinInput = styled.div.attrs({ autoFocus: true })` + display: flex; + gap: 6px; + + & input { + ${({ size }) => PinInputSize[size]} + ${({ colorScheme, theme }) => css` + border: 1px solid ${theme.color.gray[200]}; + + &:focus { + outline: 2px solid ${theme.color[colorScheme][500]}; + } + + &:placeholder-shown { + color: ${theme.color.gray[400]}; + } + `} + } +`; + +export const PinInputField = styled.input.attrs({ type: 'text', maxlength: 1, placeholder: '○' })` + aspect-ratio: 1; + text-align: center; + + &:focus { + outline: 0; + } +`; diff --git a/packages/chakra-ui-styled/src/components/form/pininput/PinInput.tsx b/packages/chakra-ui-styled/src/components/form/pininput/PinInput.tsx new file mode 100644 index 0000000..ffac48c --- /dev/null +++ b/packages/chakra-ui-styled/src/components/form/pininput/PinInput.tsx @@ -0,0 +1,47 @@ +import { StylePinInput, PinInputField } from './PinInput.style'; + +export type colorSchemeType = + | 'whiteAlpha' + | 'blackAlpha' + | 'gray' + | 'red' + | 'orange' + | 'yellow' + | 'green' + | 'teal' + | 'blue' + | 'cyan' + | 'purple' + | 'pink'; +export interface PinInputProps { + size: 'xs' | 'sm' | 'md' | 'lg'; + colorScheme: colorSchemeType; + numOfInputs: number; +} + +const PinInput = ({ size = 'md', colorScheme, numOfInputs = 4 }: PinInputProps) => { + const inputArray = Array.from({ length: numOfInputs }); + const onFocusInput = (e: React.KeyboardEvent) => { + const pinInput = e.target as HTMLInputElement; + const value = pinInput.value; + const maxLength = Number(pinInput.getAttribute('maxlength')); + + if (e.code === 'Backspace') { + if (!pinInput.previousSibling) return; + !value ? (pinInput.previousSibling as HTMLInputElement).focus() : pinInput.focus(); + } + if (value.length === maxLength && e.code !== 'Backspace') { + if (!pinInput.nextSibling) return; + (pinInput.nextSibling as HTMLInputElement).focus(); + } + }; + + return ( + + {inputArray.map((_, index) => { + return ; + })} + + ); +}; +export default PinInput; diff --git a/packages/chakra-ui-styled/src/components/form/radio/Radio.stories.tsx b/packages/chakra-ui-styled/src/components/form/radio/Radio.stories.tsx new file mode 100644 index 0000000..7c48bf3 --- /dev/null +++ b/packages/chakra-ui-styled/src/components/form/radio/Radio.stories.tsx @@ -0,0 +1,71 @@ +import styled from 'styled-components'; +import Radio, { RadioProps, colorSchemeType } from './Radio'; + +export default { + title: 'chakra-ui-styled/components/form/radio', + component: Radio, + parameters: { controls: { expanded: true } }, + + argTypes: { + text: { control: { type: 'text' } }, + size: { control: { type: 'select' } }, + colorScheme: { control: { type: 'select' } }, + defaultChecked: { control: { type: 'boolean' } }, + isDisabled: { control: { type: 'boolean' } }, + }, + args: { + text: '선택대상', + size: 'md', + colorScheme: 'blue', + defaultChecked: true, + isDisabled: false, + } +}; + +const Wrapper = styled.div` + display: flex; + flex-direction: column; + gap: 20px; +`; +const RadioGroup = styled.div` + display: flex; + flex-flow: row wrap; + flex: 1 1 30%; + gap: 5px 0px; +`; +export const RadioIndex = (args: RadioProps) => { + const radioText: string = 'Radio Label'; + const colorArr: colorSchemeType[] = ['blue', 'teal', 'green', 'cyan', 'purple', 'pink']; + return ( + + Radio + + Radio Demo + + + + + Radio Index + {colorArr.map((color) => ( + + + + + + + + + + + + + + + + + + ))} + + ); +}; +RadioIndex.storyName = 'Radio'; \ No newline at end of file diff --git a/packages/chakra-ui-styled/src/components/form/radio/Radio.styled.tsx b/packages/chakra-ui-styled/src/components/form/radio/Radio.styled.tsx new file mode 100644 index 0000000..5b3d432 --- /dev/null +++ b/packages/chakra-ui-styled/src/components/form/radio/Radio.styled.tsx @@ -0,0 +1,46 @@ +import styled, { css } from 'styled-components'; +import { RadioProps } from './Radio'; + + +const RadioSize = { sm: 12, md: 16, lg: 20, }; +const borderSize = { sm: 4, md: 5, lg: 6 }; +export const RadioForm = styled.input.attrs({ type: "Radio" })` + position: absolute; + opacity: 0; + cursor: pointer; + width: 0; + height: 0; +`; +export const Label = styled.label` + flex: 1 1 30%; + display: flex; + align-items: center; + gap: 8px; + + & span { + width: ${({ size }) => RadioSize[size]}px; + height: ${({ size }) => RadioSize[size]}px; + border-radius: 50%; + + ${({ size, defaultChecked, isDisabled, colorScheme, theme }) => css` + ${isDisabled + ? css`// 비활성o + background-color: ${theme.color.gray[200]}; + border: 2px solid ${theme.color.gray[200]}; + ${defaultChecked && css` // 동시 체크o + border: ${borderSize[size]}px solid ${theme.color.gray[200]}; + background-color: ${theme.color.gray[500]}; + `} + ` + : defaultChecked + ? css` // 비활성x, 동시 체크o + border: ${borderSize[size]}px solid ${theme.color[colorScheme][500]}; + background-color: ${theme.color.white.white}; + ` + : css` // 비활성x, 동시 체크x + border: 2px solid ${theme.color.gray[200]}; + background: none; + `} + `} + } +`; \ No newline at end of file diff --git a/packages/chakra-ui-styled/src/components/form/radio/Radio.tsx b/packages/chakra-ui-styled/src/components/form/radio/Radio.tsx new file mode 100644 index 0000000..44fb31a --- /dev/null +++ b/packages/chakra-ui-styled/src/components/form/radio/Radio.tsx @@ -0,0 +1,24 @@ +import { StyleText } from '../../../foundation/typography/Text.styled'; +import { RadioForm, Label } from './Radio.styled'; + +export type colorSchemeType = 'blue' | 'teal' | 'green' | 'cyan' | 'purple' | 'pink'; +export interface RadioProps { + size: 'sm' | 'md' | 'lg'; + colorScheme: colorSchemeType; + defaultChecked?: boolean; + isDisabled?: boolean; + text: string; +} + +const Radio = ({ size = 'md', defaultChecked = true, isDisabled = false, colorScheme, text }: RadioProps) => { + return ( + + + + + {text} + + + ); +}; +export default Radio; \ No newline at end of file diff --git a/packages/chakra-ui-styled/src/components/form/select/Select.stories.tsx b/packages/chakra-ui-styled/src/components/form/select/Select.stories.tsx new file mode 100644 index 0000000..5e98bc5 --- /dev/null +++ b/packages/chakra-ui-styled/src/components/form/select/Select.stories.tsx @@ -0,0 +1,68 @@ +import styled from 'styled-components'; +import Select, { SelectProps, colorSchemeType } from './Select'; + +export default { + title: 'chakra-ui-styled/components/form/select', + component: Select, + parameters: { controls: { expanded: true } }, + + argTypes: { + placeholder: { control: { type: 'text' } }, + size: { control: { type: 'select' } }, + colorScheme: { control: { type: 'select' } }, + disabled: { control: { type: 'boolean' } }, + readonly: { control: { type: 'boolean' } }, + isInvalid: { control: { type: 'boolean' } } + }, + args: { + placeholder: 'Hello', + size: 'md', + colorScheme: 'blue', + disabled: false, + readonly: false, + isInvalid: false + } +}; +const Wrapper = styled.div` + display: flex; + flex-direction: column; + gap: 20px; +`; +const Stack = styled.div` + display: flex; + flex-flow: row wrap; + flex: 1 1 0; + gap: 10px; +`; +export const SelectIndex = (args: SelectProps) => { + const colorArr: colorSchemeType[] = ['whiteAlpha', 'blackAlpha', 'gray', 'red', 'orange', 'yellow', 'green', 'teal', 'blue', 'cyan', 'purple', 'pink']; + return ( + + Select + + Select Demo + + + + + Select Index + {colorArr.map((color) => ( + + + + + + + + + + + + + + + ))} + + ); +}; +SelectIndex.storyName = 'Select'; diff --git a/packages/chakra-ui-styled/src/components/form/select/Select.styled.tsx b/packages/chakra-ui-styled/src/components/form/select/Select.styled.tsx new file mode 100644 index 0000000..c0dbdf5 --- /dev/null +++ b/packages/chakra-ui-styled/src/components/form/select/Select.styled.tsx @@ -0,0 +1,55 @@ +import styled, { css } from 'styled-components'; +import { SelectProps } from './Select'; + + +const selectFontSize = { + xs: css` + height: 24px; + padding: 0 32px 1px 8px; + ${({ theme }) => theme.typo.text.xs} + `, + sm: css` + height: 32px; + padding: 0 32px 1px 12px; + ${({ theme }) => theme.typo.text.sm} + `, + md: css` + height: 40px; + padding: 0 32px 1px 16px; + ${({ theme }) => theme.typo.text.md} + `, + lg: css` + height: 48px; + padding: 0 32px 1px 16px; + ${({ theme }) => theme.typo.text.lg} + `, +}; +export const SelectStyle = styled.select` + width: 320px; + border-radius: 6px; + ${({ size }) => selectFontSize[size]} + &:focus { + outline: 0; + } + + ${({ disabled, readOnly, isInvalid, colorScheme, theme }) => css` + ${disabled || readOnly + ? css` + // 비활성o + opacity: 0.5; + border: 1px solid ${theme.color.gray[200]}; + ` + : css` + // 기본 + border: 1px solid ${theme.color.gray[200]}; + &:focus { + outline: 1px solid ${theme.color[colorScheme][500]}; + } + // 기본 + 값이 있을때만 조건 충족 : 아웃라인 들어와야함 + ${isInvalid && + css` + outline: 1px solid ${theme.color[colorScheme][500]}; + `} + `} + `} +`; \ No newline at end of file diff --git a/packages/chakra-ui-styled/src/components/form/select/Select.tsx b/packages/chakra-ui-styled/src/components/form/select/Select.tsx new file mode 100644 index 0000000..bc6ace0 --- /dev/null +++ b/packages/chakra-ui-styled/src/components/form/select/Select.tsx @@ -0,0 +1,20 @@ +import { SelectStyle } from './Select.styled'; + +export type colorSchemeType = 'whiteAlpha' | 'blackAlpha' | 'gray' | 'red' | 'orange' | 'yellow' | 'green' | 'teal' | 'blue' | 'cyan' | 'purple' | 'pink' ; +export interface SelectProps { + size: 'xs' | 'sm' | 'md' | 'lg'; + colorScheme: colorSchemeType; + isInvalid?: boolean; + disabled?: boolean; + readOnly?: boolean; + placeholder: string; +} + +const Select = ({placeholder = 'Hello', size='md', colorScheme, disabled = false, readOnly = false, isInvalid = false }: SelectProps) => { + return ( + + {placeholder} + + ) +}; +export default Select; diff --git a/packages/chakra-ui-styled/src/components/form/slider/Slider.stories.tsx b/packages/chakra-ui-styled/src/components/form/slider/Slider.stories.tsx new file mode 100644 index 0000000..c6efa96 --- /dev/null +++ b/packages/chakra-ui-styled/src/components/form/slider/Slider.stories.tsx @@ -0,0 +1,78 @@ +import styled from 'styled-components'; +import Slider, { SliderProps, colorSchemeType } from './Slider'; + +export default { + title: 'chakra-ui-styled/components/form/slider', + component: Slider, + parameters: { controls: { expanded: true } }, + + argTypes: { + size: { control: { type: 'select' } }, + colorScheme: { control: { type: 'select' } }, + disabled: { control: { type: 'boolean' } }, + readonly: { control: { type: 'boolean' } }, + value: { control: { type: 'number' } }, + min: { control: { type: 'number' } }, + max: { control: { type: 'number' } }, + step: { control: { type: 'number' } }, + }, + args: { + size: 'sm', + colorScheme: 'blue', + disabled: false, + readonly: false, + value: 50, + min: 0, + max: 100, + step: 1, + } +}; +const Wrapper = styled.div` + display: flex; + flex-direction: column; + gap: 20px; +`; +const Stack = styled.div` + display: flex; + align-items: center; + flex: 1 1 0; + gap: 50px; +`; +export const SliderIndex = (args: SliderProps) => { + const colorArr: colorSchemeType[] = ['whiteAlpha', 'blackAlpha', 'gray', 'red', 'orange', 'yellow', 'green', 'teal', 'blue', 'cyan', 'purple', 'pink']; + return ( + + Slider + + Slider Demo + + + + + Slider Index + {colorArr.map((color) => ( + + + + + + + + + ))} + + ); +}; +SliderIndex.storyName = 'Slider'; diff --git a/packages/chakra-ui-styled/src/components/form/slider/Slider.styled.tsx b/packages/chakra-ui-styled/src/components/form/slider/Slider.styled.tsx new file mode 100644 index 0000000..1dc1796 --- /dev/null +++ b/packages/chakra-ui-styled/src/components/form/slider/Slider.styled.tsx @@ -0,0 +1,100 @@ +import styled, { css } from 'styled-components'; +import { SliderProps } from './Slider'; + +const SliderTrackSize = { + sm: css` + height: 2px; + border-radius: 2px; + `, + md: css` + height: 4px; + border-radius: 4px; + `, + lg: css` + height: 4px; + border-radius: 4px; + `, +}; +const SliderThumbSize = { sm: 10, md: 14, lg: 16 }; +export const StyleSlider = styled.div` + display: flex; + align-items: center; + flex: 1 1 30%; + position: relative; + height: ${({ size }) => SliderThumbSize[size]}px; + & input[type="range"]{ + &::-webkit-slider-thumb{ + width: ${({ size }) => SliderThumbSize[size]}px; + } + } + & .sliderTrack{ + ${({ size }) => SliderTrackSize[size]} + } + & .sliderFilledTrack{ + ${({ size }) => SliderTrackSize[size]} + width: 50%; + } + + ${({ value, disabled, readOnly, colorScheme, theme }) => css` + & input[type="range"]{ + &::-webkit-slider-thumb{ + left: ${value}%; + } + } + & .sliderTrack{ + background: ${theme.color.gray[200]}; + } + & .sliderFilledTrack{ + background: ${theme.color[colorScheme][500]}; + width: ${value}%; + } + ${disabled || readOnly + ? css` + // 비활성o + opacity: 0.6; + & input[type="range"]{ + &::-webkit-slider-thumb{ + background: ${theme.color.gray[300]} + } + } + & .sliderTrack{ + background: ${theme.color.gray[300]}; + } + & .sliderFilledTrack{ + background: ${theme.color[colorScheme][500]}; + } + ` + : css``} + `} +`; +export const SliderThumb = styled.input.attrs({ type: "range" })` + width:100%; + appearance: none; + &::-webkit-slider-thumb{ + appearance: none; + aspect-ratio: 1; + border-radius: 50%; + background: #fff; + box-shadow: 0px 1px 2px 0px rgba(0,0,0,0.06), 0px 1px 3px 0px rgba(0,0,0,0.1); + position: absolute; + top: 50%; + transform: translate(-50%, -50%); + cursor: pointer; + } + +`; +export const SliderTrack = styled.div` + &.sliderTrack{ + position: absolute; + width: 100%; + top: 50%; + transform: translateY(-50%); + } +`; +export const SliderFilledTrack = styled.div` + &.sliderFilledTrack{ + position: absolute; + top: 0; + } +`; + diff --git a/packages/chakra-ui-styled/src/components/form/slider/Slider.tsx b/packages/chakra-ui-styled/src/components/form/slider/Slider.tsx new file mode 100644 index 0000000..28d76b8 --- /dev/null +++ b/packages/chakra-ui-styled/src/components/form/slider/Slider.tsx @@ -0,0 +1,36 @@ +import { StyleSlider, SliderThumb, SliderTrack, SliderFilledTrack } from './Slider.styled'; +import { ChangeEvent, useState } from "react" + +export type InputValue = string | number | ReadonlyArray +export type InputChangeEvent = ChangeEvent; +export type colorSchemeType = 'whiteAlpha' | 'blackAlpha' | 'gray' | 'red' | 'orange' | 'yellow' | 'green' | 'teal' | 'blue' | 'cyan' | 'purple' | 'pink' ; +export interface SliderProps { + size: 'sm' | 'md' | 'lg'; + colorScheme: colorSchemeType; + disabled?: boolean; + readOnly?: boolean; + value: InputValue; + min: number; + max: number; + step: number; + onChange?: (e: InputChangeEvent) => void; +} +let ariaLabel = 'slider-ex-1' as const; +const Slider = ({ size = 'md', colorScheme, value, min, max, step, disabled = false, readOnly = false, onChange }: SliderProps) => { + const [inputValue, setInputValue] = useState(value); + const changeHandler = (e: InputChangeEvent) => { + setInputValue(e.target.value); + onChange && onChange(e) // optional로 인한 코드 + } + return ( + + + + + + + ); +}; +export default Slider; \ No newline at end of file diff --git a/packages/chakra-ui-styled/src/components/form/switch/Switch.stories.tsx b/packages/chakra-ui-styled/src/components/form/switch/Switch.stories.tsx new file mode 100644 index 0000000..9ccafbe --- /dev/null +++ b/packages/chakra-ui-styled/src/components/form/switch/Switch.stories.tsx @@ -0,0 +1,71 @@ +import styled from 'styled-components'; +import Switch, { SwitchProps, colorSchemeType } from './Switch'; + +export default { + title: 'chakra-ui-styled/components/form/switch', + component: Switch, + parameters: { controls: { expanded: true } }, + + argTypes: { + text: { control: { type: 'text' } }, + size: { control: { type: 'select' } }, + colorScheme: { control: { type: 'select' } }, + defaultChecked: { control: { type: 'boolean' } }, + isDisabled: { control: { type: 'boolean' } }, + }, + args: { + text: '선택대상', + size: 'md', + colorScheme: 'blue', + defaultChecked: true, + isDisabled: false, + } +}; + +const Wrapper = styled.div` + display: flex; + flex-direction: column; + gap: 20px; +`; +const SwitchGroup = styled.div` + display: flex; + flex-flow: row wrap; + flex: 1 1 30%; + gap: 5px 0px; +`; +export const SwitchIndex = (args: SwitchProps) => { + const switchText: string = 'Switch Label'; + const colorArr: colorSchemeType[] = ['blue', 'teal', 'green', 'cyan', 'purple', 'pink']; + return ( + + Switch + + Switch Demo + + + + + Switch Index + {colorArr.map((color) => ( + + + + + + + + + + + + + + + + + + ))} + + ); +}; +SwitchIndex.storyName = 'Switch'; \ No newline at end of file diff --git a/packages/chakra-ui-styled/src/components/form/switch/Switch.styled.tsx b/packages/chakra-ui-styled/src/components/form/switch/Switch.styled.tsx new file mode 100644 index 0000000..7e15e19 --- /dev/null +++ b/packages/chakra-ui-styled/src/components/form/switch/Switch.styled.tsx @@ -0,0 +1,58 @@ +import styled, { css } from 'styled-components'; +import { SwitchProps } from './Switch'; + +const SwitchSize = { sm: 12, md: 16, lg: 24 }; +export const SwitchForm = styled.input.attrs({ type: "Radio" })` + position: absolute; + opacity: 0; + cursor: pointer; + width: 0; + height: 0; +`; +export const Label = styled.label` + flex: 1 1 30%; + display: flex; + align-items: center; + gap: 13px; + + & span { + width: ${({ size }) => SwitchSize[size] * 2 + 2}px; + height: ${({ size }) => SwitchSize[size] + 4}px; + padding: 2px; + border-radius: 9999px; + + &::after { + content: ''; + display: block; + width: ${({ size }) => SwitchSize[size]}px; + height: ${({ size }) => SwitchSize[size]}px; + border-radius: 100%; + transition: 0.3s; + background-color: #fff; + } + + ${({ defaultChecked, isDisabled, theme, colorScheme }) => css` + ${isDisabled + ? css`// 비활성o + opacity: 40%; + background-color: ${theme.color.gray[300]}; + ${defaultChecked && css` // 동시 체크o + &::after { + transform: translateX(calc(100% - 2px)); + } + background-color: ${theme.color[colorScheme][500]}; + `} + ` + : defaultChecked + ? css` // 비활성x, 동시 체크o + &::after { + transform: translateX(calc(100% - 2px)); + } + background-color: ${theme.color[colorScheme][500]}; + ` + : css` // 비활성x, 동시 체크x + background-color: ${theme.color.gray[300]}; + `} + `} + } +`; \ No newline at end of file diff --git a/packages/chakra-ui-styled/src/components/form/switch/Switch.tsx b/packages/chakra-ui-styled/src/components/form/switch/Switch.tsx new file mode 100644 index 0000000..f795fbb --- /dev/null +++ b/packages/chakra-ui-styled/src/components/form/switch/Switch.tsx @@ -0,0 +1,24 @@ +import { StyleText } from '../../../foundation/typography/Text.styled'; +import { SwitchForm, Label } from './Switch.styled'; + +export type colorSchemeType = 'blue' | 'teal' | 'green' | 'cyan' | 'purple' | 'pink'; +export interface SwitchProps { + size: 'sm' | 'md' | 'lg'; + colorScheme: colorSchemeType; + defaultChecked?: boolean; + isDisabled?: boolean; + text: string; +} + +const Switch = ({ size = 'md', defaultChecked = true, isDisabled = false, colorScheme, text }: SwitchProps) => { + return ( + + + + + {text} + + + ); +}; +export default Switch; \ No newline at end of file diff --git a/packages/chakra-ui-styled/src/components/form/textarea/Textarea.stories.tsx b/packages/chakra-ui-styled/src/components/form/textarea/Textarea.stories.tsx new file mode 100644 index 0000000..65a5c2c --- /dev/null +++ b/packages/chakra-ui-styled/src/components/form/textarea/Textarea.stories.tsx @@ -0,0 +1,53 @@ +import styled from 'styled-components'; +import Textarea, { TextareaProps, colorSchemeType } from './Textarea'; + +export default { + title: 'chakra-ui-styled/components/form/textarea', + component: Textarea, + parameters: { controls: { expanded: true } }, + + argTypes: { + colorScheme: { control: { type: 'select' } }, + disabled: { control: { type: 'boolean' } }, + isInvalid: { control: { type: 'boolean' } } + }, + args: { + colorScheme: 'blue', + disabled: false, + isInvalid: false + } +}; +const Wrapper = styled.div` + display: flex; + flex-direction: column; + gap: 20px; +`; +const Stack = styled.div` + display: flex; + flex-flow: row wrap; + flex: 1 1 0; + gap: 10px; +`; +export const TextareaIndex = (args: TextareaProps) => { + const colorArr: colorSchemeType[] = ['whiteAlpha', 'blackAlpha', 'gray', 'red', 'orange', 'yellow', 'green', 'teal', 'blue', 'cyan', 'purple', 'pink']; + return ( + + Textarea + + Textarea Demo + + + + + Textarea Index + {colorArr.map((color) => ( + + + + + + ))} + + ); +}; +TextareaIndex.storyName = 'Textarea'; diff --git a/packages/chakra-ui-styled/src/components/form/textarea/Textarea.styled.tsx b/packages/chakra-ui-styled/src/components/form/textarea/Textarea.styled.tsx new file mode 100644 index 0000000..26d50e1 --- /dev/null +++ b/packages/chakra-ui-styled/src/components/form/textarea/Textarea.styled.tsx @@ -0,0 +1,33 @@ +import styled, { css } from 'styled-components'; +import { TextareaProps } from './Textarea'; + +export const TextareaStyle = styled.textarea` + width: 320px; + height: 80px; + border-radius: 6px; + padding: 8px 12px; + &:focus { + outline: 0; + } + + ${({ disabled, readOnly, isInvalid, colorScheme,theme }) => css` + ${disabled || readOnly + ? css` + // 비활성o + opacity: 0.4; + border: 1px solid ${theme.color.gray[200]}; + ` + : css` + // 기본 + border: 1px solid ${theme.color.gray[200]}; + &:focus { + outline: 1px solid ${theme.color[colorScheme][500]}; + } + // 기본 + 값이 있을때만 조건 충족 : 아웃라인 들어와야함 + ${isInvalid && + css` + outline: 1px solid ${theme.color[colorScheme][500]}; + `} + `} + `} +`; \ No newline at end of file diff --git a/packages/chakra-ui-styled/src/components/form/textarea/Textarea.tsx b/packages/chakra-ui-styled/src/components/form/textarea/Textarea.tsx new file mode 100644 index 0000000..4bd90dc --- /dev/null +++ b/packages/chakra-ui-styled/src/components/form/textarea/Textarea.tsx @@ -0,0 +1,15 @@ +import { TextareaStyle } from "./Textarea.styled"; + +export type colorSchemeType = 'whiteAlpha' | 'blackAlpha' | 'gray' | 'red' | 'orange' | 'yellow' | 'green' | 'teal' | 'blue' | 'cyan' | 'purple' | 'pink' ; +export interface TextareaProps { + colorScheme: colorSchemeType; + isInvalid?: boolean; + disabled?: boolean; + readOnly?: boolean; + placeholder: string; +} + +const Textarea = ({ placeholder = 'Hello', colorScheme, disabled = false, readOnly = false, isInvalid = false }: TextareaProps) => { + return ; +}; +export default Textarea; diff --git a/packages/chakra-ui-styled/src/components/kbd/Kbd.stories.tsx b/packages/chakra-ui-styled/src/components/kbd/Kbd.stories.tsx new file mode 100644 index 0000000..3397dc2 --- /dev/null +++ b/packages/chakra-ui-styled/src/components/kbd/Kbd.stories.tsx @@ -0,0 +1,38 @@ +import styled from 'styled-components'; +import Kbd, { KbdProps } from './Kbd'; + +export default { + title: 'chakra-ui-styled/components/Kbd', + component: Kbd, + parameters: { controls: { expanded: true } }, + + argTypes: { + children: { control: { type: 'text' } } + }, + args: { + children: 'shift' + } +}; +const Wrapper = styled.div` + display: flex; + flex-direction: column; + gap: 20px; +`; + +export const KbdIndex = (args: KbdProps) => { + const KbdText: string = '⌘K'; + return ( + + Kbd + + Kbd Demo + + + + + Kbd Index + {KbdText} + + ); +}; +KbdIndex.storyName = 'Kbd'; diff --git a/packages/chakra-ui-styled/src/components/kbd/Kbd.styled.tsx b/packages/chakra-ui-styled/src/components/kbd/Kbd.styled.tsx new file mode 100644 index 0000000..3a8cec8 --- /dev/null +++ b/packages/chakra-ui-styled/src/components/kbd/Kbd.styled.tsx @@ -0,0 +1,20 @@ +import styled, { css } from 'styled-components'; + +export const KbdStyle = styled.div` + ${({ theme }) => css` + display: inline-flex; + flex: 1; + flex: 0 0 auto; + gap: 10px; + align-items: center; + align-self: flex-start; + justify-content: center; + justify-self: flex-start; + width: auto; + padding: 2px 4px; + color: ${theme.color.gray[700]}; + background-color: ${theme.color.gray[50]}; + border-radius: ${theme.radii.md}rem; + box-shadow: 0 -2px 0 0 ${theme.color.gray[200]} inset; + `} +`; diff --git a/packages/chakra-ui-styled/src/components/kbd/Kbd.tsx b/packages/chakra-ui-styled/src/components/kbd/Kbd.tsx new file mode 100644 index 0000000..7ea2789 --- /dev/null +++ b/packages/chakra-ui-styled/src/components/kbd/Kbd.tsx @@ -0,0 +1,18 @@ +import { StyleText } from '../../foundation/typography/Text.styled'; +import { KbdStyle } from './Kbd.styled'; + +export interface KbdProps { + children: React.ReactNode; +} + +const Kbd = ({ children }: KbdProps) => { + return ( + + + {children} + + + ); +}; + +export default Kbd; diff --git a/packages/chakra-ui-styled/src/components/media/Avatar/Avatar.stories.tsx b/packages/chakra-ui-styled/src/components/media/Avatar/Avatar.stories.tsx new file mode 100644 index 0000000..27a37d5 --- /dev/null +++ b/packages/chakra-ui-styled/src/components/media/Avatar/Avatar.stories.tsx @@ -0,0 +1,68 @@ +import styled from 'styled-components'; +import Avatar, { AvatarProps, AvatarSize } from './Avatar'; + +export default { + title: 'chakra-ui-styled/components/Avatar', + component: Avatar, + parameters: { controls: { expanded: true } }, + + argTypes: { + size: { control: { type: 'select' } }, + userName: { control: { type: 'text', maxLength: 2 } } + }, + args: { + size: '2xl', + img: 'https://images.unsplash.com/photo-1552058544-f2b08422138a?q=80&w=1299&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D' + } +}; +const Wrapper = styled.div` + display: flex; + flex-direction: column; + gap: 20px; +`; +const AvatarWrap = styled.div` + display: flex; + gap: 45px; + align-items: center; +`; + +export const AvatarIndex = (args: AvatarProps) => { + const AvatarArr: AvatarSize[] = ['xs', 'sm', 'md', 'lg', 'xl', '2xl']; + return ( + + Avatar + + Avatar Demo + + + + + Avatar Index + + + {AvatarArr.map((size) => { + return ( + + ); + })} + + + + {AvatarArr.map((size) => { + return ; + })} + + + + {AvatarArr.map((size) => { + return ; + })} + + + ); +}; +AvatarIndex.storyName = 'Avatar'; diff --git a/packages/chakra-ui-styled/src/components/media/Avatar/Avatar.styled.tsx b/packages/chakra-ui-styled/src/components/media/Avatar/Avatar.styled.tsx new file mode 100644 index 0000000..e8c3aee --- /dev/null +++ b/packages/chakra-ui-styled/src/components/media/Avatar/Avatar.styled.tsx @@ -0,0 +1,161 @@ +import styled, { css } from 'styled-components'; +import { AvatarStyleProps } from './Avatar'; +import { StyleText } from '../../../foundation/typography/Text.styled'; + +const AvatarSize = { + '2xl': { + size: '128px', + typo: '48px', + badge: css` + width: 40px; + height: 40px; + border-style: solid; + border-width: 8px; + border-radius: ${({ theme }) => theme.radii.full}; + ` + }, + xl: { + size: '96px', + typo: '38px', + badge: css` + width: 24px; + height: 24px; + border-style: solid; + border-width: 5px; + border-radius: ${({ theme }) => theme.radii.full}; + ` + }, + lg: { + size: '64px', + typo: '24px', + badge: css` + width: 16px; + height: 16px; + border-style: solid; + border-width: 3px; + border-radius: ${({ theme }) => theme.radii.full}; + ` + }, + md: { + size: '48px', + typo: '20px', + badge: css` + width: 16px; + height: 16px; + border-style: solid; + border-width: 3px; + border-radius: ${({ theme }) => theme.radii.full}; + ` + }, + sm: { + size: '32px', + typo: '12px', + badge: css` + width: 8px; + height: 8px; + border-style: solid; + border-width: 2px; + border-radius: ${({ theme }) => theme.radii.full}; + ` + }, + xs: { + size: '24px', + typo: '10px', + badge: css` + width: 6px; + height: 6px; + border-style: solid; + border-width: 1px; + border-radius: ${({ theme }) => theme.radii.full}; + ` + } +}; +const AvatarText = { + lg: css` + ${({ theme }) => theme.typo.text.md}; + font-weight: ${({ theme }) => theme.typo.fontWeight.medium}; + line-height: 1.5; + `, + md: css` + ${({ theme }) => theme.typo.text.sm}; + font-weight: ${({ theme }) => theme.typo.fontWeight.medium}; + line-height: 1.3; + `, + sm: css` + ${({ theme }) => theme.typo.text.xs}; + font-weight: ${({ theme }) => theme.typo.fontWeight.medium}; + ` +}; + +export const AvatarStyle = styled.div<{ $props: AvatarStyleProps }>` + ${({ theme, $props }) => css` + position: relative; + display: inline-flex; + flex: none; + align-items: center; + justify-content: center; + width: ${AvatarSize[$props.size].size}; + height: ${AvatarSize[$props.size].size}; + border-radius: ${theme.radii.full}rem; + & ${StyleText} { + ${AvatarSize[$props.size].typo} + } + + /* img */ + ${$props.img && + css` + & img { + background-color: ${theme.color.gray[100]}; + border-radius: inherit; + } + `} + + ${$props.userName && + css` + background-color: ${theme.color.blue[300]}; + + .user-name { + font-size: ${AvatarSize[$props.size].typo}; + font-weight: 500; + line-height: 1.1; + text-transform: uppercase; + } + `} + /* avtar */ + ${!$props.img && + !$props.userName && + css` + color: white; + background-color: ${theme.color.gray[400]}; + + & svg { + width: calc(${AvatarSize[$props.size].size} / 1.5); + } + `} + + + /* badge */ + ${$props.badge && + css` + &::after { + position: absolute; + right: 0; + bottom: 0; + display: block; + content: ''; + border-radius: ${theme.radii.full}rem; + transform: translateY(10%); + ${AvatarSize[$props.size].badge}; + ${$props.badge === 'on' + ? css` + background-color: ${theme.color.green[500]}; + border-color: ${theme.color.white.white}; + ` + : css` + background-color: ${theme.color.red[500]}; + border-color: ${theme.color.red[100]}; + `} + } + `} + `} +`; diff --git a/packages/chakra-ui-styled/src/components/media/Avatar/Avatar.tsx b/packages/chakra-ui-styled/src/components/media/Avatar/Avatar.tsx new file mode 100644 index 0000000..f6b71da --- /dev/null +++ b/packages/chakra-ui-styled/src/components/media/Avatar/Avatar.tsx @@ -0,0 +1,37 @@ +import { AvatarStyle } from './Avatar.styled'; +import Image from 'next/image'; +export type AvatarSize = '2xl' | 'xl' | 'lg' | 'md' | 'sm' | 'xs'; +export type AvatarStyleProps = { + size: AvatarSize; + badge?: 'on' | 'off'; + img?: string; + userName?: string; +}; +export type AvatarProps = AvatarStyleProps & {}; +const AvatarIcon = () => { + return ( + + + + ); +}; +const Avatar = ({ size, userName, img, badge = 'on' }: AvatarProps) => { + return ( + + {/* 1. userName 존재하고 이미지 없을경우 */} + {userName && !img && {userName}} + {/* 2.이미지 존재할 경우 */} + {img && } + {/* 3. userName존재하지 않고 이미지 존재하지않을경우 */} + {!img && !userName && } + + ); +}; + +export default Avatar; diff --git a/packages/chakra-ui-styled/src/components/navigation/BreadCrumb/BreadCrumb.styled.tsx b/packages/chakra-ui-styled/src/components/navigation/BreadCrumb/BreadCrumb.styled.tsx new file mode 100644 index 0000000..dabf1f5 --- /dev/null +++ b/packages/chakra-ui-styled/src/components/navigation/BreadCrumb/BreadCrumb.styled.tsx @@ -0,0 +1,29 @@ +import styled, { css } from 'styled-components'; +import { colorSchemeType } from './BreadCrumbs'; + +export const StyleBreadCrumb = styled.div<{ $color: colorSchemeType }>` + display: flex; + align-items: center; + + span[data-separator='true'] { + display: inline-flex; + align-items: center; + justify-content: center; + width: 24px; + color: ${({ theme, $color }) => theme.color[$color][800]}; + } +`; + +export const StyleBreadCrumbLink = styled.span<{ as: HTMLElementTagNameMap; $color: colorSchemeType }>` + ${({ theme, as, $color }) => css` + ${theme.typo.text.md}; + color: ${theme.color[$color][700]}; + ${as === 'a' && + css` + &:hover { + color: ${theme.color[$color][500]}; + text-decoration: underline; + } + `}; + `} +`; diff --git a/packages/chakra-ui-styled/src/components/navigation/BreadCrumb/BreadCrumbs.tsx b/packages/chakra-ui-styled/src/components/navigation/BreadCrumb/BreadCrumbs.tsx new file mode 100644 index 0000000..435b1ad --- /dev/null +++ b/packages/chakra-ui-styled/src/components/navigation/BreadCrumb/BreadCrumbs.tsx @@ -0,0 +1,46 @@ +import { StyleBreadCrumb, StyleBreadCrumbLink } from './BreadCrumb.styled'; + +type BreadCrumbsPageType = { + title: string; + href: string; + current: boolean; +}; +type BreadCrumbsVariantType = 'dash' | 'arrow' | 'slash'; +export type colorSchemeType = 'blue' | 'gray' | 'teal' | 'red' | 'orange' | 'yellow' | 'pink' | 'purple' | 'green'; + +export type BreadCrumbsType = { + variant?: BreadCrumbsVariantType; + pages: BreadCrumbsPageType[]; + $colorScheme?: colorSchemeType; +}; + +const getVariant = { + dash: '-', + slash: '/', + arrow: '›' +}; + +const BreadCrumb = ({ pages, variant = 'dash', $colorScheme = 'gray' }: BreadCrumbsType) => { + return ( + + {pages.map((item) => ( + <> + {item.current === false ? ( + <> + + {item.title} + + {getVariant[variant]} + > + ) : ( + <> + {item.title} + > + )} + > + ))} + + ); +}; + +export default BreadCrumb; diff --git a/packages/chakra-ui-styled/src/components/navigation/BreadCrumb/Breadcrumbs.stories.tsx b/packages/chakra-ui-styled/src/components/navigation/BreadCrumb/Breadcrumbs.stories.tsx new file mode 100644 index 0000000..ab9c486 --- /dev/null +++ b/packages/chakra-ui-styled/src/components/navigation/BreadCrumb/Breadcrumbs.stories.tsx @@ -0,0 +1,64 @@ +import styled from 'styled-components'; +import BreadCrumbs, { BreadCrumbsType, colorSchemeType } from './BreadCrumbs'; + +export default { + title: 'chakra-ui-styled/components/navigation/BreadCrumb', + component: BreadCrumbs, + parameters: { controls: { expanded: true } }, + + argTypes: { + variant: { control: { type: 'select' }, options: ['slash', 'arrow', 'dash'] }, + $colorScheme: { + control: { type: 'select' }, + options: ['blue', 'gray', 'teal', 'red', 'orange', 'yellow', 'pink', 'purple', 'green'] + } + }, + args: { + variant: 'arrow', + pages: [ + { title: 'Home', href: '/', current: false }, + { title: 'Link1', href: '/', current: false }, + { title: 'Link2', href: '/', current: false }, + { title: 'Current', href: '/', current: true } + ] + } +}; +const Wrapper = styled.div` + display: flex; + flex-direction: column; + gap: 20px; +`; + +export const BreadCrumbsIndex = (args: BreadCrumbsType) => { + const pages = [ + { title: 'Home', href: '/', current: false }, + { title: 'Link1', href: '/', current: false }, + { title: 'Link2', href: '/', current: false }, + { title: 'Current', href: '/', current: true } + ]; + return ( + + BreadCrumb + + BreadCrumb Demo + + + + + BreadCrumb Index + + + + + + + + + + + + + + ); +}; +BreadCrumbsIndex.storyName = 'BreadCrumb'; diff --git a/packages/chakra-ui-styled/src/components/overlay/menu/Menu.stories.tsx b/packages/chakra-ui-styled/src/components/overlay/menu/Menu.stories.tsx new file mode 100644 index 0000000..973501a --- /dev/null +++ b/packages/chakra-ui-styled/src/components/overlay/menu/Menu.stories.tsx @@ -0,0 +1,33 @@ +import styled from 'styled-components'; +import Menu, { MenuProps } from './Menu'; + + +export default { + title: 'chakra-ui-styled/components/overlay/menu', + component: Menu, + parameters: { controls: { expanded: true } }, + + argTypes: { + isOpen: { control: { type: 'boolean' } } + }, + args: { + isOpen: false + } +}; +const Wrapper = styled.div` + display: flex; + flex-direction: column; + gap: 20px; +`; + +export const MenuIndex = (args: MenuProps) => { + return ( + + Menu + + Menu Demo + + + ); +}; +MenuIndex.storyName = 'Menu'; diff --git a/packages/chakra-ui-styled/src/components/overlay/menu/Menu.styled.tsx b/packages/chakra-ui-styled/src/components/overlay/menu/Menu.styled.tsx new file mode 100644 index 0000000..ca8d206 --- /dev/null +++ b/packages/chakra-ui-styled/src/components/overlay/menu/Menu.styled.tsx @@ -0,0 +1,36 @@ +import styled from 'styled-components'; + +export const StyleMenu = styled.div` + position: relative; +`; +export const MenuList = styled.div<{ isOpen: boolean }>` + display: ${({ isOpen }) => (isOpen ? 'flex' : 'none')}; + flex-direction: column; + gap: 10px; + padding: 10px 0; + border-radius: 12px; + background-color: #fff; + position: absolute; + left: 0; + top: calc(100% + 9px); + box-shadow: 0px 1px 2px 0px rgba(0,0,0,0.05); + border: 1px solid ${({ theme }) => theme.color.gray[200]}; + min-width: 278px; +`; +export const MenuItem = styled.div` + ${({ theme }) => theme.typo.text.lg}; + display: flex; + flex: 1; + white-space: nowrap; + gap: 10px; + padding: 6px 22px; + cursor: pointer; + &:hover{ + background-color: ${({ theme }) => theme.color.gray[200]}; + } +`; +export const MenuDivider = styled.div` + height: 1px; + width: 100%; + background-color: ${({ theme }) => theme.color.gray[200]}; +`; \ No newline at end of file diff --git a/packages/chakra-ui-styled/src/components/overlay/menu/Menu.tsx b/packages/chakra-ui-styled/src/components/overlay/menu/Menu.tsx new file mode 100644 index 0000000..ddf9c84 --- /dev/null +++ b/packages/chakra-ui-styled/src/components/overlay/menu/Menu.tsx @@ -0,0 +1,28 @@ +import { StyleMenu, MenuList, MenuItem, MenuDivider } from './Menu.styled'; +import { useState } from 'react'; +import Button from '../../form/button/Button'; + +export interface MenuProps { + isOpen: boolean; +} + +const Menu = ({ isOpen }: MenuProps) => { + const [menuIsOpen, setMenuIsOpen] = useState(false); + const openMenu = () => setMenuIsOpen(!isOpen); + + return ( + + + {isOpen ? 'MenuClose' : 'MenuOpen'} + + + + My Account + Payments + + Docs + + + ); +}; +export default Menu; diff --git a/packages/chakra-ui-styled/src/components/overlay/modal/Modal.stories.tsx b/packages/chakra-ui-styled/src/components/overlay/modal/Modal.stories.tsx new file mode 100644 index 0000000..f4a5140 --- /dev/null +++ b/packages/chakra-ui-styled/src/components/overlay/modal/Modal.stories.tsx @@ -0,0 +1,43 @@ +import styled from 'styled-components'; +import Modal, { ModalProps } from './Modal'; + + +export default { + title: 'chakra-ui-styled/components/overlay/modal', + component: Modal, + parameters: { controls: { expanded: true } }, + + argTypes: { + title: { control: { type: 'text' } }, + contents: { control: { type: 'text' } }, + isOpen: { control: { type: 'boolean' } } + }, + args: { + title: 'Modal Title', + contents: 'Sit nulla est ex deserunt exercitation anim occaecat. Nostrud ullamco deserunt aute id consequat veniam incididunt duis in sint irure nisi. Mollit officia cillum Lorem ullamco minim nostrud elit officia tempor esse quis.', + isOpen: false + } +}; +const Wrapper = styled.div` + display: flex; + flex-direction: column; + gap: 20px; +`; +const Wrap = styled.div` + display: inline-flex; + padding: 50px 80px; +`; + +export const ModalIndex = (args: ModalProps) => { + return ( + + Modal + + Modal Demo + + + + + ); +}; +ModalIndex.storyName = 'Modal'; diff --git a/packages/chakra-ui-styled/src/components/overlay/modal/Modal.styled.tsx b/packages/chakra-ui-styled/src/components/overlay/modal/Modal.styled.tsx new file mode 100644 index 0000000..7284197 --- /dev/null +++ b/packages/chakra-ui-styled/src/components/overlay/modal/Modal.styled.tsx @@ -0,0 +1,49 @@ +import styled from 'styled-components'; +import CloseButton from '../../form/closebutton/CloseButton'; + +export const StyleModal = styled.div<{ isOpen: boolean }>` + display: ${({ isOpen }) => (isOpen ? 'flex' : 'none')}; +`; +export const ModalOverlay = styled.div` + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background-color: ${({ theme }) => theme.color.blackAlpha[600]}; + z-index: 100; +`; +export const ModalContent = styled.div` + border-radius: 6px; + background-color: #fff; + position: absolute; + top: 40%; + left: 50%; + transform: translate(-50%, -50%); + box-shadow: 0px 4px 6px -2px rgba(0,0,0,0.05), 0px 10px 15px -3px rgba(0,0,0,0.1); + min-width: 448px; + z-index: 110; + +`; +export const ModalHeader = styled.div` + display: flex; + align-items: center; + padding: 16px 24px; + width: 100%; + ${({ theme }) => theme.typo.text.lg}; +`; +export const ModalBody = styled.div` + padding: 8px 24px; + ${({ theme }) => theme.typo.text.md}; +`; +export const ModalFooter = styled.div` + padding: 16px 24px; + display: flex; + justify-content: flex-end; + gap: 10px; +`; +export const StyledCloseButton = styled(CloseButton)` + position: absolute; + top: 8px; + right: 16px; + ` \ No newline at end of file diff --git a/packages/chakra-ui-styled/src/components/overlay/modal/Modal.tsx b/packages/chakra-ui-styled/src/components/overlay/modal/Modal.tsx new file mode 100644 index 0000000..cca2575 --- /dev/null +++ b/packages/chakra-ui-styled/src/components/overlay/modal/Modal.tsx @@ -0,0 +1,53 @@ +import { + StyleModal, + ModalOverlay, + ModalContent, + ModalHeader, + StyledCloseButton, + ModalBody, + ModalFooter +} from './Modal.styled'; +import { useState } from 'react'; +import Button from '../../form/button/Button'; +import { CloseIconStyle } from '../../form/closebutton/CloseButton.styled'; + +export interface ModalProps { + isOpen: boolean; + title?: string; + contents?: string; +} + +const Modal = ({ isOpen, title, contents }: ModalProps) => { + const [modalIsOpen, setModalIsOpen] = useState(isOpen); + const openModal = () => setModalIsOpen(true); + const closeModal = () => setModalIsOpen(false); + + return ( + <> + {/* 임시버튼 */} + + Open Modal + + + + + + {title} + } /> + + {contents} + + + + Close + + + Cancel + + + + + > + ); +}; +export default Modal; diff --git a/packages/chakra-ui-styled/src/components/overlay/tooltip/Tooltip.stories.tsx b/packages/chakra-ui-styled/src/components/overlay/tooltip/Tooltip.stories.tsx new file mode 100644 index 0000000..fac0be7 --- /dev/null +++ b/packages/chakra-ui-styled/src/components/overlay/tooltip/Tooltip.stories.tsx @@ -0,0 +1,68 @@ +import styled from 'styled-components'; +import Tooltip, { TooltipProps, placementType } from './Tooltip'; +import { ArrowIconStyle } from './Tooltip.styled'; + + +export default { + title: 'chakra-ui-styled/components/overlay/tooltip', + component: Tooltip, + parameters: { controls: { expanded: true } }, + + argTypes: { + label: { control: { type: 'text' } }, + // placement: { control: { type: 'select' } }, + // 패널이 셀렉트박스가 구현안됨 + placement: { control: { type: 'text' } }, + }, + args: { + label: 'Hover me', + placement: 'auto-start', + arrowIcon: , + } +}; +const Wrapper = styled.div` + display: flex; + flex-direction: column; + gap: 20px; +`; +const Wrap = styled.div` + display: inline-flex; + padding: 50px 80px; +`; +const Stack = styled.div` + padding: 0 80px; + display: flex; + flex-flow: row wrap; + gap: 50px 90px; + & > div{ + display: inline-flex; + flex-direction: column; + align-items: center; + gap: 20px; + } +`; + +export const TooltipIndex = (args: TooltipProps) => { + const placementArr: placementType[] = ['auto-start', 'auto', 'auto-end', 'top-start', 'top', 'top-end', 'right-start', 'right', 'right-end', 'bottom-start', 'bottom', 'bottom-end', 'left-start', 'left', 'left-end']; + return ( + + Tooltip + + Tooltip Demo + + + + + Tooltip Index + + {placementArr.map((placement) => ( + + {placement} + } /> + + ))} + + + ); +}; +TooltipIndex.storyName = 'Tooltip'; diff --git a/packages/chakra-ui-styled/src/components/overlay/tooltip/Tooltip.styled.tsx b/packages/chakra-ui-styled/src/components/overlay/tooltip/Tooltip.styled.tsx new file mode 100644 index 0000000..8f2b92e --- /dev/null +++ b/packages/chakra-ui-styled/src/components/overlay/tooltip/Tooltip.styled.tsx @@ -0,0 +1,190 @@ +import styled, { css } from 'styled-components'; +import { TooltipProps } from './Tooltip'; + +const tooltipPosition = { + ["auto-start"]: css` + top: 0; + right: 0; + transform: translateX(calc(100% + 8px)); + & figure{ + top: 50%; + left: 0; + transform: translate(calc(-100% + 6px), -50%) rotate(-90deg) + } + `, + ["auto"]: css` + top: 50%; + left: 0; + transform: translate(calc(-100% - 8px), -50%); + & figure{ + top: 50%; + right: 0; + transform: translate(calc(100% - 6px), -50%) rotate(90deg) + } + `, + ["auto-end"]: css` + top: 0; + left: 0; + transform: translateX(calc(-100% - 8px)); + & figure{ + top: 50%; + right: 0; + transform: translate(calc(100% - 6px), -50%) rotate(90deg) + } + `, + ["top-start"]: css` + top: 0; + left: 0; + transform: translateY(calc(-100% - 8px)); + & figure{ + bottom: 0; + left: 0; + transform: translate(8px, calc(100% - 2px)) rotate(180deg) + } + `, + ["top"]: css` + top: 0; + left: 50%; + transform: translate( -50%, calc(-100% - 8px)); + & figure{ + bottom: 0; + left: 50%; + transform: translate(-50%, calc(100% - 2px)) rotate(180deg) + } + `, + ["top-end"]: css` + top: 0; + right: 0; + transform: translateY(calc(-100% - 8px)); + & figure{ + bottom: 0; + right: 0; + transform: translate(-8px, calc(100% - 2px)) rotate(180deg) + } + `, + ["right-start"]: css` + top: 0; + right: 0; + transform: translateX(calc(100% + 8px)); + & figure{ + top: 50%; + left: 0; + transform: translate(calc(-100% + 6px), -50%) rotate(-90deg) + } + `, + ["right"]: css` + top: 50%; + right: 0; + transform: translate(calc(100% + 8px), -50%); + & figure{ + top: 50%; + left: 0; + transform: translate(calc(-100% + 6px), -50%) rotate(-90deg) + } + `, + ["right-end"]: css` + bottom: 0; + right: 0; + transform: translateX(calc(100% + 8px)); + & figure{ + top: 50%; + left: 0; + transform: translate(calc(-100% + 6px), -50%) rotate(-90deg) + } + `, + ["bottom-start"]: css` + bottom: 0; + left: 0; + transform: translateY(calc(100% + 8px)); + & figure{ + top: 0; + left: 0; + transform: translate(8px, calc(-100% + 2px)) + } + `, + ["bottom"]: css` + bottom: 0; + left: 50%; + transform: translate(-50%, calc(100% + 8px)); + & figure{ + top: 0; + left: 50%; + transform: translate(-50%, calc(-100% + 2px)) + } + `, + ["bottom-end"]: css` + bottom: 0; + right: 0; + transform: translateY(calc(100% + 8px)); + & figure{ + top: 0; + right: 0; + transform: translate(-8px, calc(-100% + 2px)) + } + `, + ["left-start"]: css` + top: 0; + left: 0; + transform: translateX(calc(-100% - 8px)); + & figure{ + top: 50%; + right: 0; + transform: translate(calc(100% - 6px), -50%) rotate(90deg) + } + `, + ["left"]: css` + top: 50%; + left: 0; + transform: translate(calc(-100% - 8px), -50%); + & figure{ + top: 50%; + right: 0; + transform: translate(calc(100% - 6px), -50%) rotate(90deg) + } + `, + ["left-end"]: css` + bottom: 0; + left: 0; + transform: translateX(calc(-100% - 8px)); + & figure{ + top: 50%; + right: 0; + transform: translate(calc(100% - 6px), -50%) rotate(90deg) + } + `, +}; +export const ArrowIconStyle = () => { + return ( + + + + ); +}; +export const StyleTooltip = styled.div` + position: relative; + display: inline-flex; + & span{ + ${({ placement }) => tooltipPosition[placement]} + } + &:hover span{ + opacity: 1; + } +`; +export const StyleText = styled.span` + position: absolute; + color: #fff; + display: inline-flex; + white-space: nowrap; + padding: 2px 8px; + border-radius: 4px; + ${({ theme }) => theme.typo.text.sm}; + background-color: ${({ theme }) => theme.color.gray[900]}; + opacity: 0; + transition: 0.3s; + & figure{ + width: 16px; + height: 8px; + position: absolute; + & svg{ position:absolute } + } +`; \ No newline at end of file diff --git a/packages/chakra-ui-styled/src/components/overlay/tooltip/Tooltip.tsx b/packages/chakra-ui-styled/src/components/overlay/tooltip/Tooltip.tsx new file mode 100644 index 0000000..8301939 --- /dev/null +++ b/packages/chakra-ui-styled/src/components/overlay/tooltip/Tooltip.tsx @@ -0,0 +1,28 @@ +import { StyleTooltip, StyleText } from './Tooltip.styled'; +import Button from '../../form/button/Button'; + +export type colorSchemeType = 'whiteAlpha' | 'blackAlpha' | 'gray' | 'red' | 'orange' | 'yellow' | 'green' | 'teal' | 'blue' | 'cyan' | 'purple' | 'pink' ; +export type placementType = 'auto-start' | 'auto' | 'auto-end' | 'top-start' | 'top' | 'top-end' | 'right-start' | 'right' | 'right-end' | 'bottom-start' | 'bottom' | 'bottom-end' | 'left-start' | 'left' | 'left-end' ; +export interface TooltipProps { + colorScheme?: colorSchemeType; + placement: placementType; + label: string; + arrowIcon?: React.ReactNode; +} +const setIcon = (arrowIcon: React.ReactNode) => { + return {arrowIcon}; +}; +const ToolTip = ({ label, placement, arrowIcon }: TooltipProps) => { + return( + + {Button} + { + + {label} + {arrowIcon && setIcon(arrowIcon)} + + } + + ) +} +export default ToolTip; diff --git a/packages/chakra-ui-styled/src/components/tabs/Tabs.tsx b/packages/chakra-ui-styled/src/components/tabs/Tabs.tsx deleted file mode 100644 index 157589e..0000000 --- a/packages/chakra-ui-styled/src/components/tabs/Tabs.tsx +++ /dev/null @@ -1,22 +0,0 @@ -const Container = styled.div``; - -const Tabs = () => { - return <>>; -}; - -// tab atoms 종류 -// -// unstyled -// soft-rounded -// solid-rounded -// enclosed -// line -// -// tab 사이즈 -// -// lg -// md -// sm -// tabs 종류별 1묶음으로 크기 분류 - -export default Tabs; diff --git a/packages/chakra-ui-styled/src/components/tabs/tab/Tab.styles.tsx b/packages/chakra-ui-styled/src/components/tabs/tab/Tab.styles.tsx deleted file mode 100644 index e69de29..0000000 diff --git a/packages/chakra-ui-styled/src/components/tabs/tab/Tab.tsx b/packages/chakra-ui-styled/src/components/tabs/tab/Tab.tsx deleted file mode 100644 index a8f8d7f..0000000 --- a/packages/chakra-ui-styled/src/components/tabs/tab/Tab.tsx +++ /dev/null @@ -1,6 +0,0 @@ -const Tab = () => { - //rounded = fsz semibold 그외 medium - return <>>; -}; - -export default Tab; diff --git a/packages/chakra-ui-styled/src/foundation/typography/Heading.styled.ts b/packages/chakra-ui-styled/src/foundation/typography/Heading.styled.ts index 219c67c..18e8a16 100644 --- a/packages/chakra-ui-styled/src/foundation/typography/Heading.styled.ts +++ b/packages/chakra-ui-styled/src/foundation/typography/Heading.styled.ts @@ -2,7 +2,7 @@ import styled, { css } from 'styled-components'; import { HeadingProps } from './Heading'; export const StyleHeading = styled.h1` - ${({ theme, size, weight }) => css` + ${({ theme, size, weight, lineHeight }) => css` ${theme.typo.fontFamily}; ${theme.breakpoint.base} { font-size: ${theme.typo.small[size].fontSize}; @@ -12,7 +12,7 @@ export const StyleHeading = styled.h1` ${theme.breakpoint.lg} { font-size: ${theme.typo.large[size].fontSize}; font-weight: ${weight ? theme.typo.fontWeight[weight] : theme.typo.large[size].fontWeight}; - line-height: ${theme.typo.large[size].lineHeight}; + line-height: ${lineHeight ? theme.typo.lineHeight[lineHeight] : theme.typo.large[size].lineHeight}; } `}; `; diff --git a/packages/chakra-ui-styled/src/foundation/typography/Text.styled.ts b/packages/chakra-ui-styled/src/foundation/typography/Text.styled.ts index 0a53d4c..dc9de9b 100644 --- a/packages/chakra-ui-styled/src/foundation/typography/Text.styled.ts +++ b/packages/chakra-ui-styled/src/foundation/typography/Text.styled.ts @@ -1,12 +1,11 @@ - import styled, { css } from 'styled-components'; import { TextProps } from './Text'; export const StyleText = styled.p` - ${({ theme, size, weight }) => css` + ${({ theme, size, weight, lineHeight }) => css` ${theme.typo.fontFamily}; font-size: ${theme.typo.text[size].fontSize}; font-weight: ${weight ? theme.typo.fontWeight[weight] : theme.typo.text[size].fontWeight}; - line-height: ${theme.typo.text[size].lineHeight}; + line-height: ${lineHeight ? theme.typo.lineHeight[lineHeight] : theme.typo.text[size].lineHeight}; `}; `; diff --git a/packages/chakra-ui-styled/src/foundation/typography/typography.types.ts b/packages/chakra-ui-styled/src/foundation/typography/typography.types.ts index e655521..1ffe2bf 100644 --- a/packages/chakra-ui-styled/src/foundation/typography/typography.types.ts +++ b/packages/chakra-ui-styled/src/foundation/typography/typography.types.ts @@ -18,4 +18,7 @@ export interface TypographyType { text: TypographyProps; fontFamily: TypoProps; fontWeight: TypoProps; + lineHeight: TypoProps; } + +export type sStylingProps = { [key: string]: string };
{children}
{text}