Skip to content

feat(docs-next): Collapsable table of contents#2240

Draft
abovedave wants to merge 256 commits intomainfrom
STACKS-843/refined-toc
Draft

feat(docs-next): Collapsable table of contents#2240
abovedave wants to merge 256 commits intomainfrom
STACKS-843/refined-toc

Conversation

@abovedave
Copy link
Copy Markdown
Collaborator

Adds back a more refined table of contents treatment for smaller screens.

dancormier and others added 30 commits April 15, 2026 12:32
Removes 88 files (~10 MB) from static/legacy/ that are not referenced
by stacks-docs-next or the fragment HTML files:

- assets/dist/ (entire directory, ~8.1 MB)
  - docs.css — not loaded by stacks-docs-next or any fragment
  - docs.js.LICENSE.txt — build artifact, not served
  - entry.stacks-editor.js — 6 MB bundle, not loaded
  - all other entry.*.js files — not loaded by stacks-docs-next

- assets/img/ (76 unreferenced images, ~2 MB)
  - logos/ — entire brand logos directory (56 files)
  - icons/ — logo glyph SVGs (6 files)
  - favicons/ — favicon files (3 files)
  - various root-level images not referenced by any fragment

Remaining in assets/img/: the 10 images actually used by fragments
(avatar and email preview assets).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replaces 38 static legacy HTML fragments with mdsvex Markdown files in
src/docs/public/system/, served natively by the SvelteKit page server.

Converted pages (base/ and components/ and foundation/):
- base/height, margin, padding, width
- components/activity-indicator, avatars, badges, bling, breadcrumbs,
  button-groups, cards, code-blocks, empty-states, expandable, inputs,
  labels, link-previews, links, loader, menus, page-titles, pagination,
  post-summary, progress-bars, radio, select, tables, tags, textarea,
  toggle-switch, topbar, uploader, user-cards, vote
- foundation/accessibility, color-fundamentals, colors, typography

Each MD file has YAML frontmatter (title, description, svelte URL,
figma URL where available) extracted from the legacy fragment header,
with the content HTML following.

Also removed the `legacy:` field from structure.yaml for all 67 pages
(38 newly converted + 29 that already had MD files but were being
bypassed by the legacy-first serving order).

10 pages remain as legacy fragments because they contain inline
<script> demos that require manual conversion to Svelte components:
banners, buttons (already has full index.md), checkbox, editor,
modals, navigation, notices, popovers, prose, sidebar-widgets, theming.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…r to mdsvex

Establishes the pattern for converting legacy HTML docs pages to clean,
maintainable mdsvex.

**ClassTable.svelte** — generic CSS class documentation table:
- Auto-detects which columns to show based on the data (no config needed)
- Supports both component pages (modifies/description) and base utility
  pages (output/define/responsive) with the same component
- Exports ClassTableRow type for use in page script blocks

**activity-indicator.md** — prototype of the new page format:
- 588 lines → 92 lines
- Uses the actual ActivityIndicator Svelte component for live demos
  instead of pre-rendered HTML
- Uses ClassTable with typed class data
- Uses standard markdown headings (processed by rehype-slug +
  rehype-autolink-headings — no custom heading component needed)
- Uses fenced code blocks for HTML usage examples

The same pattern applies to all other converted pages:
1. Import ClassTable + the relevant stacks-svelte component
2. Define class data as a typed array in the script block
3. Use markdown headings + prose
4. Render live demos with Svelte components
5. Show HTML class usage in fenced code blocks

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…a11y

- Prop was named 'rows' but usage passes '{classes}', causing rows to be
  undefined on render
- Added role="region" + aria-label to the scrollable wrapper so tabindex
  on a non-interactive element is valid

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… order

- Code block first, then live example (matching original layout)
- Restore all compound examples:
  - Standalone indicators (empty, numbers, text)
  - Activity indicator on avatar (ActivityIndicator + Icon + raw s-avatar HTML)
  - Activity indicator on notification icon (Icon + ActivityIndicator with positioning classes)
  - Activity indicator count pill on notification icon
- Use {#each} over variants to eliminate repetition in the Variations section
- Replace @svg.* C# syntax in code blocks with commented HTML equivalents

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…kage

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Example.svelte wraps live demos in a light gray bordered container
with padding, keeping examples visually distinct from prose and code
blocks. Used in activity-indicator.md as the pattern to follow.

Also adds TODO comments in both the script block and the two avatar
examples noting where IconShieldXSm should be added once the icon
is published in @stackoverflow/stacks-icons.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Changes rehype-autolink-headings from behavior:"wrap" (which made the
heading text itself a silent link) to behavior:"append" (which appends
the IconLink SVG after the heading text).

Pairs with CSS in app.css that makes h2/h3/h4 flex containers so the
icon is pushed to the right edge, matching the original legacy layout.
The anchor is aria-hidden so screen readers aren't confused by the
duplicate link — the heading id is the accessible anchor.

This is a site-wide fix that works automatically for all mdsvex pages
without needing a custom heading component.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…in breadcrumb

Removes the "Copy" button from the page actions row and adds a small
link icon button (s-btn__xs s-btn__clear s-btn__icon) inline at the end
of the breadcrumb nav. Clicking it copies the current page URL to the
clipboard using the existing copyToClipboard action.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…button

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…b copy link

- Replace raw <button> with <Button link icon> using the link prop
- Handle clipboard write with an inline async onclick instead of the
  use:copyToClipboard action (actions can't be applied to components)
- Size icon with w16 h16 Stacks atomic classes — removes the custom CSS
  rule and the .breadcrumb-copy-link class
- Remove unused copyToClipboard import and copysuccess window listener

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Remove flex--item from nav; nav is already a flex child via the outer div
- Make nav itself d-flex ai-center g6 so items are evenly spaced and
  vertically aligned, including the copy link button
- Remove pr6/mr6 from individual items — gap handles all spacing
- Move separator before each item (index !== 0) instead of after,
  which is cleaner with a flex gap layout
- Remove ml4 from Button — gap handles the spacing

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds @stackoverflow/stacks-icons-legacy as a dependency (workspace *).
IconShieldXSm lives there rather than in the main stacks-icons package.
Restores the shield badge icon to both the Default and Variations avatar
examples in activity-indicator.md.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… reordering to top

Replaces md:order-first (which moved the TOC to the top of the page in
column layout) with md:d-none (hides it entirely). Also removes the now-
unused collapsible toggle button, isOpen state, and related Icon imports.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…scroll

wmn1 (min-width: 1rem) prevented the content column from shrinking
below that value in a flex container. wmn0 (min-width: 0) is the
standard CSS fix that allows flex children to shrink to fit the
available viewport width.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ilities

- flex--item9  → fl-grow1  (main content column; grows to fill space)
- flex--item3  → fl-shrink0 w25  (TOC sidebar; fixed 25% width)
- flex--item6  → w50  (sidebar footer GitHub/ThemeToggle halves)
- flex--item   → removed  (bare flex--item on buttons/badges was
                           redundant — they're already flex children)
- flex--item in GridColumn → fl-grow1

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds wmx12 (max-width: 1280px) + w100 to the article element so it
never exceeds 1280px but still fills narrower viewports fully.

With the TOC sidebar at w25 (25% = 320px), the content column (fl-grow1)
naturally occupies the remaining ~75% = ~960px at max width, matching
the ws9 threshold the user wanted without needing a custom class.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
wmx9 = max-width: var(--su960) — the .doc column grows via fl-grow1
to fill available space but never exceeds 960px, and still shrinks via
wmn0 when the viewport is narrow. The article is left at w100 with
mx-auto so the TOC sidebar and padding are not artificially constrained.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1113 lines → 235. Uses Avatar and ActivityIndicator Svelte components
for live demos and {#each sizes} to eliminate copy-pasted size variants.

Three example sections:
- Users: size table using Avatar with src image
- Activity: size table using Avatar with status='online'
- Stack Internal: size table with 3 columns (no color / custom color /
  custom avatar), each using Avatar with badge + letter or src props

Code blocks kept verbatim from original (including @Svg.ShieldXSm Razor
syntax as that is what was shown in the legacy docs).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…Internal examples

- Column 1: bg-blue-400 (no custom color)
- Column 2: bg-theme-primary (custom brand color)
- Column 3: team-avatar.png (custom image)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… / Brand color / Custom avatar

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds overflow-visible to Example.svelte so content (dropdowns, tooltips,
etc.) is not clipped by the bordered container. Also removes the
overflow-x-auto wrapper divs from the avatars tables accordingly.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…Custom color

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…buttons

Replaces size='sm' weight='clear' with the link prop on the three page
action buttons, matching the style of the copy-link button. Wraps them
in a d-flex ai-center g8 container for consistent spacing.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
dancormier and others added 25 commits April 20, 2026 14:24
Replace the writable-store-based column counting in Grid/GridColumn
with a plain CSS grid layout. The store caused `grid__0` to render on
the initial SSR pass because children hadn't updated the count yet.

The new layout uses `repeat(auto-fit, minmax(min(220px, 100%), 1fr))`
for equal-width, gap-consistent columns, with a single-column breakpoint
at the sm: breakpoint (48.75rem) for mobile stacking.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- layout.svelte: add mt24 above hero images so they don't butt against
  the page header
- ColorHeadlines: fix Navigation margin (mbn24 → mb8)
- ColorCodes: fix horizontal overflow — switch grid columns from
  `repeat(6, 1fr)` to `repeat(6, minmax(0, 1fr))` so swatches shrink
  to fit the container; remove overflow-auto
- TypographyWeights / TypographyCharacter: remove ws-nowrap from
  Navigation; add mb8 spacing below the tab bar
- TypographyCharacter: replace non-existent bg-brand-orange utility
  with inline style using the --brand-color-orange CSS variable
- TypographyNotch: same fix for bg-brand-beige → --brand-color-beige
- brand/typography/index.md: add mt16 gap between TypographyWeights
  demo and the Grid below it

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
docs-copy styling:
- naming.md, styleguide.md, messages.md: add docs-copy class to all
  <ul> elements inside Grid/GridColumn slots (rehype only applies it to
  markdown-level elements, not HTML in Svelte slots)

settings.md:
- Replace raw <input class="s-checkbox"> markup with Checkbox Svelte
  component
- Replace raw <input class="s-input"> markup with TextInput Svelte
  component (with {#snippet description()} for helper text)

voice.md:
- Add docs-copy to all <p> elements inside GridColumn slots
- Add scoped <style> to bring <h1> from the global fs-display3 (72px)
  down to fs-headline1 (28px) — the global rule is designed for page
  titles, not inline copy example blocks

accessibility/alt.md:
- Convert inline s-notice div to <Notice> Svelte component
- Wrap example boxes in <Example>

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Remove the legacy conversion checklist (that work is now complete) and
replace with forward-focused guidance: page anatomy, adding new pages,
doc component reference, Grid/GridColumn usage, and key gotchas
(docs-copy in Svelte slots, Notice p-tag rule, global h1 sizing,
missing bg-brand-* utility classes).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add fullWidth/hideToc page data flags; layout applies w100 to <main>
  and suppresses the Contents TOC sidebar on the icons page only
- Hide the icon inspector aside on all screen sizes when nothing is selected

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
stacks-editor and stacks-icons-legacy were added to package.json in
previous commits but the lockfile workspace metadata was not updated,
causing npm ci to fail on Netlify.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Rollup (used by Vite for production builds) cannot statically extract
named exports from webpack's UMD bundle format, causing
"hidePopover is not exported" when stacks-editor's ESM source imports
from @stackoverflow/stacks.

- Add lib/esm-no-css.ts: an ESM entry that mirrors lib/index.ts but
  omits the CSS side-effect (the docs site imports the CSS directly
  via app.css)
- Alias @stackoverflow/stacks to this entry in vite.config.ts (exact
  match via regex; subpath imports like /dist/css/stacks.css are
  unaffected)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Remove dead legacy-rendering code from +page.server.ts and +page.svelte
- Rename .doc class to .docs for consistency
- Replace .docs-editor-tall with .hmn6 applied directly to StacksEditorDemo
- Move editor docs and example content into editor/ subdirectory
- Colocate backgrounds SVG with its docs page in backgrounds/ subdirectory

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…icator

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…tion

Moves Checkbox, Inputs, Labels, Radio, Select, and Textarea out of
Components and into a new Forms section under Product.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ubsection]/+page.svelte

Co-authored-by: David Longworth <dlongworth@stackoverflow.com>
Co-authored-by: David Longworth <dlongworth@stackoverflow.com>
…body

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@abovedave abovedave changed the title STACKS-843: Collapsable table of contents feat(docs-next): Collapsable table of contents Apr 21, 2026
@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented Apr 21, 2026

⚠️ No Changeset found

Latest commit: f3f5300

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@abovedave abovedave requested a review from dancormier April 21, 2026 09:34
backdrop-filter: invert(1);
-webkit-backdrop-filter: invert(1);
}
@media (max-width: 71.875rem) {
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's no CSS var for md breakpoint, right?

Base automatically changed from STACKS-843/legacy-header-extraction to main April 21, 2026 17:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants