Redesign DatePicker (#108)

This commit is contained in:
Charles Bochet
2023-05-06 18:13:16 +02:00
committed by GitHub
parent 41c46c36ed
commit 760a49c5e3
3 changed files with 183 additions and 7 deletions

View File

@ -1,6 +1,6 @@
import styled from '@emotion/styled';
import React, { ReactElement, forwardRef, useState } from 'react';
import ReactDatePicker from 'react-datepicker';
import ReactDatePicker, { CalendarContainerProps } from 'react-datepicker';
import 'react-datepicker/dist/react-datepicker.css';
@ -9,12 +9,17 @@ export type DatePickerProps = {
date: Date;
onChangeHandler: (date: Date) => void;
customInput?: ReactElement;
customContainer?(props: CalendarContainerProps): React.ReactNode;
};
const StyledContainer = styled.div`
& .react-datepicker {
border-color: ${(props) => props.theme.primaryBorder};
background: transparent;
font-family: 'Inter';
font-size: ${(props) => props.theme.fontSizeMedium};
border: none;
display: block;
}
& .react-datepicker__triangle::after {
@ -25,17 +30,150 @@ const StyledContainer = styled.div`
display: none;
}
// Header
& .react-datepicker__header {
background-color: ${(props) => props.theme.primaryBackground};
border-bottom-color: ${(props) => props.theme.primaryBorder};
background: transparent;
border: none;
}
& .react-datepicker__header__dropdown {
display: flex;
margin-left: ${(props) => props.theme.spacing(1)};
margin-bottom: ${(props) => props.theme.spacing(1)};
}
& .react-datepicker__month-dropdown-container,
& .react-datepicker__year-dropdown-container {
text-align: left;
border-radius: 4px;
margin-left: ${(props) => props.theme.spacing(1)};
margin-right: 0;
padding: ${(props) => props.theme.spacing(2)};
padding-right: ${(props) => props.theme.spacing(4)};
background-color: ${(props) => props.theme.tertiaryBackground};
}
& .react-datepicker__month-read-view--down-arrow,
& .react-datepicker__year-read-view--down-arrow {
height: 5px;
width: 5px;
border-width: 1px 1px 0 0;
border-color: ${(props) => props.theme.text40};
top: 3px;
right: -6px;
}
& .react-datepicker__year-read-view,
& .react-datepicker__month-read-view {
padding-right: ${(props) => props.theme.spacing(2)};
}
& .react-datepicker__month-dropdown-container {
width: 80px;
}
& .react-datepicker__year-dropdown-container {
width: 50px;
}
& .react-datepicker__month-dropdown {
left: ${(props) => props.theme.spacing(2)};
top: ${(props) => props.theme.spacing(2)};
width: calc(80px + ${(props) => props.theme.spacing(6)});
border: ${(props) => props.theme.primaryBorder};
}
& .react-datepicker__year-dropdown {
left: calc(${(props) => props.theme.spacing(9)} + 80px);
top: ${(props) => props.theme.spacing(2)};
width: calc(50px + ${(props) => props.theme.spacing(6)});
border: ${(props) => props.theme.primaryBorder};
}
& .react-datepicker__navigation--years {
display: none;
}
& .react-datepicker__month-option--selected,
& .react-datepicker__year-option--selected {
display: none;
}
& .react-datepicker__year-option,
& .react-datepicker__month-option {
line-height: 32px;
text-align: left;
padding-left: ${(props) => props.theme.spacing(2)};
width: calc(100% - ${(props) => props.theme.spacing(2)});
background-color: ${(props) => props.theme.tertiaryBackground};
&:hover {
color: ${(props) => props.theme.text100};
font-weight: bold;
}
}
& .react-datepicker__current-month {
display: none;
}
& .react-datepicker__day-name {
color: ${(props) => props.theme.text60};
width: 34px;
height: 40px;
line-height: 40px;
}
// Days
& .react-datepicker__month {
margin-top: 0;
}
& .react-datepicker__day {
width: 34px;
height: 34px;
line-height: 34px;
}
& .react-datepicker__day--selected {
background-color: ${(props) => props.theme.blue};
}
& .react-datepicker__navigation--previous {
right: 44px;
top: 12px;
left: auto;
}
& .react-datepicker__navigation--next {
right: 6px;
top: 12px;
}
& .react-datepicker__navigation-icon::before {
height: 7px;
width: 7px;
border-width: 1px 1px 0 0;
border-color: ${(props) => props.theme.text40};
}
& .react-datepicker__day--outside-month {
color: ${(props) => props.theme.text40};
}
& .react-datepicker__day--keyboard-selected {
background-color: inherit;
}
`;
function DatePicker({ date, onChangeHandler, customInput }: DatePickerProps) {
function DatePicker({
date,
onChangeHandler,
customInput,
customContainer,
}: DatePickerProps) {
const [startDate, setStartDate] = useState(date);
type DivProps = React.HTMLProps<HTMLDivElement>;
@ -58,11 +196,14 @@ function DatePicker({ date, onChangeHandler, customInput }: DatePickerProps) {
<ReactDatePicker
open={true}
selected={startDate}
showMonthDropdown
showYearDropdown
onChange={(date: Date) => {
setStartDate(date);
onChangeHandler(date);
}}
customInput={customInput ? customInput : <DefaultDateDisplay />}
calendarContainer={customContainer ? customContainer : undefined}
/>
</StyledContainer>
);

View File

@ -2,6 +2,8 @@ import styled from '@emotion/styled';
import { forwardRef, useState } from 'react';
import EditableCellWrapper from './EditableCellWrapper';
import DatePicker from '../../form/DatePicker';
import { CalendarContainer } from 'react-datepicker';
import { modalBackground } from '../../../layout/styles/themes';
export type EditableDateProps = {
value: Date;
@ -13,6 +15,21 @@ const StyledContainer = styled.div`
display: flex;
align-items: center;
`;
export type StyledCalendarContainerProps = {
editModeHorizontalAlign?: 'left' | 'right';
};
const StyledCalendarContainer = styled.div<StyledCalendarContainerProps>`
position: absolute;
border: 1px solid ${(props) => props.theme.primaryBorder};
border-radius: 8px;
width: 280px;
box-shadow: 0px 3px 12px rgba(0, 0, 0, 0.09);
z-index: 1;
left: -10px;
${modalBackground};
`;
function EditableDate({
value,
changeHandler,
@ -36,6 +53,24 @@ function EditableDate({
),
);
interface DatePickerContainerProps {
className?: string;
children: React.ReactNode;
}
const DatePickerContainer = ({
className,
children,
}: DatePickerContainerProps) => {
return (
<StyledCalendarContainer>
<CalendarContainer className={className}>
<div style={{ position: 'relative' }}>{children}</div>
</CalendarContainer>
</StyledCalendarContainer>
);
};
return (
<EditableCellWrapper
isEditMode={isEditMode}
@ -51,6 +86,7 @@ function EditableDate({
setInputValue(date);
}}
customInput={<DateDisplay />}
customContainer={DatePickerContainer}
/>
</StyledContainer>
}

View File

@ -27,7 +27,7 @@ const lightThemeSpecific = {
purpleBackground: '#e0e0ff',
yellowBackground: '#fff2e7',
secondaryBackgroundSmallTransparency: 'rgba(252, 252, 252, 0.8)',
secondaryBackgroundSmallTransparency: 'rgba(252, 252, 252, 0.97)',
primaryBorder: 'rgba(0, 0, 0, 0.08)',
@ -59,7 +59,7 @@ const darkThemeSpecific: typeof lightThemeSpecific = {
purpleBackground: '#1111b7',
yellowBackground: '#cc660a',
secondaryBackgroundSmallTransparency: 'rgba(23, 23, 23, 0.8)',
secondaryBackgroundSmallTransparency: 'rgba(23, 23, 23, 0.97)',
primaryBorder: 'rgba(255, 255, 255, 0.08)',
@ -83,7 +83,6 @@ const darkThemeSpecific: typeof lightThemeSpecific = {
export const modalBackground = (props: any) =>
css`
backdrop-filter: blur(20px);
background: ${props.theme.secondaryBackgroundSmallTransparency};
`;