From 0754d986e9afda3824b32e30e819f17e8496b13f Mon Sep 17 00:00:00 2001 From: claude Date: Sat, 13 Jun 2026 11:47:00 +0000 Subject: [PATCH] build 220: XS compact view reuses classic table cells for full detail MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace the CSS-only compact card hack with a dedicated ProjectCardCompact component that reuses FormatCell, OwnerCell, LastUpdatedCell (with tooltip + updated-by), ActionsCell (full set), and InlineTags — identical data to the classic table view. CSS Grid aligns columns across rows: checkbox | name+tags | format | owner | date | actions. Actions fade in on row hover. Co-Authored-By: Claude Sonnet 4.6 --- .../components/project-list-lumiere.tsx | 53 +++++- .../pages/project-list-lumiere.scss | 165 ++++++++++-------- 2 files changed, 145 insertions(+), 73 deletions(-) diff --git a/services/web/frontend/js/features/project-list/components/project-list-lumiere.tsx b/services/web/frontend/js/features/project-list/components/project-list-lumiere.tsx index 94bdfa7274..3f77935149 100644 --- a/services/web/frontend/js/features/project-list/components/project-list-lumiere.tsx +++ b/services/web/frontend/js/features/project-list/components/project-list-lumiere.tsx @@ -27,6 +27,11 @@ import { DownloadProjectButtonTooltip } from './table/cells/action-buttons/downl import { CompileAndDownloadProjectPDFButtonTooltip } from './table/cells/action-buttons/compile-and-download-project-pdf-button' import { ArchiveProjectButtonTooltip } from './table/cells/action-buttons/archive-project-button' import { TrashProjectButtonTooltip } from './table/cells/action-buttons/trash-project-button' +import FormatCell from './table/cells/format-cell' +import OwnerCell from './table/cells/owner-cell' +import LastUpdatedCell from './table/cells/last-updated-cell' +import ActionsCell from './table/cells/actions-cell' +import InlineTags from './table/cells/inline-tags' // ── Tile zoom ───────────────────────────────────────────────────────────────── @@ -176,6 +181,44 @@ const ProjectCard = memo(function ProjectCard({ ) }) +// ── XS compact row (reuses classic table cell components for full detail) ───── + +const ProjectCardCompact = memo(function ProjectCardCompact({ + project, +}: { + project: Project +}) { + return ( +
+
+ +
+
+ + {project.name} + + +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ ) +}) + export function ProjectListLumiere() { const navbarProps = getMeta('ol-navbar') const footerProps = getMeta('ol-footer') @@ -309,9 +352,13 @@ export function ProjectListLumiere() { // eslint-disable-next-line @typescript-eslint/consistent-type-assertions style={cardScale === 0 ? {} : ({ '--lum-card-scale': cardScale } as React.CSSProperties)} > - {visibleProjects.map(project => ( - - ))} + {visibleProjects.map(project => + cardScale === 0 ? ( + + ) : ( + + ) + )} )} diff --git a/services/web/frontend/stylesheets/pages/project-list-lumiere.scss b/services/web/frontend/stylesheets/pages/project-list-lumiere.scss index 12502f1c24..763d33ca0d 100644 --- a/services/web/frontend/stylesheets/pages/project-list-lumiere.scss +++ b/services/web/frontend/stylesheets/pages/project-list-lumiere.scss @@ -732,87 +732,112 @@ $lum-noise: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' wi // ── XS compact list view ───────────────────────────────────────────────── // Activated via .lumiere-card-grid--compact (cardScale === 0). - // Cards become flat rows; thumbnail is hidden; only name, badge, owner, - // date, and action strip remain. + // Uses ProjectCardCompact which reuses the classic table cell components + // (FormatCell, OwnerCell, LastUpdatedCell, ActionsCell) laid out in a + // CSS Grid so every row aligns like a proper table. .lumiere-card-grid--compact { display: flex; flex-direction: column; - gap: 0.3rem; + gap: 0.25rem; margin-top: 0.5rem; + } - // Card row — horizontal instead of vertical - .lumiere-card { - flex-direction: row; + .lumiere-compact-row { + display: grid; + // checkbox | name+tags | format | owner | date | actions + grid-template-columns: 28px 1fr 70px 130px 160px auto; + align-items: center; + column-gap: 0.85rem; + padding: 0.45rem 0.75rem; + background: rgba(255, 255, 255, 0.82); + backdrop-filter: blur(8px); + -webkit-backdrop-filter: blur(8px); + border: 1px solid rgba(255, 255, 255, 0.6); + border-radius: 7px; + box-shadow: 0 1px 4px rgba(0, 0, 0, 0.06); + transition: background-color 0.15s ease, box-shadow 0.15s ease; + + &:hover { + background: rgba(255, 255, 255, 0.96); + box-shadow: 0 2px 10px rgba(0, 0, 0, 0.09); + } + } + + .lumiere-compact-checkbox { + display: flex; + align-items: center; + + input[type='checkbox'] { + width: 16px; + height: 16px; + cursor: pointer; + accent-color: $lum-teal; + } + } + + .lumiere-compact-name-cell { + display: flex; + align-items: center; + gap: 0.4rem; + overflow: hidden; + min-width: 0; + } + + .lumiere-compact-name { + font-size: 0.875rem; + font-weight: 600; + color: $lum-text; + text-decoration: none; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + + &:hover, + &:focus { + color: $lum-teal; + text-decoration: none; + } + } + + .lumiere-compact-owner { + font-size: 0.8rem; + color: $lum-text-sub; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + } + + .lumiere-compact-date { + font-size: 0.8rem; + color: $lum-text-muted; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + } + + .lumiere-compact-actions { + display: flex; + align-items: center; + gap: 1px; + + .action-btn { + color: $lum-text-muted !important; + border-radius: 6px !important; + opacity: 0; + transition: opacity 0.12s ease, color 0.12s ease, background-color 0.12s ease; &:hover, - &:focus-within { - transform: none; - box-shadow: 0 2px 10px rgba(0, 0, 0, 0.09); + &:focus { + color: $lum-teal !important; + background: rgba($lum-teal, 0.09) !important; } } + } - // Checkbox: vertically centered in the row - .lumiere-card-checkbox { - top: 50%; - transform: translateY(-50%); - } - - // Link area fills the row, items laid out horizontally - .lumiere-card-link { - flex-direction: row; - align-items: center; - padding: 0.45rem 0.75rem 0.45rem 2.2rem; - gap: 0.65rem; - } - - // Hide the preview thumbnail - .lumiere-card-thumb { - display: none; - } - - // Body becomes a horizontal strip - .lumiere-card-body { - flex-direction: row; - align-items: center; - gap: 0.65rem; - padding: 0; - flex: 1; - min-width: 0; - } - - // Name stretches to fill remaining space, single line - .lumiere-card-name { - flex: 1; - min-width: 0; - font-size: 0.85rem; - -webkit-line-clamp: 1; - } - - // More room for the owner label in list mode - .lumiere-card-owner { - max-width: 160px; - } - - // Date sits inline, no top margin - .lumiere-card-date { - margin-top: 0; - flex-shrink: 0; - } - - // Actions: vertical strip on the right, border-left instead of border-top - .lumiere-card-actions { - border-top: none; - border-left: 1px solid rgba($lum-teal, 0.10); - flex-direction: row; - align-self: stretch; - align-items: center; - padding: 0.25rem 0.4rem; - - .action-btn { - padding: 3px !important; - } - } + .lumiere-compact-row:hover .lumiere-compact-actions .action-btn, + .lumiere-compact-row:focus-within .lumiere-compact-actions .action-btn { + opacity: 1; } // ── Selection bar — tool buttons ──────────────────────────────────────────