Skip to content

Commit

Permalink
Merge pull request #1364 from Wizleap-Inc/feat/calendar-today-react
Browse files Browse the repository at this point in the history
Feat(calendar, date-picker, date-range-picker): 今日の日付を目立つようにする & キャンセル・適用ボタンの追加 React
  • Loading branch information
ichi-h authored Dec 26, 2024
2 parents 578e1ef + 44c0b9b commit 26c0d64
Show file tree
Hide file tree
Showing 15 changed files with 606 additions and 37 deletions.
8 changes: 8 additions & 0 deletions .changeset/olive-snails-tie.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
"@wizleap-inc/wiz-ui-react": minor
"@wizleap-inc/wiz-ui-next": minor
"@wizleap-inc/wiz-ui-constants": minor
"@wizleap-inc/wiz-ui-styles": minor
---

今日の日付を目立つようにする & キャンセル・適用ボタンの追加
2 changes: 2 additions & 0 deletions packages/constants/component/aria-label.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,6 @@ export const ARIA_LABELS = {
FULL_MODAL_VIEW: {
CLOSE: "モーダルを閉じる",
},
APPLY: "適用",
CANCEL: "キャンセル",
} as const;
8 changes: 8 additions & 0 deletions packages/styles/bases/calendar.css.ts
Original file line number Diff line number Diff line change
Expand Up @@ -125,3 +125,11 @@ export const calendarItemInteractiveStyle = style([
},
},
]);
export const calendarItemInteractiveTodayStyle = style([
calendarItemInteractiveStyle,
{
border: `1px solid ${THEME.color.green[800]}`,
borderRadius: "50%",
boxSizing: "border-box",
},
]);
Original file line number Diff line number Diff line change
Expand Up @@ -179,3 +179,72 @@ FilledWeeks.parameters = {
},
},
};

export const Today = Template.bind({});
Today.args = {
currentMonth: new Date("2023-03"),
_today: new Date("2023-03-05"),
};
Today.parameters = {
docs: {
description: {
story:
"本日の日付が丸で囲われるようになっています。通常利用では `_today` パラメータの設定は不要ですが、 `_today`パラメータを設定することで任意の日付を本日の日付として扱うことができます。",
},
source: {
code: `
<template>
<div>
<WizCalendar :_today="new Date('2023-03-05')" />
</div>
</template>
`,
},
},
};

export const DisabledToday = Template.bind({});
DisabledToday.args = {
currentMonth: new Date("2023-03"),
_today: new Date("2023-03-05"),
disabledDate: (date: Date) => date.getDate() === 5,
};
DisabledToday.parameters = {
docs: {
description: {
story: "本日の日付がdisabledの場合も丸で囲われます。",
},
source: {
code: `
<template>
<div>
<WizCalendar :_today="new Date('2023-03-05')" :disabledDate="(date: Date) => date.getDate() === 5" />
</div>
</template>
`,
},
},
};

export const SelectedToday = Template.bind({});
SelectedToday.args = {
currentMonth: new Date("2023-03"),
_today: new Date("2023-03-05"),
activeDates: [{ date: new Date("2023-03-05"), state: "primary" }],
};
SelectedToday.parameters = {
docs: {
description: {
story: "本日の日付がActiveの場合はActiveの見た目が優先されます。",
},
source: {
code: `
<template>
<div>
<WizCalendar :_today="new Date('2023-03-05')" :activeDates="[{ date: new Date("2023-03-05"), state: "primary" }]" />
</div>
</template>
`,
},
},
};
25 changes: 24 additions & 1 deletion packages/wiz-ui-next/src/components/base/calendar/calendar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,13 @@
)
"
>
<div :class="styles.calendarItemInteractiveStyle">
<div
:class="
isToday(row, col, adjacent.current.day)
? styles.calendarItemInteractiveTodayStyle
: styles.calendarItemInteractiveStyle
"
>
{{ adjacent.current.day }}
</div>
</div>
Expand Down Expand Up @@ -99,6 +105,12 @@ const props = defineProps({
required: false,
default: () => false,
},
// eslint-disable-next-line vue/prop-name-casing
_today: {
type: Date as PropType<Date>,
required: false,
default: new Date(),
},
});
const calendars = computed(() => {
Expand Down Expand Up @@ -250,6 +262,17 @@ const updateSelectedDate = (row: number, col: number, day: string) => {
}
};
const isToday = (row: number, col: number, day: string) => {
if (!isCurrentMonth(row, col)) return false;
const date = new Date(
props.currentMonth.getFullYear(),
props.currentMonth.getMonth(),
Number(day)
);
return date.toDateString() === (props._today || new Date()).toDateString();
};
const isActiveDate = computed(() => {
const activeDatesSet = new Set(
props.activeDates?.map((activeDate) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,7 @@ Test.play = async ({ canvasElement }) => {

// その月の15日を選択
const body = within(canvasElement.ownerDocument.body);
const initialDate = new Date(date.getFullYear(), date.getMonth(), 1);
const clickDate = new Date(date.getFullYear(), date.getMonth(), 15);
const pastClickDate = new Date(date.getFullYear(), date.getMonth() - 1, 15);
const clickDateEl = body.getByLabelText(_formatDateJp(clickDate));
Expand All @@ -270,11 +271,24 @@ Test.play = async ({ canvasElement }) => {
`${_formatDateJp(clickDate)}-選択済み`
)
);

// クリックした段階ではまだInputに反映されていないこと
await waitFor(() =>
expect(button.textContent).toBe(_formatDateJp(initialDate))
);

// 適用ボタンをクリック
const applyButton = body.getByText(ARIA_LABELS.APPLY);
await userEvent.click(applyButton);

// Input内が選択した日付になることを確認
await waitFor(() =>
expect(button.textContent).toBe(_formatDateJp(clickDate))
);

// カレンダー再オープン
await userEvent.click(button);

// 月セレクターのPrevを1回押して操作月を1ヶ月前にする
const monthSelectorPrev = body.getByLabelText(
ARIA_LABELS.MONTH_SELECTOR_PREV
Expand All @@ -296,6 +310,14 @@ Test.play = async ({ canvasElement }) => {
)
);

// Input内が選択した日付になることを確認
await waitFor(() =>
expect(button.textContent).toBe(_formatDateJp(new Date(clickDate)))
);

// 適用ボタンをクリック
await userEvent.click(applyButton);

// Input内が選択した日付になることを確認
await waitFor(() =>
expect(button.textContent).toBe(_formatDateJp(new Date(pastClickDate)))
Expand Down Expand Up @@ -340,3 +362,48 @@ const date = ref<Date | null>(null);
},
},
};

export const Today: StoryFn<typeof WizDatepicker> = (args) => ({
components: { WizDatepicker, WizHStack },
setup() {
const date = ref<Date | null>(new Date(2023, 2, 1));
const isOpen = ref(true);
const setIsOpen = (value: boolean) => (isOpen.value = value);
const today = new Date(2023, 2, 5);
return { args, date, isOpen, setIsOpen, today };
},
template: `
<WizDatepicker
v-bind="args"
v-model="date"
:isOpen="isOpen"
:_today="today"
@update:modelValue="args.onClick"
@update:isOpen="setIsOpen"
/>
`,
});

export const DisabledToday: StoryFn<typeof WizDatepicker> = (args) => ({
components: { WizDatepicker, WizHStack },
setup() {
const date = ref<Date | null>(new Date(2023, 2, 1));
const isOpen = ref(true);
const setIsOpen = (value: boolean) => (isOpen.value = value);
const today = new Date(2023, 2, 15);
const disabledDate = (date: Date) =>
date.getDate() >= 10 && date.getDate() < 17;
return { args, date, isOpen, setIsOpen, today, disabledDate };
},
template: `
<WizDatepicker
v-bind="args"
v-model="date"
:isOpen="isOpen"
:_today="today"
:disabledDate="disabledDate"
@update:modelValue="args.onClick"
@update:isOpen="setIsOpen"
/>
`,
});
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
</button>
<WizPopup
:isOpen="!disabled && isOpen"
@onClose="setIsOpen(false)"
@onClose="onClose"
:isDirectionFixed="isDirectionFixed"
>
<div :class="datePickerSelectorStyle">
Expand Down Expand Up @@ -107,10 +107,10 @@
</WizHStack>
<WizCalendar
:activeDates="
calendarValue
tempDate
? [
{
date: calendarValue,
date: tempDate,
state: 'primary',
},
]
Expand All @@ -120,7 +120,17 @@
:currentMonth="currentMonth"
filledWeeks
:disabledDate="disabledDate"
:_today="_today || new Date()"
/>
<WizDivider color="gray.300" />
<WizHStack p="sm" gap="sm" justify="end">
<WizTextButton @click="onClose" variant="sub">
{{ ARIA_LABELS.CANCEL }}
</WizTextButton>
<WizTextButton @click="onSubmit">
{{ ARIA_LABELS.APPLY }}
</WizTextButton>
</WizHStack>
</div>
</WizPopup>
</WizPopupContainer>
Expand All @@ -147,11 +157,13 @@ import { PropType, computed, inject, ref } from "vue";
import {
WizCalendar,
WizDivider,
WizHStack,
WizIcon,
WizPopup,
WizPopupContainer,
WizText,
WizTextButton,
WizVStack,
} from "@/components";
import {
Expand Down Expand Up @@ -231,6 +243,12 @@ const props = defineProps({
default: (date: Date) =>
`${date.getFullYear()}年${date.getMonth() + 1}月${date.getDate()}日`,
},
// eslint-disable-next-line vue/prop-name-casing
_today: {
type: Date as PropType<Date>,
required: false,
default: new Date(),
},
});
const emit = defineEmits<Emit>();
Expand All @@ -239,7 +257,7 @@ const defaultCurrentMonth = props.modelValue || new Date();
const currentMonth = ref(defaultCurrentMonth);
const setIsOpen = (value: boolean) => emit("update:isOpen", value);
const onClickCancel = () => emit("update:modelValue", null);
const tempDate = ref(props.modelValue);
const clickToNextMonth = (e: KeyboardEvent | MouseEvent) => {
e.preventDefault();
Expand Down Expand Up @@ -305,5 +323,24 @@ const variant = computed(() => {
return "default";
});
const handleClickCalendar = (date: Date) => (calendarValue.value = date);
const handleClickCalendar = (date: Date) => (tempDate.value = date);
const onClickCancel = (e: MouseEvent) => {
e.stopPropagation();
tempDate.value = null;
currentMonth.value = new Date(defaultCurrentMonth);
emit("update:modelValue", null);
setIsOpen(false);
};
const onClose = () => {
tempDate.value = calendarValue.value;
currentMonth.value = new Date(defaultCurrentMonth);
setIsOpen(false);
};
const onSubmit = () => {
calendarValue.value = tempDate.value;
setIsOpen(false);
};
</script>
Loading

0 comments on commit 26c0d64

Please sign in to comment.