diff --git a/app/src/components/Archive.js b/app/src/components/Archive.js index a2aff695..a8d97418 100644 --- a/app/src/components/Archive.js +++ b/app/src/components/Archive.js @@ -20,7 +20,8 @@ import { SearchInput, TabLinks, textEllipsis, - useTitle + mimetypeColor, + useTitle, } from "./Common"; import { deleteDomain, @@ -425,7 +426,8 @@ export function ArchiveCard({file}) { ; - return + return
diff --git a/app/src/components/Files.js b/app/src/components/Files.js index a1c1edbe..1b3644de 100644 --- a/app/src/components/Files.js +++ b/app/src/components/Files.js @@ -17,7 +17,8 @@ import { TagIcon, Toggle, textEllipsis, - useTitle + mimetypeColor, + useTitle, } from "./Common"; import { usePages, @@ -116,6 +117,7 @@ function EbookCard({file, sortField}) { return } title={{header}} meta={meta} + color={mimetypeColor(file.mimetype, file.primary_path)} /> } @@ -134,6 +136,7 @@ function ImageCard({file}) { return } title={{header}} meta={meta} + color={mimetypeColor(file.mimetype, file.primary_path)} /> } @@ -175,7 +178,8 @@ function FileCard({file}) { } ; - return } title={header} meta={meta}/> + return } title={header} meta={meta} + color={mimetypeColor(file.mimetype, file.primary_path)}/> } export function FileCards({files}) { diff --git a/app/src/components/ThemeSamplePage.js b/app/src/components/ThemeSamplePage.js index 4a60dd46..80083a7e 100644 --- a/app/src/components/ThemeSamplePage.js +++ b/app/src/components/ThemeSamplePage.js @@ -382,20 +382,26 @@ export function ThemeSamplePage() {
{[ - ['How To Sharpen An Axe The Right Way', 'Wranglerstar · 2024-11-03'], - ['Pressure Canning Basics', 'RoseRed Homestead · 2025-02-17'], - ['Solar Panel Wiring: Series vs Parallel', 'DIY Solar Power · 2025-08-21'], - ['Ham Radio General License, Part 1', 'Ham Radio Crash Course · 2024-05-09'], - ].map(([title, meta]) =>
} + }}>} />)} +

+ The top edge carries the file type's colour, so a grid of results is + scannable by kind before any title is read. It comes from a token, so night + and amber render the accent in their own single hue rather than four. +

diff --git a/app/src/components/ui/Surfaces.tsx b/app/src/components/ui/Surfaces.tsx index 87bef8fb..7389727e 100644 --- a/app/src/components/ui/Surfaces.tsx +++ b/app/src/components/ui/Surfaces.tsx @@ -124,10 +124,17 @@ export interface CardProps { meta?: React.ReactNode; children?: React.ReactNode; onClick?: React.MouseEventHandler; + /** + * A token colour name, drawn as an accent along the card's top edge. File cards use + * it to carry the mimetype's colour, so a grid of results is scannable by kind before + * any text is read. It remaps per theme, so night gets a red accent rather than a + * dozen hues. + */ + color?: string; className?: string; } -export function Card({media, title, meta, children, onClick, className}: CardProps) { +export function Card({media, title, meta, children, onClick, color, className}: CardProps) { return {media &&
{media}
} diff --git a/app/src/components/ui/ui.test.js b/app/src/components/ui/ui.test.js index 6a68b673..53dc2666 100644 --- a/app/src/components/ui/ui.test.js +++ b/app/src/components/ui/ui.test.js @@ -11,6 +11,7 @@ import {themeChoices} from '../../themes/names'; import { ActionInput, Button, + Card, Confirm, Header, Icon, @@ -432,6 +433,23 @@ describe('Table', () => { }); }); +describe('Card', () => { + it('draws a mimetype accent from a token, not a hex', () => { + // File cards carry the mimetype's colour on their top edge so a grid of results is + // scannable by kind. Semantic did this with ``; two migrated + // files had dropped the accent because our Card had no equivalent. + const {container} = renderUI(); + + expect(container.firstChild).toHaveStyle({borderTop: '3px solid var(--red)'}); + }); + + it('has no accent when no colour is given', () => { + const {container} = renderUI(); + + expect(container.firstChild.style.borderTop).toBe(''); + }); +}); + describe('Panel', () => { it('marks danger zones', () => { const {container} = renderUI(Destructive actions);