Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
209 changes: 123 additions & 86 deletions DESIGN.md

Large diffs are not rendered by default.

10 changes: 10 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 0 additions & 3 deletions packages/frontend/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,6 @@
(t === 'dark' || (!t && matchMedia('(prefers-color-scheme: dark)').matches)) ? 'dark' : 'light';
})();
</script>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=IBM+Plex+Sans:wght@400;500;600&display=swap" rel="stylesheet">
</head>
<body>
<div id="root"></div>
Expand Down
1 change: 1 addition & 0 deletions packages/frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
"typecheck": "tsc -b"
},
"dependencies": {
"@fontsource-variable/lexend": "^5.2.11",
"@jspsych/metadata": "^0.0.3",
"fflate": "^0.8.3",
"jsonld": "^8.3.2",
Expand Down
2 changes: 1 addition & 1 deletion packages/frontend/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ function App() {
</button>
)}
{page === 'landing'
? <Landing onStart={handleStart} />
? <Landing onStart={handleStart} embedded={embedded} />
: <AppShell
jsPsychMetadata={jsPsychMetadata}
existingMetadataFile={existingMetadataFile}
Expand Down
4 changes: 2 additions & 2 deletions packages/frontend/src/components/AppShell.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
.content {
flex: 1;
overflow-y: auto;
padding: 4.5rem 2rem 3rem;
padding: 3rem 2rem;
background-color: var(--c-bg);
}

Expand All @@ -21,7 +21,7 @@
border-radius: 20px;
padding: 0.35rem 0.85rem;
font-size: 0.82rem;
font-family: 'IBM Plex Sans', system-ui, sans-serif;
font-family: 'Lexend Variable', system-ui, -apple-system, sans-serif;
color: var(--c-ink-2);
cursor: pointer;
display: inline-flex;
Expand Down
10 changes: 5 additions & 5 deletions packages/frontend/src/components/JsonViewer.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@
}

.toggle:hover {
color: #13b24b;
color: var(--c-accent);
}

.hidden {
Expand All @@ -61,8 +61,8 @@

/* Dark mode token overrides — media query covers OS dark mode, data-theme covers manual toggle */
@media (prefers-color-scheme: dark) {
.key { color: #13b24b; } /* logo bright green — readable on dark bg */
.str { color: #f78f1e; } /* logo amber (hue ~34°) — full brightness on dark */
.key { color: #32bb64; } /* theme dark primary green — readable on dark bg */
.str { color: #ff9c3b; } /* theme dark orange — full brightness on dark */
.num { color: #f03d2a; } /* clear red (hue ~5°) — 3.3:1 on dark bg */
.bool { color: #4bd172; } /* lighter green, distinct from key — 6.6:1 on dark bg */
.null { color: #6b7280; }
Expand All @@ -73,8 +73,8 @@
.toggle { color: #6b7280; }
}

:global([data-theme="dark"]) .key { color: #13b24b; }
:global([data-theme="dark"]) .str { color: #f78f1e; }
:global([data-theme="dark"]) .key { color: #32bb64; }
:global([data-theme="dark"]) .str { color: #ff9c3b; }
:global([data-theme="dark"]) .num { color: #f03d2a; }
:global([data-theme="dark"]) .bool { color: #4bd172; }
:global([data-theme="dark"]) .null { color: #6b7280; }
Expand Down
30 changes: 0 additions & 30 deletions packages/frontend/src/components/PageHeader.module.css

This file was deleted.

15 changes: 0 additions & 15 deletions packages/frontend/src/components/PageHeader.tsx

This file was deleted.

120 changes: 84 additions & 36 deletions packages/frontend/src/components/Sidebar.module.css
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
.sidebar {
width: 210px;
min-width: 210px;
background-color: var(--c-bg-sidebar);
background-color: var(--c-bg);
display: flex;
flex-direction: column;
padding: 1.5rem 0 1rem;
border-right: 1px solid var(--c-border);
border-right: 1px solid var(--c-border-sub);
}

.header {
Expand All @@ -30,82 +30,132 @@
.stepList {
list-style: none;
margin: 0;
padding: 0;
/* Node column aligns with the header/footer text (1.25rem from the sidebar
edge): 0.5rem list padding + 0.75rem step padding lands the node there.
--step-gap feeds both the row gap and the connector height below. */
padding: 0 0.5rem;
--step-gap: 0.3rem;
display: flex;
flex-direction: column;
gap: 1px;
gap: var(--step-gap);
flex: 1;
}

/* Each step is a row: a node on a vertical connector, then a label. The
connector threads every node so the list reads as a flow of steps, not a
bullet list — filled green through completed steps, muted for the road ahead. */
.step {
position: relative;
display: flex;
align-items: center;
gap: 0.65rem;
gap: 0.7rem;
width: 100%;
padding: 0.55rem 1.25rem 0.55rem calc(1.25rem - 3px);
padding: 0.55rem 0.75rem;
background: none;
border: none;
border-left: 3px solid transparent;
border-radius: 0;
border-radius: 7px;
color: var(--c-ink-2);
font-size: 0.88rem;
font-size: 1rem;
font-weight: 400;
font-family: inherit;
cursor: pointer;
text-align: left;
transition: color 0.15s, background-color 0.15s, border-color 0.15s;
transition: color 0.15s, background-color 0.15s;
}

/* Connector: from this node's center down to the next node's. Equal-height rows
make calc(100% + gap) land exactly on the next node. Paints over the active
pill (positioned z-index:0 beats the button background) but under the node
(z-index:1). Every .step is the ONLY child of its <li>, so the last step is
suppressed via the last <li> — NOT :last-child on the button (always true).
Green through completed steps (progress), muted for the road ahead. */
.step::before {
content: '';
position: absolute;
left: calc(0.75rem + 11px); /* step padding-left + node radius = node center */
top: 50%;
width: 2px;
height: calc(100% + var(--step-gap));
transform: translateX(-50%);
background: var(--c-border);
z-index: 0;
}

.stepList li:last-child .step::before {
display: none;
}

.step:hover:not(:disabled) {
.completed::before {
background: var(--c-forest-bright);
}

.step:hover:not(:disabled):not(.active) {
color: var(--c-ink);
background-color: var(--c-bg-card-hover);
background-color: var(--c-bg-raised);
}

.active {
border-left-color: var(--c-amber-text);
background-color: rgba(247, 143, 30, 0.12);
color: var(--c-amber-text);
background-color: var(--c-accent-wash);
color: var(--c-accent);
font-weight: 600;
}

.completed {
color: var(--c-ink-2);
color: var(--c-ink);
}

.locked {
color: var(--c-ink-3);
cursor: not-allowed;
}

/* Node: a 22px circle on the connector. Default = hollow muted ring (upcoming);
active = accent ring with a filled center dot; completed = solid green disc
with a check. */
.indicator {
width: 16px;
position: relative;
z-index: 1;
box-sizing: border-box;
width: 22px;
height: 22px;
border-radius: 50%;
border: 2px solid var(--c-border);
background: var(--c-bg);
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
font-size: 0.75rem;
color: var(--c-forest-bright);
font-size: 0.72rem;
font-weight: 600;
color: var(--c-cta-text); /* the ✓ glyph — legible on the green disc, both modes */
transition: border-color 0.15s, background-color 0.15s;
}

.active .indicator {
border-color: var(--c-accent);
}

.completed .indicator {
border-color: var(--c-forest-bright);
background: var(--c-forest-bright);
}

/* Inner dot — only on the active node (ring + dot); hidden on the others. */
.dot {
display: block;
width: 5px;
height: 5px;
display: none;
width: 8px;
height: 8px;
border-radius: 50%;
background-color: var(--c-ink-4);
background-color: var(--c-accent);
}

.active .dot {
background-color: var(--c-amber-text);
}

.locked .dot {
background-color: var(--c-ink-3);
display: block;
}

.footer {
padding: 1rem 1.25rem 0;
border-top: 1px solid var(--c-border);
border-top: 1px solid var(--c-border-sub);
margin-top: 0.5rem;
display: flex;
flex-direction: column;
Expand Down Expand Up @@ -144,15 +194,14 @@
border-color: var(--c-danger);
}

/* Light mode: locked steps need to look clearly faded vs the dark base step color.
--c-ink-3 (oklch 52%) is too close to --c-ink-2 (oklch 37%) on the pale sidebar. */
/* Light mode: locked steps read clearly faded — --c-ink-3 (oklch 52%) sits too
close to --c-ink-2 (37%) on the pale sidebar, so lift the locked label lighter. */
:global([data-theme="light"]) .locked { color: oklch(66% 0.008 155); }
:global([data-theme="light"]) .locked .dot { background-color: oklch(66% 0.008 155); }

/* Light mode: Start Over border (--c-danger-border at oklch 88%) is near-invisible on the
pale sidebar (oklch 94%). Give it a tinted background and a readable border. */
:global(:root:not([data-theme="dark"])) .startOver {
background-color: rgba(217, 48, 37, 0.07);
background-color: rgba(219, 52, 36, 0.07);
border-color: oklch(82% 0.09 27);
}

Expand All @@ -161,10 +210,9 @@
background-color: var(--c-danger-bg);
}

/* Dark mode: increase contrast of sidebar text and border */
:global([data-theme="dark"]) .sidebar { border-right-color: #4e5f57; }
/* Dark mode: lift sidebar text contrast (the divider stays a hairline so the
nav reads as part of the content surface, not a walled-off zone). */
:global([data-theme="dark"]) .appTitle { color: var(--c-ink); }
:global([data-theme="dark"]) .step:not(.active):not(.locked) { color: oklch(82% 0.012 155); }
:global([data-theme="dark"]) .psychdsLink { color: var(--c-ink-2); }
:global([data-theme="dark"]) .psychdsLink:hover { color: var(--c-forest-bright); }

Expand Down
Loading
Loading