diff --git a/src/components/experimental/Calendar/Calendar.tsx b/src/components/experimental/Calendar/Calendar.tsx new file mode 100644 index 00000000..0f269f85 --- /dev/null +++ b/src/components/experimental/Calendar/Calendar.tsx @@ -0,0 +1,134 @@ +import React, { ReactElement } from 'react'; +import { + Calendar as BaseCalendar, + CalendarProps as BaseCalendarProps, + CalendarCell, + CalendarGrid as BaseCalendarGrid, + CalendarGridHeader, + CalendarGridBody, + CalendarHeaderCell, + Heading as BaseHeading, + DateValue, + Button as BaseButton +} from 'react-aria-components'; +import styled from 'styled-components'; +import { ChevronLeftIcon, ChevronRightIcon } from '../../../icons'; +import { getSemanticValue } from '../../../essentials/experimental'; +import { textStyles } from '../Text/Text'; +import { get } from '../../../utils/experimental/themeGet'; + +const Header = styled.header` + display: flex; + align-items: center; + justify-content: space-between; + padding-bottom: ${get('space.3')}; +`; + +const Button = styled(BaseButton)` + appearance: none; + background: none; + border: none; + display: flex; + cursor: pointer; + margin: 0; + padding: 0; + color: ${getSemanticValue('on-surface')}; + outline: 0; + + &[data-focused] { + outline: ${getSemanticValue('accent')} solid 0.125rem; + } + + &[data-disabled] { + opacity: 0; + } +`; + +const Heading = styled(BaseHeading)` + margin: 0; + color: ${getSemanticValue('on-surface')}; + ${textStyles.variants.title2} +`; + +const CalendarGrid = styled(BaseCalendarGrid)` + border-collapse: collapse; + border-spacing: 0; + + td { + padding: 0; + } + + th { + padding: 0 0 ${get('space.1')}; + } +`; + +const WeekDay = styled(CalendarHeaderCell)` + color: ${getSemanticValue('on-surface')}; + ${textStyles.variants.label2} +`; + +const Day = styled(CalendarCell)` + display: flex; + align-items: center; + justify-content: center; + color: ${getSemanticValue('on-surface')}; + width: 2.5rem; + height: 2.5rem; + border-radius: 50%; + ${textStyles.variants.label2} + transition: background ease 200ms; + + &[data-focused] { + outline: ${getSemanticValue('accent')} solid 0.125rem; + } + + &[data-hovered] { + cursor: pointer; + background: ${getSemanticValue('surface-variant')}; + } + + &[data-selected] { + outline: 0; + background: ${getSemanticValue('interactive-container')}; + color: ${getSemanticValue('on-interactive-container')}; + } + + &[data-disabled] { + opacity: 0.38; + } + + &[data-outside-month] { + opacity: 0; + } +`; + +type CalendarProps = BaseCalendarProps; + +function Calendar(props: CalendarProps): ReactElement { + return ( + +
+ + + +
+ + {weekDay => {weekDay}} + + {date => ( + + {({ formattedDate }) => (formattedDate.length > 1 ? formattedDate : `0${formattedDate}`)} + + )} + + +
+ ); +} + +export { Calendar }; diff --git a/src/components/experimental/Calendar/docs/Calendar.stories.tsx b/src/components/experimental/Calendar/docs/Calendar.stories.tsx new file mode 100644 index 00000000..637e02eb --- /dev/null +++ b/src/components/experimental/Calendar/docs/Calendar.stories.tsx @@ -0,0 +1,36 @@ +import { I18nProvider } from 'react-aria-components'; +import { getLocalTimeZone, today } from '@internationalized/date'; +import { StoryObj, Meta } from '@storybook/react'; +import React from 'react'; +import { Calendar } from '../Calendar'; + +const meta: Meta = { + title: 'Experimental/Components/Calendar', + component: Calendar, + parameters: { + layout: 'centered' + }, + decorators: [ + Story => ( + + + + ) + ], + args: { + 'aria-label': 'Appointment date', + defaultValue: today(getLocalTimeZone()) + } +}; + +export default meta; + +type Story = StoryObj; + +export const Default: Story = {}; + +export const WithMinValue: Story = { + args: { + minValue: today(getLocalTimeZone()) + } +}; diff --git a/src/components/experimental/index.ts b/src/components/experimental/index.ts index 7a87fbea..ab4e244c 100644 --- a/src/components/experimental/index.ts +++ b/src/components/experimental/index.ts @@ -1,4 +1,5 @@ export { Button } from './Button/Button'; +export { Calendar } from './Calendar/Calendar'; export { Chip } from './Chip/Chip'; export { Label } from './Label/Label'; export { Text } from './Text/Text';