Responsive layout
This commit is contained in:
parent
dd8b231cbc
commit
ff6657cbcc
@ -1,14 +1,9 @@
|
||||
/* Layout variables */
|
||||
:root {
|
||||
/* Layout */
|
||||
--row-h: 2.2em;
|
||||
--week-w: 3em;
|
||||
--week-w: 3rem;
|
||||
--day-w: 1fr;
|
||||
--row-h: 12vh;
|
||||
--month-w: 4em;
|
||||
--month-w: 2rem;
|
||||
--row-h: 15vh;
|
||||
}
|
||||
|
||||
/* Layout & typography */
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
@ -100,35 +95,10 @@ header {
|
||||
#calendar-viewport::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.jogwheel-viewport,
|
||||
#jogwheel-viewport {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
width: var(--month-w);
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
scrollbar-width: none;
|
||||
z-index: 20;
|
||||
cursor: ns-resize;
|
||||
}
|
||||
.jogwheel-viewport::-webkit-scrollbar,
|
||||
#jogwheel-viewport::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.jogwheel-content,
|
||||
#jogwheel-content {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
}
|
||||
.calendar-content,
|
||||
#calendar-content {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
/* Week row: label + 7-day grid + jogwheel column */
|
||||
.week-row {
|
||||
display: grid;
|
||||
|
@ -347,7 +347,7 @@ function createWeek(virtualWeek) {
|
||||
text: `${getLocalizedMonthName(monthToLabel)} '${year}`,
|
||||
month: monthToLabel,
|
||||
weeksSpan: weeksSpan,
|
||||
height: weeksSpan * rowHeight.value,
|
||||
monthClass: monthAbbr[monthToLabel],
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -651,18 +651,6 @@ function openSettings() {
|
||||
// Heuristic: rotate month label (180deg) only for predominantly Latin text.
|
||||
// We explicitly avoid locale detection; rely solely on characters present.
|
||||
// Disable rotation if any CJK Unified Ideograph or Compatibility Ideograph appears.
|
||||
function shouldRotateMonth(label) {
|
||||
if (!label) return false
|
||||
// Rotate ONLY if any Latin script alphabetic character is present.
|
||||
// Prefer Unicode script property when supported.
|
||||
try {
|
||||
if (/\p{Script=Latin}/u.test(label)) return true
|
||||
} catch (e) {
|
||||
// Fallback for environments lacking Unicode property escapes.
|
||||
if (/[A-Za-z\u00C0-\u024F\u1E00-\u1EFF]/u.test(label)) return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
// Keep roughly same visible date when first_day setting changes.
|
||||
watch(
|
||||
() => calendarStore.config.first_day,
|
||||
@ -723,19 +711,6 @@ window.addEventListener('resize', () => {
|
||||
@day-touchstart="handleDayTouchStart"
|
||||
@event-click="handleEventClick"
|
||||
/>
|
||||
<!-- Month labels positioned absolutely -->
|
||||
<div
|
||||
v-for="week in visibleWeeks"
|
||||
:key="`month-${week.virtualWeek}`"
|
||||
class="month-name-label"
|
||||
:class="{ 'no-rotate': !shouldRotateMonth(week.monthLabel?.text) }"
|
||||
:style="{
|
||||
top: week.top + 'px',
|
||||
height: week.monthLabel?.height + 'px',
|
||||
}"
|
||||
>
|
||||
<span>{{ week.monthLabel?.text }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Jogwheel as sibling to calendar-viewport -->
|
||||
@ -796,34 +771,6 @@ header h1 {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.month-name-label {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
width: 3rem; /* Match jogwheel width */
|
||||
font-size: 2em;
|
||||
font-weight: 700;
|
||||
color: var(--muted);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
pointer-events: none;
|
||||
z-index: 15;
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
.month-name-label > span {
|
||||
display: inline-block;
|
||||
white-space: nowrap;
|
||||
writing-mode: vertical-rl;
|
||||
text-orientation: mixed;
|
||||
transform: rotate(180deg);
|
||||
transform-origin: center;
|
||||
}
|
||||
|
||||
.month-name-label.no-rotate > span {
|
||||
transform: none;
|
||||
}
|
||||
|
||||
.row-height-probe {
|
||||
position: absolute;
|
||||
visibility: hidden;
|
||||
|
@ -33,6 +33,16 @@ const handleDayTouchStart = (dateStr) => {
|
||||
const handleEventClick = (payload) => {
|
||||
emit('event-click', payload)
|
||||
}
|
||||
|
||||
// Only apply upside-down rotation (bottomup) for Latin script month labels
|
||||
function shouldRotateMonth(label) {
|
||||
if (!label) return false
|
||||
try {
|
||||
return /\p{Script=Latin}/u.test(label)
|
||||
} catch (e) {
|
||||
return /[A-Za-z\u00C0-\u024F\u1E00-\u1EFF]/u.test(label)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@ -51,13 +61,24 @@ const handleEventClick = (payload) => {
|
||||
/>
|
||||
<EventOverlay :week="props.week" @event-click="handleEventClick" />
|
||||
</div>
|
||||
<!-- Month name label (only on first week containing the 1st of the month) -->
|
||||
<div
|
||||
v-if="props.week.monthLabel"
|
||||
class="month-label"
|
||||
:class="props.week.monthLabel.monthClass"
|
||||
:style="{ height: `calc(var(--row-h) * ${props.week.monthLabel.weeksSpan})` }"
|
||||
>
|
||||
<span :class="{ bottomup: shouldRotateMonth(props.week.monthLabel.text) }">{{
|
||||
props.week.monthLabel.text
|
||||
}}</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.week-row {
|
||||
display: grid;
|
||||
grid-template-columns: var(--week-w) repeat(7, 1fr) 3rem;
|
||||
grid-template-columns: var(--week-w) repeat(7, 1fr) var(--month-w);
|
||||
position: absolute;
|
||||
height: var(--row-h);
|
||||
width: 100%;
|
||||
@ -70,15 +91,8 @@ const handleEventClick = (payload) => {
|
||||
color: var(--muted);
|
||||
font-size: 1.2em;
|
||||
font-weight: 500;
|
||||
/* Prevent text selection */
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
-webkit-touch-callout: none;
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
}
|
||||
|
||||
.days-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(7, 1fr);
|
||||
@ -86,10 +100,32 @@ const handleEventClick = (payload) => {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/* Fixed heights for cells and labels (from cells.css) */
|
||||
.week-row :deep(.cell),
|
||||
.week-label {
|
||||
height: var(--row-h);
|
||||
}
|
||||
.month-label {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
width: var(--month-w);
|
||||
background-image: linear-gradient(to bottom, rgba(186, 186, 186, 0.3), rgba(186, 186, 186, 0.2));
|
||||
font-size: 2em;
|
||||
font-weight: 700;
|
||||
color: var(--muted);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
z-index: 15;
|
||||
overflow: hidden;
|
||||
}
|
||||
.month-label > span {
|
||||
display: inline-block;
|
||||
white-space: nowrap;
|
||||
writing-mode: vertical-rl;
|
||||
text-orientation: mixed;
|
||||
transform-origin: center;
|
||||
}
|
||||
.bottomup {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
</style>
|
||||
|
@ -183,20 +183,12 @@ defineExpose({
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
width: 3rem; /* Use fixed width since minmax() doesn't work for absolute positioning */
|
||||
width: var(--month-w);
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
scrollbar-width: none;
|
||||
z-index: 20;
|
||||
cursor: ns-resize;
|
||||
background: rgba(0, 0, 0, 0.05); /* Temporary background to see the area */
|
||||
/* Prevent text selection */
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
-webkit-touch-callout: none;
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
}
|
||||
|
||||
.jogwheel-viewport::-webkit-scrollbar {
|
||||
|
Loading…
x
Reference in New Issue
Block a user