Skip to content

Commit 905f778

Browse files
committed
Fix pipeline [1]
1 parent 673a8cd commit 905f778

6 files changed

Lines changed: 291 additions & 93 deletions

File tree

web/src/style.css

Lines changed: 118 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -13,32 +13,48 @@
1313
}
1414

1515
@media (min-width: 640px) {
16-
:root { --floor-h: 2.85rem; --label-col: 3.2rem; --hall-col: 6.25rem; }
16+
:root {
17+
--floor-h: 2.85rem;
18+
--label-col: 3.2rem;
19+
--hall-col: 6.25rem;
20+
}
1721
}
1822
@media (prefers-reduced-motion: reduce) {
19-
:root { --cabin-travel: 0ms; }
23+
:root {
24+
--cabin-travel: 0ms;
25+
}
2026
}
2127

2228
@layer base {
23-
html { color-scheme: light; }
29+
html {
30+
color-scheme: light;
31+
}
2432
body {
2533
@apply min-h-screen text-ink-900 font-sans antialiased;
2634
background-color: theme('colors.paper.100');
2735
background-image:
28-
radial-gradient(46rem 28rem at 92% -8%, rgba(0, 173, 216, 0.10), transparent 60%),
36+
radial-gradient(46rem 28rem at 92% -8%, rgba(0, 173, 216, 0.1), transparent 60%),
2937
radial-gradient(42rem 28rem at -8% 108%, rgba(201, 121, 33, 0.07), transparent 60%),
3038
url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='180' height='180'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 0.05 0 0 0 0 0.1 0 0 0 0 0.17 0 0 0 0.07 0'/></filter><rect width='100%25' height='100%25' filter='url(%23n)'/></svg>");
3139
}
40+
::selection {
41+
background: theme('colors.gopher.500');
42+
color: theme('colors.paper.50');
43+
}
3244
::selection { background: theme('colors.gopher.500'); color: theme('colors.paper.50'); }
3345
}
3446

3547
@layer components {
36-
.frame { @apply mx-auto max-w-6xl px-4 sm:px-6; }
48+
.frame {
49+
@apply mx-auto max-w-6xl px-4 sm:px-6;
50+
}
3751

3852
.card {
3953
@apply rounded-xl bg-paper-50/80 backdrop-blur-sm;
4054
border: 1px solid var(--rule);
41-
box-shadow: 0 1px 0 rgba(255, 255, 255, 0.6) inset, 0 16px 32px -22px rgba(14, 27, 44, 0.22);
55+
box-shadow:
56+
0 1px 0 rgba(255, 255, 255, 0.6) inset,
57+
0 16px 32px -22px rgba(14, 27, 44, 0.22);
4258
}
4359

4460
.btn {
@@ -48,18 +64,32 @@
4864
background: theme('colors.paper.50');
4965
color: theme('colors.ink.900');
5066
}
67+
.btn:hover:not(:disabled) {
68+
border-color: theme('colors.ink.900');
69+
}
5170
.btn:hover:not(:disabled) { border-color: theme('colors.ink.900'); }
5271

5372
.btn-primary {
54-
background: theme('colors.ink.900'); color: theme('colors.paper.50');
73+
background: theme('colors.ink.900');
74+
color: theme('colors.paper.50');
5575
border-color: theme('colors.ink.900');
5676
}
77+
.btn-primary:hover:not(:disabled) {
78+
background: theme('colors.gopher.500');
79+
border-color: theme('colors.gopher.500');
80+
color: theme('colors.ink.900');
81+
}
5782
.btn-primary:hover:not(:disabled) { background: theme('colors.gopher.500'); border-color: theme('colors.gopher.500'); color: theme('colors.ink.900'); }
5883

5984
.btn-danger {
60-
background: theme('colors.amber.500'); color: theme('colors.paper.50');
85+
background: theme('colors.amber.500');
86+
color: theme('colors.paper.50');
6187
border-color: theme('colors.amber.500');
6288
}
89+
.btn-danger:hover:not(:disabled) {
90+
background: theme('colors.amber.600');
91+
border-color: theme('colors.amber.600');
92+
}
6393
.btn-danger:hover:not(:disabled) { background: theme('colors.amber.600'); border-color: theme('colors.amber.600'); }
6494

6595
.btn-segment {
@@ -68,6 +98,21 @@
6898
border-right: 1px solid var(--rule);
6999
color: theme('colors.ink.500');
70100
}
101+
.btn-segment:last-child {
102+
border-right: 0;
103+
}
104+
.btn-segment:hover {
105+
color: theme('colors.ink.900');
106+
background: rgba(229, 221, 196, 0.6);
107+
}
108+
.btn-segment-active {
109+
color: theme('colors.paper.50');
110+
background: theme('colors.ink.900');
111+
}
112+
.btn-segment-active:hover {
113+
background: theme('colors.ink.900');
114+
color: theme('colors.paper.50');
115+
}
71116
.btn-segment:last-child { border-right: 0; }
72117
.btn-segment:hover { color: theme('colors.ink.900'); background: rgba(229, 221, 196, 0.6); }
73118
.btn-segment-active { color: theme('colors.paper.50'); background: theme('colors.ink.900'); }
@@ -79,6 +124,11 @@
79124
background: theme('colors.paper.50');
80125
color: theme('colors.ink.900');
81126
}
127+
.input:focus {
128+
outline: none;
129+
border-color: theme('colors.ink.900');
130+
box-shadow: 0 0 0 3px rgba(0, 173, 216, 0.18);
131+
}
82132
.input:focus { outline: none; border-color: theme('colors.ink.900'); box-shadow: 0 0 0 3px rgba(0, 173, 216, 0.18); }
83133

84134
.mono { @apply font-mono tabular-nums; }
@@ -99,20 +149,52 @@
99149
theme('colors.paper.50');
100150
border: 1px solid var(--rule);
101151
}
152+
.eyebrow {
153+
@apply mono text-[0.66rem] uppercase tracking-[0.18em] text-ink-500;
154+
}
155+
156+
.pill {
157+
@apply inline-flex items-center gap-1.5 rounded-full px-2.5 py-0.5 text-[0.7rem] font-medium;
158+
border: 1px solid var(--rule);
159+
background: theme('colors.paper.50');
160+
}
161+
.pill .dot {
162+
@apply inline-block h-1.5 w-1.5 rounded-full bg-current;
163+
}
164+
165+
/* — Building schematic — */
166+
.schematic {
167+
@apply relative isolate overflow-hidden rounded-lg;
168+
background:
169+
repeating-linear-gradient(
170+
90deg,
171+
transparent 0 calc(50% - 0.5px),
172+
rgba(14, 27, 44, 0.04) calc(50% - 0.5px) calc(50% + 0.5px),
173+
transparent calc(50% + 0.5px) 100%
174+
),
175+
theme('colors.paper.50');
176+
border: 1px solid var(--rule);
177+
}
102178

103179
.building-grid {
104180
display: grid;
105181
grid-template-columns: var(--label-col) minmax(0, 1fr) var(--hall-col);
106182
grid-auto-rows: var(--floor-h);
107183
}
108-
.building-row { @apply contents; }
184+
.building-row {
185+
@apply contents;
186+
}
109187

110188
.floor-label {
111189
@apply mono grid place-items-center text-[0.7rem] text-ink-500;
112190
border-right: 1px dashed var(--rule);
113191
}
114-
.floor-cell { border-top: 1px solid var(--rule-soft); }
115-
.floor-cell:first-of-type { border-top: 0; }
192+
.floor-cell {
193+
border-top: 1px solid var(--rule-soft);
194+
}
195+
.floor-cell:first-of-type {
196+
border-top: 0;
197+
}
116198
.hall-cell {
117199
@apply flex items-center justify-end gap-1 pr-2.5;
118200
border-left: 1px dashed var(--rule);
@@ -125,7 +207,10 @@
125207
background: theme('colors.paper.50');
126208
color: theme('colors.ink.500');
127209
}
128-
.hall-btn:hover { border-color: theme('colors.ink.900'); color: theme('colors.ink.900'); }
210+
.hall-btn:hover {
211+
border-color: theme('colors.ink.900');
212+
color: theme('colors.ink.900');
213+
}
129214
.hall-btn-pending {
130215
background: theme('colors.gopher.500');
131216
color: theme('colors.paper.50');
@@ -138,11 +223,19 @@
138223
border: 1.5px solid theme('colors.ink.900');
139224
background: theme('colors.paper.50');
140225
color: theme('colors.ink.900');
141-
transition: bottom var(--cabin-travel) var(--cabin-easing), background var(--cabin-travel) ease, color var(--cabin-travel) ease;
226+
transition:
227+
bottom var(--cabin-travel) var(--cabin-easing),
228+
background var(--cabin-travel) ease,
229+
color var(--cabin-travel) ease;
142230
}
143231
.cabin::before {
144-
content: ""; position: absolute; inset: 3px;
145-
border: 1px dashed currentColor; opacity: 0.25; border-radius: 1px; pointer-events: none;
232+
content: '';
233+
position: absolute;
234+
inset: 3px;
235+
border: 1px dashed currentColor;
236+
opacity: 0.25;
237+
border-radius: 1px;
238+
pointer-events: none;
146239
}
147240
.cabin-open {
148241
background: theme('colors.gopher.500');
@@ -162,7 +255,10 @@
162255
background: theme('colors.paper.50');
163256
color: theme('colors.ink.500');
164257
}
165-
.cabin-key:hover:not(:disabled) { border-color: theme('colors.ink.900'); color: theme('colors.ink.900'); }
258+
.cabin-key:hover:not(:disabled) {
259+
border-color: theme('colors.ink.900');
260+
color: theme('colors.ink.900');
261+
}
166262
.cabin-key-queued {
167263
background: theme('colors.gopher.100');
168264
border-color: theme('colors.gopher.500');
@@ -180,6 +276,12 @@
180276
border-radius: 4px;
181277
background: theme('colors.paper.50');
182278
}
279+
.stat dt {
280+
@apply eyebrow;
281+
}
282+
.stat dd {
283+
@apply mono text-sm font-semibold text-ink-900;
284+
}
183285
.stat dt { @apply eyebrow; }
184286
.stat dd { @apply mono text-sm font-semibold text-ink-900; }
185287
}

web/src/views/building.ts

Lines changed: 56 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,15 @@ export interface BuildingHandlers {
99
onCabinSelect(elevatorId: number, floor: number): void;
1010
}
1111

12-
interface CabinNodes { shell: HTMLElement; badge: HTMLElement; }
13-
interface PanelNodes { panel: HTMLElement; status: HTMLElement; buttons: HTMLButtonElement[]; }
12+
interface CabinNodes {
13+
shell: HTMLElement;
14+
badge: HTMLElement;
15+
}
16+
interface PanelNodes {
17+
panel: HTMLElement;
18+
status: HTMLElement;
19+
buttons: HTMLButtonElement[];
20+
}
1421

1522
export class BuildingView {
1623
private floors = 0;
@@ -34,7 +41,9 @@ export class BuildingView {
3441
private scaffold(s: Snapshot): void {
3542
this.floors = s.floors;
3643
this.cabinCount = s.elevators.length;
37-
this.cabins.clear(); this.halls.clear(); this.panels.clear();
44+
this.cabins.clear();
45+
this.halls.clear();
46+
this.panels.clear();
3847

3948
const rows: HTMLElement[] = [];
4049
for (let f = s.floors; f >= 1; f--) rows.push(this.row(f, s.floors));
@@ -50,13 +59,20 @@ export class BuildingView {
5059
this.shaft!.appendChild(nodes.shell);
5160
});
5261

53-
mount(this.root, h('div', {
54-
class: 'schematic',
55-
style: `--floors:${s.floors}`,
56-
}, [
57-
h('div', { class: 'building-grid', role: 'grid', 'aria-label': 'Building' }, rows),
58-
this.shaft,
59-
]));
62+
mount(
63+
this.root,
64+
h(
65+
'div',
66+
{
67+
class: 'schematic',
68+
style: `--floors:${s.floors}`,
69+
},
70+
[
71+
h('div', { class: 'building-grid', role: 'grid', 'aria-label': 'Building' }, rows),
72+
this.shaft,
73+
],
74+
),
75+
);
6076
mount(this.panelRoot, this.allPanels(s));
6177
}
6278

@@ -72,18 +88,27 @@ export class BuildingView {
7288
}
7389

7490
private hallBtn(floor: number, dir: Hall): HTMLButtonElement {
75-
const btn = h('button', {
76-
type: 'button', class: 'hall-btn',
77-
'aria-label': `Call ${dir} from floor ${floor}`,
78-
onClick: () => this.handlers.onHallCall(floor, dir),
79-
}, DIRECTION_GLYPH[dir] ?? '');
91+
const btn = h(
92+
'button',
93+
{
94+
type: 'button',
95+
class: 'hall-btn',
96+
'aria-label': `Call ${dir} from floor ${floor}`,
97+
onClick: () => this.handlers.onHallCall(floor, dir),
98+
},
99+
DIRECTION_GLYPH[dir] ?? '',
100+
);
80101
this.halls.set(`${floor}-${dir}`, btn);
81102
return btn;
82103
}
83104

84105
private cabin(e: Elevator, i: number, total: number): CabinNodes {
85106
const badge = h('span', { class: 'mono text-[11px]' });
86-
const shell = h('div', { class: 'cabin', style: shaftStyle(i, this.cabinCount, e.currentFloor, total) }, [badge]);
107+
const shell = h(
108+
'div',
109+
{ class: 'cabin', style: shaftStyle(i, this.cabinCount, e.currentFloor, total) },
110+
[badge],
111+
);
87112
return { shell, badge };
88113
}
89114

@@ -100,16 +125,25 @@ export class BuildingView {
100125
private panel(e: Elevator, i: number, total: number): PanelNodes {
101126
const status = h('span', { class: 'eyebrow' });
102127
const buttons: HTMLButtonElement[] = [];
103-
const grid = h('div', { class: 'grid grid-cols-5 gap-1.5 sm:grid-cols-6 lg:grid-cols-5' },
128+
const grid = h(
129+
'div',
130+
{ class: 'grid grid-cols-5 gap-1.5 sm:grid-cols-6 lg:grid-cols-5' },
104131
Array.from({ length: total }, (_, k) => {
105132
const floor = k + 1;
106-
const btn = h('button', {
107-
type: 'button', class: 'cabin-key', 'data-floor': floor,
108-
onClick: () => this.handlers.onCabinSelect(e.id, floor),
109-
}, String(floor));
133+
const btn = h(
134+
'button',
135+
{
136+
type: 'button',
137+
class: 'cabin-key',
138+
'data-floor': floor,
139+
onClick: () => this.handlers.onCabinSelect(e.id, floor),
140+
},
141+
String(floor),
142+
);
110143
buttons.push(btn);
111144
return btn;
112-
}));
145+
}),
146+
);
113147
const panel = h('article', { class: 'card p-4', 'aria-label': `Cabin #${e.id}` }, [
114148
h('header', { class: 'mb-3 flex items-center justify-between' }, [
115149
h('div', { class: 'flex items-center gap-2' }, [

0 commit comments

Comments
 (0)