Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add date pickers #54

Merged
merged 3 commits into from
Jan 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import type { Meta, StoryObj } from '@storybook/react';

import {
DateValue,
getLocalTimeZone,
isWeekend,
parseDate,
today,
} from '@internationalized/date';
import { useLocale } from '@react-aria/i18n';
import React from 'react';
import { Calendar } from '../../../src/components';

// More on how to set up stories at: https://storybook.js.org/docs/react/writing-stories/introduction#default-export
const meta = {
title: 'Controls/Dates/Calendar',
component: Calendar,
args: {
isDisabled: false,
},
parameters: {
// Optional parameter to center the component in the Canvas. More info: https://storybook.js.org/docs/react/configure/story-layout
layout: 'centered',
},
// This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/react/writing-docs/autodocs
tags: ['autodocs'],
} satisfies Meta<typeof Calendar>;

export default meta;
type Story = StoryObj<typeof meta>;

// More on writing stories with args: https://storybook.js.org/docs/react/writing-stories/args
export const Default: Story = {
args: {},
render: (args) => (
<div>
<Calendar
{...args}
minValue={parseDate('1900-02-03')}
defaultValue={parseDate('2020-02-03')}
onChange={(date) => console.log(date.toString())}
/>
</div>
),
};
export const Disabled: Story = {
args: {},
render: (args) => (
<div>
<Calendar
{...args}
isDisabled
defaultValue={parseDate('2020-02-03')}
onChange={(date) => console.log(date.toString())}
/>
</div>
),
};

export const UnavailableDates: Story = {
name: 'Unavailable Dates',
args: {},
render: (args) => {
let now = today(getLocalTimeZone());
let disabledRanges = [
[now, now.add({ days: 5 })],
[now.add({ days: 14 }), now.add({ days: 16 })],
[now.add({ days: 23 }), now.add({ days: 24 })],
];

let { locale } = useLocale();
let isDateUnavailable = (date: DateValue) =>
isWeekend(date, locale) ||
disabledRanges.some(
(interval) =>
date.compare(interval[0]) >= 0 && date.compare(interval[1]) <= 0,
);

return (
<div style={{ width: 300 }}>
<Calendar
{...args}
aria-label="Appointment date"
minValue={today(getLocalTimeZone())}
isDateUnavailable={isDateUnavailable}
/>
</div>
);
},
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import type { Meta, StoryObj } from '@storybook/react';

import {
getLocalTimeZone,
parseDate,
parseZonedDateTime,
today,
} from '@internationalized/date';
import React from 'react';
import { DateField, Flex, dateFieldPropDefs } from '../../../src/components';
// More on how to set up stories at: https://storybook.js.org/docs/react/writing-stories/introduction#default-export
const meta = {
title: 'Controls/Dates/DateField',
component: DateField,
args: {
size: dateFieldPropDefs.size.default,
color: dateFieldPropDefs.color.default,
'aria-label': 'Birth date',
},
parameters: {
// Optional parameter to center the component in the Canvas. More info: https://storybook.js.org/docs/react/configure/story-layout
layout: 'centered',
},
// This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/react/writing-docs/autodocs
tags: ['autodocs'],
} satisfies Meta<typeof DateField>;

export default meta;
type Story = StoryObj<typeof meta>;

// More on writing stories with args: https://storybook.js.org/docs/react/writing-stories/args
export const Default: Story = {
args: {},
render: (args) => (
<div style={{ width: 300 }}>
<DateField
{...args}
defaultValue={parseDate('2020-02-03')}
onChange={(date) => console.log(date?.toString())}
/>
</div>
),
};

export const Size: Story = {
args: {},
render: (args) => (
<Flex direction={'column'} gap="4" style={{ width: 300 }}>
<DateField {...args} defaultValue={parseDate('2020-02-03')} size="1" />
<DateField {...args} defaultValue={parseDate('2020-02-03')} size="2" />
<DateField {...args} defaultValue={parseDate('2020-02-03')} size="3" />
</Flex>
),
};

export const MinValue: Story = {
args: {},
render: (args) => (
<Flex direction={'column'} gap="4" style={{ width: 300 }}>
<DateField
{...args}
minValue={today(getLocalTimeZone())}
defaultValue={parseDate('2020-02-03')}
validationBehavior="aria"
/>
</Flex>
),
};

export const WithTime: Story = {
name: 'With time',
args: {},
render: (args) => (
<Flex direction={'column'} gap="4" style={{ width: 300 }}>
<DateField
{...args}
defaultValue={parseZonedDateTime(
'2022-11-07T00:45[America/Los_Angeles]',
)}
/>
<DateField
{...args}
defaultValue={parseZonedDateTime(
'2022-11-07T00:45[America/Los_Angeles]',
)}
hideTimeZone
/>
<DateField
{...args}
defaultValue={parseZonedDateTime(
'2022-11-07T00:45[America/Los_Angeles]',
)}
hideTimeZone
granularity="second"
/>
</Flex>
),
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
import type { Meta, StoryObj } from '@storybook/react';

import { DateValue, parseDate } from '@internationalized/date';
import React from 'react';
import {
Button,
Calendar,
DatePicker,
Flex,
Popover,
datePickerPropDefs,
} from '../../../src/components';

// More on how to set up stories at: https://storybook.js.org/docs/react/writing-stories/introduction#default-export
const meta = {
title: 'Controls/Dates/DatePicker',
component: DatePicker,
args: {
size: datePickerPropDefs.size.default,
color: datePickerPropDefs.color.default,
defaultValue: parseDate('2020-02-03'),
onChange: (date) => console.log(date?.toString()),
'aria-label': 'Birth date',
isDisabled: false,
},
parameters: {
// Optional parameter to center the component in the Canvas. More info: https://storybook.js.org/docs/react/configure/story-layout
layout: 'centered',
},
// This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/react/writing-docs/autodocs
tags: ['autodocs'],
} satisfies Meta<typeof DatePicker>;

export default meta;
type Story = StoryObj<typeof meta>;

// More on writing stories with args: https://storybook.js.org/docs/react/writing-stories/args
export const Default: Story = {
args: {},
render: (args) => (
<Flex direction="column" gap="5">
<DatePicker {...args} />
</Flex>
),
};

export const Sizes: Story = {
args: {},
render: (args) => (
<Flex direction="column" gap="5">
<DatePicker {...args} size="1" />
<DatePicker {...args} size="2" />
<DatePicker {...args} size="3" />
</Flex>
),
};

export const Custom: Story = {
args: {},
render: () => {
const [date, setDate] = React.useState<DateValue>(parseDate('2020-02-03'));
const [open, setOpen] = React.useState(true);
return (
<div style={{ marginTop: -200 }}>
<Popover.Root open={open} onOpenChange={setOpen}>
<Popover.Trigger>
<Button size="3">
{' '}
<CalendarIcon /> {date.toString()}
</Button>
</Popover.Trigger>
<Popover.Content
variant="translucent"
align="center"
style={{ width: 'unset' }}
>
<Calendar
minValue={parseDate('2020-01-03')}
defaultValue={date}
maxValue={parseDate('2020-03-03')}
onChange={(value) => {
setDate(value);
setOpen(false);
}}
/>
</Popover.Content>
</Popover.Root>
</div>
);
},
};

const CalendarIcon = () => (
<svg
width="16"
height="16"
viewBox="0 0 16 16"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<g clipPath="url(#clip0_1869_102855)">
<path
fillRule="evenodd"
clipRule="evenodd"
d="M4 0C4.41421 0 4.75 0.335786 4.75 0.75V2H11.25V0.75C11.25 0.335786 11.5858 0 12 0C12.4142 0 12.75 0.335786 12.75 0.75V2.03304C14.5847 2.27749 16 3.84846 16 5.75V12.25C16 14.3211 14.3211 16 12.25 16H3.75C1.67893 16 0 14.3211 0 12.25V5.75C0 3.84846 1.41532 2.27749 3.25 2.03304V0.75C3.25 0.335786 3.58579 0 4 0ZM12 3.5H4H3.75C2.50736 3.5 1.5 4.50736 1.5 5.75V6H14.5V5.75C14.5 4.50736 13.4926 3.5 12.25 3.5H12ZM1.5 7.5V12.25C1.5 13.4926 2.50736 14.5 3.75 14.5H12.25C13.4926 14.5 14.5 13.4926 14.5 12.25V7.5H1.5Z"
fill="var(--gray-10)"
/>
</g>
<defs>
<clipPath id="clip0_1869_102855">
<rect width="16" height="16" fill="var(--gray-10)" />
</clipPath>
</defs>
</svg>
);
Loading