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
3 changes: 1 addition & 2 deletions src/App.css
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,6 @@ button { font: inherit; }
ready states float as a small pill so they never push the lesson down. */
.r-status { display: flex; align-items: center; gap: 0.6rem; font-size: 0.85rem; padding: 0.45rem 0.6rem 0.45rem 0.9rem; border-radius: 999px; }
.r-status.ready, .r-status.busy {
position: fixed; z-index: 35; right: max(1rem, env(safe-area-inset-right)); bottom: max(1rem, env(safe-area-inset-bottom));
box-shadow: var(--shadow); border: 1px solid var(--line); background: var(--surface);
animation: pill-in var(--medium) var(--ease) both;
}
Expand Down Expand Up @@ -558,7 +557,7 @@ button { font: inherit; }
}

@media print {
.topbar, .sidebar, .nav-backdrop, .r-status, .lesson-nav, .reading-progress, .section-guide, .toaster { display: none !important; }
.topbar, .sidebar, .nav-backdrop, .r-status, .corner-stack, .lesson-nav, .reading-progress, .section-guide, .toaster { display: none !important; }
.app { display: block; }
body { background: #fff; }
.app-main { max-width: none; padding: 0; }
Expand Down
8 changes: 6 additions & 2 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ export default function App() {
<Sidebar open={navOpen} />
{navOpen && <div className="nav-backdrop" aria-hidden="true" onClick={() => setNavOpen(false)} />}
<main id="main" tabIndex={-1} className="app-main">
<RStatus />
<RStatus where="page" />
<div ref={page} className={`page page-${pathname.split('/')[1] || 'home'}`}>
<Routes key={restarts}>
<Route path="/" element={<Home />} />
Expand All @@ -135,7 +135,11 @@ export default function App() {
</div>
</main>
<Toaster />
<SiteGuide />
{/* One stack, so the helper and the R pill can never overlap, whatever their height. */}
<div className="corner-stack">
<SiteGuide />
<RStatus where="corner" />
</div>
<Tour />
</div>
);
Expand Down
7 changes: 6 additions & 1 deletion src/components/RStatus.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
import { useEffect, useState } from 'react';
import { onStatus, restartR, type RStatus as Status } from '../r/webrClient';

export default function RStatus() {
/**
* `where` splits the two homes: an error sits in the page ("page"), the ready
* and busy pill stacks under the helper in the corner ("corner").
*/
export default function RStatus({ where }: { where?: 'page' | 'corner' }) {
const [status, setStatus] = useState<Status>({ phase: 'idle' });
useEffect(() => onStatus(setStatus), []);

// Nothing has started yet, so claim nothing: an amber "Starting R…" pill for
// idle would be a lie on any page reached before the boot effect runs.
if (status.phase === 'idle') return null;
if (where === (status.phase === 'error' ? 'corner' : 'page')) return null;

if (status.phase === 'ready') {
return <div className="r-status ready"><span>R is ready</span><button type="button" onClick={restartR} title="Use this if R stops responding">Restart R</button></div>;
Expand Down
5 changes: 2 additions & 3 deletions src/components/SiteGuide.css
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/* The avatar helper in the bottom right corner. */
.site-guide { position: fixed; right: max(1rem, env(safe-area-inset-right)); bottom: max(1rem, env(safe-area-inset-bottom)); z-index: 50; display: flex; flex-direction: column; align-items: flex-end; gap: 0.6rem; }
.corner-stack { position: fixed; right: max(1rem, env(safe-area-inset-right)); bottom: max(1rem, env(safe-area-inset-bottom)); z-index: 50; display: flex; flex-direction: column; align-items: flex-end; gap: 0.6rem; }
.site-guide { display: flex; flex-direction: column; align-items: flex-end; gap: 0.6rem; }
.site-guide-button {
display: flex; align-items: center; gap: 0.4rem; padding: 0.25rem 0.9rem 0.25rem 0.25rem; border-radius: 999px; cursor: pointer;
border: 1.5px solid var(--brand); background: var(--surface); color: var(--brand-ink); font-weight: 700; box-shadow: var(--shadow-lg);
Expand Down Expand Up @@ -27,6 +28,4 @@
@media print { .site-guide { display: none; } }
.site-guide-compact .site-guide-label { display: none; }
.site-guide-compact .site-guide-button { padding: 0.25rem; }
/* The R status pill also sits bottom right: stand on top of it while it shows. */
body:has(.r-status.ready, .r-status.busy) .site-guide { bottom: calc(max(1rem, env(safe-area-inset-bottom)) + 3.5rem); }
.site-guide-tour { display: block; margin: 0.8rem 0 0; padding: 0; font: inherit; font-size: 0.88rem; background: none; border: 0; color: var(--brand-ink); text-decoration: underline; cursor: pointer; }