Skip to content

feat: global language selector with implicit tabs#748

Draft
mkmeral wants to merge 4 commits intostrands-agents:mainfrom
mkmeral:feat/language-selector
Draft

feat: global language selector with implicit tabs#748
mkmeral wants to merge 4 commits intostrands-agents:mainfrom
mkmeral:feat/language-selector

Conversation

@mkmeral
Copy link
Copy Markdown
Contributor

@mkmeral mkmeral commented Apr 8, 2026

Implements a page-level Python/TypeScript toggle that replaces per-section tab clicking with a single global selector:

Components:

  • LanguageSelector: Pill toggle in the header (Python | TypeScript)

    • Persists preference in localStorage
    • Syncs with Starlight's tab sync mechanism
    • Sets data-strands-language on for CSS-based switching
    • Bidirectional: clicking a tab updates the selector too
  • LanguageContent: Conditional prose blocks

    • ...
    • CSS-based show/hide using data-strands-language attribute
    • SEO-friendly: both blocks are in HTML, CSS toggles visibility
    • Graceful degradation: both visible if no JS
  • LanguageTabsMarker: Auto-detects Python/TypeScript tab groups

    • Marks them with data-lang-tabs attribute
    • CSS hides the tab bar (making tabs 'implicit')
    • Shows subtle active-language indicator
  • Demo page: hooks-demo.mdx showcases all patterns

How it works:

  1. User clicks Python/TypeScript in header pill
  2. localStorage is set (both our key + Starlight's synced-tabs key)
  3. All starlight-tabs on page programmatically switch
  4. LanguageContent blocks show/hide via CSS
  5. Tab bars on language tabs are hidden (implicit)
  6. Preference persists across page navigations

Description

Related Issues

Type of Change

  • New content
  • Content update/revision
  • Structure/organization improvement
  • Typo/formatting fix
  • Bug fix
  • Other (please describe):

Checklist

  • I have read the CONTRIBUTING document
  • My changes follow the project's documentation style
  • I have tested the documentation locally using npm run dev
  • Links in the documentation are valid and working

By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.

Implements a page-level Python/TypeScript toggle that replaces
per-section tab clicking with a single global selector:

Components:
- LanguageSelector: Pill toggle in the header (Python | TypeScript)
  - Persists preference in localStorage
  - Syncs with Starlight's tab sync mechanism
  - Sets data-strands-language on <html> for CSS-based switching
  - Bidirectional: clicking a tab updates the selector too

- LanguageContent: Conditional prose blocks
  - <LanguageContent lang='python'>...</LanguageContent>
  - CSS-based show/hide using data-strands-language attribute
  - SEO-friendly: both blocks are in HTML, CSS toggles visibility
  - Graceful degradation: both visible if no JS

- LanguageTabsMarker: Auto-detects Python/TypeScript tab groups
  - Marks them with data-lang-tabs attribute
  - CSS hides the tab bar (making tabs 'implicit')
  - Shows subtle active-language indicator

- Demo page: hooks-demo.mdx showcases all patterns

How it works:
1. User clicks Python/TypeScript in header pill
2. localStorage is set (both our key + Starlight's synced-tabs key)
3. All starlight-tabs on page programmatically switch
4. LanguageContent blocks show/hide via CSS
5. Tab bars on language tabs are hidden (implicit)
6. Preference persists across page navigations
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 8, 2026

Documentation Preview Ready

Your documentation preview has been successfully deployed!

Preview URL: https://d3ehv1nix5p99z.cloudfront.net/pr-cms-748/docs/user-guide/quickstart/overview/

Updated at: 2026-04-08T23:28:22.049Z

…oImport ordering

Two issues caused the Astro build to fail:

1. hooks-demo.mdx had an explicit 'import LanguageContent' while AutoImport
   in astro.config.mjs also injected it globally, causing:
   'Identifier LanguageContent has already been declared'

2. AutoImport was placed AFTER mdx() in the integrations array, which
   Astro warned about: auto-imports in .mdx files won't work unless
   AutoImport comes before the MDX integration.

Fixes:
- Remove explicit import from hooks-demo.mdx (AutoImport handles it)
- Move AutoImport before mdx() in astro.config.mjs integrations array

Verified: full build passes (455 pages, 0 broken links, 0 errors).
1. Mobile: Use compact labels (PY/TS) on small screens instead of
   full 'Python|TypeScript' pill that was too wide for mobile.
   Full labels still show on desktop.

2. Remove language labels: Deleted the ::before pseudo-element that
   showed 'PYTHON' or 'TYPESCRIPT' above implicit tab content.
   Content now just shows directly — no chrome, no visual indicator.

3. New <Lang> component for inline use: Renders as <span> so you can
   swap method names, API ref links, and short phrases WITHIN paragraphs:

     Use <Lang lang='python'>`add_hook()`</Lang><Lang lang='typescript'>`addHook()`</Lang> to register.

4. LanguageContent now uses display:contents — transparent wrapper
   that adds zero visual box when visible, hides with display:none.

Build: 455 pages, 0 broken links, 0 errors.
The mobile header had too many elements crammed together:
Logo | Search | PY/TS pill | Navigate ▾ | ☰ hamburger

Now on mobile, the language selector lives inside the nav dropdown
menu (at the top, before the section links). Tapping the nav dropdown
shows the PY/TS toggle first, then the navigation links.

Mobile header is now clean: Logo | Search | Navigate ▾ | ☰

Desktop header is unchanged — selector stays in the right group.

Also simplified LanguageSelector labels (removed the short/full span
trick since the dropdown has plenty of room).
@ryanycoleman
Copy link
Copy Markdown
Member

I'm going to adopt this as part of my upcoming work on language switching

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.

4 participants