Styling changes, avoid glitches even on very small screens.

This commit is contained in:
Leo Vasanko
2025-09-25 07:19:40 -06:00
parent d461a42ae5
commit 0859e77b6a
9 changed files with 46 additions and 64 deletions

View File

@@ -7,7 +7,9 @@
* { * {
box-sizing: border-box; box-sizing: border-box;
} }
html {
font-size: min(3vmin, 16px);
}
html, html,
body { body {
height: 100%; height: 100%;
@@ -16,7 +18,7 @@ body {
body { body {
margin: 0; margin: 0;
font: font:
500 14px/1.2 ui-sans-serif, 500 1rem/1.2 ui-sans-serif,
system-ui, system-ui,
-apple-system, -apple-system,
Segoe UI, Segoe UI,

View File

@@ -206,7 +206,7 @@ onUnmounted(() => {
</div> </div>
</template> </template>
<style scoped> <style>
.ec-modal { .ec-modal {
position: fixed; /* still fixed for overlay & dragging, but now top/left are set dynamically */ position: fixed; /* still fixed for overlay & dragging, but now top/left are set dynamically */
background: color-mix(in srgb, var(--panel) 85%, transparent); background: color-mix(in srgb, var(--panel) 85%, transparent);

View File

@@ -9,14 +9,12 @@ const props = defineProps({
// Reactive viewport width detection // Reactive viewport width detection
const isNarrowView = ref(false) const isNarrowView = ref(false)
const isVeryNarrowView = ref(false)
const isSmallView = ref(false) const isSmallView = ref(false)
function checkViewportWidth() { function checkViewportWidth() {
const width = window.innerWidth const width = window.innerWidth
isSmallView.value = width < 800 isSmallView.value = width < 800
isNarrowView.value = width < 600 isNarrowView.value = width < 600
isVeryNarrowView.value = width < 400
} }
onMounted(() => { onMounted(() => {
@@ -30,27 +28,12 @@ onBeforeUnmount(() => {
const formattedDate = computed(() => { const formattedDate = computed(() => {
const date = fromLocalString(props.day.date) const date = fromLocalString(props.day.date)
let options = { weekday: 'short', day: 'numeric', month: 'short' }
let options = { day: 'numeric', month: 'short' } // Remove weekday on very small viewports
if (isNarrowView.value) options = { day: 'numeric', month: 'short' }
if (isVeryNarrowView.value) {
// Very narrow: show only day number
options = { day: 'numeric' }
} else if (isNarrowView.value) {
// Narrow: show day and month, no weekday
options = { day: 'numeric', month: 'short' }
} else {
// Wide: show weekday, day, and month
options = { weekday: 'short', day: 'numeric', month: 'short' }
}
let formatted = date.toLocaleDateString(undefined, options) let formatted = date.toLocaleDateString(undefined, options)
// Split between weekday and day/month on small viewports
// Below 700px, replace first space with newline to force weekday on separate line if (isSmallView.value) formatted = formatted.replace(/\s/, '\n')
if (isSmallView.value && !isNarrowView.value && !isVeryNarrowView.value) {
formatted = formatted.replace(/\s/, '\n')
}
// Replace the last space (between month and day) with nbsp to prevent breaking there // Replace the last space (between month and day) with nbsp to prevent breaking there
// but keep the space after weekday (if present) as regular space to allow wrapping // but keep the space after weekday (if present) as regular space to allow wrapping
formatted = formatted.replace(/\s+(?=\S+$)/, '\u00A0') formatted = formatted.replace(/\s+(?=\S+$)/, '\u00A0')
@@ -167,10 +150,9 @@ const formattedDate = computed(() => {
.lunar-phase { .lunar-phase {
grid-area: lunar-phase; grid-area: lunar-phase;
position: absolute; position: absolute;
inset-block-start: 0.5em; inset-block-start: 0.1em;
inset-inline-end: 0.2em; inset-inline-end: 0.1em;
font-size: 0.8em; font-size: 0.8rem;
opacity: 0.7;
} }
.compact-date { .compact-date {
@@ -178,7 +160,8 @@ const formattedDate = computed(() => {
top: 0.25em; top: 0.25em;
left: 0.25em; left: 0.25em;
inset-inline-end: 1rem; /* Space for lunar phase */ inset-inline-end: 1rem; /* Space for lunar phase */
font-weight: 400; font-weight: 300;
font-size: 0.8rem;
color: var(--ink); color: var(--ink);
line-height: 1; line-height: 1;
pointer-events: none; pointer-events: none;
@@ -204,7 +187,7 @@ const formattedDate = computed(() => {
overflow: hidden; overflow: hidden;
max-width: 100%; max-width: 100%;
color: var(--holiday); color: var(--holiday);
font-size: 1em; font-size: 0.8em;
font-weight: 400; font-weight: 400;
line-height: 1.0; line-height: 1.0;
padding-inline: 0.15em; padding-inline: 0.15em;

View File

@@ -119,7 +119,7 @@ const weekdayNames = computed(() => {
.calendar-header { .calendar-header {
display: grid; display: grid;
grid-template-columns: var(--week-w) repeat(7, 1fr) var(--month-w); grid-template-columns: var(--week-w) repeat(7, 1fr) var(--month-w);
border-bottom: 2px solid var(--muted); border-bottom: .1rem solid var(--muted);
align-items: last baseline; align-items: last baseline;
flex-shrink: 0; flex-shrink: 0;
width: 100%; width: 100%;

View File

@@ -6,7 +6,6 @@ import WeekdaySelector from './WeekdaySelector.vue'
import Numeric from './Numeric.vue' import Numeric from './Numeric.vue'
import { import {
addDaysStr, addDaysStr,
getMondayOfISOWeek,
fromLocalString, fromLocalString,
formatDateShort, formatDateShort,
formatDateLong, formatDateLong,
@@ -683,7 +682,7 @@ const recurrenceSummary = computed(() => {
.ec-field input[type='time'], .ec-field input[type='time'],
.ec-field input[type='number'], .ec-field input[type='number'],
.ec-field select { .ec-field select {
border: 1px solid var(--muted); border: .1rem solid var(--muted);
border-radius: 0.4rem; border-radius: 0.4rem;
padding: 0.5rem 0.6rem; padding: 0.5rem 0.6rem;
width: 100%; width: 100%;
@@ -853,7 +852,7 @@ const recurrenceSummary = computed(() => {
.freq-select { .freq-select {
padding: 0.4rem 0.55rem; padding: 0.4rem 0.55rem;
font-size: 0.75rem; font-size: 0.75rem;
border: 1px solid var(--input-border); border: .1rem solid var(--input-border);
background: var(--panel-alt); background: var(--panel-alt);
color: var(--ink); color: var(--ink);
border-radius: 0.45rem; border-radius: 0.45rem;
@@ -867,15 +866,15 @@ const recurrenceSummary = computed(() => {
background: var(--panel-accent); background: var(--panel-accent);
color: var(--ink); color: var(--ink);
box-shadow: box-shadow:
0 0 0 1px var(--input-focus), 0 0 0 .1rem var(--input-focus),
0 0 0 4px rgba(37, 99, 235, 0.15); 0 0 0 .4rem rgba(37, 99, 235, 0.15);
} }
.interval-input, .interval-input,
.occ-input { .occ-input {
display: none; display: none;
} }
.ec-field input[type='text'] { .ec-field input[type='text'] {
border: 1px solid var(--input-border); border: .1rem solid var(--input-border);
background: var(--panel-alt); background: var(--panel-alt);
border-radius: 0.45rem; border-radius: 0.45rem;
padding: 0.4rem 0.5rem; padding: 0.4rem 0.5rem;
@@ -889,8 +888,8 @@ const recurrenceSummary = computed(() => {
border-color: var(--input-focus); border-color: var(--input-focus);
background: var(--panel-accent); background: var(--panel-accent);
box-shadow: box-shadow:
0 0 0 1px var(--input-focus), 0 0 0 .1rem var(--input-focus),
0 0 0 4px rgba(37, 99, 235, 0.15); 0 0 0 .4rem rgba(37, 99, 235, 0.15);
} }
.hint { .hint {
font-size: 0.65rem; font-size: 0.65rem;
@@ -908,7 +907,7 @@ const recurrenceSummary = computed(() => {
align-items: center; align-items: center;
width: 100%; width: 100%;
padding: 0.6rem 0.8rem; padding: 0.6rem 0.8rem;
border: 1px solid var(--muted); border: .1rem solid var(--muted);
background: var(--panel); background: var(--panel);
border-radius: 0.4rem; border-radius: 0.4rem;
cursor: pointer; cursor: pointer;
@@ -931,7 +930,7 @@ const recurrenceSummary = computed(() => {
display: grid; display: grid;
gap: 0.6rem; gap: 0.6rem;
padding: 0.6rem; padding: 0.6rem;
border: 1px solid var(--muted); border: .1rem solid var(--muted);
border-radius: 0.4rem; border-radius: 0.4rem;
background: color-mix(in srgb, var(--muted) 20%, transparent); background: color-mix(in srgb, var(--muted) 20%, transparent);
} }
@@ -945,7 +944,7 @@ const recurrenceSummary = computed(() => {
.ec-repeat-modes .mode-btn { .ec-repeat-modes .mode-btn {
flex: 1 1 auto; flex: 1 1 auto;
padding: 0.4rem 0.6rem; padding: 0.4rem 0.6rem;
border: 1px solid var(--muted); border: .1rem solid var(--muted);
background: var(--panel); background: var(--panel);
border-radius: 0.4rem; border-radius: 0.4rem;
cursor: pointer; cursor: pointer;

View File

@@ -321,7 +321,6 @@ function startLocalDrag(init, evt) {
let originalWeekday = null let originalWeekday = null
let originalPattern = null let originalPattern = null
if (init.mode === 'move') { if (init.mode === 'move') {
try {
originalWeekday = new Date(init.startDate + 'T00:00:00').getDay() originalWeekday = new Date(init.startDate + 'T00:00:00').getDay()
const baseEv = store.getEventById(init.id) const baseEv = store.getEventById(init.id)
if ( if (
@@ -332,7 +331,6 @@ function startLocalDrag(init, evt) {
) { ) {
originalPattern = [...baseEv.recur.weekdays] originalPattern = [...baseEv.recur.weekdays]
} }
} catch {}
} }
dragState.value = { dragState.value = {
@@ -565,7 +563,7 @@ function applyRangeDuringDrag(st, startDate, endDate) {
inset: 0; inset: 0;
display: grid; display: grid;
grid-template-columns: repeat(7, 1fr); grid-template-columns: repeat(7, 1fr);
margin-top: 1.8em; margin-top: 1.0rem;
pointer-events: none; pointer-events: none;
} }
.segment-grid { .segment-grid {

View File

@@ -272,13 +272,13 @@ onBeforeUnmount(() => {
.header-controls-leave-to { .header-controls-leave-to {
opacity: 0; opacity: 0;
max-height: 0; max-height: 0;
transform: translateY(-20px); transform: translateY(-1rem);
} }
.header-controls-enter-to, .header-controls-enter-to,
.header-controls-leave-from { .header-controls-leave-from {
opacity: 1; opacity: 1;
max-height: 100px; max-height: 4rem;
transform: translateY(0); transform: translateY(0);
} }

View File

@@ -487,7 +487,7 @@ function parseGoToDateCandidate(input, refStr) {
padding: 0.32rem 0.5rem; padding: 0.32rem 0.5rem;
padding-inline-start: 2.05rem; /* increased space for icon */ padding-inline-start: 2.05rem; /* increased space for icon */
border-radius: 0.45rem; border-radius: 0.45rem;
border: 1px solid color-mix(in srgb, var(--muted) 35%, transparent); border: .1rem solid color-mix(in srgb, var(--muted) 35%, transparent);
background: color-mix(in srgb, var(--panel) 88%, transparent); background: color-mix(in srgb, var(--panel) 88%, transparent);
font: inherit; font: inherit;
line-height: 1.1; line-height: 1.1;
@@ -532,7 +532,7 @@ function parseGoToDateCandidate(input, refStr) {
background: color-mix(in srgb, var(--panel) 85%, transparent); background: color-mix(in srgb, var(--panel) 85%, transparent);
padding: 0.15rem 0.3rem; padding: 0.15rem 0.3rem;
border-radius: 0.25rem; border-radius: 0.25rem;
border: 1px solid color-mix(in srgb, var(--muted) 25%, transparent); border: .1rem solid color-mix(in srgb, var(--muted) 25%, transparent);
} }
.search-bar input:focus + .shortcut-hint, .search-bar input:focus + .shortcut-hint,
@@ -551,7 +551,7 @@ function parseGoToDateCandidate(input, refStr) {
background: color-mix(in srgb, var(--panel) 92%, transparent); background: color-mix(in srgb, var(--panel) 92%, transparent);
backdrop-filter: blur(0.6em); backdrop-filter: blur(0.6em);
-webkit-backdrop-filter: blur(0.6em); -webkit-backdrop-filter: blur(0.6em);
border: 1px solid color-mix(in srgb, var(--muted) 35%, transparent); border: .1rem solid color-mix(in srgb, var(--muted) 35%, transparent);
border-radius: 0.55rem; border-radius: 0.55rem;
max-height: 16rem; max-height: 16rem;
overflow: auto; overflow: auto;
@@ -593,7 +593,7 @@ function parseGoToDateCandidate(input, refStr) {
background: color-mix(in srgb, var(--panel) 92%, transparent); background: color-mix(in srgb, var(--panel) 92%, transparent);
backdrop-filter: blur(0.6em); backdrop-filter: blur(0.6em);
-webkit-backdrop-filter: blur(0.6em); -webkit-backdrop-filter: blur(0.6em);
border: 1px solid color-mix(in srgb, var(--muted) 35%, transparent); border: .1rem solid color-mix(in srgb, var(--muted) 35%, transparent);
border-radius: 0.55rem; border-radius: 0.55rem;
box-shadow: 0 0.5em 1.25em rgba(0, 0, 0, 0.3); box-shadow: 0 0.5em 1.25em rgba(0, 0, 0, 0.3);
font-size: 0.7rem; font-size: 0.7rem;

View File

@@ -253,7 +253,7 @@ defineExpose({ open })
border-inline-start: 2px solid var(--border-color); border-inline-start: 2px solid var(--border-color);
} }
select { select {
border: 1px solid var(--muted); border: .1rem solid var(--muted);
background: var(--panel-alt, transparent); background: var(--panel-alt, transparent);
color: var(--ink); color: var(--ink);
padding: 0.4rem 0.5rem; padding: 0.4rem 0.5rem;
@@ -291,7 +291,7 @@ select {
gap: 0.5rem; gap: 0.5rem;
} }
.ec-btn { .ec-btn {
border: 1px solid var(--muted); border: .1rem solid var(--muted);
background: transparent; background: transparent;
color: var(--ink); color: var(--ink);
padding: 0.5rem 0.8rem; padding: 0.5rem 0.8rem;