Skip to content
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
c9aa612
fix modal so it always appears over mobile header and fix dropzone width
LFDanLu Sep 16, 2025
0ecf094
add title font size resizing behavior to s2 docs
LFDanLu Sep 16, 2025
96e5138
dont use useResizeObserver because we want to catch fonts changing
LFDanLu Sep 16, 2025
8827283
fix mobile header icon and library label
LFDanLu Sep 16, 2025
ebc6a23
fix cross page anchor navigation scrolling and mobile cross page navi…
LFDanLu Sep 4, 2025
36b0463
properly close mobile header menu when clicking on component card
LFDanLu Sep 18, 2025
52f64c5
making image coordinator example wrap to new row instead of squishing…
LFDanLu Sep 18, 2025
c7c7a30
set a minwidth large enough so disallowEmptySelection have its label …
LFDanLu Sep 18, 2025
987cff4
properly reobserve the new page post-navigation so the page nav picke…
LFDanLu Sep 18, 2025
48b0cd1
remove broken title resizer code and fix rebase
LFDanLu Sep 29, 2025
74ef767
restore styles
LFDanLu Sep 29, 2025
e3bfb1c
Merge branch 'main' of github.com:adobe/react-spectrum into docs_fixes
LFDanLu Oct 2, 2025
451ac67
fix internationalized logo
LFDanLu Oct 2, 2025
1d5918e
add 404 page
LFDanLu Oct 3, 2025
ed3fdf5
Merge branch 'main' of github.com:adobe/react-spectrum into docs_fixes
LFDanLu Oct 3, 2025
018be32
forgot to remove test code
LFDanLu Oct 3, 2025
e2aaa67
Merge remote-tracking branch 'origin/main' into docs_fixes
reidbarber Oct 6, 2025
f1ee9ed
hide error page from search
reidbarber Oct 6, 2025
4ef11a8
update S2 popover example
LFDanLu Oct 6, 2025
8c9b45f
update icon in example
LFDanLu Oct 6, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions packages/dev/s2-docs/pages/s2/DropZone.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,13 @@ function Example(props) {
return (
<DropZone
{...props}
styles={style({width: 320})}
styles={style({width: 320, maxWidth: '90%'})}
/* PROPS */
isFilled={!!content}
// Determine whether dragged content should be accepted.
getDropOperation={types => (
['text/plain', 'image/jpeg', 'image/png', 'image/gif'].some(t => types.has(t))
? 'copy'
? 'copy'
: 'cancel'
)}
onDrop={async (event) => {
Expand Down
2 changes: 1 addition & 1 deletion packages/dev/s2-docs/pages/s2/Image.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ import {style} from '@react-spectrum/s2/style' with {type: 'macro'};
<div
className={style({
display: 'grid',
gridTemplateColumns: '1fr 1fr 1fr 1fr',
gridTemplateColumns: 'repeat(auto-fit, minmax(140px, 1fr))',
gridTemplateRows: [180],
gap: 8
})}>
Expand Down
35 changes: 7 additions & 28 deletions packages/dev/s2-docs/src/Layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -96,36 +96,15 @@ export function Layout(props: PageProps & {children: ReactElement<any>}) {
lg: 'none'
}
})}>
<div
className={style({
isolation: 'isolate',
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
maxWidth: {
default: 'full',
lg: 1280
},
marginX: 'auto',
marginY: 0,
padding: {
default: 0,
lg: 12
},
paddingBottom: 0,
gap: {
default: 0,
lg: 12
}
})}>
<div className={style({isolation: 'isolate', width: 'full'})}>
<Header pages={pages} currentPage={currentPage} />
<MobileHeader
toc={<MobileToc key="toc" toc={currentPage.tableOfContents ?? []} />}
pages={pages}
currentPage={currentPage} />
currentPage={currentPage}
toc={<MobileToc key="toc" toc={currentPage.tableOfContents ?? []} currentPage={currentPage} />}
pages={pages} />
<div className={style({display: 'flex', width: 'full'})}>
<Nav pages={pages} currentPage={currentPage} />
<main
<main
key={currentPage.url}
style={{borderBottomLeftRadius: 0, borderBottomRightRadius: 0}}
className={style({
Expand Down Expand Up @@ -203,9 +182,9 @@ function Toc({toc}) {
);
}

function MobileToc({toc}) {
function MobileToc({toc, currentPage}) {
return (
<MobileOnPageNav>
<MobileOnPageNav currentPage={currentPage}>
{renderMobileToc(toc)}
</MobileOnPageNav>
);
Expand Down
12 changes: 8 additions & 4 deletions packages/dev/s2-docs/src/MobileHeader.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
'use client';

import {ActionButton, DialogTrigger} from '@react-spectrum/s2';
import {AdobeLogo} from './AdobeLogo';
import {getLibraryFromPage} from './library';
import {keyframes} from '../../../@react-spectrum/s2/style/style-macro' with {type: 'macro'};
import MenuHamburger from '@react-spectrum/s2/icons/MenuHamburger';
import {Modal} from '../../../@react-spectrum/s2/src/Modal';
import React, {CSSProperties, lazy, useEffect, useRef} from 'react';
import {style} from '@react-spectrum/s2/style' with {type: 'macro'};
import {TAB_DEFS} from './constants';

const MobileSearchMenu = lazy(() => import('./SearchMenu').then(({MobileSearchMenu}) => ({default: MobileSearchMenu})));

Expand Down Expand Up @@ -80,6 +81,9 @@ export function MobileHeader({toc, pages, currentPage}) {
}
}, []);

let currentLibrary = getLibraryFromPage(currentPage);
let icon = TAB_DEFS[currentLibrary].icon;

return (
<div
ref={ref}
Expand Down Expand Up @@ -123,8 +127,8 @@ export function MobileHeader({toc, pages, currentPage}) {
alignItems: 'center',
flexGrow: 1
})}>
<AdobeLogo />
<h2
{icon}
<h2
className={style({
font: 'heading-sm',
marginY: 0,
Expand All @@ -135,7 +139,7 @@ export function MobileHeader({toc, pages, currentPage}) {
animationTimeline: 'scroll()',
animationRange
} as CSSProperties}>
React Aria
{TAB_DEFS[currentLibrary].label}
</h2>
</div>
<div
Expand Down
36 changes: 16 additions & 20 deletions packages/dev/s2-docs/src/MobileSearchMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@

import {CloseButton, Content, Heading, IllustratedMessage, SearchField, Tab, TabList, TabPanel, Tabs, Tag, TagGroup} from '@react-spectrum/s2';
import {ComponentCardItem, ComponentCardView} from './ComponentCardView';
import {composeRenderProps, OverlayTriggerStateContext, Dialog as RACDialog, DialogProps as RACDialogProps} from 'react-aria-components';
import {getLibraryFromPage} from './library';
import {type Library, TAB_DEFS} from './constants';
// eslint-disable-next-line monorepo/no-internal-import
import NoSearchResults from '@react-spectrum/s2/illustrations/linear/NoSearchResults';
import {OverlayTriggerStateContext, Dialog as RACDialog, DialogProps as RACDialogProps} from 'react-aria-components';
import type {PageProps} from '@parcel/rsc';
import React, {useCallback, useEffect, useMemo, useRef, useState} from 'react';
import React, {useCallback, useContext, useEffect, useMemo, useRef, useState} from 'react';
import {style} from '@react-spectrum/s2/style' with {type: 'macro'};


Expand Down Expand Up @@ -55,13 +55,7 @@ const MobileCustomDialog = function MobileCustomDialog(props: MobileDialogProps)
return (
<RACDialog
{...props}
className={dialogStyle({padding})}>
{composeRenderProps(props.children, (children) => (
<OverlayTriggerStateContext.Provider value={null}>
{children}
</OverlayTriggerStateContext.Provider>
))}
</RACDialog>
className={dialogStyle({padding})} />
);
};

Expand Down Expand Up @@ -103,7 +97,7 @@ function MobileNav({pages, currentPage}: PageProps) {
});
return sectionArray;
}, [getSectionsForLibrary, selectedLibrary]);


useEffect(() => {
// Auto-select first section initially or when library changes
Expand Down Expand Up @@ -168,7 +162,7 @@ function MobileNav({pages, currentPage}: PageProps) {
if (!searchValue.trim()) {
return pages;
}

let searchLower = searchValue.toLowerCase();
return pages.filter(page => {
let pageTitle = title(page).toLowerCase();
Expand All @@ -179,9 +173,9 @@ function MobileNav({pages, currentPage}: PageProps) {
let getSectionContent = (sectionName: string, libraryId: string, searchValue: string = ''): ComponentCardItem[] => {
let librarySections = getSectionsForLibrary(libraryId);
let pages = librarySections.get(sectionName) ?? [];

let filteredPages = filterPages(pages, searchValue);

return filteredPages
.sort((a, b) => title(a).localeCompare(title(b)))
.map(page => ({id: page.url.replace(/^\//, ''), name: title(page), href: page.url}));
Expand Down Expand Up @@ -209,7 +203,7 @@ function MobileNav({pages, currentPage}: PageProps) {
let getSectionNamesForLibrary = (libraryId: string) => {
let librarySections = getSectionsForLibrary(libraryId);
let sectionArray = [...librarySections.keys()];

// Show 'Components' first
sectionArray.sort((a, b) => {
if (a === 'Components') {
Expand All @@ -220,7 +214,7 @@ function MobileNav({pages, currentPage}: PageProps) {
}
return a.localeCompare(b);
});

return sectionArray;
};

Expand Down Expand Up @@ -263,10 +257,11 @@ function MobileNav({pages, currentPage}: PageProps) {
scrollContainerRef.current.scrollTo({top: 0, behavior: 'auto'});
}
}, [selectedSection, selectedLibrary]);
let state = useContext(OverlayTriggerStateContext);

return (
<div className={style({minHeight: '100dvh', paddingBottom: 24, boxSizing: 'border-box'})}>
<Tabs
<Tabs
aria-label="Libraries"
density="compact"
selectedKey={selectedLibrary}
Expand Down Expand Up @@ -294,16 +289,16 @@ function MobileNav({pages, currentPage}: PageProps) {
ref={headerRef}
className={style({position: 'sticky', zIndex: 1, backgroundColor: 'layer-2'})}
style={{top: tabListHeight}}>
<SearchField
aria-label="Search"
<SearchField
aria-label="Search"
value={searchValue}
onChange={handleSearchChange}
onFocus={handleSearchFocus}
onBlur={handleSearchBlur}
styles={style({marginY: 12})} />
<TagGroup
aria-label="Navigation sections"
selectionMode="single"
aria-label="Navigation sections"
selectionMode="single"
selectedKeys={selectedSection ? [selectedSection] : []}
onSelectionChange={handleTagSelection}
styles={style({margin: 12})}
Expand All @@ -313,6 +308,7 @@ function MobileNav({pages, currentPage}: PageProps) {
</div>
<div ref={scrollContainerRef}>
<ComponentCardView
onAction={() => state?.close()}
items={getItemsForSelection(selectedSection, library.id, searchValue)}
ariaLabel="Pages"
size="S"
Expand Down
8 changes: 3 additions & 5 deletions packages/dev/s2-docs/src/Nav.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -209,13 +209,11 @@ export function OnPageNav({children}) {
);
}

export function MobileOnPageNav({children}) {
export function MobileOnPageNav({children, currentPage}) {
let [selected, setSelected] = useState('');

useEffect(() => {
let elements = Array.from(document.querySelectorAll('article > :is(h1,h2,h3,h4,h5)'));
elements.reverse();

let visible = new Set();
let observer = new IntersectionObserver(entries => {
for (let entry of entries) {
Expand All @@ -225,7 +223,7 @@ export function MobileOnPageNav({children}) {
visible.delete(entry.target);
}
}

let lastVisible = elements.find(e => visible.has(e));
if (lastVisible) {
setSelected('#' + lastVisible.id!);
Expand All @@ -244,7 +242,7 @@ export function MobileOnPageNav({children}) {
}

return () => observer.disconnect();
}, []);
}, [currentPage]);

return (
<Picker aria-label="Table of contents" selectedKey={selected} isQuiet size="L">
Expand Down
2 changes: 1 addition & 1 deletion packages/dev/s2-docs/src/VisualExample.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ const exampleStyle = style({
const controlsStyle = style({
display: 'grid',
gridTemplateColumns: {
default: 'repeat(auto-fit, minmax(130px, 1fr))',
default: 'repeat(auto-fit, minmax(200px, 1fr))',
lg: ['1fr']
},
gridAutoFlow: 'dense',
Expand Down
16 changes: 15 additions & 1 deletion packages/dev/s2-docs/src/client.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,29 @@ let updateRoot = hydrate({
});

// A very simple router. When we navigate, we'll fetch a new RSC payload from the server,
// and in a React transition, stream in the new page. Once complete, we'll pushState to
// and in a React transition, stream in the new page. Once complete, we'll pushState to
// update the URL in the browser.
async function navigate(pathname: string, push = false) {
let res = fetchRSC<ReactElement>(pathname.replace('.html', '.rsc'));
let currentPath = location.pathname;
let [newBasePath, newPathAnchor] = pathname.split('#');

updateRoot(res, () => {
if (push) {
history.pushState(null, '', pathname);
push = false;
}

// Reset scroll if navigating to a different page without an anchor, primarily for the mobile case.
// Otherwise, make sure to scroll the anchor into view if any
if (currentPath !== newBasePath && !newPathAnchor) {
window.scrollTo(0, 0);
} else if (newPathAnchor) {
let element = document.getElementById(newPathAnchor);
if (element) {
element.scrollIntoView();
}
}
});
}

Expand Down
8 changes: 5 additions & 3 deletions packages/dev/s2-docs/src/icons/ReactAriaLogo.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import React from 'react';
import React, {useId} from 'react';
import {style} from '@react-spectrum/s2/style' with { type: 'macro' };

export const ReactAriaLogo = () => {
const clipPathId = `react-aria-logo-clip-${useId()}`;

return (
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 160 160" className={style({margin: 0, height: 40, width: 40})}>
<defs>
<clipPath id="a">
<clipPath id={clipPathId}>
<path
d="M80 136c30.93 0 56-25.07 56-56s-25.07-56-56-56-56 25.07-56 56 25.07 56 56 56Zm8.48-86.3c0 4.69-3.8 8.48-8.48 8.48s-8.48-3.8-8.48-8.48 3.8-8.48 8.48-8.48 8.48 3.8 8.48 8.48ZM51.09 61.78c.52-1.8 2.39-2.85 4.2-2.33a89.865 89.865 0 0 0 48.82.17l.64-.18c1.81-.5 3.68.55 4.18 2.36a3.39 3.39 0 0 1-2.36 4.18l-.64.18a97.139 97.139 0 0 1-15.51 2.98c-1.03.11-1.82.97-1.82 2.01v14.89c0 .18.03.37.08.55 1.37 4.83 2.94 10.39 4.32 15.27.98 3.46 1.86 6.58 2.49 8.85.32 1.14.58 2.06.76 2.71l.04.15c.13.48.27.97.31 1.16a3.38 3.38 0 0 1-2.66 3.99 3.38 3.38 0 0 1-3.99-2.66c.02.09 0 .04-.08-.27-.04-.13-.09-.31-.15-.54-.18-.65-.44-1.57-.76-2.7-.64-2.27-1.52-5.39-2.49-8.85l-3.74-13.21a1.992 1.992 0 0 0-1.92-1.45h-1.6c-.89 0-1.68.59-1.92 1.45-1.22 4.3-2.55 9.01-3.74 13.21-.98 3.46-1.85 6.58-2.49 8.85-.32 1.13-.58 2.06-.76 2.7-.06.23-.11.41-.15.54-.09.31-.1.36-.08.27a3.39 3.39 0 1 1-6.65-1.33c.04-.18.18-.68.31-1.16l.04-.15c.18-.65.44-1.58.76-2.71.64-2.27 1.52-5.39 2.49-8.85 1.38-4.88 2.95-10.44 4.32-15.27.05-.18.08-.36.08-.55V71.16c0-1.04-.79-1.9-1.82-2.01a96.504 96.504 0 0 1-16.17-3.17 3.395 3.395 0 0 1-2.33-4.2Z"
style={{
Expand All @@ -22,7 +24,7 @@ export const ReactAriaLogo = () => {
}} />
<g
style={{
clipPath: 'url(#a)'
clipPath: `url(#${clipPathId})`
}}>
<path
d="M15.79 17.64H147v126.14H15.79z"
Expand Down