Rebuild the page actions row: Copy as markdown and Open in Claude - #3330
Draft
enf0rc3 wants to merge 5 commits into
Draft
Rebuild the page actions row: Copy as markdown and Open in Claude#3330enf0rc3 wants to merge 5 commits into
enf0rc3 wants to merge 5 commits into
Conversation
|
Pull request environment is available at https://stoctodocspr3330.z22.web.core.windows.net. You can view the ephemeral environment status in Octopus Deploy. This environment will be automatically deprovisioned when the pull request is closed, or after 7 days of inactivity. |
enf0rc3
force-pushed
the
wl/open-in-llm
branch
2 times, most recently
from
August 11, 2026 02:41
3c7c692 to
4eb9610
Compare
The "Use Octopus docs with AI" pill offered three markdown actions. The design replaces it with a split button: a primary "Open in Claude", and a caret that opens a list of assistants. Each entry hands the assistant this page's .md URL to read. The markdown actions come back as a separate copy button once the shared copy module lands. Both halves reuse the .btn component, so the pair matches "Edit on GitHub" beside it in the page actions row, and the whole control moves from the foot of the article up under the header. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The split button hand-wrote `class="btn btn--small"`. Astro compiles Button.astro's `.btn` rules to `.btn[data-astro-cid-ekguhzzh]` and only stamps that attribute on elements Button itself renders, so none of the button styles reached this markup. Reuse the component instead of its class names. Button gains an `as` prop so a `<details>` disclosure trigger can be a real Button: a `<summary>` is a list item that carries its own marker, and dragging over a trigger selects its text rather than opening it, so both resets belong with the rest of the button styles. `<summary>` has no native disabled state, so `disabled` maps to `aria-disabled`, which the existing state rules already key off. Move the `.octo-llm` rules out of main.css into the component. Reaching into Button from here needs `:global()`, because the parent's scope attribute lands on the Button root but never on the icon spans inside it. Keeping `.octo-llm` in front of the `:global()` leaves the compiled selector scoped, so these rules cannot escape the component. Verified against the built output: the emitted CSS is unchanged by the pending move of button styles into an imported stylesheet, since that changes where the rules are authored and not what they compile to. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The page actions row lost its copy action when the AI dropdown became a split button, on the grounds that it would come back once the shared copy module landed. It has, so this brings it back as its own button. copy-button.js grows two things. A labelled button now shows its result in its label rather than a tooltip, which is what the design asks for and what an icon-only button cannot do. And copyFetchedOnClick covers text that has to be fetched: it hands ClipboardItem a pending promise so the click's user activation survives the request, which awaiting the fetch first would spend. The eligibility check both page actions need moves to pageMarkdownUrl, so neither component re-derives the slug. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
globSync returns backslash-separated paths on Windows, and both call sites feed them into forward-slash logic. pathToSlug strips a trailing `/index`, so `argo-cd\index` kept its suffix and the page was written to dist/docs/argo-cd/index.md. Every request for /docs/argo-cd.md 404d, which took the page actions and llms.txt parity with it. The shared content lookup keys off path.posix.join, which leaves a backslash mid-key and never matches the include paths written in the source files. A page whose include failed to resolve was judged ineligible, so 1252 rather than 846 pages now get a .md companion on a Windows build. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
enf0rc3
force-pushed
the
wl/open-in-llm
branch
from
August 11, 2026 02:49
4eb9610 to
10242e3
Compare
`unclipped` and `neighbour` were only in comments, and `hrefs` only a local name, so none of them needs a dictionary entry. `neighbour` in particular would have committed the repo to a British spelling that the dictionary does not otherwise establish. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Implements two designs from Documentation vision: Open in LLM and Copy to clipboard.
What changed
The "Use Octopus docs with AI" pill at the foot of the article is gone. Under the page header, next to Edit on GitHub, there are now two actions:
Copy as markdown — fetches this page's
.mdcompanion and puts it on the clipboard. Swaps to a check icon and "Copied" for two seconds, then reverts.Open in Claude with a caret — the primary half opens Claude with a prompt pointing at the page's
.mdURL. The caret opens a 256px menu of Open in Claude, Open in ChatGPT, Open in Gemini, as link-styled rows with a provider logo and an external-link icon.Both are the
Buttoncomponent, so borders, radius, hover, pressed and focus states come from the design-system tokens.Buttongains anasprop so the caret can be a<summary>; the split button's two halves collapse into one divider via a negative margin, which keeps each half's focus ring unclipped. Menu chrome uses--colorMenuListBackground*and--shadowMedium, so both themes work with no extra rules.Four icons added under
src/assets/icons/, exported from the Figma file and applied as CSS masks so they take--colorIconPrimaryin a button and--colorTextLinkDefaultin the menu.Reusing the shared copy module
copy-button.js(from #3317) grows two things rather than the copy action reimplementing them:showResultwrites to.btn__labelwhen there is one, and falls back to the tooltip otherwise. The design wants the result in the label; the two existing icon-only consumers are unchanged.copyFetchedOnClickcovers text that has to be fetched. It handsClipboardItema pending promise so the click's user activation survives the request — awaiting the fetch first and then writing loses it in Safari, which is the trap the module's own comment warns about.The button also locks its measured width before the label shortens, so "Open in Claude" beside it doesn't shuffle. Measured rather than hardcoded, so it holds for any translation.
The eligibility check both actions need moved to
pageMarkdownUrl(), so neither component re-derives the slug.Fixes a markdown emitter bug on Windows
globSyncreturns backslash-separated paths on Windows andllm-md-emitter.tsfed them into forward-slash logic in two places. Two lines ofposix: true:pathToSlugstrips a trailing/index, soargo-cd\indexkept its suffix and the page was written todist/docs/argo-cd/index.md. Every request for/docs/argo-cd.md404d, taking the page actions and llms.txt parity with it.path.posix.join, which leaves a backslash mid-key and never matches the include paths in the source files. A page whose include failed to resolve was judged ineligible, so 1252 rather than 846 pages now get a.mdcompanion on a Windows build.Linux was unaffected, which is why this survived. It is in this PR because it is what the two new actions point at.
One thing to call out
Gemini points at AI Studio.
gemini.google.com/apphas no native prompt parameter — the?prompt=trick needs a browser extension. The label stays "Open in Gemini" per the design while the href isaistudio.google.com/prompts/new_chat?prompt=…, which does prefill. Happy to change the label if that reads wrong.Testing
astro buildfrom a cleandist: exit 0, 2673 pages, 1252.mdemitted.tests/llm-endpoints.spec.ts: 13 passed, 0 failed. The two CopyMarkdown tests are rewritten and two added for the copy action, including one that clicks it and reads the clipboard back to confirm the page markdown actually arrives. Before the emitter fix, five of these failed.Verified in a real browser in both themes: menu open and closed, and the copy button through rest, copied and reverted.
🤖 Generated with Claude Code