Skip to content

Commit

Permalink
feat: implement date picker component
Browse files Browse the repository at this point in the history
  • Loading branch information
jinhojang6 committed Feb 27, 2023
1 parent 24b67d5 commit c6c192d
Show file tree
Hide file tree
Showing 7 changed files with 229 additions and 0 deletions.
2 changes: 2 additions & 0 deletions packages/lsd-react/src/components/CSSBaseline/CSSBaseline.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { CardBodyStyles } from '../CardBody/CardBody.styles'
import { CardHeaderStyles } from '../CardHeader/CardHeader.styles'
import { CollapseStyles } from '../Collapse/Collapse.styles'
import { CollapseHeaderStyles } from '../CollapseHeader/CollapseHeader.styles'
import { DatePickerStyles } from '../DatePicker/DatePicker.styles'
import { DropdownStyles } from '../Dropdown/Dropdown.styles'
import { DropdownItemStyles } from '../DropdownItem/DropdownItem.styles'
import { IconButtonStyles } from '../IconButton/IconButton.styles'
Expand Down Expand Up @@ -44,6 +45,7 @@ const componentStyles: Array<ReturnType<typeof withTheme> | SerializedStyles> =
QuoteStyles,
CollapseStyles,
CollapseHeaderStyles,
DatePickerStyles,
]

export const CSSBaseline: React.FC<{ theme?: Theme }> = ({
Expand Down
16 changes: 16 additions & 0 deletions packages/lsd-react/src/components/DatePicker/DatePicker.classes.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
export const datePickerClasses = {
root: `lsd-date-picker`,

inputContainer: `lsd-date-picker-input-container`,
input: `lsd-date-picker-input-container__input`,
icon: `lsd-date-picker-input-container__icon`,
clearButton: `lsd-date-picker-input-container__clear-button`,

supportingText: 'lsd-date-picker__supporting-text',

disabled: `lsd-date-picker--disabled`,
error: 'lsd-date-picker--error',

large: `lsd-date-picker--large`,
medium: `lsd-date-picker--medium`,
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { Meta, Story } from '@storybook/react'
import { DatePicker, DatePickerProps } from './DatePicker'

export default {
title: 'DatePicker',
component: DatePicker,
argTypes: {
size: {
type: {
name: 'enum',
value: ['medium', 'large'],
},
defaultValue: 'large',
},
},
} as Meta

export const Root: Story<DatePickerProps> = ({ ...args }) => {
return <DatePicker {...args}>DatePicker</DatePicker>
}

Root.args = {
size: 'large',
supportingText: 'Supporting text',
disabled: false,
error: false,
errorIcon: false,
clearButton: true,
onChange: undefined,
}
82 changes: 82 additions & 0 deletions packages/lsd-react/src/components/DatePicker/DatePicker.styles.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import { css } from '@emotion/react'
import { datePickerClasses } from './DatePicker.classes'

export const DatePickerStyles = css`
.${datePickerClasses.root} {
width: auto;
border-bottom: 1px solid rgb(var(--lsd-border-primary));
box-sizing: border-box;
}
.${datePickerClasses.inputContainer} {
display: flex;
align-items: center;
justify-content: space-between;
}
.${datePickerClasses.disabled} {
opacity: 0.34;
}
.${datePickerClasses.input} {
border: none;
outline: none;
font-size: 14px;
color: rgb(var(--lsd-text-primary));
background: none;
width: 100%;
}
.${datePickerClasses.input}::-webkit-inner-spin-button,
.${datePickerClasses.input}::-webkit-calendar-picker-indicator {
display: none;
-webkit-appearance: none;
}
.${datePickerClasses.input}:hover {
outline: none;
}
.${datePickerClasses.input}:focus::-webkit-datetime-edit {
color: rgb(var(--lsd-text-primary));
opacity: 0.3;
}
.${datePickerClasses.error}
.${datePickerClasses.input}::-webkit-datetime-edit-fields-wrapper {
text-decoration: line-through;
}
.${datePickerClasses.supportingText} {
width: fit-content;
margin-top: 20px;
}
.${datePickerClasses.large} {
width: 208px;
height: 40px;
padding: 10px 14px;
}
.${datePickerClasses.medium} {
width: 188px;
height: 32px;
padding: 6px 12px;
}
.${datePickerClasses.clearButton} {
padding: 0;
width: auto;
height: auto;
margin: 0;
border: 0;
svg {
width: 100%;
height: auto;
}
}
.${datePickerClasses.icon} {
}
`
97 changes: 97 additions & 0 deletions packages/lsd-react/src/components/DatePicker/DatePicker.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
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 { datePickerClasses } from './DatePicker.classes'

export type DatePickerProps = Omit<
React.HTMLAttributes<HTMLDivElement>,
'onChange' | 'value'
> &
Pick<React.InputHTMLAttributes<HTMLInputElement>, 'onChange'> & {
size?: 'large' | 'medium'
error?: boolean
errorIcon?: boolean
clearButton?: boolean
disabled?: boolean
supportingText?: string
value?: string
defaultValue?: string
placeholder?: string
inputProps?: React.InputHTMLAttributes<HTMLInputElement>
}

export const DatePicker: React.FC<DatePickerProps> & {
classes: typeof datePickerClasses
} = ({
size = 'large',
error = false,
errorIcon = false,
clearButton,
supportingText,
children,
value,
placeholder,
defaultValue,
disabled,
onChange,
inputProps = {},
...props
}) => {
const ref = useRef<HTMLInputElement>(null)
const input = useInput({ defaultValue, value, onChange, ref })

const onCancel = () => input.setValue('')

return (
<div
aria-disabled={disabled ? 'true' : 'false'}
{...props}
className={clsx(
props.className,
datePickerClasses.root,
datePickerClasses[size],
disabled && datePickerClasses.disabled,
error && datePickerClasses.error,
)}
>
<div className={datePickerClasses.inputContainer}>
<input
type="date"
placeholder={placeholder}
{...inputProps}
ref={ref}
value={input.value}
onChange={input.onChange}
className={clsx(inputProps.className, datePickerClasses.input)}
/>
{error && errorIcon ? (
<ErrorIcon color="primary" className={datePickerClasses.icon} />
) : clearButton && input.filled ? (
<IconButton
disabled={disabled}
onClick={() => !disabled && onCancel()}
aria-label="clear"
className={datePickerClasses.clearButton}
>
<CloseIcon color="primary" className={datePickerClasses.icon} />
</IconButton>
) : null}
</div>
{supportingText && (
<div className={clsx(datePickerClasses.supportingText)}>
<Typography
variant={size === 'large' ? 'label1' : 'label2'}
component="p"
>
{supportingText}
</Typography>
</div>
)}
</div>
)
}

DatePicker.classes = datePickerClasses
1 change: 1 addition & 0 deletions packages/lsd-react/src/components/DatePicker/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './DatePicker'
1 change: 1 addition & 0 deletions packages/lsd-react/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,4 @@ export * from './components/TabItem'
export * from './components/Tabs'
export * from './components/Tag'
export * from './components/Theme'
export * from './components/DatePicker'

0 comments on commit c6c192d

Please sign in to comment.