{isLeft ? left : isRight ? right : null}
@@ -139,6 +142,7 @@ export const NavButtons = memo(function NavButtons({
size="small"
className={styles.focusInteractive}
disabled={prevDisabled}
+ data-testid="date-picker-nav-prev"
onClick={onPrev}
>
@@ -151,6 +155,7 @@ export const NavButtons = memo(function NavButtons({
size="small"
className={styles.focusInteractive}
disabled={nextDisabled}
+ data-testid="date-picker-nav-next"
onClick={onNext}
>
diff --git a/packages/frontend/component/src/ui/date-picker/calendar/month-picker.tsx b/packages/frontend/component/src/ui/date-picker/calendar/month-picker.tsx
index 6502fbf93f..f868016ff7 100644
--- a/packages/frontend/component/src/ui/date-picker/calendar/month-picker.tsx
+++ b/packages/frontend/component/src/ui/date-picker/calendar/month-picker.tsx
@@ -73,6 +73,8 @@ export const MonthPicker = memo(function MonthPicker(
const onKeyDown = (e: KeyboardEvent) => {
if (e.key === 'Escape') {
+ e.preventDefault();
+ e.stopPropagation();
closeMonthPicker();
return;
}
@@ -101,6 +103,7 @@ export const MonthPicker = memo(function MonthPicker(
const HeaderLeft = useMemo(() => {
return (
diff --git a/packages/frontend/component/src/ui/date-picker/calendar/year-picker.tsx b/packages/frontend/component/src/ui/date-picker/calendar/year-picker.tsx
index dc3479c083..6cd29f7c72 100644
--- a/packages/frontend/component/src/ui/date-picker/calendar/year-picker.tsx
+++ b/packages/frontend/component/src/ui/date-picker/calendar/year-picker.tsx
@@ -84,6 +84,8 @@ export const YearPicker = memo(function YearPicker(
const onKeyDown = (e: KeyboardEvent) => {
if (e.key === 'Escape') {
+ e.preventDefault();
+ e.stopPropagation();
closeYearPicker();
return;
}
diff --git a/packages/frontend/core/src/components/page-list/filter/date-select.css.ts b/packages/frontend/core/src/components/page-list/filter/date-select.css.ts
new file mode 100644
index 0000000000..279eacda34
--- /dev/null
+++ b/packages/frontend/core/src/components/page-list/filter/date-select.css.ts
@@ -0,0 +1,17 @@
+import { cssVar } from '@toeverything/theme';
+import { style } from '@vanilla-extract/css';
+
+export const datePickerTriggerInput = style({
+ fontSize: cssVar('fontXs'),
+ width: '50px',
+ fontWeight: '600',
+ display: 'flex',
+ alignItems: 'center',
+ justifyContent: 'center',
+ height: '22px',
+ textAlign: 'center',
+ ':hover': {
+ background: cssVar('hoverColor'),
+ borderRadius: '4px',
+ },
+});
diff --git a/packages/frontend/core/src/components/page-list/filter/date-select.tsx b/packages/frontend/core/src/components/page-list/filter/date-select.tsx
new file mode 100644
index 0000000000..07a434fa81
--- /dev/null
+++ b/packages/frontend/core/src/components/page-list/filter/date-select.tsx
@@ -0,0 +1,51 @@
+import { DatePicker, Popover, type PopoverProps } from '@affine/component';
+import { useAFFiNEI18N } from '@affine/i18n/hooks';
+import dayjs from 'dayjs';
+import { useCallback, useState } from 'react';
+
+import { datePickerTriggerInput } from './date-select.css';
+
+const datePickerPopperContentOptions: PopoverProps['contentOptions'] = {
+ style: { padding: 20, marginTop: 10 },
+};
+
+export const DateSelect = ({
+ value,
+ onChange,
+}: {
+ value: number;
+ onChange: (value: number) => void;
+}) => {
+ const t = useAFFiNEI18N();
+ const [open, setOpen] = useState(false);
+
+ const onDateChange = useCallback(
+ (e: string) => {
+ setOpen(false);
+ onChange(dayjs(e, 'YYYY-MM-DD').valueOf());
+ },
+ [onChange]
+ );
+
+ return (
+
+ }
+ >
+
+
+ );
+};
diff --git a/packages/frontend/core/src/components/page-list/filter/literal-matcher.tsx b/packages/frontend/core/src/components/page-list/filter/literal-matcher.tsx
index fc3e259fec..07b4dacf56 100644
--- a/packages/frontend/core/src/components/page-list/filter/literal-matcher.tsx
+++ b/packages/frontend/core/src/components/page-list/filter/literal-matcher.tsx
@@ -1,8 +1,8 @@
-import { AFFiNEDatePicker, Input, Menu, MenuItem } from '@affine/component';
+import { Input, Menu, MenuItem } from '@affine/component';
import type { LiteralValue, Tag } from '@affine/env/filter';
-import dayjs from 'dayjs';
import { type ReactNode } from 'react';
+import { DateSelect } from './date-select';
import { FilterTag } from './filter-tag-translation';
import { inputStyle } from './index.css';
import { tBoolean, tDate, tDateRange, tTag } from './logical/custom-type';
@@ -67,12 +67,7 @@ literalMatcher.register(tBoolean.create(), {
});
literalMatcher.register(tDate.create(), {
render: ({ value, onChange }) => (
-
{
- onChange(dayjs(e, 'YYYY-MM-DD').valueOf());
- }}
- />
+
),
});
const getTagsOfArrayTag = (type: TType): Tag[] => {
diff --git a/packages/frontend/core/src/pages/workspace/detail-page/editor-sidebar/extensions/journal.css.ts b/packages/frontend/core/src/pages/workspace/detail-page/editor-sidebar/extensions/journal.css.ts
index 03b720a1c0..0e8d3783e1 100644
--- a/packages/frontend/core/src/pages/workspace/detail-page/editor-sidebar/extensions/journal.css.ts
+++ b/packages/frontend/core/src/pages/workspace/detail-page/editor-sidebar/extensions/journal.css.ts
@@ -1,5 +1,6 @@
import { cssVar } from '@toeverything/theme';
-import { globalStyle, style } from '@vanilla-extract/css';
+import { style } from '@vanilla-extract/css';
+
const interactive = style({
position: 'relative',
cursor: 'pointer',
@@ -41,6 +42,7 @@ export const journalPanel = style({
display: 'flex',
flexDirection: 'column',
alignItems: 'stretch',
+ overflow: 'hidden',
});
export const dailyCount = style({
height: 0,
@@ -179,14 +181,47 @@ export const journalConflictMoreTrigger = style([
},
]);
-// TODO: when date-picker's cell is customizable, we should implement by custom cell
-// override date-picker's active day when is not journal
-globalStyle(
- `.${journalPanel}[data-is-journal="false"] .react-datepicker__day[aria-selected="true"]`,
+// customize date-picker cell
+export const journalDateCell = style([
+ interactive,
{
- backgroundColor: 'transparent',
+ width: '100%',
+ height: '100%',
+ borderRadius: 8,
+ fontSize: cssVar('fontSm'),
color: cssVar('textPrimaryColor'),
- fontWeight: 500,
- border: `1px solid ${cssVar('primaryColor')}`,
- }
-);
+ fontWeight: 400,
+ position: 'relative',
+
+ selectors: {
+ '&[data-is-today="true"]': {
+ fontWeight: 600,
+ color: cssVar('brandColor'),
+ },
+ '&[data-not-current-month="true"]': {
+ color: cssVar('black10'),
+ },
+ '&[data-selected="true"]': {
+ backgroundColor: cssVar('brandColor'),
+ fontWeight: 500,
+ color: cssVar('pureWhite'),
+ },
+ '&[data-is-journal="false"][data-selected="true"]': {
+ backgroundColor: 'transparent',
+ color: 'var(--affine-text-primary-color)',
+ fontWeight: 500,
+ border: `1px solid ${cssVar('primaryColor')}`,
+ },
+ },
+ },
+]);
+export const journalDateCellDot = style({
+ width: 4,
+ height: 4,
+ borderRadius: '50%',
+ backgroundColor: cssVar('primaryColor'),
+ position: 'absolute',
+ bottom: 0,
+ left: '50%',
+ transform: 'translateX(-50%)',
+});
diff --git a/packages/frontend/core/src/pages/workspace/detail-page/editor-sidebar/extensions/journal.tsx b/packages/frontend/core/src/pages/workspace/detail-page/editor-sidebar/extensions/journal.tsx
index b6df10577c..26da3d69aa 100644
--- a/packages/frontend/core/src/pages/workspace/detail-page/editor-sidebar/extensions/journal.tsx
+++ b/packages/frontend/core/src/pages/workspace/detail-page/editor-sidebar/extensions/journal.tsx
@@ -1,5 +1,6 @@
import {
- AFFiNEDatePicker,
+ type DateCell,
+ DatePicker,
IconButton,
Menu,
Scrollable,
@@ -80,6 +81,7 @@ interface JournalBlockProps extends EditorExtensionProps {
const EditorJournalPanel = (props: EditorExtensionProps) => {
const { workspace, page } = props;
+ const t = useAFFiNEI18N();
const { journalDate, isJournal } = useJournalInfoHelper(
page.workspace,
page.id
@@ -99,14 +101,45 @@ const EditorJournalPanel = (props: EditorExtensionProps) => {
[journalDate, openJournal]
);
+ const customDayRenderer = useCallback(
+ (cell: DateCell) => {
+ // TODO: add a dot to indicate journal
+ // has performance issue for now, better to calculate it in advance
+ // const hasJournal = !!getJournalsByDate(cell.date.format('YYYY-MM-DD'))?.length;
+ const hasJournal = false;
+ return (
+
+ );
+ },
+ [isJournal]
+ );
+
return (
diff --git a/tests/affine-local/e2e/all-page.spec.ts b/tests/affine-local/e2e/all-page.spec.ts
index cdc6332ff8..38fcf06968 100644
--- a/tests/affine-local/e2e/all-page.spec.ts
+++ b/tests/affine-local/e2e/all-page.spec.ts
@@ -99,7 +99,6 @@ test('use monthpicker to modify the month of datepicker', async ({ page }) => {
await selectMonthFromMonthPicker(page, lastMonth);
await checkDatePickerMonth(page, lastMonth);
// change month
- await clickDatePicker(page);
const nextMonth = new Date();
nextMonth.setMonth(nextMonth.getMonth() + 1);
await selectMonthFromMonthPicker(page, nextMonth);
diff --git a/tests/kit/utils/filter.ts b/tests/kit/utils/filter.ts
index 61c336bff5..92e5918cdb 100644
--- a/tests/kit/utils/filter.ts
+++ b/tests/kit/utils/filter.ts
@@ -78,68 +78,8 @@ export const fillDatePicker = async (page: Page, date: Date) => {
.fill(dateFormat(date));
};
-const checkIsLastMonth = (date: Date): boolean => {
- const targetMonth = date.getMonth();
- const currentMonth = new Date().getMonth();
- const lastMonth = currentMonth === 0 ? 11 : currentMonth - 1;
- return targetMonth === lastMonth;
-};
-
-const checkIsNextMonth = (date: Date): boolean => {
- const targetMonth = date.getMonth();
- const currentMonth = new Date().getMonth();
- const nextMonth = currentMonth === 11 ? 0 : currentMonth + 1;
- return targetMonth === nextMonth;
-};
-
-export const selectDateFromDatePicker = async (page: Page, date: Date) => {
- const datePickerPopup = page.locator('.react-datepicker-popper');
- const day = date.getDate();
- const month = date.toLocaleString('en-US', { month: 'long' });
- const weekday = date.toLocaleString('en-US', { weekday: 'long' });
- const year = date.getFullYear().toString();
- const nth = function (d: number) {
- if (d > 3 && d < 21) return 'th';
- switch (d % 10) {
- case 1:
- return 'st';
- case 2:
- return 'nd';
- case 3:
- return 'rd';
- default:
- return 'th';
- }
- };
- const daySuffix = nth(day);
- // Open the date picker popup
- await clickDatePicker(page);
- const selectDate = async (): Promise => {
- if (checkIsLastMonth(date)) {
- const lastMonthButton = page.locator(
- '[data-testid="date-picker-prev-button"]'
- );
- await lastMonthButton.click();
- } else if (checkIsNextMonth(date)) {
- const nextMonthButton = page.locator(
- '[data-testid="date-picker-next-button"]'
- );
- await nextMonthButton.click();
- }
- // Click on the day cell
- const dateCell = page.locator(
- `[aria-disabled="false"][aria-label="Choose ${weekday}, ${month} ${day}${daySuffix}, ${year}"]`
- );
- await dateCell.click();
- };
- await selectDate();
-
- // Wait for the date picker popup to close
- await datePickerPopup.waitFor({ state: 'hidden' });
-};
-
export const selectMonthFromMonthPicker = async (page: Page, date: Date) => {
- const month = date.toLocaleString('en-US', { month: 'long' });
+ const month = (date.getMonth() + 1).toString().padStart(2, '0');
const year = date.getFullYear();
// Open the month picker popup
await clickMonthPicker(page);
@@ -148,14 +88,16 @@ export const selectMonthFromMonthPicker = async (page: Page, date: Date) => {
.getByTestId('month-picker-current-year')
.innerText());
if (selectedYear > year) {
- await page.locator('[data-testid="month-picker-prev-button"]').click();
+ await page.locator('[data-testid="date-picker-nav-prev"]').click();
return await selectMonth();
} else if (selectedYear < year) {
- await page.locator('[data-testid="month-picker-next-button"]').click();
+ await page.locator('[data-testid="date-picker-nav-next"]').click();
return await selectMonth();
}
// Click on the day cell
- const monthCell = page.locator(`[aria-label="Choose ${month} ${year}"]`);
+ const monthCell = page.locator(
+ `[data-is-month-cell][aria-label="${year}-${month}"]`
+ );
await monthCell.click();
};
await selectMonth();
@@ -163,8 +105,8 @@ export const selectMonthFromMonthPicker = async (page: Page, date: Date) => {
export const checkDatePickerMonth = async (page: Page, date: Date) => {
expect(
- await page.locator('[data-testid="date-picker-current-month"]').innerText()
- ).toBe(date.toLocaleString('en-US', { month: 'long' }));
+ await page.getByTestId('month-picker-button').evaluate(e => e.dataset.month)
+ ).toBe(date.getMonth().toString());
};
const createTag = async (page: Page, name: string) => {