11import { SectionShell } from "@/components/design-system/SectionShell" ;
2+ import { Select } from "@/components/ui/select" ;
23
3- const code = `<nav className="flex items-end justify-between gap-4 border-b border-hairline">
4+ const code = `{/* Mobile (< md): full-width dropdown showing the active tab */}
5+ <div className="md:hidden border-b border-hairline">
6+ <div className="py-2">
7+ <Select
8+ aria-label="Section"
9+ value={active}
10+ onChange={(e) => onChange(e.target.value)}
11+ className="w-full"
12+ >
13+ <option value="overview">Overview</option>
14+ <option value="activity">Activity</option>
15+ <option value="members">Members</option>
16+ <option value="billing">Billing</option>
17+ </Select>
18+ </div>
19+ </div>
20+
21+ {/* Desktop (md+): horizontal tab strip */}
22+ <nav className="hidden md:flex items-end justify-between gap-4 border-b border-hairline">
423 <div className="flex items-center gap-6">
524 <a href="#" className="-mb-px cursor-pointer border-b-2 border-accent px-1 py-3 text-sm font-medium text-accent-display no-underline">Overview</a>
625 <a href="#" className="-mb-px cursor-pointer border-b-2 border-transparent px-1 py-3 text-sm text-ink-body no-underline hover:text-ink-display">Activity</a>
@@ -25,7 +44,10 @@ export function SubNavSection() {
2544 app (settings sub-pages, project tabs, profile sections). The
2645 active tab's underline merges with the row's bottom hairline. An
2746 optional right-side slot accepts secondary links, filters, search
28- fields, or small actions.
47+ fields, or small actions. Below the < code > md</ code > breakpoint,
48+ the tab strip collapses into a full-width dropdown that surfaces
49+ the active tab — tap to switch sections without horizontal
50+ scrolling or wrapped rows.
2951 </ >
3052 }
3153 whenToUse = {
@@ -46,7 +68,23 @@ export function SubNavSection() {
4668 < div className = "space-y-8" >
4769 < div >
4870 < p className = "mb-2 text-xs uppercase tracking-wider text-ink-muted" >
49- Tabs only
71+ Mobile (< md) — full-width dropdown
72+ </ p >
73+ < div className = "max-w-sm border-b border-hairline" >
74+ < div className = "py-2" >
75+ < Select aria-label = "Section" defaultValue = "overview" className = "w-full" >
76+ < option value = "overview" > Overview</ option >
77+ < option value = "activity" > Activity</ option >
78+ < option value = "members" > Members</ option >
79+ < option value = "billing" > Billing</ option >
80+ </ Select >
81+ </ div >
82+ </ div >
83+ </ div >
84+
85+ < div >
86+ < p className = "mb-2 text-xs uppercase tracking-wider text-ink-muted" >
87+ Desktop (md+) — tab strip
5088 </ p >
5189 < nav className = "flex items-end gap-6 border-b border-hairline" >
5290 < span className = "-mb-px cursor-pointer border-b-2 border-accent px-1 py-3 text-sm font-medium text-accent-display" >
@@ -66,7 +104,7 @@ export function SubNavSection() {
66104
67105 < div >
68106 < p className = "mb-2 text-xs uppercase tracking-wider text-ink-muted" >
69- With right-side content
107+ Desktop — with right-side content
70108 </ p >
71109 < nav className = "flex items-end justify-between gap-4 border-b border-hairline" >
72110 < div className = "flex items-center gap-6" >
@@ -90,6 +128,15 @@ export function SubNavSection() {
90128 code = { code }
91129 options = {
92130 < ul className = "list-disc pl-5" >
131+ < li >
132+ < strong > Mobile breakpoint</ strong > : tabs collapse into a
133+ full-width < code > <Select></ code > below the < code > md</ code > { " " }
134+ breakpoint. Show the dropdown with{ " " }
135+ < code > md:hidden</ code > and the tab strip with{ " " }
136+ < code > hidden md:flex</ code > . The dropdown's current value is the
137+ active tab so users can see and change sections without
138+ horizontal scrolling.
139+ </ li >
93140 < li >
94141 < strong > Active state</ strong > :{ " " }
95142 < code > border-b-2 border-accent text-accent-display font-medium</ code > { " " }
@@ -100,13 +147,23 @@ export function SubNavSection() {
100147 < strong > Right-side slot</ strong > : any flex children — links,
101148 filters, search fields, small icon buttons. Use{ " " }
102149 < code > pb-2</ code > to keep them visually centered against the tab
103- text baseline.
150+ text baseline. On mobile, stack right-side content above the
151+ dropdown trigger (use < code > flex flex-col gap-2</ code > on the
152+ wrapper) so the dropdown remains truly full-width.
104153 </ li >
105154 < li >
106155 < strong > Pair with Page header</ strong > : drop the parent{ " " }
107156 < code > border-b</ code > off the page header, then place this nav
108157 beneath it. Result: two horizontal lines.
109158 </ li >
159+ < li >
160+ < strong > Rich dropdown variant</ strong > : when tabs carry icons or
161+ status indicators that wouldn't survive a native{ " " }
162+ < code > <select></ code > , swap the < code > Select</ code > for a{ " " }
163+ < code > DropdownMenu</ code > with a full-width trigger and
164+ matching < code > w-[var(--radix-dropdown-menu-trigger-width)]</ code > { " " }
165+ content width.
166+ </ li >
110167 </ ul >
111168 }
112169 />
0 commit comments