Fix translations, center logo/footer, add tile zoom control
Build and Deploy Verso / deploy (push) Successful in 14m8s
Build and Deploy Verso / deploy (push) Successful in 14m8s
- i18n: unwrap webpack module object on dynamic JSON import (lang.default ?? lang) so French bundle keys are correctly registered in the i18next store - Login logo: use flex centering on wrapper instead of display:block + margin:auto - Footer (project list + login): align-items:center on .row for vertical centering - Tile zoom: S/M/L control in header with CSS custom property (--lum-card-scale) that scales grid column width and card thumbnail height; persisted in localStorage Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 4.6
parent
d08e834f49
commit
592b4d3dad
@@ -1,4 +1,4 @@
|
||||
import { memo, useCallback, useEffect, useRef } from 'react'
|
||||
import React, { memo, useCallback, useEffect, useRef, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { useProjectListContext } from '../context/project-list-context'
|
||||
import { Project } from '../../../../../types/project/dashboard/api'
|
||||
@@ -28,6 +28,46 @@ import { CompileAndDownloadProjectPDFButtonTooltip } from './table/cells/action-
|
||||
import { ArchiveProjectButtonTooltip } from './table/cells/action-buttons/archive-project-button'
|
||||
import { TrashProjectButtonTooltip } from './table/cells/action-buttons/trash-project-button'
|
||||
|
||||
// ── Tile zoom ─────────────────────────────────────────────────────────────────
|
||||
|
||||
type ZoomLevel = 0.75 | 1 | 1.35
|
||||
const ZOOM_OPTIONS: { value: ZoomLevel; label: string }[] = [
|
||||
{ value: 0.75, label: 'S' },
|
||||
{ value: 1, label: 'M' },
|
||||
{ value: 1.35, label: 'L' },
|
||||
]
|
||||
const ZOOM_STORAGE_KEY = 'lumiere-card-scale'
|
||||
|
||||
function useLumiereCardScale(): [ZoomLevel, (z: ZoomLevel) => void] {
|
||||
const [scale, setScale] = useState<ZoomLevel>(() => {
|
||||
try {
|
||||
const stored = localStorage.getItem(ZOOM_STORAGE_KEY)
|
||||
if (stored) {
|
||||
const val = parseFloat(stored)
|
||||
if ((ZOOM_OPTIONS.map(o => o.value) as number[]).includes(val)) {
|
||||
return val as ZoomLevel
|
||||
}
|
||||
}
|
||||
} catch (_) {
|
||||
// storage unavailable
|
||||
}
|
||||
return 1
|
||||
})
|
||||
|
||||
const updateScale = useCallback((z: ZoomLevel) => {
|
||||
setScale(z)
|
||||
try {
|
||||
localStorage.setItem(ZOOM_STORAGE_KEY, String(z))
|
||||
} catch (_) {
|
||||
// ignore
|
||||
}
|
||||
}, [])
|
||||
|
||||
return [scale, updateScale]
|
||||
}
|
||||
|
||||
// ── Format helpers ─────────────────────────────────────────────────────────────
|
||||
|
||||
type FormatVariant = 'latex' | 'typst' | 'quarto' | 'quarto-slides'
|
||||
|
||||
function getFormatVariant(
|
||||
@@ -137,6 +177,7 @@ export function ProjectListLumiere() {
|
||||
const navbarProps = getMeta('ol-navbar')
|
||||
const footerProps = getMeta('ol-footer')
|
||||
const { t } = useTranslation()
|
||||
const [cardScale, setCardScale] = useLumiereCardScale()
|
||||
const {
|
||||
error,
|
||||
visibleProjects,
|
||||
@@ -206,6 +247,23 @@ export function ProjectListLumiere() {
|
||||
filter={filter}
|
||||
selectedTag={selectedTag}
|
||||
/>
|
||||
<div
|
||||
className="lumiere-zoom-control"
|
||||
role="group"
|
||||
aria-label="Taille des cartes"
|
||||
>
|
||||
{ZOOM_OPTIONS.map(({ value, label }) => (
|
||||
<button
|
||||
key={value}
|
||||
type="button"
|
||||
className={`lumiere-zoom-btn${cardScale === value ? ' active' : ''}`}
|
||||
onClick={() => setCardScale(value)}
|
||||
aria-pressed={cardScale === value}
|
||||
>
|
||||
{label}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
<NewProjectButton
|
||||
id="lumiere-new-project-button"
|
||||
showAddAffiliationWidget
|
||||
@@ -241,7 +299,11 @@ export function ProjectListLumiere() {
|
||||
{visibleProjects.length === 0 ? (
|
||||
<p className="lumiere-empty">{t('no_projects')}</p>
|
||||
) : (
|
||||
<div className="lumiere-card-grid">
|
||||
<div
|
||||
className="lumiere-card-grid"
|
||||
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
||||
style={{ '--lum-card-scale': cardScale } as React.CSSProperties}
|
||||
>
|
||||
{visibleProjects.map(project => (
|
||||
<ProjectCard key={project.id} project={project} />
|
||||
))}
|
||||
|
||||
Reference in New Issue
Block a user