Skip to content

Commit 5f1c46b

Browse files
Bring the datasets page in line with the models page
The datasets page arrived from main built against the pre-redesign models page, so it kept a gradient masthead, the small search bar and a card copied from the old model card. Masthead, search and empty state now match the models page: one accent word instead of a gradient, the large search bar with a count in its placeholder, and the empty state as a card with a clear-filters button rather than loose centred text. The dataset card imported the redesigned model-card module while still carrying `border-gray-300 bg-white shadow-lg` and a `.paired` class that no longer exists. Those were dead weight — a CSS module beats a utility, so the module's own border, surface and shadow were already winning. Its type, author line and tag row now follow the model card, including the two-row clamp with a `+N` chip. Two things syncing the page exposed: the filter row said "All models" on the datasets page, and the placeholder read "Search 1 datasets". Also drops the second sentence from the footer blurb. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TpogQiNgM8Lg8PTTfTGSNk
1 parent 618ac10 commit 5f1c46b

4 files changed

Lines changed: 67 additions & 51 deletions

File tree

src/elements/components/dataset-card.tsx

Lines changed: 30 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { useWebApi } from '../../lib/hooks/use-web-api';
99
import { joinList } from '../../lib/react-util';
1010
import { Dataset, DatasetId, ImageSize, PairedImage } from '../../lib/schema';
1111
import { asArray, assertNever, joinClasses } from '../../lib/util';
12+
import { ClampedTags } from './clamped-tags';
1213
import { EditableTags } from './editable-tags';
1314
import { Link } from './link';
1415
import style from './model-card.module.scss';
@@ -87,7 +88,9 @@ const SideBySideImage = ({ datasetName, image }: { datasetName: string; image: P
8788
const getDatasetCardImageComponent = (dataset: Dataset | undefined) => {
8889
const image = dataset?.images?.[0];
8990
if (!dataset || !image) {
90-
return <div className="margin-auto z-0 w-full py-20 text-center text-gray-500">No Image</div>;
91+
return (
92+
<div className="z-0 flex h-full w-full items-center justify-center text-sm text-ink-subtle">No preview</div>
93+
);
9194
}
9295
switch (image.type) {
9396
case 'paired': {
@@ -119,31 +122,29 @@ const DatasetCardContent = memo(({ id, dataset }: DatasetCardProps) => {
119122
const { webApi, editMode } = useWebApi();
120123
const { updateDatasetProperty } = useUpdateDataset(webApi, id);
121124

122-
const isPaired = dataset.images?.[0]?.type === 'paired' && !editMode;
123-
124125
return (
125126
<div className={style.inner}>
126127
<Link
127-
className={joinClasses(style.thumbnail, isPaired && style.paired, 'bg-fade-300 dark:bg-fade-700 ')}
128+
className={joinClasses(style.thumbnail, 'bg-surface-sunken')}
128129
href={`/datasets/${id}`}
129130
tabIndex={-1}
130131
>
131132
{getDatasetCardImageComponent(dataset)}
132133
</Link>
133134

134-
<div className={joinClasses(style.details, isPaired && style.paired)}>
135+
<div className={style.details}>
135136
<Link
136-
className={`${style.name} block text-xl font-bold text-gray-800 dark:text-gray-100`}
137+
className={`${style.name} block text-base font-semibold leading-snug text-ink line-clamp-2`}
137138
href={`/datasets/${id}`}
138139
>
139140
{dataset.name}
140141
</Link>
141-
<div className="text-sm text-gray-600 dark:text-gray-400">
142+
<div className="truncate text-sm text-ink-muted">
142143
{'by '}
143144
{joinList(
144145
asArray(dataset.author).map((userId) => (
145146
<Link
146-
className="font-bold text-accent-600 dark:text-accent-400"
147+
className="font-medium text-accent-text hover:underline"
147148
href={`/users/${userId}`}
148149
key={userId}
149150
>
@@ -154,18 +155,24 @@ const DatasetCardContent = memo(({ id, dataset }: DatasetCardProps) => {
154155
</div>
155156

156157
{/* Description */}
157-
<div className="mb-2 mt-1 text-sm text-gray-600 line-clamp-3 dark:text-gray-400">
158-
{dataset.description}
159-
</div>
160-
161-
{/* Tags */}
162-
<div className="flex flex-row flex-wrap gap-1 text-xs">
163-
<EditableTags
164-
readonly={!editMode}
158+
<div className="mt-1 mb-2 text-sm leading-snug text-ink-muted line-clamp-2">{dataset.description}</div>
159+
160+
{/* Tags. Same split as the model card: edit mode keeps the full
161+
editor, read mode clamps to two rows with a `+N` chip. */}
162+
{editMode ? (
163+
<div className={joinClasses(style.tagRow, style.tagRowOpen, 'text-xs')}>
164+
<EditableTags
165+
readonly={false}
166+
tags={dataset.tags}
167+
onChange={(tags) => updateDatasetProperty('tags', tags)}
168+
/>
169+
</div>
170+
) : (
171+
<ClampedTags
172+
className={joinClasses(style.tagRow, 'text-xs')}
165173
tags={dataset.tags}
166-
onChange={(tags) => updateDatasetProperty('tags', tags)}
167174
/>
168-
</div>
175+
)}
169176
</div>
170177
</div>
171178
);
@@ -174,14 +181,11 @@ const DatasetCardContent = memo(({ id, dataset }: DatasetCardProps) => {
174181
export const DatasetCard = memo(({ id, dataset, lazy = false }: DatasetCardProps) => {
175182
const { editMode } = useWebApi();
176183

184+
// No border/background/shadow utilities: `.modelCard` carries all three
185+
// from the design tokens now, and being a CSS module it wins over them
186+
// anyway — they were dead weight fighting the card they sat on.
177187
const inner = (
178-
<div
179-
className={joinClasses(
180-
style.modelCard,
181-
!editMode && style.overflowHidden,
182-
'border-gray-300 bg-white shadow-lg hover:shadow-2xl dark:border-gray-700 dark:bg-fade-900'
183-
)}
184-
>
188+
<div className={joinClasses(style.modelCard, !editMode && style.overflowHidden)}>
185189
<DatasetCardContent
186190
dataset={dataset}
187191
id={id}
@@ -192,13 +196,7 @@ export const DatasetCard = memo(({ id, dataset, lazy = false }: DatasetCardProps
192196
if (!lazy) return inner;
193197

194198
return (
195-
<LazyLoadComponent
196-
placeholder={
197-
<div
198-
className={`${style.modelCard} border-gray-300 bg-white shadow-lg hover:shadow-2xl dark:border-gray-700 dark:bg-fade-900`}
199-
/>
200-
}
201-
>
199+
<LazyLoadComponent placeholder={<div className={joinClasses(style.modelCard, style.placeholder)} />}>
202200
{inner}
203201
</LazyLoadComponent>
204202
);

src/elements/footer.tsx

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -60,10 +60,7 @@ export function Footer() {
6060
<div className={style.inner}>
6161
<div className={style.columns}>
6262
<div className={style.about}>
63-
<p className={style.blurb}>
64-
A community-driven database of AI upscaling models. Everything here is maintained in the
65-
open — corrections and new models are welcome.
66-
</p>
63+
<p className={style.blurb}>A community-driven database of AI upscaling models.</p>
6764
<div className={style.social}>
6865
<Link
6966
external

src/elements/tag-selector.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -255,7 +255,7 @@ function SimpleTagSelector({ selection, onChange, context = 'models' }: TagSelec
255255
<div className={style.groupTags}>
256256
<TagButton
257257
noIcon
258-
name="All models"
258+
name={context === 'datasets' ? 'All datasets' : 'All models'}
259259
state={selected === undefined ? 'required' : 'any'}
260260
onClick={() => {
261261
if (selected !== undefined) {

src/pages/datasets/index.tsx

Lines changed: 35 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import { SearchResult } from '../../lib/search/search-index';
1515
import { tokenize } from '../../lib/search/token';
1616
import { fileApi } from '../../lib/server/file-data';
1717
import { TagSelection, getTagCondition } from '../../lib/tag-condition';
18+
import { EMPTY_MAP } from '../../lib/util';
1819

1920
interface Props {
2021
datasetData: Record<DatasetId, Dataset>;
@@ -63,20 +64,26 @@ export default function Page({ datasetData: staticDatasetData }: Props) {
6364
scrollToTop
6465
wrapper
6566
>
66-
<h1 className="mb-4 text-center text-4xl font-extrabold md:mb-6 md:text-5xl lg:text-6xl">
67-
<span className="font-bold text-gray-800 dark:text-gray-100">Training </span>
68-
<span className="bg-gradient-to-r from-accent-400 via-accent-500 to-accent-600 bg-clip-text text-transparent">
69-
Datasets
70-
</span>
71-
</h1>
67+
{/* Same masthead as the models page: one accent word rather
68+
than a gradient, and theme tokens instead of paired greys. */}
69+
<section className="mx-auto max-w-3xl pt-8 pb-2 text-center md:pt-12">
70+
<h1 className="m-0 text-4xl font-extrabold leading-tight tracking-tight text-ink md:text-5xl lg:text-6xl">
71+
Training <span className="text-accent-text">Datasets</span>
72+
</h1>
7273

73-
<p className="mx-auto mb-8 max-w-screen-md text-center text-gray-600 dark:text-gray-400 md:text-lg">
74-
Explore and search for datasets used to train upscaling and restoration models.
75-
</p>
74+
<p className="mx-auto mt-4 max-w-2xl text-base leading-relaxed text-ink-muted md:text-lg">
75+
Explore and search for datasets used to train upscaling and restoration models.
76+
</p>
77+
</section>
7678

7779
{/* Search */}
7880
<SearchBar
79-
className="mb-4 w-full"
81+
aria-label="Search datasets"
82+
className="mx-auto mt-7 w-full max-w-3xl"
83+
placeholder={`Search ${datasetData.size.toLocaleString('en-US')} dataset${
84+
datasetData.size === 1 ? '' : 's'
85+
} by name or purpose`}
86+
size="large"
8087
value={searchQuery}
8188
onChange={(e) => setSearchQuery(e.target.value, 400)}
8289
onEnter={(e) => {
@@ -98,7 +105,7 @@ export default function Page({ datasetData: staticDatasetData }: Props) {
98105
/>
99106

100107
{/* Tags */}
101-
<div className="my-4">
108+
<div className="mt-8 mb-10">
102109
<TagSelector
103110
context="datasets"
104111
selection={tagSelection}
@@ -117,9 +124,23 @@ export default function Page({ datasetData: staticDatasetData }: Props) {
117124
datasets={selectedDatasets}
118125
/>
119126
) : (
120-
<div className="mt-10 flex flex-col items-center justify-center p-6">
121-
<div className="text-2xl font-bold text-accent-500 dark:text-gray-100">No datasets found</div>
122-
<div className="text-gray-500 dark:text-gray-400">Try changing your search filters</div>
127+
<div className="flex flex-col items-center justify-center rounded-card border border-solid border-line bg-surface px-6 py-16 text-center">
128+
<p className="m-0 text-lg font-semibold text-ink">No datasets match those filters</p>
129+
<p className="m-0 mt-1 max-w-md text-sm text-ink-muted">
130+
{searchQuery
131+
? `Nothing matched “${searchQuery}”. Try a broader term, or clear the filters to start over.`
132+
: 'That combination of tags has no datasets. Try removing one, or clear the filters to start over.'}
133+
</p>
134+
<button
135+
className="mt-5 cursor-pointer rounded-control border-0 bg-accent-600 px-4 py-2 text-sm font-semibold text-white transition-opacity hover:opacity-90 dark:bg-accent-500"
136+
type="button"
137+
onClick={() => {
138+
setSearchQuery('', 0);
139+
setTagSelection(EMPTY_MAP, 0);
140+
}}
141+
>
142+
Clear search and filters
143+
</button>
123144
</div>
124145
)}
125146
</PageContainer>

0 commit comments

Comments
 (0)