Skip to content

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

Merged
dancormier merged 264 commits intomainfrom
STACKS-843/refined-toc
May 1, 2026
Merged

feat(docs-next): Collapsable table of contents#2240
dancormier merged 264 commits intomainfrom
STACKS-843/refined-toc

Conversation

@abovedave
Copy link
Copy Markdown
Collaborator

@abovedave abovedave commented Apr 21, 2026

STACKS-869

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

Screenshot 2026-04-22 at 17 35 32

dancormier and others added 30 commits April 15, 2026 13:24
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>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replaces IntersectionObserver with a passive scroll listener. The active
item is now always the last heading whose top edge has scrolled past
120px from the top of the viewport, which matches where the user is
actually reading. IntersectionObserver was firing too early because it
activated a heading as soon as it entered the lower portion of the
viewport, before the user had reached that section.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Uses the Badge Svelte component throughout all examples:
- Achievement/tag sections use the award prop (gold/silver/bronze)
- States section uses a states array + {#each} to eliminate repetition
- Squared, important, user, and sizes sections use inline Badge instances
- All icons imported from @stackoverflow/stacks-icons/icons

Code blocks kept verbatim from original including @svg.* Razor syntax.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Tables with more than 8 rows collapse to show the first 8, with a
tonal full-width button below: 'Show all N classes'. Clicking toggles
to show all rows and changes the label to 'Hide classes'. This matches
the js-docs-table-expand pattern from the legacy docs.

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

- Remove wmx5 from the in-page description paragraph (the content
  column is already capped by wmx9 on .doc)
- Replace gs4 with g4 in the page action row and the homepage badge row

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

Matches the original stacks-docs docs-table pattern more closely:

- Uses CSS v-truncate-fade (height fade) instead of row slicing — the
  original removed v-truncate/v-truncate-fade classes on expand, never
  re-collapsed
- One-way expand: button disappears after clicking, aria-expanded='false'
  while collapsed (matching original jQuery behavior)
- expandButtonText prop (default 'Show All Classes') for non-class contexts
- showHeadings prop (default true) to hide the thead row conditionally
- headings prop to override individual column label text
- expandable prop (default true) to opt out of the fold entirely

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
70 docs-table uses in stacks-docs, only 15 use the expand button —
it is explicitly opt-in, not the default behavior. Changed expandable
prop default from true to false. Added expandable to avatars and badges
which had the button in the original docs.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
dancormier and others added 7 commits April 20, 2026 19:17
…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: ad3a2b7

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?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

That's right, CSS vars can't be used in media query conditions

Base automatically changed from STACKS-843/legacy-header-extraction to main April 21, 2026 17:47
@netlify
Copy link
Copy Markdown

netlify Bot commented Apr 22, 2026

Deploy Preview for stacks ready!

Name Link
🔨 Latest commit ad3a2b7
🔍 Latest deploy log https://app.netlify.com/projects/stacks/deploys/69f51b9c82d0ff00083c3b8e
😎 Deploy Preview https://deploy-preview-2240--stacks.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@abovedave abovedave added the docs Issues with the documentation site label Apr 22, 2026
@abovedave abovedave marked this pull request as ready for review April 22, 2026 16:37
@dancormier dancormier requested a review from a team April 22, 2026 16:40
dancormier
dancormier previously approved these changes May 1, 2026
Copy link
Copy Markdown
Contributor

@dancormier dancormier left a comment

Choose a reason for hiding this comment

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

Thanks for this @abovedave

I saw some opportunity for cleanup so I made some changes to split out the mobile and standard contents to prevent most of the component-specific styles. I also simplified the scrolling logic and made some accessibility improvements, plus I resolved the merge conflicts from the stacks-docs-next to stacks-docs shuffle.

Gone mergin'!

backdrop-filter: invert(1);
-webkit-backdrop-filter: invert(1);
}
@media (max-width: 71.875rem) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

That's right, CSS vars can't be used in media query conditions

-webkit-backdrop-filter: invert(1);
@media (max-width: 71.875rem) {
.contents-inner-mobile {
max-height: calc(100vh - 200px);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

If possible, I'd suggest we used a sizing unit custom property here (--su*) since those custom properties use rem which is more accessible and will allow the sizing to scale organically based on user preferences

Suggested change
max-height: calc(100vh - 200px);
max-height: calc(100vh - var(--su256));

@dancormier dancormier self-requested a review May 1, 2026 21:41
@dancormier dancormier merged commit 988f3ca into main May 1, 2026
17 checks passed
@dancormier dancormier deleted the STACKS-843/refined-toc branch May 1, 2026 21:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

docs Issues with the documentation site

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants