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
12 changes: 7 additions & 5 deletions .fork/customizations.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -674,11 +674,13 @@
absolutely positioned overlay outside the editor's scroll box — wraps and
paints straight through the 48px box, and stably so (the overlay never
changes the observed editor height, so the latch cannot rescue it). A
narrow viewport resolves tall regardless. States the designs do not draw
also resolve tall: an approval request, a pending user-input question, and
the plan follow-up banner all own the box's internals and carry their own
action rows. Attachments deliberately do not force tall — attachment cards
render as a full-width band above the inline row.
narrow viewport resolves tall regardless. On desktop slim the default
empty-state hint is a shorter string that still names @, $, and /; tall
keeps the long form. States the designs do not draw also resolve tall: an
approval request, a pending user-input question, and the plan follow-up
banner all own the box's internals and carry their own action rows.
Attachments deliberately do not force tall — attachment cards render as a
full-width band above the inline row.
The control row renders in every density, including collapsed; only its
left half is conditional. The run controls are gated on a pending approval
— they moved out of the box, which upstream unmounted wholesale during
Expand Down
5 changes: 5 additions & 0 deletions .fork/notes/FORK-CUSTOMIZATION-DECISIONS.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,11 @@ Related deep-dives that predate this file and stay where they are:
beats them regardless of specificity.
- Attachments forcing the tall shell was considered and declined; attachment cards render as a
full-width band above the inline row instead.
- Absolutely-positioned content in the prompt column is invisible to the wrap latch by
construction: it never changes the observed editor height. Phone widths already force tall for
that reason; on desktop slim the 64-character default hint wraps under the inline pills. Truncating
it would eat `$use skills` / `/ commands`, which have no other discovery surface — so slim uses a
shorter hint that still names `@`, `$`, and `/`, and tall keeps the long form.
- A general weakness worth remembering for future guards: the composer-shell guards assert on the
text of the stylesheet rather than on what it matches, so a selector that stops matching (for
example, upstream adding a second child inside the frame) keeps every guard green. Selecting
Expand Down
24 changes: 24 additions & 0 deletions apps/web/src/__fork_guards__/forkComposerShell.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,30 @@ describe("fork guard: fork-composer-shell", () => {
).toBe("tall");
});

it("shortens the empty-state hint in the slim shell instead of truncating it", () => {
// The absolute placeholder is invisible to the wrap latch (empty prompt ⇒
// latch false; placeholder only exists when empty). Truncating the 64-char
// default hint would eat `$use skills` / `/ commands`, which have no other
// discovery surface — so slim uses a shorter string that still names all
// three affordances, and tall keeps the long one.
expect(chatComposer).toMatch(
/isComposerSlim\s*\?\s*"Ask anything, @tag, \$skills, \/ commands"/u,
);
expect(chatComposer).toContain(
"Ask anything, @tag files/folders, $use skills, or / for commands",
);
// Truncation was considered and declined: no ellipsis rule on the
// placeholder sibling, so a sync that reintroduces one is a regression.
const rules = cssRules(theme);
const placeholderTruncate = rules.find(
(rule) =>
rule.selector.includes('[data-testid="composer-editor"]') &&
rule.selector.includes("~") &&
(rule.body.includes("text-overflow") || rule.body.includes("ellipsis")),
);
expect(placeholderTruncate, "slim placeholder must not truncate").toBeUndefined();
});

it("keeps the branch controls reachable while collapsed, and gates modes on approval", () => {
// Two upstream behaviours the control row has to preserve. Upstream showed
// BranchToolbar while collapsed (gated on showComposerContextStrip alone),
Expand Down
8 changes: 7 additions & 1 deletion apps/web/src/components/chat/ChatComposer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2769,7 +2769,13 @@ export const ChatComposer = memo(function ChatComposer(props: ChatComposerProps)
? "Enable a provider in Settings to send a message"
: phase === "disconnected"
? "Ask for follow-up changes or attach images"
: "Ask anything, @tag files/folders, $use skills, or / for commands"
: /* fork:begin fork-composer-shell — see .fork/customizations.yaml#fork-composer-shell */
// Absolute placeholder is invisible to the wrap latch. Slim shortens
// the hint so @/$/ stay discoverable instead of truncating them away.
isComposerSlim
? "Ask anything, @tag, $skills, / commands"
: /* fork:end fork-composer-shell */
"Ask anything, @tag files/folders, $use skills, or / for commands"
}
disabled={isConnecting || isComposerApprovalState || projectSelectionRequired}
/>
Expand Down
Loading