Enhance duty timeline rendering and styling
All checks were successful
CI / lint-and-test (push) Successful in 15s
All checks were successful
CI / lint-and-test (push) Successful in 15s
- Updated the HTML structure for duty timeline rows to include a date cell with a visual track, improving the layout and user experience. - Modified CSS to define new variables for timeline date and track widths, enhancing flexibility in styling. - Improved the styling of duty timeline elements, including today’s duties, to provide clearer visual cues and better alignment. - Ensured consistent display of date labels and added visual enhancements for better accessibility and readability.
This commit is contained in:
@@ -520,17 +520,20 @@
|
||||
dates.forEach(function (date) {
|
||||
const isToday = date === todayKey;
|
||||
const dayClass = "duty-timeline-day" + (isToday ? " duty-timeline-day--today" : "");
|
||||
const dateLabel = isToday ? "Сегодня, " + dateKeyToDDMM(date) : dateKeyToDDMM(date);
|
||||
const dateLabel = isToday ? dateKeyToDDMM(date) : dateKeyToDDMM(date);
|
||||
const dateCellHtml = isToday
|
||||
? "<span class=\"duty-timeline-date\"><span class=\"duty-timeline-date-label\">Сегодня</span><span class=\"duty-timeline-date-dot\" aria-hidden=\"true\"></span><span class=\"duty-timeline-date-day\">" + escapeHtml(dateLabel) + "</span></span>"
|
||||
: "<span class=\"duty-timeline-date\">" + escapeHtml(dateLabel) + "</span>";
|
||||
const dayDuties = duties.filter(function (d) { return localDateString(new Date(d.start_at)) === date; }).sort(function (a, b) { return new Date(a.start_at) - new Date(b.start_at); });
|
||||
let dayHtml = "";
|
||||
dayDuties.forEach(function (d) {
|
||||
const start = new Date(d.start_at);
|
||||
const end = new Date(d.end_at);
|
||||
const isCurrent = isToday && start <= now && now < end;
|
||||
dayHtml += "<div class=\"duty-timeline-row\"><span class=\"duty-timeline-date\">" + escapeHtml(dateLabel) + "</span><div class=\"duty-timeline-card-wrap\">" + dutyTimelineCardHtml(d, isCurrent) + "</div></div>";
|
||||
dayHtml += "<div class=\"duty-timeline-row\">" + dateCellHtml + "<span class=\"duty-timeline-track\" aria-hidden=\"true\"></span><div class=\"duty-timeline-card-wrap\">" + dutyTimelineCardHtml(d, isCurrent) + "</div></div>";
|
||||
});
|
||||
if (dayDuties.length === 0 && isToday) {
|
||||
dayHtml += "<div class=\"duty-timeline-row duty-timeline-row--empty\"><span class=\"duty-timeline-date\">" + escapeHtml(dateLabel) + "</span><div class=\"duty-timeline-card-wrap\"></div></div>";
|
||||
dayHtml += "<div class=\"duty-timeline-row duty-timeline-row--empty\">" + dateCellHtml + "<span class=\"duty-timeline-track\" aria-hidden=\"true\"></span><div class=\"duty-timeline-card-wrap\"></div></div>";
|
||||
}
|
||||
fullHtml += "<div class=\"" + dayClass + "\" data-date=\"" + escapeHtml(date) + "\">" + dayHtml + "</div>";
|
||||
});
|
||||
|
||||
119
webapp/style.css
119
webapp/style.css
@@ -9,6 +9,8 @@
|
||||
--unavailable: #e0af68;
|
||||
--vacation: #7dcfff;
|
||||
--error: #f7768e;
|
||||
--timeline-date-width: 3.6em;
|
||||
--timeline-track-width: 10px;
|
||||
}
|
||||
|
||||
/* Light theme: prefer Telegram themeParams (--tg-theme-*), fallback to Telegram-like palette */
|
||||
@@ -285,11 +287,20 @@ body {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
/* Timeline: dates left, cards right */
|
||||
/* Timeline: dates | track (line + dot) | cards */
|
||||
.duty-list.duty-timeline {
|
||||
border-left: 2px solid var(--muted);
|
||||
padding-left: 0;
|
||||
margin-left: 2px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.duty-list.duty-timeline::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
left: calc(var(--timeline-date-width) + var(--timeline-track-width) / 2 - 1px);
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
width: 2px;
|
||||
background: var(--muted);
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.duty-timeline-day {
|
||||
@@ -302,25 +313,121 @@ body {
|
||||
|
||||
.duty-timeline-row {
|
||||
display: grid;
|
||||
grid-template-columns: 4.2em 1fr;
|
||||
gap: 0 10px;
|
||||
grid-template-columns: var(--timeline-date-width) var(--timeline-track-width) 1fr;
|
||||
gap: 0 4px;
|
||||
align-items: start;
|
||||
margin-bottom: 8px;
|
||||
min-height: 1px;
|
||||
}
|
||||
|
||||
.duty-timeline-date {
|
||||
position: relative;
|
||||
font-size: 0.8rem;
|
||||
color: var(--muted);
|
||||
padding-top: 10px;
|
||||
padding-bottom: 10px;
|
||||
flex-shrink: 0;
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
.duty-timeline-date::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
left: 0;
|
||||
bottom: 4px;
|
||||
width: calc(100% + var(--timeline-track-width) / 2);
|
||||
height: 2px;
|
||||
background: linear-gradient(
|
||||
to right,
|
||||
color-mix(in srgb, var(--muted) 40%, transparent) 0%,
|
||||
color-mix(in srgb, var(--muted) 40%, transparent) 50%,
|
||||
var(--muted) 70%,
|
||||
var(--muted) 100%
|
||||
);
|
||||
}
|
||||
|
||||
.duty-timeline-date::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
left: calc(100% + (var(--timeline-track-width) / 2) - 1px);
|
||||
bottom: 2px;
|
||||
width: 2px;
|
||||
height: 6px;
|
||||
background: var(--muted);
|
||||
}
|
||||
|
||||
.duty-timeline-day--today .duty-timeline-date {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
padding-top: 4px;
|
||||
color: var(--today);
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.duty-timeline-day--today .duty-timeline-date::before,
|
||||
.duty-timeline-day--today .duty-timeline-date::after {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.duty-timeline-date-label,
|
||||
.duty-timeline-date-day {
|
||||
display: block;
|
||||
line-height: 1.25;
|
||||
}
|
||||
|
||||
.duty-timeline-date-day {
|
||||
align-self: flex-start;
|
||||
text-align: left;
|
||||
padding-left: 0;
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
.duty-timeline-date-dot {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 8px;
|
||||
min-height: 8px;
|
||||
position: relative;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.duty-timeline-date-dot::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 50%;
|
||||
margin-top: -1px;
|
||||
width: calc(100% + var(--timeline-track-width) / 2);
|
||||
height: 1px;
|
||||
background: color-mix(in srgb, var(--today) 45%, transparent);
|
||||
}
|
||||
|
||||
.duty-timeline-date-dot::after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
left: calc(100% + (var(--timeline-track-width) / 2) - 1px);
|
||||
top: 50%;
|
||||
margin-top: -3px;
|
||||
width: 2px;
|
||||
height: 6px;
|
||||
background: var(--today);
|
||||
}
|
||||
|
||||
.duty-timeline-day--today .duty-timeline-date .duty-timeline-date-label {
|
||||
color: var(--today);
|
||||
}
|
||||
|
||||
.duty-timeline-day--today .duty-timeline-date .duty-timeline-date-day {
|
||||
color: var(--muted);
|
||||
font-weight: 400;
|
||||
font-size: 0.75rem;
|
||||
}
|
||||
|
||||
.duty-timeline-track {
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.duty-timeline-card-wrap {
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user