frontend: switch calendar zoom to slider and add intuitive expand icons
This commit is contained in:
@@ -1909,13 +1909,6 @@ const calendarViewOptions: { value: CalendarView; label: string }[] = [
|
||||
{ value: "agenda", label: "Agenda" },
|
||||
];
|
||||
|
||||
const calendarZoomOptions: Array<{ value: number; label: string }> = [
|
||||
{ value: 1, label: "400%" },
|
||||
{ value: 2, label: "250%" },
|
||||
{ value: 3, label: "100%" },
|
||||
{ value: 4, label: "50%" },
|
||||
];
|
||||
|
||||
const calendarZoomLevel = computed<number>({
|
||||
get() {
|
||||
if (calendarView.value === "day") return 1;
|
||||
@@ -1941,6 +1934,13 @@ const calendarZoomLevel = computed<number>({
|
||||
},
|
||||
});
|
||||
|
||||
const calendarZoomLabel = computed(() => {
|
||||
if (calendarView.value === "day") return "Day";
|
||||
if (calendarView.value === "week") return "Week";
|
||||
if (calendarView.value === "month" || calendarView.value === "agenda") return "Month";
|
||||
return "Year";
|
||||
});
|
||||
|
||||
const monthCells = computed(() => {
|
||||
const year = calendarCursor.value.getFullYear();
|
||||
const month = calendarCursor.value.getMonth();
|
||||
@@ -3649,15 +3649,20 @@ async function decideFeedCard(card: FeedCard, decision: "accepted" | "rejected")
|
||||
|
||||
<div class="justify-self-end flex items-center gap-2">
|
||||
<span class="text-[10px] uppercase tracking-wide text-base-content/60">Zoom</span>
|
||||
<select v-model.number="calendarZoomLevel" class="select select-bordered select-xs w-24">
|
||||
<option
|
||||
v-for="option in calendarZoomOptions"
|
||||
:key="`calendar-zoom-${option.value}`"
|
||||
:value="option.value"
|
||||
<div class="flex items-center gap-2 rounded-lg border border-base-300 bg-base-100 px-2 py-1">
|
||||
<input
|
||||
v-model.number="calendarZoomLevel"
|
||||
type="range"
|
||||
min="1"
|
||||
max="4"
|
||||
step="1"
|
||||
class="range range-xs w-24 calendar-zoom-range"
|
||||
aria-label="Calendar zoom level"
|
||||
>
|
||||
{{ option.label }}
|
||||
</option>
|
||||
</select>
|
||||
<span class="min-w-[3.2rem] text-right text-[10px] font-semibold uppercase tracking-wide text-base-content/70">
|
||||
{{ calendarZoomLabel }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -3711,10 +3716,14 @@ async function decideFeedCard(card: FeedCard, decision: "accepted" | "rejected")
|
||||
<button
|
||||
type="button"
|
||||
class="calendar-hover-jump calendar-hover-jump-row"
|
||||
title="Open week view"
|
||||
title="Zoom to week"
|
||||
aria-label="Zoom to week"
|
||||
@click.stop="openWeekView(row.startKey)"
|
||||
>
|
||||
Week
|
||||
<svg viewBox="0 0 20 20" class="h-3.5 w-3.5 fill-none stroke-current" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
|
||||
<circle cx="8.5" cy="8.5" r="4.5" />
|
||||
<path d="M12 12l4.2 4.2" />
|
||||
</svg>
|
||||
</button>
|
||||
<div class="grid grid-cols-7 gap-1">
|
||||
<button
|
||||
@@ -3729,13 +3738,17 @@ async function decideFeedCard(card: FeedCard, decision: "accepted" | "rejected")
|
||||
@click="pickDate(cell.key)"
|
||||
>
|
||||
<p class="mb-1 text-xs font-semibold">{{ cell.day }}</p>
|
||||
<span
|
||||
<button
|
||||
type="button"
|
||||
class="calendar-hover-jump"
|
||||
title="Open day view"
|
||||
title="Expand to day"
|
||||
aria-label="Expand to day"
|
||||
@click.stop="openDayView(cell.key)"
|
||||
>
|
||||
Day
|
||||
</span>
|
||||
<svg viewBox="0 0 20 20" class="h-3.5 w-3.5 fill-none stroke-current" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
|
||||
<path d="M7 13L3 17M13 7l4-4M3 13V17h4M17 7V3h-4" />
|
||||
</svg>
|
||||
</button>
|
||||
<button
|
||||
v-for="event in monthCellEvents(cell.events)"
|
||||
:key="event.id"
|
||||
@@ -3763,10 +3776,13 @@ async function decideFeedCard(card: FeedCard, decision: "accepted" | "rejected")
|
||||
<button
|
||||
type="button"
|
||||
class="calendar-hover-jump calendar-hover-jump-week"
|
||||
title="Open day view"
|
||||
title="Expand day line"
|
||||
aria-label="Expand day line"
|
||||
@click.stop="openDayView(day.key)"
|
||||
>
|
||||
Day
|
||||
<svg viewBox="0 0 20 20" class="h-3.5 w-3.5 fill-none stroke-current" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
|
||||
<path d="M10 3v14M6 7l4-4 4 4M6 13l4 4 4-4" />
|
||||
</svg>
|
||||
</button>
|
||||
<div class="space-y-1">
|
||||
<button
|
||||
@@ -4924,16 +4940,14 @@ async function decideFeedCard(card: FeedCard, decision: "accepted" | "rejected")
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-width: 36px;
|
||||
height: 20px;
|
||||
padding: 0 8px;
|
||||
border-radius: 999px;
|
||||
min-width: 26px;
|
||||
width: 26px;
|
||||
height: 26px;
|
||||
padding: 0;
|
||||
border-radius: 8px;
|
||||
border: 1px solid color-mix(in oklab, var(--color-primary) 35%, transparent);
|
||||
background: color-mix(in oklab, var(--color-base-100) 86%, transparent);
|
||||
color: color-mix(in oklab, var(--color-base-content) 78%, transparent);
|
||||
font-size: 10px;
|
||||
font-weight: 600;
|
||||
letter-spacing: 0.02em;
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
transition: opacity 120ms ease, transform 120ms ease, background-color 120ms ease;
|
||||
@@ -4948,6 +4962,14 @@ async function decideFeedCard(card: FeedCard, decision: "accepted" | "rejected")
|
||||
transform: translateY(0);
|
||||
}
|
||||
|
||||
.calendar-hover-jump:focus-visible {
|
||||
opacity: 1;
|
||||
pointer-events: auto;
|
||||
transform: translateY(0);
|
||||
outline: 2px solid color-mix(in oklab, var(--color-primary) 58%, transparent);
|
||||
outline-offset: 1px;
|
||||
}
|
||||
|
||||
.calendar-hover-jump:hover {
|
||||
background: color-mix(in oklab, var(--color-primary) 12%, var(--color-base-100));
|
||||
}
|
||||
@@ -4956,7 +4978,11 @@ async function decideFeedCard(card: FeedCard, decision: "accepted" | "rejected")
|
||||
.calendar-hover-jump-row {
|
||||
top: 8px;
|
||||
right: 10px;
|
||||
min-width: 46px;
|
||||
}
|
||||
|
||||
.calendar-zoom-range {
|
||||
--range-shdw: color-mix(in oklab, var(--color-primary) 72%, white 8%);
|
||||
--range-bg: color-mix(in oklab, var(--color-base-300) 85%, white 10%);
|
||||
}
|
||||
|
||||
@media (max-width: 960px) {
|
||||
|
||||
Reference in New Issue
Block a user