Преглед изворни кода

Fix: task table header alignment + status dropdown visibility + per-input tint

- Sortable headers (Task / Owner / Prio / Tot) get whitespace-nowrap so the
  label and the ↕ sort indicator never wrap to two lines.
- Assignment cells get whitespace-nowrap so the day input and the status
  <select> always sit on the same line.
- .assign-status-select bumped from 1rem (16px) to 22×22px with a real
  bordered button affordance and text-indent: -9999px to hide the
  selected option text — was previously near-invisible behind
  font-size:0 + transparent border. Dark-mode variant added.
- .assign-status-* tint moved off the <td> onto the inner
  input[data-assign] / read-only span. Cell padding no longer paints a
  stripe of status colour; only the field background reflects state.
- buildTaskRow in sprint-planner.js mirrors the new whitespace-nowrap on
  JS-built assignment cells (admin "+ Add task" path).

Tests untouched (pure CSS / Twig / vanilla JS), still 108 / 281.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
chiappa пре 3 дана
родитељ
комит
f204611
3 измењених фајлова са 45 додато и 34 уклоњено
  1. 39 28
      assets/css/input.css
  2. 1 1
      public/assets/js/sprint-planner.js
  3. 5 5
      views/sprints/_task_list.twig

+ 39 - 28
assets/css/input.css

@@ -56,45 +56,56 @@
         padding: 0.5rem 0.25rem;
     }
 
-    /* Phase 18: per-cell task-assignment status. The colour class
-       applies directly to the <td> — no nested wrapper — so the cell's
-       table-layout and the input it contains render exactly as they
-       did before the feature, with only the cell background tinting.
-       The four .assign-status-* class names are interpolated server-
-       side ("assign-status-<?= $st ?>"), so they're held in
+    /* Phase 18: per-cell task-assignment status. The colour class lives
+       on the <td> (so JS / filters can read data-status off the cell),
+       but the visible tint is applied to the day input / read-only span
+       inside — colouring just the <td> made the cell padding stripe a
+       different colour from the field, which read as visual noise. The
+       four .assign-status-* class names are interpolated server-side
+       ("assign-status-<?= $st ?>"), so they're held in
        tailwind.config.js's safelist; otherwise the JIT prunes them. */
-    .assign-status-zugewiesen { /* default: no override, stays whatever
-                                   the row's bg is */ }
-    .assign-status-gestartet     { background-color: theme('colors.yellow.200'); }
-    .assign-status-abgeschlossen { background-color: theme('colors.green.200'); }
-    .assign-status-abgebrochen   { background-color: theme('colors.red.200'); }
-    .dark .assign-status-gestartet     { background-color: theme('colors.yellow.700'); }
-    .dark .assign-status-abgeschlossen { background-color: theme('colors.green.700'); }
-    .dark .assign-status-abgebrochen   { background-color: theme('colors.red.700'); }
+    .assign-status-zugewiesen { /* default: no tint */ }
+    .assign-status-gestartet     input[data-assign],
+    .assign-status-gestartet     > span.font-mono   { background-color: theme('colors.yellow.200'); }
+    .assign-status-abgeschlossen input[data-assign],
+    .assign-status-abgeschlossen > span.font-mono   { background-color: theme('colors.green.200'); }
+    .assign-status-abgebrochen   input[data-assign],
+    .assign-status-abgebrochen   > span.font-mono   { background-color: theme('colors.red.200'); }
+    .dark .assign-status-gestartet     input[data-assign],
+    .dark .assign-status-gestartet     > span.font-mono { background-color: theme('colors.yellow.700'); }
+    .dark .assign-status-abgeschlossen input[data-assign],
+    .dark .assign-status-abgeschlossen > span.font-mono { background-color: theme('colors.green.700'); }
+    .dark .assign-status-abgebrochen   input[data-assign],
+    .dark .assign-status-abgebrochen   > span.font-mono { background-color: theme('colors.red.700'); }
 
-    /* Tiny chevron-only <select> sitting next to the day input. We hide
-       the selected text via font-size:0 + color:transparent so only the
-       browser's native dropdown arrow shows; clicking it opens the
-       option list with its full-size text restored. */
+    /* Compact chevron-only <select> sitting inline next to the day
+       input. ≥ 18px wide with a clear bordered button affordance so
+       it's obvious users can click it; selected option text is hidden
+       with text-indent so only the native dropdown arrow shows. */
     .assign-status-select {
-        width: 1rem;
-        min-width: 0;
-        margin-left: 2px;
+        display: inline-block;
+        vertical-align: middle;
+        width: 22px;
+        min-width: 22px;
+        height: 22px;
+        margin-left: 4px;
         padding: 0;
-        border: 0;
-        background-color: transparent;
-        font-size: 0;
-        line-height: 1;
-        color: transparent;
+        text-indent: -9999px;
+        border: 1px solid theme('colors.slate.300');
+        border-radius: 3px;
+        background-color: theme('colors.white');
         cursor: pointer;
-        vertical-align: middle;
+    }
+    .dark .assign-status-select {
+        border-color: theme('colors.slate.600');
+        background-color: theme('colors.slate.700');
     }
     .assign-status-select:focus {
         outline: 2px solid theme('colors.slate.400');
         outline-offset: 1px;
-        border-radius: 2px;
     }
     .assign-status-select option {
+        text-indent: 0;
         font-size: 0.875rem;
         color: theme('colors.slate.900');
         background-color: theme('colors.white');

+ 1 - 1
public/assets/js/sprint-planner.js

@@ -428,7 +428,7 @@
         sprintWorkerHeaders().forEach(function (sw) {
             const v = Number(assignments[sw.id] || 0);
             const td = document.createElement('td');
-            td.className = 'px-1 py-1 text-center';
+            td.className = 'px-1 py-1 text-center whitespace-nowrap';
             td.setAttribute('data-col', 'sw-' + sw.id);
             td.setAttribute('data-sort-value-sw-' + sw.id, v.toFixed(2));
 

+ 5 - 5
views/sprints/_task_list.twig

@@ -143,13 +143,13 @@
             <thead class="bg-slate-50 text-slate-600 text-xs uppercase tracking-wider dark:bg-slate-700 dark:text-slate-300">
                 <tr>
                     <th class="w-6 px-2 py-2"></th>
-                    <th class="text-left px-2 py-2 font-semibold cursor-pointer select-none"
+                    <th class="text-left px-2 py-2 font-semibold cursor-pointer select-none whitespace-nowrap"
                         data-sort-col="title">Task <span class="sort-ind opacity-30">↕</span></th>
-                    <th class="text-left px-2 py-2 font-semibold cursor-pointer select-none"
+                    <th class="text-left px-2 py-2 font-semibold cursor-pointer select-none whitespace-nowrap"
                         data-sort-col="owner" data-col="owner">Owner <span class="sort-ind opacity-30">↕</span></th>
-                    <th class="text-center px-2 py-2 font-semibold cursor-pointer select-none"
+                    <th class="text-center px-2 py-2 font-semibold cursor-pointer select-none whitespace-nowrap"
                         data-sort-col="prio" data-col="prio">Prio <span class="sort-ind opacity-30">↕</span></th>
-                    <th class="text-center px-2 py-2 font-semibold cursor-pointer select-none"
+                    <th class="text-center px-2 py-2 font-semibold cursor-pointer select-none whitespace-nowrap"
                         data-sort-col="tot" data-col="tot">Tot <span class="sort-ind opacity-30">↕</span></th>
                     {% for sw in sprintWorkers %}
                         <th class="text-center px-2 py-2 font-semibold cursor-pointer select-none whitespace-nowrap"
@@ -232,7 +232,7 @@
                                 {% set d = assign[sw.id]|default(0.0) %}
                                 {% set st = statusGrid[t.id][sw.id]|default(STATUS_ZUGEWIESEN) %}
                                 {% set tdExtraClass = taskStatusEnabled ? ' assign-status-' ~ st : '' %}
-                                <td class="px-1 py-1 text-center{{ tdExtraClass }}"
+                                <td class="px-1 py-1 text-center whitespace-nowrap{{ tdExtraClass }}"
                                     data-col="sw-{{ sw.id }}"
                                     {% if taskStatusEnabled %}data-assign-cell data-status="{{ st }}" data-sw-id="{{ sw.id }}"{% endif %}
                                     data-sort-value-sw-{{ sw.id }}="{{ d|number_format(2, '.', '') }}">