From 2537acf89d2bf68596e193d6e669c1505dc5ecc3 Mon Sep 17 00:00:00 2001 From: jinhojang6 Date: Mon, 10 Apr 2023 22:00:51 +0900 Subject: [PATCH] feat: add label element to DateField and adjust styles --- .../components/Calendar/Calendar.context.ts | 2 +- .../components/Calendar/Calendar.stories.tsx | 2 +- .../src/components/Calendar/Calendar.tsx | 2 +- .../components/DateField/DateField.classes.ts | 13 ++- .../DateField/DateField.stories.tsx | 15 +++- .../components/DateField/DateField.styles.ts | 83 +++++++++++++++---- .../src/components/DateField/DateField.tsx | 55 ++++++++---- .../DatePicker/DatePicker.classes.ts | 6 +- .../DatePicker/DatePicker.stories.tsx | 15 +++- .../DatePicker/DatePicker.styles.ts | 19 +++++ .../src/components/DatePicker/DatePicker.tsx | 27 +++++- 11 files changed, 190 insertions(+), 49 deletions(-) diff --git a/packages/lsd-react/src/components/Calendar/Calendar.context.ts b/packages/lsd-react/src/components/Calendar/Calendar.context.ts index 97a2163..46cad87 100644 --- a/packages/lsd-react/src/components/Calendar/Calendar.context.ts +++ b/packages/lsd-react/src/components/Calendar/Calendar.context.ts @@ -2,7 +2,7 @@ import React from 'react' export type CalendarContextType = { focusedDate: Date | null - size?: 'large' | 'medium' + size?: 'large' | 'medium' | 'small' isDateFocused: (date: Date) => boolean isDateSelected: (date: Date) => boolean isDateHovered: (date: Date) => boolean diff --git a/packages/lsd-react/src/components/Calendar/Calendar.stories.tsx b/packages/lsd-react/src/components/Calendar/Calendar.stories.tsx index 48b8f08..0b49344 100644 --- a/packages/lsd-react/src/components/Calendar/Calendar.stories.tsx +++ b/packages/lsd-react/src/components/Calendar/Calendar.stories.tsx @@ -9,7 +9,7 @@ export default { size: { type: { name: 'enum', - value: ['medium', 'large'], + value: ['small', 'medium', 'large'], }, defaultValue: 'large', }, diff --git a/packages/lsd-react/src/components/Calendar/Calendar.tsx b/packages/lsd-react/src/components/Calendar/Calendar.tsx index ebf3a01..3cc0779 100644 --- a/packages/lsd-react/src/components/Calendar/Calendar.tsx +++ b/packages/lsd-react/src/components/Calendar/Calendar.tsx @@ -20,7 +20,7 @@ export type CalendarProps = Omit< value?: string onChange: (data: Date) => void handleRef: React.RefObject - size?: 'large' | 'medium' + size?: 'large' | 'medium' | 'small' onClose?: () => void } diff --git a/packages/lsd-react/src/components/DateField/DateField.classes.ts b/packages/lsd-react/src/components/DateField/DateField.classes.ts index c39607e..bb8ebca 100644 --- a/packages/lsd-react/src/components/DateField/DateField.classes.ts +++ b/packages/lsd-react/src/components/DateField/DateField.classes.ts @@ -1,10 +1,11 @@ export const dateFieldClasses = { root: `lsd-date-field`, + label: 'lsd-date-field__label', - inputContainer: `lsd-date-field-input-container`, - input: `lsd-date-field-input-container__input`, - icon: `lsd-date-field-input-container__icon`, - iconButton: `lsd-date-field-input-container__icon-button`, + inputContainer: `lsd-date-field__input-container`, + input: `lsd-date-field__input-container__input`, + icon: `lsd-date-field__input-container__icon`, + iconButton: `lsd-date-field__input-container__icon-button`, supportingText: 'lsd-date-field__supporting-text', @@ -13,4 +14,8 @@ export const dateFieldClasses = { large: `lsd-date-field--large`, medium: `lsd-date-field--medium`, + small: `lsd-date-field--small`, + + outlined: `lsd-date-field--outlined`, + outlinedBottom: `lsd-date-field--outlined-bottom`, } diff --git a/packages/lsd-react/src/components/DateField/DateField.stories.tsx b/packages/lsd-react/src/components/DateField/DateField.stories.tsx index 0f6af24..be8b6f8 100644 --- a/packages/lsd-react/src/components/DateField/DateField.stories.tsx +++ b/packages/lsd-react/src/components/DateField/DateField.stories.tsx @@ -8,7 +8,14 @@ export default { size: { type: { name: 'enum', - value: ['medium', 'large'], + value: ['small', 'medium', 'large'], + }, + defaultValue: 'large', + }, + variant: { + type: { + name: 'enum', + value: ['outlined', 'outlined-bottom'], }, defaultValue: 'large', }, @@ -24,6 +31,7 @@ export const Controlled: Story = ({ ...args }) => { } Uncontrolled.args = { + id: 'label', size: 'large', supportingText: 'Supporting text', disabled: false, @@ -32,9 +40,12 @@ Uncontrolled.args = { error: false, errorIcon: false, clearButton: true, + variant: 'outlined-bottom', + label: 'Label', } Controlled.args = { + id: 'label', size: 'large', supportingText: 'Supporting text', disabled: false, @@ -43,4 +54,6 @@ Controlled.args = { error: false, errorIcon: false, clearButton: true, + variant: 'outlined-bottom', + label: 'Label', } diff --git a/packages/lsd-react/src/components/DateField/DateField.styles.ts b/packages/lsd-react/src/components/DateField/DateField.styles.ts index 0fd6002..608b209 100644 --- a/packages/lsd-react/src/components/DateField/DateField.styles.ts +++ b/packages/lsd-react/src/components/DateField/DateField.styles.ts @@ -4,10 +4,27 @@ import { dateFieldClasses } from './DateField.classes' export const DateFieldStyles = css` .${dateFieldClasses.root} { width: auto; - border-bottom: 1px solid rgb(var(--lsd-border-primary)); box-sizing: border-box; } + .${dateFieldClasses.label} { + display: block; + } + + .${dateFieldClasses.icon} { + cursor: pointer; + display: flex; + align-items: center; + } + + .${dateFieldClasses.outlined} { + border: 1px solid rgb(var(--lsd-border-primary)); + } + + .${dateFieldClasses.outlinedBottom} { + border-bottom: 1px solid rgb(var(--lsd-border-primary)); + } + .${dateFieldClasses.inputContainer} { display: flex; align-items: center; @@ -48,32 +65,64 @@ export const DateFieldStyles = css` } .${dateFieldClasses.supportingText} { - width: fit-content; - margin-top: 20px; + position: absolute; } .${dateFieldClasses.large} { width: 208px; - height: 40px; - padding: 10px 14px; + + .${dateFieldClasses.label} { + margin: 0 0 6px 18px; + } + .${dateFieldClasses.inputContainer} { + height: 40px; + } + .${dateFieldClasses.input} { + padding: 9px 13px 9px 17px; + } + .${dateFieldClasses.icon} { + padding: 12px 13px; + } + .${dateFieldClasses.supportingText} { + margin: 6px 18px 0 18px; + } } .${dateFieldClasses.medium} { width: 188px; - height: 32px; - padding: 6px 12px; + .${dateFieldClasses.label} { + margin: 0 0 6px 14px; + } + .${dateFieldClasses.inputContainer} { + height: 32px; + } + .${dateFieldClasses.input} { + padding: 5px 11px 5px 13px; + } + .${dateFieldClasses.icon} { + padding: 8px 11px; + } + .${dateFieldClasses.supportingText} { + margin: 6px 14px 0 14px; + } } - .${dateFieldClasses.iconButton} { - padding: 0; - width: auto; - height: auto; - margin: 0; - border: 0; - - svg { - width: 100%; - height: auto; + .${dateFieldClasses.small} { + width: 164px; + .${dateFieldClasses.label} { + margin: 0 0 6px 12px; + } + .${dateFieldClasses.inputContainer} { + height: 28px; + } + .${dateFieldClasses.input} { + padding: 5px 9px 5px 11px; + } + .${dateFieldClasses.icon} { + padding: 6px 9px; + } + .${dateFieldClasses.supportingText} { + margin: 6px 12px 0 12px; } } ` diff --git a/packages/lsd-react/src/components/DateField/DateField.tsx b/packages/lsd-react/src/components/DateField/DateField.tsx index 7dde40f..d163cff 100644 --- a/packages/lsd-react/src/components/DateField/DateField.tsx +++ b/packages/lsd-react/src/components/DateField/DateField.tsx @@ -1,7 +1,6 @@ import clsx from 'clsx' import React, { useRef } from 'react' import { useInput } from '../../utils/useInput' -import { IconButton } from '../IconButton' import { CloseIcon, ErrorIcon } from '../Icons' import { Typography } from '../Typography' import { dateFieldClasses } from './DateField.classes' @@ -11,7 +10,8 @@ export type DateFieldProps = Omit< 'onChange' | 'value' > & Pick, 'onChange'> & { - size?: 'large' | 'medium' + label?: React.ReactNode + size?: 'large' | 'medium' | 'small' error?: boolean errorIcon?: boolean clearButton?: boolean @@ -23,11 +23,13 @@ export type DateFieldProps = Omit< icon?: React.ReactNode onIconClick?: () => void inputProps?: React.InputHTMLAttributes + variant?: 'outlined' | 'outlined-bottom' } export const DateField: React.FC & { classes: typeof dateFieldClasses } = ({ + label, size = 'large', error = false, errorIcon = false, @@ -42,6 +44,7 @@ export const DateField: React.FC & { icon, onIconClick, inputProps = {}, + variant = 'outlined-bottom', ...props }) => { const ref = useRef(null) @@ -49,6 +52,8 @@ export const DateField: React.FC & { const onCancel = () => input.setValue('') + const inputId = inputProps?.id ?? (props.id || 'date-field') + '-input' + return (
& { error && dateFieldClasses.error, )} > -
+ {label && ( + + {label} + + )} +
& { className={clsx(inputProps.className, dateFieldClasses.input)} /> {icon ? ( - !disabled && onIconClick && onIconClick()} > {icon} - + ) : error && errorIcon ? ( - + + + ) : clearButton && input.filled ? ( - !disabled && onCancel()} - aria-label="clear" - className={dateFieldClasses.iconButton} + className={dateFieldClasses.icon} > - - + + ) : null}
{supportingText && (
- + {supportingText}
diff --git a/packages/lsd-react/src/components/DatePicker/DatePicker.classes.ts b/packages/lsd-react/src/components/DatePicker/DatePicker.classes.ts index ce145e8..1e0e2d1 100644 --- a/packages/lsd-react/src/components/DatePicker/DatePicker.classes.ts +++ b/packages/lsd-react/src/components/DatePicker/DatePicker.classes.ts @@ -1,5 +1,9 @@ export const datePickerClasses = { root: `lsd-date-picker`, - calendar: `lsd-date-picker-calendar`, + calendar: `lsd-date-picker__calendar`, + + large: `lsd-date-picker--large`, + medium: `lsd-date-picker--medium`, + small: `lsd-date-picker--small`, } diff --git a/packages/lsd-react/src/components/DatePicker/DatePicker.stories.tsx b/packages/lsd-react/src/components/DatePicker/DatePicker.stories.tsx index f966d55..cdc9319 100644 --- a/packages/lsd-react/src/components/DatePicker/DatePicker.stories.tsx +++ b/packages/lsd-react/src/components/DatePicker/DatePicker.stories.tsx @@ -8,7 +8,14 @@ export default { size: { type: { name: 'enum', - value: ['medium', 'large'], + value: ['small', 'medium', 'large'], + }, + defaultValue: 'large', + }, + variant: { + type: { + name: 'enum', + value: ['outlined', 'outlined-bottom'], }, defaultValue: 'large', }, @@ -24,6 +31,7 @@ export const Controlled: Story = ({ ...args }) => { } Uncontrolled.args = { + id: 'label', supportingText: 'Supporting text', disabled: false, error: false, @@ -33,9 +41,12 @@ Uncontrolled.args = { clearButton: true, withCalendar: true, size: 'large', + variant: 'outlined-bottom', + label: 'Label', } Controlled.args = { + id: 'label', supportingText: 'Supporting text', disabled: false, error: false, @@ -45,4 +56,6 @@ Controlled.args = { clearButton: true, withCalendar: true, size: 'large', + variant: 'outlined-bottom', + label: 'Label', } diff --git a/packages/lsd-react/src/components/DatePicker/DatePicker.styles.ts b/packages/lsd-react/src/components/DatePicker/DatePicker.styles.ts index c20b358..21b3965 100644 --- a/packages/lsd-react/src/components/DatePicker/DatePicker.styles.ts +++ b/packages/lsd-react/src/components/DatePicker/DatePicker.styles.ts @@ -1,5 +1,6 @@ import { css } from '@emotion/react' import { datePickerClasses } from './DatePicker.classes' +import { dateFieldClasses } from '../DateField/DateField.classes' export const DatePickerStyles = css` .${datePickerClasses.root} { @@ -9,4 +10,22 @@ export const DatePickerStyles = css` .${datePickerClasses.calendar} { border-top: none !important; } + + .${datePickerClasses.large} { + .${dateFieldClasses.large} { + width: 318px; + } + } + + .${datePickerClasses.medium} { + .${dateFieldClasses.medium} { + width: 290px; + } + } + + .${datePickerClasses.small} { + .${dateFieldClasses.small} { + width: 262px; + } + } ` diff --git a/packages/lsd-react/src/components/DatePicker/DatePicker.tsx b/packages/lsd-react/src/components/DatePicker/DatePicker.tsx index c5c7c3a..12e9007 100644 --- a/packages/lsd-react/src/components/DatePicker/DatePicker.tsx +++ b/packages/lsd-react/src/components/DatePicker/DatePicker.tsx @@ -16,6 +16,7 @@ export type DatePickerProps = Omit< 'onChange' | 'value' > & Pick, 'onChange'> & { + label?: React.ReactNode error?: boolean errorIcon?: boolean clearButton?: boolean @@ -25,13 +26,22 @@ export type DatePickerProps = Omit< value?: string defaultValue?: string placeholder?: string - size?: 'large' | 'medium' + size?: 'large' | 'medium' | 'small' + variant?: 'outlined' | 'outlined-bottom' inputProps?: React.InputHTMLAttributes } export const DatePicker: React.FC & { classes: typeof datePickerClasses -} = ({ value: valueProp, onChange, withCalendar = true, ...props }) => { +} = ({ + label, + size = 'large', + value: valueProp, + onChange, + withCalendar = true, + variant = 'outlined-bottom', + ...props +}) => { const ref = useRef(null) const [openCalendar, setOpenCalendar] = useState(false) @@ -48,18 +58,27 @@ export const DatePicker: React.FC & { const handleDateChange = (date: Date) => input.setValue(dateToISODateString(removeDateTimezoneOffset(date))) + const inputId = (props.id || 'date-picker') + '-input' + return (
} onIconClick={() => setOpenCalendar((prev) => !prev)} value={input.value} onChange={input.onChange} - style={{ width: '310px' }} {...props} >