feat(settings): library card grid max columns in Appearance (4–12, default 6)

Persist libraryGridMaxColumns, wire useCardGridMetrics and card grid layout,
add i18n and settings search index; document performance hint in copy.
This commit is contained in:
Maxim Isaev
2026-05-15 02:19:20 +03:00
parent 7c6d3694d4
commit 0f5ece6d03
21 changed files with 169 additions and 16 deletions
+16 -6
View File
@@ -1,16 +1,26 @@
import { describe, expect, it } from 'vitest';
import { computeCardGridColumnCount, CARD_GRID_MAX_COLS } from './cardGridLayout';
import { computeCardGridColumnCount } from './cardGridLayout';
import { LIBRARY_GRID_MAX_COLUMNS_MAX, LIBRARY_GRID_MAX_COLUMNS_MIN } from '../store/authStoreDefaults';
describe('computeCardGridColumnCount', () => {
it('never exceeds CARD_GRID_MAX_COLS', () => {
expect(computeCardGridColumnCount(20_000)).toBe(CARD_GRID_MAX_COLS);
it('never exceeds the configured max', () => {
expect(computeCardGridColumnCount(20_000, 6)).toBe(6);
expect(computeCardGridColumnCount(20_000, 4)).toBe(4);
});
it('clamps requested max to store-wide upper bound', () => {
expect(computeCardGridColumnCount(20_000, 99)).toBe(LIBRARY_GRID_MAX_COLUMNS_MAX);
});
it('clamps requested max to store-wide lower bound', () => {
expect(computeCardGridColumnCount(20_000, 2)).toBe(LIBRARY_GRID_MAX_COLUMNS_MIN);
});
it('returns at least one column', () => {
expect(computeCardGridColumnCount(50)).toBe(1);
expect(computeCardGridColumnCount(50, 6)).toBe(1);
});
it('uses six columns on wide desktop widths', () => {
expect(computeCardGridColumnCount(1200)).toBe(6);
it('uses six columns on wide desktop when max allows', () => {
expect(computeCardGridColumnCount(1200, 6)).toBe(6);
});
});
+15 -3
View File
@@ -3,15 +3,27 @@
* and row-height estimates derived from measured cell width (TanStack virtual rows).
*/
import {
DEFAULT_LIBRARY_GRID_MAX_COLUMNS,
LIBRARY_GRID_MAX_COLUMNS_MAX,
LIBRARY_GRID_MAX_COLUMNS_MIN,
} from '../store/authStoreDefaults';
export const CARD_GRID_GAP_PX = 16;
export const CARD_GRID_MIN_TILE_PX = 140;
export const CARD_GRID_MAX_COLS = 6;
export function computeCardGridColumnCount(containerWidthPx: number): number {
/** @deprecated use `DEFAULT_LIBRARY_GRID_MAX_COLUMNS` from `authStoreDefaults` */
export const CARD_GRID_MAX_COLS = DEFAULT_LIBRARY_GRID_MAX_COLUMNS;
export function computeCardGridColumnCount(containerWidthPx: number, maxColumns: number): number {
const cap = Math.max(
LIBRARY_GRID_MAX_COLUMNS_MIN,
Math.min(LIBRARY_GRID_MAX_COLUMNS_MAX, Math.round(maxColumns)),
);
const raw = Math.floor(
(containerWidthPx + CARD_GRID_GAP_PX) / (CARD_GRID_MIN_TILE_PX + CARD_GRID_GAP_PX),
);
return Math.min(CARD_GRID_MAX_COLS, Math.max(1, raw));
return Math.min(cap, Math.max(1, raw));
}
export function computeCellWidthPx(containerWidthPx: number, columnCount: number): number {