Skip to content

Commit

Permalink
docs: updated documentation for Calendar and DateTimePicker components (
Browse files Browse the repository at this point in the history
#5001)

* docs(calendar): updated docs

* docs(date-time-picker): updated docs

* chore: remove duplicate DateValue declaration

* docs: added clear selected stories

* docs(date-time-picker): custom precision story

* chore: comments cleanup

* chore: import fixes

* docs: addressed comms

* docs: updated chromatic settings to include locale picker

* chore: remove unnecessary types

* test(date-time-picker): update arrow-left test
  • Loading branch information
mizgaionutalexandru authored Dec 24, 2024
1 parent 8c94e37 commit ba424e0
Show file tree
Hide file tree
Showing 16 changed files with 584 additions and 117 deletions.
122 changes: 110 additions & 12 deletions packages/calendar/README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
## Description

`<sp-calendar>` elements display all the days within a given month, indicating the current day. Users can also see past or future months, and select a specific date via pointer, <kbd>Space</kbd> or <kbd>Enter</kbd>.

### Usage

[![See it on NPM!](https://img.shields.io/npm/v/@spectrum-web-components/calendar?style=for-the-badge)](https://www.npmjs.com/package/@spectrum-web-components/calendar)
Expand All @@ -23,20 +25,116 @@ import { Calendar } from '@spectrum-web-components/calendar';

## Example

By default, the `<sp-calendar>` element will display the current month with emphasis on the current day and no pre-selected date.

```html
<sp-calendar></sp-calendar>
```

## To-do list
## Value

A pre-selected date value can be provided to the `<sp-calendar>` element and it will dictate the displayed month of the element.
Setting the `value` property requires a `DateValue` type (`DateValue = CalendarDate | CalendarDateTime | ZonedDateTime`).
When reading the value by `element.value`, the consumer will always receive a `CalendarDate` type value.
More about these types and when to use each one can be found on the [`@internationalized/date` page](https://react-spectrum.adobe.com/internationalized/date/index.html).

To clear the element's value, the `clear` method can be used. (`element.clear()`)

```ts
import {CalendarDate} from '@internationalized/date';

<sp-calendar id="min-max-calendar"
.value=${new CalendarDate(2020, 2, 14)}
></sp-calendar>
```

## Minimum and maximum values

The `min` and `max` properties can be used to limit the selected value to a specific range. Ranges can be open, by providing only one of the mentioned properties, or closed, when both `min` and `max` are provided. These properties are also of `DateValue` type, but will always be of `CalendarDate` type when read, similar to `value`.

If the provided closed interval is not a valid one (e.g `min > max`), the assignment of those properties gets ignored. The same way, if a pre-selected value doesn't comply with the interval, it gets ignored and the element will behave as it wouldn't have a `value` provided.

```html-live
<div id="calendar-with-min-max"></div>
<script type="module">
import { CalendarDate } from '@internationalized/date';
import { SpectrumElement } from '@spectrum-web-components/base';
import { html, render } from 'lit';
import '@spectrum-web-components/calendar/sp-calendar.js';
class CalendarWithMinMax extends SpectrumElement {
render(){
return html`
<sp-calendar
.min=${new CalendarDate(2020, 2, 14)}
.max=${new CalendarDate(2020, 2, 19)}
></sp-calendar>`
}
}
customElements.define("calendar-with-min-max", CalendarWithMinMax);
onCodeExamplesLoaded(() => {
const root = document.querySelector('#calendar-with-min-max');
root.innerHTML = '';
render(html`<calendar-with-min-max></calendar-with-min-max>`, root);
})
</script>
```

<script type="module">
window.onCodeExamplesLoaded = (callback) => {
customElements.whenDefined('code-example').then(() => {
Promise.all([...document.querySelectorAll('code-example')].map(example => example.updateComplete)).then(callback);
});
}
</script>

<script type="module">
import { CalendarDate } from '@internationalized/date';
import { SpectrumElement } from '@spectrum-web-components/base';
import { html, render } from 'lit';
import '@spectrum-web-components/calendar/sp-calendar.js';

class CalendarWithMinMax extends SpectrumElement {
render(){
return html`
<sp-calendar
.min=${new CalendarDate(2020, 2, 14)}
.max=${new CalendarDate(2020, 2, 19)}
></sp-calendar>`
}
}

customElements.define("calendar-with-min-max", CalendarWithMinMax);

onCodeExamplesLoaded(() => {
const root = document.querySelector('#calendar-with-min-max');
root.innerHTML = '';
render(html`<calendar-with-min-max></calendar-with-min-max>`, root);
})
</script>

## Events

In order to react to date selection changes, consumers can leverage the `change` event and read the value of the event target in the handler.

```ts
import { CalendarDate } from '@internationalized/date';
import { Calendar } from '@spectrum-web-components/calendar';

const handleCalendarChange = (event: Event) => {
const selectedDate = (event.target as Calendar).value as CalendarDate;
// use the selectedDate...
};
```

## Internationalization

The `<sp-calendar` element supports multiple locales and updates its content accordingly.
`element.locale` represents the language in which the `<sp-calendar>` element is currently being delivered. By default, the value will represent the language established by the `lang` attribute on the root `<html>` element, with a fallback to `navigator.language`. This can be customized via a language context provider by a parent element that listens for `sp-language-context` event and supplies update language settings to the `callback` function. Applications leveraging the [`<sp-theme>`](./components/theme) element to manage the visual delivery or text direction of their content will also be provided with a reactive context for supplying language information to its descendants.

Currently the `<sp-calendar>` elements supports only the Gregorian calendar and the AD era.

- Implement a cache mechanism to store the value of `today` and use this value to initialise `currentDate`
- Include a condition to run the `setWeekdays()` method only when really needed
- Attribute 'role="heading"' removed, due to error 'The "heading" role requires the attribute "aria-level"'
- Translate the "Previous" text used in the "title" and "aria-label" of the button displayed in the header of the calendar
- Translate the "Next" text used in the "title" and "aria-label" of the button displayed in the header of the calendar
- The title must include "Today," and " selected" translated to the current language
- Implement keyboard navigation
- Add support for other types of calendars - [React Calendar: International Calendars](https://react-spectrum.adobe.com/react-spectrum/Calendar.html#international-calendars)
- Include `aria-label` in calendar for accessibility - [React Calendar: Labeling](https://react-spectrum.adobe.com/react-spectrum/Calendar.html#labeling)
- Complete documentation
- Add/Review unit tests
While providing support for screen readers, the element needs some labels to be internationalized by the consumer to offer non-english alternatives. This can be done via the `labels` property.
27 changes: 13 additions & 14 deletions packages/calendar/src/Calendar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ governing permissions and limitations under the License.
import {
CalendarDate,
DateFormatter,
DateValue,
endOfMonth,
getLocalTimeZone,
getWeeksInMonth,
Expand Down Expand Up @@ -54,10 +55,8 @@ import '@spectrum-web-components/icons-workflow/icons/sp-icon-chevron-right.js';

import {
CalendarLabels,
CalendarValue,
CalendarWeekday,
DateCellProperties,
DateValue,
} from './types.js';

export const DAYS_PER_WEEK = 7;
Expand All @@ -67,7 +66,7 @@ export const DAYS_PER_WEEK = 7;
* @slot prev-icon - The icon used in the "Previous Month" button
* @slot next-icon - The icon used in the "Next Month" button
*
* @event change - Announces when a day is selected by emitting a `Date` object
* @event change - Announces when a day is selected
*/
export class Calendar extends SpectrumElement {
public static override get styles(): CSSResultArray {
Expand All @@ -78,20 +77,20 @@ export class Calendar extends SpectrumElement {
* The selected date in the calendar. If defined, this also indicates where the calendar opens.
* If not, the calendar opens at the current month.
*/
@property({ attribute: false })
value?: CalendarValue;
@property({ type: Object })
public value?: DateValue;

/**
* The minimum allowed date a user can select
*/
@property({ attribute: false })
min?: DateValue;
@property({ type: Object })
public min?: DateValue;

/**
* The maximum allowed date a user can select
*/
@property({ attribute: false })
max?: DateValue;
@property({ type: Object })
public max?: DateValue;

/**
* Indicates when the calendar should be disabled entirely
Expand All @@ -103,8 +102,8 @@ export class Calendar extends SpectrumElement {
* Labels read by screen readers. The default values are in English
* and can be overridden to localize the content.
*/
@property({ attribute: false })
labels: CalendarLabels = {
@property({ type: Object })
public labels: CalendarLabels = {
previous: 'Previous',
next: 'Next',
today: 'Today',
Expand All @@ -129,7 +128,7 @@ export class Calendar extends SpectrumElement {
* The locale used to format the dates and weekdays.
* The default value is the language of the document or the user's browser.
*/
private get locale(): string {
public get locale(): string {
return this.languageResolver.language;
}

Expand Down Expand Up @@ -256,7 +255,7 @@ export class Calendar extends SpectrumElement {
window.__swc.warn(
this,
`<${this.localName}> expects the 'min' to be less than 'max'. Please ensure that 'min' property's date is earlier than 'max' property's date.`,
'https://opensource.adobe.com/spectrum-web-components/components/calendar' // TODO: update link
'https://opensource.adobe.com/spectrum-web-components/components/calendar'
);
this.min = undefined;
this.max = undefined;
Expand All @@ -268,7 +267,7 @@ export class Calendar extends SpectrumElement {
window.__swc.warn(
this,
`<${this.localName}> expects the preselected value to comply with the min and max constraints. Please ensure that 'value' property's date is in between the dates for the 'min' and 'max' properties.`,
'https://opensource.adobe.com/spectrum-web-components/components/calendar' // TODO: update link
'https://opensource.adobe.com/spectrum-web-components/components/calendar'
);
this.value = undefined;
}
Expand Down
9 changes: 0 additions & 9 deletions packages/calendar/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,6 @@ OF ANY KIND, either express or implied. See the License for the specific languag
governing permissions and limitations under the License.
*/

import {
CalendarDate,
CalendarDateTime,
ZonedDateTime,
} from '@internationalized/date';

export type DateValue = CalendarDate | CalendarDateTime | ZonedDateTime;
export type CalendarValue = DateValue;

export interface CalendarWeekday {
narrow: string;
long: string;
Expand Down
63 changes: 57 additions & 6 deletions packages/calendar/stories/calendar.stories.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,24 +11,30 @@ governing permissions and limitations under the License.
*/
import { CalendarDate, DateValue } from '@internationalized/date';

import { html, type TemplateResult } from '@spectrum-web-components/base';
import { CalendarValue } from '@spectrum-web-components/calendar';

import {
css,
CSSResultArray,
html,
SpectrumElement,
type TemplateResult,
} from '@spectrum-web-components/base';
import { spreadProps } from '../../../test/lit-helpers.js';

import '@spectrum-web-components/action-button/sp-action-button.js';
import '@spectrum-web-components/calendar/sp-calendar.js';
import '@spectrum-web-components/icons-workflow/icons/sp-icon-delete.js';
import '@spectrum-web-components/theme/sp-theme.js';

type ComponentArgs = {
value?: CalendarValue;
value?: DateValue;
min?: DateValue;
max?: DateValue;
padded?: boolean;
disabled?: boolean;
};

type StoryArgs = ComponentArgs & {
onChange?: (dateTime: CalendarValue) => void;
onChange?: (dateTime: DateValue) => void;
};

export default {
Expand Down Expand Up @@ -76,7 +82,7 @@ export default {
};

const computeProps = (args: StoryArgs): ComponentArgs => {
const timestampToValue = (timestamp: number): CalendarValue => {
const timestampToValue = (timestamp: number): DateValue => {
const date = new Date();
date.setTime(timestamp);
return new CalendarDate(
Expand Down Expand Up @@ -176,3 +182,48 @@ export const bengaliIndiaLocale = (args: StoryArgs): TemplateResult => {
</sp-theme>
`;
};

export const clearSelected = (args: StoryArgs): TemplateResult => {
const styles = css`
:host {
display: flex;
flex-direction: column;
align-items: center;
gap: 20px;
max-width: max-content;
}
`;

class ClearableCalendar extends SpectrumElement {
public static override get styles(): CSSResultArray {
return [styles];
}

private handleClear(): void {
this.shadowRoot?.querySelector('sp-calendar')?.clear();
}

public override render(): TemplateResult {
return html`
<sp-calendar
...=${spreadProps(computeProps(args))}
></sp-calendar>
<sp-action-button @click=${() => this.handleClear()}>
<sp-icon-delete slot="icon"></sp-icon-delete>
Clear
</sp-action-button>
`;
}
}

if (!customElements.get('clearable-calendar'))
customElements.define('clearable-calendar', ClearableCalendar);

return html`
<clearable-calendar></clearable-calendar>
`;
};

clearSelected.swc_vrt = {
skip: true,
};
4 changes: 2 additions & 2 deletions packages/calendar/test/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTA
OF ANY KIND, either express or implied. See the License for the specific language
governing permissions and limitations under the License.
*/
import { isSameDay } from '@internationalized/date';
import { DateValue, isSameDay } from '@internationalized/date';
import { elementUpdated, expect, fixture, html } from '@open-wc/testing';
import { Calendar, DateValue } from '@spectrum-web-components/calendar';
import { Calendar } from '@spectrum-web-components/calendar';
import '@spectrum-web-components/date-time-picker/sp-date-time-picker.js';
import '@spectrum-web-components/theme/sp-theme.js';
import { sendKeys } from '@web/test-runner-commands';
Expand Down
Loading

0 comments on commit ba424e0

Please sign in to comment.