@wix/design-system
Version:
@wix/design-system
339 lines (303 loc) • 8.66 kB
Markdown
## Feature Examples
### Presets
- description: Empower the user to quickly select a predefined range or date using `presets` prop.
- example:
```jsx
() => {
const [selectedValue, setSelectedValue] = React.useState();
const today = new Date();
const getDateDaysAgo = days =>
new Date(Date.now() - days * 1000 * 60 * 60 * 24);
const presets = [
{
id: 0,
selectedDays: getDateDaysAgo(1),
value: 'Yesterday',
},
{
id: 1,
selectedDays: today,
value: 'Today',
},
{
id: 2,
selectedDays: {
from: getDateDaysAgo(7),
to: today,
},
value: 'Last 7 Days',
},
{
id: 3,
selectedDays: {
from: getDateDaysAgo(30),
to: today,
},
value: 'Last 30 Days',
},
{
id: 4,
selectedDays: {
from: getDateDaysAgo(90),
to: today,
},
value: 'Last 90 Days',
},
];
return (
<CalendarPanel
presets={presets}
onChange={value => setSelectedValue(value)}
value={selectedValue}
autoFocus={false}
/>
);
};
```
### Footer
- description: Make the date selection secure by using `footer` prop which adds summarized date selection and confirmation actions.
- example:
```jsx
<CalendarPanel
value={new Date()}
footer={({ selectedDays }) => (
<CalendarPanelFooter
primaryActionLabel="Submit"
secondaryActionLabel="Cancel"
selectedDays={selectedDays}
dateToString={date => date.toLocaleDateString('en-US')}
/>
)}
autoFocus={false}
/>;
```
### Number of Months
- description: Specify a number of months visible inside of a panel with `numOfMonths` prop.<br/>
<br/>
By default panel displays 2 months at once. Display a single month only when presets are available.
- example:
```jsx
() => {
const presets = [
{
id: 0,
value: 'Last 7 Days',
},
{
id: 1,
value: 'Last Month',
},
{
id: 2,
value: 'Next 2 days',
},
{
id: 3,
value: 'Next 3 days',
},
{
id: 4,
value: 'Next 5 days',
},
];
return (
<StorybookComponents.Stack flexDirection="column">
<StorybookComponents.Stack>
<CalendarPanel numOfMonths={1} presets={presets} autoFocus={false} />
</StorybookComponents.Stack>
<StorybookComponents.Stack>
<CalendarPanel numOfMonths={2} presets={presets} autoFocus={false} />
</StorybookComponents.Stack>
</StorybookComponents.Stack>
);
};
```
### Selection Mode
- description: Enable users to select the range of dates with `selectionMode` prop. It supports 2 values:<br/>
 - `day` (default) - lets to select 1 day.<br/>
 - `range` - lets to select any range of dates.
- example:
```jsx
_selectionMode
```
### Month and Year Selection
- description: Let the user quickly change the month and year values with:<br/>
 - `showMonthDropdown` (default) - enables month selection dropdown.<br/>
 - `showYearDropdown` - enables year selection dropdown.
- example:
```jsx
<CalendarPanel showMonthDropdown showYearDropdown autoFocus={false} />;
```
### Excluding Dates
- description: Control what dates the user can select with 2 props:<br/>
 - `filterDate` (default) - define what dates will be selectable.<br/>
 - `excludePastDates` - allow selecting only today and future dates.
- example:
```jsx
<StorybookComponents.Stack flexDirection="column">
<CalendarPanel filterDate={date => date < new Date()} autoFocus={false} />
<CalendarPanel excludePastDates autoFocus={false} />
</StorybookComponents.Stack>;
```
### Localization
- description: Change the language using `locale` prop. Some languages will change the start of the week day and order of month and year.
First Day of the week can be controlled manually with `firstDayOfWeek` prop.<br/>
<br/>
Presets and footer actions aren’t controlled by this and have to be translated manually.<br/>
<br/>
When using `Yoshi 5` with `BM Flow` there's no need to use `locale` prop anymore. It is handled automatically.
- example:
```jsx
<CalendarPanel
locale="ko"
presets={[{ value: "I'm still English" }]}
footer={() => (
<CalendarPanelFooter
secondaryActionLabel="Me too"
primaryActionLabel="Me as well"
selectedDays={new Date()}
dateToString={date => date.toLocaleDateString('en-US')}
/>
)}
autoFocus={false}
/>;
```
## Common Use Case Examples
### Trigger
- description: Call it out from any action component such as `<IconButton/>`, `<TextButton/>`, `<Button/>`, etc.
Use it to filter data and content.
- example:
```jsx
() => {
const today = new Date();
const dayInMilliseconds = 1000 * 60 * 60 * 24;
const getDateDaysAgo = days =>
new Date(Date.now() - days * dayInMilliseconds);
const getShortDate = date => date.toLocaleDateString();
const oneDayChartData = [
{
value: Math.floor(Math.random() * 1000),
label: '00:00',
},
{
value: Math.floor(Math.random() * 1000),
label: '23:59',
},
];
const [currentRange, setCurrentRange] = React.useState(today);
const [analyticsData, setAnalyticsData] = React.useState({
chartData: oneDayChartData,
range: today,
rangeText: getShortDate(today),
});
const [panelShown, setPanelShown] = React.useState(false);
const presets = [
{
id: 0,
selectedDays: {
from: getDateDaysAgo(7),
to: today,
},
value: 'Last 7 Days',
},
{
id: 1,
selectedDays: {
from: getDateDaysAgo(30),
to: today,
},
value: 'Last 30 Days',
},
{
id: 2,
selectedDays: {
from: getDateDaysAgo(90),
to: today,
},
value: 'Last 90 Days',
},
];
const getRangeOfDates = (startDate, endDate) => {
const diffInDays = Math.ceil(
(endDate.getTime() - startDate.getTime()) / dayInMilliseconds + 1,
);
return new Array(diffInDays)
.fill(0)
.map(
(_, index) => new Date(startDate.getTime() + index * dayInMilliseconds),
);
};
const getChartAreaData = (startDate, endDate) => {
if (startDate.getTime() === endDate.getTime()) {
return oneDayChartData;
}
return getRangeOfDates(startDate, endDate).map((date, index) => ({
label: \`\${date.getMonth() + 1}/\${date.getDate()}\`,
value: Math.floor(Math.random() * 1000),
}));
};
const getRangeText = (startDate, endDate) =>
startDate.getTime() === endDate.getTime()
? getShortDate(startDate)
: \`\${getShortDate(startDate)}-\${getShortDate(endDate)}\`;
const onSubmitClick = () => {
setPanelShown(false);
setAnalyticsData({
range: currentRange,
chartData: getChartAreaData(currentRange.from, currentRange.to),
rangeText: getRangeText(currentRange.from, currentRange.to),
});
};
const onCancelClick = () => {
setPanelShown(false);
setCurrentRange(analyticsData.range);
};
return (
<Card>
<Card.Header
title="Analytics"
suffix={
<Popover
shown={panelShown}
onClickOutside={onCancelClick}
appendTo="window"
placement="bottom"
>
<Popover.Element>
<TextButton onClick={() => setPanelShown(!panelShown)}>
<Box verticalAlign="middle">
{analyticsData.rangeText}
<Icons.ChevronDownSmall />
</Box>
</TextButton>
</Popover.Element>
<Popover.Content>
<CalendarPanel
presets={presets}
value={currentRange}
onChange={setCurrentRange}
selectionMode="range"
footer={({ selectedDays }) => (
<CalendarPanelFooter
primaryActionLabel="Submit"
secondaryActionLabel="Cancel"
primaryActionOnClick={onSubmitClick}
secondaryActionOnClick={onCancelClick}
selectedDays={selectedDays}
dateToString={date => date.toLocaleDateString('en-US')}
/>
)}
autoFocus={false}
/>
</Popover.Content>
</Popover>
}
/>
<Card.Divider />
<Card.Content>
<AreaChart data={analyticsData.chartData} />
</Card.Content>
</Card>
);
};
```