Skip to content

Commit 8a85983

Browse files
daveearleyclaude
andcommitted
Make lineup and people pages lay out by their own width, not the viewport
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 parent 39f4653 commit 8a85983

4 files changed

Lines changed: 132 additions & 118 deletions

File tree

‎frontend/src/components/routes/event/Lineup/Lineup.module.scss‎

Lines changed: 31 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -3,27 +3,28 @@
33
$border: var(--mantine-color-gray-2);
44
$muted: var(--mantine-color-gray-6);
55

6+
.page {
7+
container: lineup-page / inline-size;
8+
}
9+
610
.pageActions {
711
display: flex;
812
flex-wrap: wrap;
913
gap: var(--mantine-spacing-xs);
14+
margin-bottom: var(--mantine-spacing-md);
1015
}
1116

1217
.pageHeader {
1318
display: flex;
19+
flex-wrap: wrap;
1420
align-items: flex-start;
1521
justify-content: space-between;
16-
gap: var(--mantine-spacing-md);
22+
column-gap: var(--mantine-spacing-md);
1723

1824
> :first-child {
19-
flex: 1;
25+
flex: 1 1 320px;
2026
min-width: 0;
2127
}
22-
23-
@include mixins.respond-below(sm) {
24-
flex-direction: column;
25-
margin-bottom: var(--mantine-spacing-md);
26-
}
2728
}
2829

2930
.loading {
@@ -47,7 +48,7 @@ $muted: var(--mantine-color-gray-6);
4748
background: var(--mantine-color-body);
4849
overflow: hidden;
4950

50-
@include mixins.respond-below(md) {
51+
@container lineup-page (max-width: 719px) {
5152
grid-template-columns: repeat(2, minmax(0, 1fr));
5253
}
5354
}
@@ -64,7 +65,7 @@ $muted: var(--mantine-color-gray-6);
6465
border-left: 0;
6566
}
6667

67-
@include mixins.respond-below(md) {
68+
@container lineup-page (max-width: 719px) {
6869
&:nth-child(3) {
6970
border-left: 0;
7071
}
@@ -107,12 +108,12 @@ $muted: var(--mantine-color-gray-6);
107108
gap: var(--mantine-spacing-md);
108109
align-items: start;
109110

110-
@include mixins.respond-below(lg) {
111+
@container lineup-page (max-width: 999px) {
111112
grid-template-columns: 260px minmax(0, 1fr);
112113
}
113114

114-
@include mixins.respond-below(md) {
115-
grid-template-columns: 1fr;
115+
@container lineup-page (max-width: 859px) {
116+
grid-template-columns: minmax(0, 1fr);
116117
}
117118
}
118119

@@ -128,7 +129,7 @@ $muted: var(--mantine-color-gray-6);
128129
border-radius: var(--mantine-radius-lg);
129130
background: var(--mantine-color-body);
130131

131-
@include mixins.respond-below(md) {
132+
@container lineup-page (max-width: 859px) {
132133
position: static;
133134
max-height: none;
134135

@@ -340,6 +341,7 @@ $muted: var(--mantine-color-gray-6);
340341
}
341342

342343
.panel {
344+
container: lineup-panel / inline-size;
343345
min-width: 0;
344346
border: 1px solid $border;
345347
border-radius: var(--mantine-radius-lg);
@@ -370,7 +372,7 @@ $muted: var(--mantine-color-gray-6);
370372
.panelBody {
371373
padding: 16px;
372374

373-
@include mixins.respond-below(sm) {
375+
@container lineup-panel (max-width: 575px) {
374376
padding: 12px;
375377
}
376378
}
@@ -415,18 +417,26 @@ $muted: var(--mantine-color-gray-6);
415417
border-radius: var(--mantine-radius-lg);
416418

417419
li {
418-
display: flex;
420+
display: grid;
421+
grid-template-columns: 26px minmax(0, 1fr) auto;
419422
align-items: center;
420-
gap: 14px;
423+
column-gap: 14px;
424+
row-gap: 10px;
421425
padding: 14px 16px;
422426
border-top: 1px solid $border;
423427

424428
&:first-child {
425429
border-top: 0;
426430
}
427431

428-
@include mixins.respond-below(sm) {
429-
flex-wrap: wrap;
432+
@container lineup-panel (max-width: 519px) {
433+
grid-template-columns: 26px minmax(0, 1fr);
434+
align-items: start;
435+
436+
> :nth-child(3) {
437+
grid-column: 2;
438+
justify-self: start;
439+
}
430440
}
431441
}
432442

@@ -454,8 +464,7 @@ $muted: var(--mantine-color-gray-6);
454464
display: flex;
455465
flex-direction: column;
456466
gap: 2px;
457-
flex: 1;
458-
min-width: 200px;
467+
min-width: 0;
459468
font-size: var(--mantine-font-size-sm);
460469

461470
span {
@@ -508,7 +517,7 @@ $muted: var(--mantine-color-gray-6);
508517
grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
509518
}
510519

511-
@include mixins.respond-below(sm) {
520+
@container lineup-panel (max-width: 479px) {
512521
&, &[data-tier="headliner"], &[data-tier="standard"] {
513522
grid-template-columns: repeat(2, minmax(0, 1fr));
514523
gap: 10px;
@@ -844,7 +853,7 @@ $muted: var(--mantine-color-gray-6);
844853
background: var(--mantine-color-gray-0);
845854
}
846855

847-
@include mixins.respond-below(sm) {
856+
@container lineup-panel (max-width: 575px) {
848857
grid-template-columns: 64px minmax(0, 1fr);
849858

850859
.agendaAdminSpace {

‎frontend/src/components/routes/event/Lineup/index.tsx‎

Lines changed: 31 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -50,36 +50,38 @@ const Lineup = () => {
5050

5151
return (
5252
<PageBody>
53-
<div className={classes.pageHeader}>
54-
<PageTitle subheading={t`Everyone appearing at this event, where they are and when. Shown on your event page as soon as you add them.`}>
55-
{t`Lineup & Schedule`}
56-
</PageTitle>
57-
{event && (
58-
<div className={classes.pageActions}>
59-
{lineup && <ImportButton event={event} lineup={lineup}/>}
60-
<ExportMenu event={event}/>
61-
<Button
62-
component="a"
63-
href={eventHomepagePath(event)}
64-
target="_blank"
65-
variant="default"
66-
size="sm"
67-
leftSection={<IconExternalLink size={16}/>}
68-
>
69-
{t`View on event page`}
70-
</Button>
71-
</div>
72-
)}
73-
</div>
53+
<div className={classes.page}>
54+
<div className={classes.pageHeader}>
55+
<PageTitle subheading={t`Everyone appearing at this event, where they are and when. Shown on your event page as soon as you add them.`}>
56+
{t`Lineup & Schedule`}
57+
</PageTitle>
58+
{event && (
59+
<div className={classes.pageActions}>
60+
{lineup && <ImportButton event={event} lineup={lineup}/>}
61+
<ExportMenu event={event}/>
62+
<Button
63+
component="a"
64+
href={eventHomepagePath(event)}
65+
target="_blank"
66+
variant="default"
67+
size="sm"
68+
leftSection={<IconExternalLink size={16}/>}
69+
>
70+
{t`View on event page`}
71+
</Button>
72+
</div>
73+
)}
74+
</div>
7475

75-
{event && lineup
76-
? <LineupWorkspace key={event.id} event={event} lineup={lineup}/>
77-
: (
78-
<div className={classes.loading}>
79-
<Skeleton height={84} radius="md"/>
80-
<Skeleton height={420} radius="md"/>
81-
</div>
82-
)}
76+
{event && lineup
77+
? <LineupWorkspace key={event.id} event={event} lineup={lineup}/>
78+
: (
79+
<div className={classes.loading}>
80+
<Skeleton height={84} radius="md"/>
81+
<Skeleton height={420} radius="md"/>
82+
</div>
83+
)}
84+
</div>
8385
</PageBody>
8486
);
8587
};

‎frontend/src/components/routes/organizer/People/People.module.scss‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ $border: var(--mantine-color-gray-2);
4141
}
4242

4343
.table {
44+
container: people-table / inline-size;
4445
border: 1px solid $border;
4546
border-radius: var(--mantine-radius-lg);
4647
background: var(--mantine-color-body);
@@ -64,7 +65,7 @@ $border: var(--mantine-color-gray-2);
6465
text-transform: uppercase;
6566
color: var(--mantine-color-gray-6);
6667

67-
@include mixins.respond-below(sm) {
68+
@container people-table (max-width: 639px) {
6869
display: none;
6970
}
7071
}
@@ -91,7 +92,7 @@ $border: var(--mantine-color-gray-2);
9192
}
9293
}
9394

94-
@include mixins.respond-below(sm) {
95+
@container people-table (max-width: 639px) {
9596
grid-template-columns: minmax(0, 1fr) 20px;
9697

9798
.appearances {

‎frontend/src/components/routes/organizer/People/index.tsx‎

Lines changed: 67 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -72,79 +72,81 @@ const People = () => {
7272

7373
return (
7474
<PageBody>
75-
<div className={lineupClasses.pageHeader}>
76-
<PageTitle subheading={t`Speakers, artists and hosts you can add to any of this organizer's events. Edit a profile once and every event shows the change.`}>
77-
{t`People`}
78-
</PageTitle>
79-
{canCreate && (
80-
<CreateButton leftSection={<IconPlus size={16}/>} onClick={() => setDrawer('new')} data-testid="people-create-button">
81-
{t`New profile`}
82-
</CreateButton>
83-
)}
84-
</div>
85-
86-
<div className={lineupClasses.stats}>
87-
{stats.map(stat => (
88-
<button
89-
key={stat.key}
90-
type="button"
91-
className={`${lineupClasses.stat} ${classes.statButton}`}
92-
data-active={filter === stat.key || undefined}
93-
onClick={() => setFilter(stat.key)}
94-
>
95-
<span className={lineupClasses.statLabel}>{stat.label}</span>
96-
<span className={lineupClasses.statValue}>{isLoading ? '–' : stat.value}</span>
97-
<span className={lineupClasses.statHint} data-warn={stat.warn || undefined}>{stat.hint}</span>
98-
</button>
99-
))}
100-
</div>
75+
<div className={lineupClasses.page}>
76+
<div className={lineupClasses.pageHeader}>
77+
<PageTitle subheading={t`Speakers, artists and hosts you can add to any of this organizer's events. Edit a profile once and every event shows the change.`}>
78+
{t`People`}
79+
</PageTitle>
80+
{canCreate && (
81+
<CreateButton leftSection={<IconPlus size={16}/>} onClick={() => setDrawer('new')} data-testid="people-create-button">
82+
{t`New profile`}
83+
</CreateButton>
84+
)}
85+
</div>
10186

102-
<div className={classes.toolbar}>
103-
<TextInput
104-
className={classes.search}
105-
leftSection={<IconSearch size={16}/>}
106-
placeholder={t`Search by name or tagline`}
107-
value={search}
108-
onChange={event => setSearch(event.currentTarget.value)}
109-
/>
110-
</div>
87+
<div className={lineupClasses.stats}>
88+
{stats.map(stat => (
89+
<button
90+
key={stat.key}
91+
type="button"
92+
className={`${lineupClasses.stat} ${classes.statButton}`}
93+
data-active={filter === stat.key || undefined}
94+
onClick={() => setFilter(stat.key)}
95+
>
96+
<span className={lineupClasses.statLabel}>{stat.label}</span>
97+
<span className={lineupClasses.statValue}>{isLoading ? '–' : stat.value}</span>
98+
<span className={lineupClasses.statHint} data-warn={stat.warn || undefined}>{stat.hint}</span>
99+
</button>
100+
))}
101+
</div>
111102

112-
<div className={classes.table}>
113-
<div className={classes.tableHead}>
114-
<span>{t`Name`}</span>
115-
<span>{t`Appears on`}</span>
116-
<span>{t`Links`}</span>
117-
<span/>
103+
<div className={classes.toolbar}>
104+
<TextInput
105+
className={classes.search}
106+
leftSection={<IconSearch size={16}/>}
107+
placeholder={t`Search by name or tagline`}
108+
value={search}
109+
onChange={event => setSearch(event.currentTarget.value)}
110+
/>
118111
</div>
119112

120-
{isLoading && Array.from({length: 5}).map((_, index) => (
121-
<div key={index} className={classes.row}><Skeleton height={36} radius="md"/></div>
122-
))}
113+
<div className={classes.table}>
114+
<div className={classes.tableHead}>
115+
<span>{t`Name`}</span>
116+
<span>{t`Appears on`}</span>
117+
<span>{t`Links`}</span>
118+
<span/>
119+
</div>
123120

124-
{!isLoading && filtered.map(profile => (
125-
<PersonRow key={profile.id} profile={profile} onOpen={() => setDrawer({profileId: profile.id})}/>
126-
))}
121+
{isLoading && Array.from({length: 5}).map((_, index) => (
122+
<div key={index} className={classes.row}><Skeleton height={36} radius="md"/></div>
123+
))}
124+
125+
{!isLoading && filtered.map(profile => (
126+
<PersonRow key={profile.id} profile={profile} onOpen={() => setDrawer({profileId: profile.id})}/>
127+
))}
128+
129+
{!isLoading && filtered.length === 0 && (
130+
<div className={lineupClasses.panelEmpty}>
131+
<IconMicrophone2 size={22} stroke={1.5}/>
132+
<p>
133+
{counts.all === 0
134+
? t`No profiles yet. Create one here, or add people straight from an event's Lineup & Schedule page.`
135+
: t`Nobody matches these filters.`}
136+
</p>
137+
</div>
138+
)}
139+
</div>
127140

128-
{!isLoading && filtered.length === 0 && (
129-
<div className={lineupClasses.panelEmpty}>
130-
<IconMicrophone2 size={22} stroke={1.5}/>
131-
<p>
132-
{counts.all === 0
133-
? t`No profiles yet. Create one here, or add people straight from an event's Lineup & Schedule page.`
134-
: t`Nobody matches these filters.`}
135-
</p>
136-
</div>
141+
{drawer && (drawer === 'new' || drawerProfile) && (
142+
<ProfileDrawer
143+
organizerId={organizerId!}
144+
profile={drawerProfile}
145+
onCreated={profile => setDrawer({profileId: profile.id})}
146+
onClose={() => setDrawer(null)}
147+
/>
137148
)}
138149
</div>
139-
140-
{drawer && (drawer === 'new' || drawerProfile) && (
141-
<ProfileDrawer
142-
organizerId={organizerId!}
143-
profile={drawerProfile}
144-
onCreated={profile => setDrawer({profileId: profile.id})}
145-
onClose={() => setDrawer(null)}
146-
/>
147-
)}
148150
</PageBody>
149151
);
150152
};

0 commit comments

Comments
 (0)