Skip to content

Commit

Permalink
feat: add arrow and allow picto placement on DateTimePicker (#270)
Browse files Browse the repository at this point in the history
* DateTimePicker now has an arrow
* DateTimePicker now has timeIconPlacement and dateIconPlacement props
with "left" "right" possible values

Signed-off-by: Paul-Xavier Ceccaldi <[email protected]>
  • Loading branch information
P1X3L authored Aug 6, 2019
1 parent edd878b commit 1c87dc7
Show file tree
Hide file tree
Showing 4 changed files with 91 additions and 7 deletions.
34 changes: 30 additions & 4 deletions src/components/DateTimePicker/CustomInput.js
Original file line number Diff line number Diff line change
@@ -1,28 +1,54 @@
import React, { PureComponent } from 'react'
import { func } from 'prop-types'
import { func, oneOf } from 'prop-types'

import { COMPONENT_TYPE, SIZES_TYPE } from '../../utils'
import { IconWrapper } from '../Field/styles'
import { Icon } from '../Icon'

import * as S from './styles'

// eslint-disable-next-line react/prefer-stateless-function
export class CustomInput extends PureComponent {
render() {
const { handleBlur, handleFocus, icon, inputRef, size, ...rest } = this.props
const {
focused,
handleBlur,
handleFocus,
icon,
iconPlacement,
inputRef,
size,
...rest
} = this.props
return (
<S.CustomInput icon={icon} onBlur={handleBlur} onFocus={handleFocus} size={size}>
{icon && <IconWrapper size={size}>{icon}</IconWrapper>}
<S.CustomInput
focused={focused}
icon={icon}
iconPlacement={iconPlacement}
onBlur={handleBlur}
onFocus={handleFocus}
size={size}
>
{icon && (
<IconWrapper iconPlacement={iconPlacement} size={size}>
{icon}
</IconWrapper>
)}
<input ref={inputRef} {...rest} />
<IconWrapper iconPlacement="right" size={size}>
<Icon name="down" size="xs" />
</IconWrapper>
</S.CustomInput>
)
}
}

CustomInput.propTypes = {
focused: oneOf('date', 'time', null),
handleBlur: func,
handleFocus: func,
icon: COMPONENT_TYPE,
iconPlacement: oneOf('right', 'left'),
inputRef: func,
size: SIZES_TYPE
}
1 change: 1 addition & 0 deletions src/components/DateTimePicker/doc.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ _Note_: Pass a value of `null` if you don't want the default value of `Date.now(
<Playground>
<DateTimePicker
timeIcon={<Icon name="date" size="sm" color="primary.500" />}
timeIconPlacement="right"
value={Date.now()}
onChange={date => console.log('date: ', date)}
/>
Expand Down
15 changes: 14 additions & 1 deletion src/components/DateTimePicker/index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React, { forwardRef, useEffect, useState } from 'react'
import { createPortal } from 'react-dom'
import { bool, func, number, object, oneOfType, string } from 'prop-types'
import { bool, func, number, object, oneOf, oneOfType, string } from 'prop-types'

import { COMPONENT_TYPE, SIZES_TYPE } from '../../utils'

Expand All @@ -22,11 +22,13 @@ export const DateTimePicker = forwardRef(
{
value = new Date(),
dateIcon,
dateIconPlacement = 'left',
datePickerOnly,
datePickerProps = {},
onChange,
size = 'lg',
timeIcon,
timeIconPlacement = 'left',
timePickerOnly,
timePickerProps = {},
...rest
Expand All @@ -38,6 +40,9 @@ export const DateTimePicker = forwardRef(
const timePickerDateFormat = timePickerProps.dateFormat || DEFAULT_TIME_FORMAT
const timeIntervals = timePickerProps.timeIntervals || DEFAULT_INTERVAL

const [focused, setFocused] = useState(
(datePickerProps.autoFocus && 'date') || (timePickerProps.autoFocus && 'time') || null
)
const [date, setDate] = useState(null)

const formatDate = date => getDate(date, timeIntervals)
Expand All @@ -61,13 +66,15 @@ export const DateTimePicker = forwardRef(
const handleFocus = (kind, e) => {
let onDatePickerFocus = datePickerProps.onFocus
let onTimePickerFocus = timePickerProps.onFocus
setFocused(kind)
kind === 'date' && onDatePickerFocus && onDatePickerFocus(e)
kind === 'time' && onTimePickerFocus && onTimePickerFocus(e)
}

const handleBlur = (kind, e) => {
let onDatePickerBlur = datePickerProps.onBlur
let onTimePickerBlur = timePickerProps.onBlur
setFocused(null)
kind === 'date' && onDatePickerBlur && onDatePickerBlur(e)
kind === 'time' && onTimePickerBlur && onTimePickerBlur(e)
}
Expand Down Expand Up @@ -99,9 +106,11 @@ export const DateTimePicker = forwardRef(
className="date-picker"
customInput={
<CustomInput
focused={focused}
handleBlur={e => handleBlur('date', e)}
handleFocus={e => handleFocus('date', e)}
icon={dateIcon}
iconPlacement={dateIconPlacement}
inputRef={timePickerOnly ? null : ref}
ref={ref}
size={size}
Expand All @@ -122,9 +131,11 @@ export const DateTimePicker = forwardRef(
className="time-picker"
customInput={
<CustomInput
focused={focused}
handleBlur={e => handleBlur('date', e)}
handleFocus={e => handleFocus('date', e)}
icon={timeIcon}
iconPlacement={timeIconPlacement}
inputRef={timePickerOnly ? ref : null}
size={size}
/>
Expand All @@ -150,11 +161,13 @@ DateTimePicker.displayName = 'DateTimePicker'

DateTimePicker.propTypes = {
dateIcon: COMPONENT_TYPE,
dateIconPlacement: oneOf('right', 'left'),
datePickerOnly: bool,
datePickerProps: object,
onChange: func,
size: SIZES_TYPE,
timeIcon: COMPONENT_TYPE,
timeIconPlacement: oneOf('right', 'left'),
timePickerOnly: bool,
timePickerProps: object,
value: oneOfType([number, object, string]).isRequired
Expand Down
48 changes: 46 additions & 2 deletions src/components/DateTimePicker/styles.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import ReactDatePicker from 'react-datepicker'

import { componentSystem, wrapperSystem } from '../../utils/'
import { fieldStyles } from '../../common/styles/form'
import { IconWrapper } from '../Field/styles'
import { Icon } from '../Icon/styles'

// Only require CSS on client
if (typeof window !== 'undefined') {
Expand All @@ -20,6 +22,10 @@ const focusStyles = css`
&:focus {
position: relative;
z-index: 1;
~ ${IconWrapper}:last-child ${Icon} {
transform: rotate3d(0, 0, 1, 180deg);
}
}
`

Expand Down Expand Up @@ -65,11 +71,41 @@ export const DateTimePicker = styled.div(
`
)

export const CustomInput = styled.div(({ icon, size, ...rest }) => {
const iconPlacementStyles = (placement, size, rest) => {
if (placement === 'right') {
return css`
${IconWrapper}:not(:last-child) {
right: ${th(`fields.sizes.${size}.height`)(rest)};
width: ${`calc(0.5 * ${th(`fields.sizes.${size}.height`)(rest)})`};
justify-content: flex-end;
}
${DatePicker}, ${TimePicker} {
padding-right: ${`calc(1.5 * ${th(`fields.sizes.${size}.height`)(rest)})`};
}
`
}
if (placement === 'left') {
return css`
${DatePicker}, ${TimePicker} {
padding-left: ${th(`fields.sizes.${size}.height`)(rest)};
}
`
}
}

export const CustomInput = styled.div(({ focused, icon, iconPlacement, size, ...rest }) => {
return css`
position: relative;
${icon && iconPlacementStyles(iconPlacement, size, rest)};
${DatePicker}, ${TimePicker} {
padding-left: ${icon ? th(`fields.sizes.${size}.height`)(rest) : null};
padding-right: ${th(`fields.sizes.${size}.height`)(rest)};
}
${Icon} {
transition: medium;
z-index: ${focused ? 2 : null};
}
`
})
Expand All @@ -90,6 +126,14 @@ export const Popper = styled.div`
font-weight: medium;
}
.react-datepicker__year-read-view--down-arrow,
.react-datepicker__month-read-view--down-arrow,
.react-datepicker__month-year-read-view--down-arrow {
top: 3px;
padding: sm 0;
transform: scale(0.5);
}
.react-datepicker__time-container {
width: 100px;
.react-datepicker__time .react-datepicker__time-box {
Expand Down

1 comment on commit 1c87dc7

@vercel
Copy link

@vercel vercel bot commented on 1c87dc7 Aug 6, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.