Feat/v2 daterangepicker (#4002)

* fixes minimum notice label

* adds story for daterange picker

* imports styles from global

* adds daterangepicker type inside packages types folder

* wraps tooltip with tooltip provider

* improvements

* further fixes

* fixes NIT

* match design specs

* adds space between input and calendar

* NITs

Co-authored-by: Peer Richelsen <peeroke@gmail.com>
pull/4081/head
Syed Ali Shahbaz 2022-09-01 15:39:08 +05:30 committed by GitHub
parent d5b7195d67
commit c455639ff4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 272 additions and 11 deletions

View File

@ -11,7 +11,7 @@ export const Default = () => {
const [selected, setSelected] = useState<Date>(new Date());
return (
<div style={{ width: "455px" }}>
{/* <DatePicker selected={selected} onChange={setSelected} locale="en" /> */}
<DatePicker selected={selected} onChange={setSelected} locale="en" />
</div>
);
};

View File

@ -0,0 +1,45 @@
import { ComponentMeta, ComponentStory } from "@storybook/react";
import "@wojtekmaj/react-daterange-picker/dist/DateRangePicker.css";
import { useState } from "react";
import DateRangePicker from "@calcom/ui/v2/core/form/date-range-picker/DateRangePicker";
import "@calcom/ui/v2/core/form/date-range-picker/styles.css";
function getISOLocalDate(date) {
const year = padStart(date.getFullYear(), 4);
const month = padStart(date.getMonth() + 1);
const day = padStart(date.getDate());
return [`${year}-${month}-${day}`];
}
function padStart(num, val = 2) {
const numStr = `${num}`;
if (numStr.length >= val) {
return num;
}
return `0000${numStr}`.slice(-val);
}
export default {
title: "Date Range Picker",
component: DateRangePicker,
} as ComponentMeta<typeof DateRangePicker>;
export const Default: ComponentStory<typeof DateRangePicker> = () => {
const [startDate, setStartDate] = useState<Date>(new Date());
const [endDate, setEndDate] = useState<Date>(new Date());
return (
<div>
<DateRangePicker
startDate={getISOLocalDate(startDate) as unknown as Date}
endDate={getISOLocalDate(endDate) as unknown as Date}
onDatesChange={({ startDate, endDate }) => {
setStartDate(startDate);
setEndDate(endDate);
}}
/>
</div>
);
};

View File

@ -2,6 +2,9 @@
@tailwind components;
@tailwind utilities;
@import "../../../packages/ui/v2/core/form/date-range-picker/styles.css";
@import "../../../node_modules/@wojtekmaj/react-daterange-picker/dist/DateRangePicker.css";
:root {
--brand-color: #292929;
--brand-text-color: #ffffff;

View File

@ -7,8 +7,7 @@ import { classNames } from "@calcom/lib";
import { useLocale } from "@calcom/lib/hooks/useLocale";
import { PeriodType } from "@calcom/prisma/client";
import { Select, Switch, Label } from "@calcom/ui/v2";
import { DateRangePicker } from "@components/ui/form/DateRangePicker";
import DateRangePicker from "@calcom/ui/v2/core/form/date-range-picker/DateRangePicker";
export const EventLimitsTab = (props: Pick<EventTypeSetupInfered, "eventType">) => {
const { t } = useLocale();
@ -112,7 +111,7 @@ export const EventLimitsTab = (props: Pick<EventTypeSetupInfered, "eventType">)
/>
</div>
<div className="w-full">
<Label htmlFor="minimumBookingNotice">{t("after_event")} </Label>
<Label htmlFor="minimumBookingNotice">{t("minimum_booking_notice")} </Label>
<Controller
name="minimumBookingNotice"
control={formMethods.control}

View File

@ -0,0 +1,18 @@
declare module "@wojtekmaj/react-daterange-picker/dist/entry.nostyle" {
import { CalendarProps } from "react-calendar";
export type DateRangePickerCalendarProps = Omit<
CalendarProps,
"calendarClassName" | "onChange" | "value"
> & {
calendarClassName?: string;
onChange: (value: [Date, Date]) => void;
value: [Date, Date];
clearIcon: JSX.Element | null;
calendarIcon: JSX.Element | null;
rangeDivider: JSX.Element | null;
disabled?: boolean | null;
nextLabel?: JSX.Element | null;
prevLabel?: JSX.Element | null;
};
export default function DateRangePicker(props: DateRangePickerCalendarProps): JSX.Element;
}

View File

@ -54,13 +54,15 @@ export default function Avatar(props: AvatarProps) {
);
return title ? (
<Tooltip.Tooltip delayDuration={300}>
<Tooltip.TooltipTrigger className="cursor-default">{avatar}</Tooltip.TooltipTrigger>
<Tooltip.Content className="rounded-sm bg-black p-2 text-sm text-white shadow-sm">
<Tooltip.Arrow />
{title}
</Tooltip.Content>
</Tooltip.Tooltip>
<Tooltip.Provider>
<Tooltip.Tooltip delayDuration={300}>
<Tooltip.TooltipTrigger className="cursor-default">{avatar}</Tooltip.TooltipTrigger>
<Tooltip.Content className="rounded-sm bg-black p-2 text-sm text-white shadow-sm">
<Tooltip.Arrow />
{title}
</Tooltip.Content>
</Tooltip.Tooltip>
</Tooltip.Provider>
) : (
<>{avatar}</>
);

View File

@ -0,0 +1,36 @@
// @see: https://github.com/wojtekmaj/react-daterange-picker/issues/91
import "@wojtekmaj/react-daterange-picker/dist/DateRangePicker.css";
import PrimitiveDateRangePicker from "@wojtekmaj/react-daterange-picker/dist/entry.nostyle";
import React from "react";
import { Icon } from "@calcom/ui/Icon";
import "@calcom/ui/v2/core/form/date-range-picker/styles.css";
type Props = {
disabled?: boolean | undefined;
startDate: Date;
endDate: Date;
onDatesChange?: ((arg: { startDate: Date; endDate: Date }) => void) | undefined;
};
const DateRangePicker = ({ disabled, startDate, endDate, onDatesChange }: Props) => {
return (
<>
<PrimitiveDateRangePicker
disabled={disabled || false}
className="rounded-sm border-gray-300 text-sm"
clearIcon={null}
calendarIcon={<Icon.FiCalendar className="h-4 w-4 text-gray-500" />}
rangeDivider={<Icon.FiArrowRight className="h-4 w-4 text-gray-400 ltr:mr-2 rtl:ml-2" />}
value={[startDate, endDate]}
onChange={([startDate, endDate]: [Date, Date]) => {
if (typeof onDatesChange === "function") onDatesChange({ startDate, endDate });
}}
nextLabel={<Icon.FiChevronRight className="h-4 w-4 text-gray-500" />}
prevLabel={<Icon.FiChevronLeft className="h-4 w-4 text-gray-500" />}
/>
</>
);
};
export default DateRangePicker;

View File

@ -0,0 +1,158 @@
.react-daterange-picker > .react-daterange-picker__wrapper {
padding: .625rem .75rem;
font-size: .875rem;
line-height: 1.25rem;
border-radius: .375rem;
border-color: #E5E7EB;
width: 360px;
display: flex;
flex-direction: row;
align-items: center;
height: 36px;
}
.react-daterange-picker__wrapper > .react-daterange-picker__calendar-button.react-daterange-picker__button {
padding: 4px 0;
}
.react-daterange-picker > .react-daterange-picker__wrapper > .react-daterange-picker__inputGroup {
height: auto;
}
.react-daterange-picker.react-daterange-picker--disabled {
background-color: transparent;
}
.react-daterange-picker.react-daterange-picker--disabled > .react-daterange-picker__wrapper {
background-color: #F3F4F6;
}
.react-daterange-picker > .react-daterange-picker__wrapper:focus-within,
.react-daterange-picker > .react-daterange-picker__wrapper:focus-within:hover {
border-color: #111827;
border-width: 2px;
}
.react-daterange-picker > .react-daterange-picker__wrapper input {
margin: 0;
height: auto;
border-radius: .125rem;
}
.react-daterange-picker__calendar.react-daterange-picker__calendar--open {
width: 360px;
}
.react-daterange-picker__calendar > .react-calendar{
padding: 0.5rem;
border-radius: 0.375rem;
border-width: 1px;
border-color: #E5E7EB;
width: 360px;
margin-top: 4px;
}
.react-calendar__navigation > .react-calendar__navigation__arrow {
display: flex;
justify-content: center;
align-items: center;
border-radius: 6px;
}
.react-calendar__navigation > .react-calendar__navigation__arrow.react-calendar__navigation__prev2-button,
.react-calendar__navigation > .react-calendar__navigation__arrow.react-calendar__navigation__next2-button {
display: none;
}
.react-calendar__navigation > .react-calendar__navigation__label {
display: flex;
padding-left: 0.5rem;
padding-right: 0.5rem;
color: #111827;
order: -9999;
justify-content: flex-start;
align-items: center;
font-size: 16px;
}
.react-calendar__navigation > .react-calendar__navigation__arrow {
text-align: center;
color: #6b7280;
}
.react-calendar__month-view__weekdays__weekday > abbr {
font-weight: 500;
text-decoration: none;
font-size: 12px;
}
.react-calendar__month-view__days {
padding: 0.25rem;
gap: 0.25rem;
font-size: 14px;
}
button.react-calendar__tile.react-calendar__month-view__days__day {
flex : 0 0 13.25% !important;
border-radius: 0.375rem;
padding-top: 13px;
padding-bottom: 13px;
position: relative;
}
.react-calendar__tile--now,
.react-calendar__tile.react-calendar__tile--hover:not(.react-calendar__tile--active) {
background-color: #E5E7EB !important;
}
.react-calendar__month-view__days > .react-calendar__tile.react-calendar__tile--hasActive,
.react-calendar__month-view__days > .react-calendar__tile.react-calendar__tile--active,
.react-calendar__month-view__days > button.react-calendar__tile.react-calendar__tile--active:hover {
background-color: #111827;
color: #ffffff;
}
.react-calendar__tile.react-calendar__tile--active.react-calendar__month-view__days__day--weekend {
color: #ffffff;
}
.react-calendar__tile.react-calendar__month-view__days__day--weekend {
color: #111827;
}
.react-calendar__tile.react-calendar__month-view__days__day--neighboringMonth {
color: #9ca3af;
}
.react-calendar__tile--now::before {
content:"\A";
width: 4px;
height: 4px;
border-radius: 50%;
position: absolute;
background-color: #111827;
left: 50%;
transform: translateX(-50%);
bottom: 0;
z-index: inherit;
}
button.react-calendar__tile.react-calendar__month-view__days__day:hover,
.react-calendar__tile.react-calendar__year-view__months__month:hover {
background-color: #D1D5DB;
color: #111827;
}
.react-daterange-picker > .react-daterange-picker__wrapper:hover {
border-color: #9CA3AF;
}
.react-daterange-picker.react-daterange-picker--disabled > .react-daterange-picker__wrapper:hover {
border-color: #E5E7EB;
}
.react-calendar__navigation button.react-calendar__navigation__label:enabled:hover,
.react-calendar__navigation button.react-calendar__navigation__label:enabled:focus {
background-color: transparent;
}