build 220: XS compact view reuses classic table cells for full detail
Build and Deploy Verso / deploy (push) Successful in 20m14s
Build and Deploy Verso / deploy (push) Successful in 20m14s
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 <noreply@anthropic.com>
This commit is contained in:
@@ -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 (
|
||||
<div className="lumiere-compact-row">
|
||||
<div className="lumiere-compact-checkbox">
|
||||
<ProjectCheckbox projectId={project.id} projectName={project.name} />
|
||||
</div>
|
||||
<div className="lumiere-compact-name-cell">
|
||||
<a
|
||||
href={`/project/${project.id}`}
|
||||
className="lumiere-compact-name"
|
||||
translate="no"
|
||||
>
|
||||
{project.name}
|
||||
</a>
|
||||
<InlineTags projectId={project.id} />
|
||||
</div>
|
||||
<div className="lumiere-compact-format">
|
||||
<FormatCell project={project} />
|
||||
</div>
|
||||
<div className="lumiere-compact-owner" translate="no">
|
||||
<OwnerCell project={project} />
|
||||
</div>
|
||||
<div className="lumiere-compact-date">
|
||||
<LastUpdatedCell project={project} />
|
||||
</div>
|
||||
<div className="lumiere-compact-actions">
|
||||
<ActionsCell project={project} />
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
})
|
||||
|
||||
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 ? (
|
||||
<ProjectCardCompact key={project.id} project={project} />
|
||||
) : (
|
||||
<ProjectCard key={project.id} project={project} />
|
||||
))}
|
||||
)
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
<LoadMore />
|
||||
|
||||
@@ -732,89 +732,114 @@ $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,
|
||||
&:focus-within {
|
||||
transform: none;
|
||||
&:hover {
|
||||
background: rgba(255, 255, 255, 0.96);
|
||||
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.09);
|
||||
}
|
||||
}
|
||||
|
||||
// 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;
|
||||
.lumiere-compact-checkbox {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0.45rem 0.75rem 0.45rem 2.2rem;
|
||||
gap: 0.65rem;
|
||||
|
||||
input[type='checkbox'] {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
cursor: pointer;
|
||||
accent-color: $lum-teal;
|
||||
}
|
||||
}
|
||||
|
||||
// Hide the preview thumbnail
|
||||
.lumiere-card-thumb {
|
||||
display: none;
|
||||
}
|
||||
|
||||
// Body becomes a horizontal strip
|
||||
.lumiere-card-body {
|
||||
flex-direction: row;
|
||||
.lumiere-compact-name-cell {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.65rem;
|
||||
padding: 0;
|
||||
flex: 1;
|
||||
gap: 0.4rem;
|
||||
overflow: hidden;
|
||||
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;
|
||||
.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;
|
||||
}
|
||||
}
|
||||
|
||||
// More room for the owner label in list mode
|
||||
.lumiere-card-owner {
|
||||
max-width: 160px;
|
||||
.lumiere-compact-owner {
|
||||
font-size: 0.8rem;
|
||||
color: $lum-text-sub;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
// Date sits inline, no top margin
|
||||
.lumiere-card-date {
|
||||
margin-top: 0;
|
||||
flex-shrink: 0;
|
||||
.lumiere-compact-date {
|
||||
font-size: 0.8rem;
|
||||
color: $lum-text-muted;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
// 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;
|
||||
.lumiere-compact-actions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0.25rem 0.4rem;
|
||||
gap: 1px;
|
||||
|
||||
.action-btn {
|
||||
padding: 3px !important;
|
||||
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 {
|
||||
color: $lum-teal !important;
|
||||
background: rgba($lum-teal, 0.09) !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 ──────────────────────────────────────────
|
||||
|
||||
.lumiere-selection-bar {
|
||||
|
||||
Reference in New Issue
Block a user