Mobile-Support: Smartphones für die ganze Seite

- Dashboard-Bewerbungsliste auf Handy als gestapelte Karten statt horizontal gescrolltem 760px-Raster
- Modals auf Handy scrollbar (Inhalt wurde bisher unten abgeschnitten)
- Chat: Thread-Aktionen auf Touch sichtbar, Sidebar/Chat-Höhen für mobil
- Bewerbungs-Antwort-Toolbar & Admin-Stat-Boxen umbruchfähig

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2026-07-14 10:24:49 +02:00
co-authored by Claude
parent 295c447d58
commit 3c7f5d7c74
5 changed files with 77 additions and 16 deletions
+62 -7
View File
@@ -422,16 +422,71 @@ button.loading::after {
table {
min-width: 768px;
}
}
/* Adjust modal width on mobile */
.max-w-lg {
max-width: 90vw;
margin: 0 5vw;
/* ============================================
Smartphone support (< 640px)
The layout already collapses most grids via Tailwind's sm:/md: prefixes and
the header ships a burger menu. The rules below cover the few surfaces that
still assume desktop: tall modals, the 7-column dashboard grid, and a couple
of non-wrapping toolbars.
============================================ */
/* Modals: the overlay locks body scroll (overflow:hidden on <body>), so a panel
taller than the viewport would have its bottom cut off and unreachable. Cap
the panel to the viewport and let it scroll internally; align the wrapper to
the top so the close button stays in reach instead of being clipped. */
@media (max-width: 640px) {
.max-w-lg,
.max-w-md {
max-width: calc(100vw - 2rem) !important;
max-height: calc(100vh - 2rem) !important;
overflow-y: auto !important;
margin: 0 !important;
}
.fixed.inset-0 > .min-h-screen {
align-items: flex-start !important;
}
.max-w-md {
max-width: 90vw;
margin: 0 5vw;
/* Dashboard application list: the desktop layout is a 7-column grid forced to
760px and scrolled horizontally — usable on a phone only with two-thumb
scrolling. On a smartphone, restyle each row into a stacked card so the
primary content fits the viewport. The column header row is hidden; the
cells are re-placed via grid-template-areas (their DOM order is unrelated
to their visual position). */
.app-head {
display: none !important;
}
.app-line.app-grid {
grid-template-columns: 1.25rem 1fr auto !important;
grid-template-areas:
"chevron firma actions"
"chevron stelle actions"
"chevron datum actions"
"chevron art actions"
"chevron status actions" !important;
row-gap: 0.2rem !important;
column-gap: 0.625rem !important;
padding: 0.75rem 1rem !important;
align-items: start !important;
}
.app-line.app-grid > *:nth-child(1) { grid-area: chevron; align-self: center; }
.app-line.app-grid > *:nth-child(2) { grid-area: datum; }
.app-line.app-grid > *:nth-child(3) { grid-area: firma; }
.app-line.app-grid > *:nth-child(4) { grid-area: stelle; }
.app-line.app-grid > *:nth-child(5) { grid-area: art; }
.app-line.app-grid > *:nth-child(6) { grid-area: status; }
.app-line.app-grid > *:nth-child(7) { grid-area: actions; align-self: center; }
/* Let text wrap inside a card instead of truncating to the now-narrow column. */
.app-line.app-grid .truncate {
white-space: normal !important;
overflow: visible !important;
text-overflow: clip !important;
}
/* Enlarge the edit/delete hit targets for touch. */
.app-line.app-grid .app-actions a,
.app-line.app-grid .app-actions button {
padding: 0.5rem !important;
}
}
+1 -1
View File
@@ -28,7 +28,7 @@
</h2>
<p class="text-sm text-gray-500 dark:text-gray-400 mt-1">Konten anlegen, Passwörter zurücksetzen, ein Konto übernehmen oder Benutzer inkl. aller Daten löschen.</p>
</div>
<div class="flex gap-3">
<div class="flex flex-wrap gap-3">
<div class="rounded-xl border border-gray-200 bg-white px-4 py-2.5 text-center shadow-sm dark:border-white/5 dark:bg-gray-800">
<div class="text-xl font-bold leading-none"><%= users.length %></div>
<div class="text-[11px] uppercase tracking-wide text-gray-500 dark:text-gray-400 mt-1">Benutzer</div>
+2 -2
View File
@@ -500,9 +500,9 @@
<label class="block text-xs font-medium text-gray-500 dark:text-gray-400 mb-1">Betreff</label>
<input type="text" name="subject" value="<%= /^\s*(re|aw)\s*:/i.test(e.subject || '') ? (e.subject || '') : ('Re: ' + (e.subject || '')) %>"
class="reply-subject w-full px-3 py-2 mb-2 border border-gray-300 dark:border-gray-600 rounded-md bg-white dark:bg-gray-700 text-gray-800 dark:text-white text-sm">
<div class="flex items-center justify-between mb-1">
<div class="flex flex-wrap items-center justify-between gap-2 mb-1">
<label class="block text-xs font-medium text-gray-500 dark:text-gray-400">Nachricht</label>
<div class="flex items-center gap-2">
<div class="flex flex-wrap items-center gap-2">
<select class="ai-reply-typ text-xs px-1.5 py-0.5 border border-gray-300 dark:border-gray-600 rounded-md bg-white dark:bg-gray-700 text-gray-700 dark:text-gray-200">
<option value="antwort">Antwort</option>
<option value="absage">Absage (andere Stelle)</option>
+9 -3
View File
@@ -21,6 +21,12 @@
@media (prefers-reduced-motion: reduce) {
.typing-dot { animation: none; opacity: 0.6; }
}
/* Thread rename/delete rely on hover/focus to appear — neither exists on a
touchscreen, so the controls would be unreachable. Show them on small
(likely touch) screens. */
@media (max-width: 768px) {
.threadRename, .threadDelete { opacity: 1 !important; }
}
/* Markdown rendering inside assistant bubbles */
.chat-md { line-height: 1.5; }
.chat-md > *:first-child { margin-top: 0; }
@@ -52,9 +58,9 @@
</button>
</div>
<div class="grid grid-cols-1 md:grid-cols-[240px_1fr] gap-3 h-[calc(100vh-180px)] min-h-[360px]">
<div class="grid grid-cols-1 md:grid-cols-[240px_1fr] gap-3 min-h-[360px] md:h-[calc(100vh-180px)]">
<!-- Thread sidebar -->
<aside class="rounded-lg border border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-800 overflow-hidden flex flex-col">
<aside class="rounded-lg border border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-800 overflow-hidden flex flex-col max-h-48 md:max-h-none">
<div class="px-3 py-2 text-xs font-semibold uppercase tracking-wide text-gray-500 dark:text-gray-400 border-b border-gray-200 dark:border-gray-700">Verläufe</div>
<ul id="threadList" class="overflow-y-auto flex-1 divide-y divide-gray-100 dark:divide-gray-700">
<% threads.forEach(function(t) { %>
@@ -90,7 +96,7 @@
</aside>
<!-- Message area -->
<section class="rounded-lg border border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-800 flex flex-col overflow-hidden">
<section class="rounded-lg border border-gray-200 dark:border-gray-700 bg-white dark:bg-gray-800 flex flex-col overflow-hidden h-[60vh] md:h-auto">
<div id="chatLog" class="flex-1 overflow-y-auto p-4 space-y-3 text-gray-800 dark:text-gray-100">
<% if (!messages.length) { %>
<div class="h-full flex items-center justify-center text-gray-400 text-sm px-6">
+3 -3
View File
@@ -107,9 +107,9 @@
}
</style>
<div class="bg-white dark:bg-gray-800 rounded-lg shadow-md overflow-x-auto">
<div class="min-w-[760px]">
<!-- Column labels -->
<div class="app-grid px-6 py-3 bg-gray-50 dark:bg-gray-700 text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">
<div class="md:min-w-[760px]">
<!-- Column labels (desktop only — on phones the rows become stacked cards) -->
<div class="app-head app-grid px-6 py-3 bg-gray-50 dark:bg-gray-700 text-xs font-medium text-gray-500 dark:text-gray-300 uppercase tracking-wider">
<span></span>
<span>Datum</span>
<span>Firma</span>