feat(steps): an early exit reads as a guard clause, not as a branch

A fork with nothing on one side is `if (!user) return` — a reader takes it as a
guard, not as a decision with two sides. Drawn as a branch it costs a column
and a step right, and a handler with four guards (every server handler) read as
four nested branches with three-quarters of the width holding the words
"returns here". It is now one line — the condition and where the code leaves —
with everything below it running because it did not, and the rail stays on its
own hairline. next-saas-starter's `signIn` goes from not fitting the screen to
fitting it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01REFyW9hmNrxhwN5wxRoAkC
This commit is contained in:
Colby McHenry
2026-08-29 13:53:50 -05:00
co-authored by Claude Opus 5
parent 22f92a828b
commit 75686502e3
2 changed files with 50 additions and 15 deletions
+5 -2
View File
@@ -623,8 +623,11 @@ layout engine, a column of boxes with a hairline down its left and a fork as a r
`StepBox.svelte`, the canvas's box exactly (the canvas wraps it in handles; the rail lets it size to its words), and so
are the click, the double-click-to-start-here and the panel. The fork's head says the decision once and its arms say
only which side they are — **WHEN** / **WHEN NOT** — except a `switch`, whose arms each have a case to say, and a
`try`, which says `on error` once. `StepsKey.svelte` is the key: floating over the canvas, last in the document on the
rail, which scrolls and cannot have things sitting on it.
`try`, which says `on error` once. **An early exit is drawn as a guard clause, not as a branch** — a fork with nothing on
one side (`if (!user) return`) is one line, the condition and where the code leaves (`userWithTeam.length === 0
· returns here`), with everything below it running because it did not; a rail of guard clauses would otherwise step
right once per guard and a handler with four of them would read as four nested branches. `StepsKey.svelte` is the key:
floating over the canvas, last in the document on the rail, which scrolls and cannot have things sitting on it.
**Which reading opens** travels in the URL (`&view=order` / `&view=tree`) and the summary offers both; without one the
answer's own `defaultView` decides — the code's order for a handler, an endpoint or any function, the tree for a
+45 -13
View File
@@ -58,20 +58,38 @@
</div>
{/if}
{:else if item.kind === 'fork'}
<div class="fork">
<div class="cond mono">{@render words(item.words)}</div>
<div class="arms">
{#each item.arms as arm, a (a)}
<div class="arm">
<div class="armh mono">{@render words(arm.words)}</div>
{#if arm.body.length > 0}
<Self items={arm.body} {project} {selected} {lit} {onSelect} {onStart} {canStart} />
{/if}
{#if arm.ends}<div class="ends">{arm.ends}</div>{/if}
</div>
{/each}
{@const guard = item.arms.length <= 2 && item.arms[0]?.body.length === 0 && item.arms[0]?.ends !== null}
{#if guard}
<!--
An early exit is a fork with nothing on one side: `if (!user) return`.
A reader takes it as a guard, not as a branch — one line saying where
the code leaves, and everything below it running when it did not — so
it is drawn as one, and the rail does not step right for it.
-->
<div class="guard">
<span class="cond mono">{@render words(item.words)}</span>
<span class="ends inline">{item.arms[0]!.ends}</span>
</div>
</div>
{#if item.arms[1] && item.arms[1].body.length > 0}
<Self items={item.arms[1].body} {project} {selected} {lit} {onSelect} {onStart} {canStart} />
{/if}
{#if item.arms[1]?.ends}<div class="ends">{item.arms[1].ends}</div>{/if}
{:else}
<div class="fork">
<div class="cond mono">{@render words(item.words)}</div>
<div class="arms">
{#each item.arms as arm, a (a)}
<div class="arm">
<div class="armh mono">{@render words(arm.words)}</div>
{#if arm.body.length > 0}
<Self items={arm.body} {project} {selected} {lit} {onSelect} {onStart} {canStart} />
{/if}
{#if arm.ends}<div class="ends">{arm.ends}</div>{/if}
</div>
{/each}
</div>
</div>
{/if}
{:else if item.kind === 'group'}
<div class="group" class:again={item.again}>
<div class="label">
@@ -178,6 +196,20 @@
padding-top: 4px;
align-self: stretch;
}
/* An early exit: the condition and where it leaves, on one line. */
.guard {
display: flex;
align-items: baseline;
gap: 8px;
max-width: 100%;
min-width: 0;
}
.ends.inline {
border-top: 0;
padding-top: 0;
align-self: auto;
white-space: nowrap;
}
.kw {
font-weight: 600;
}