From 481402e09fe760634b826b09e302e2e1bfec88b1 Mon Sep 17 00:00:00 2001 From: shu Date: Mon, 7 Sep 2026 15:48:36 +0800 Subject: feat: initialize React Spectrum template with layouts and showcases --- src/components/layout-basic.module.css | 156 +++++++++++++++++++++++++++++++++ 1 file changed, 156 insertions(+) create mode 100644 src/components/layout-basic.module.css (limited to 'src/components/layout-basic.module.css') diff --git a/src/components/layout-basic.module.css b/src/components/layout-basic.module.css new file mode 100644 index 0000000..cc29f98 --- /dev/null +++ b/src/components/layout-basic.module.css @@ -0,0 +1,156 @@ +.appLayout { + --navigation-inset: 12px; + /* SideNav's leading gutter (12) plus half the shared icon size (20). */ + --navigation-icon-center: calc(var(--navigation-inset) + 1.375rem * var(--s2-scale, 1)); + display: grid; + grid-template-columns: 240px minmax(0, 1fr); + height: 100dvh; + overflow: hidden; + color: var(--text); + background: var(--bg); +} + +.sidebar { + display: flex; + flex-direction: column; + min-height: 0; + border-inline-end: 1px solid var(--border); + background: var(--social-bg); +} + +.sidebarBrand, +.topbar { + display: flex; + align-items: center; + box-sizing: border-box; + height: 64px; + flex-shrink: 0; + padding: 0 24px; + border-bottom: 1px solid var(--border); + color: var(--text-h); + font-size: 16px; + font-weight: 600; +} + +.sidebarNavigation { + flex: 1; + min-height: 0; + padding: 16px var(--navigation-inset); +} + +.expandedNavigation { + height: 100%; +} + +.topbar { + gap: 12px; +} + +.topbarActions { + margin-inline-start: auto; + display: flex; + align-items: center; + flex-shrink: 0; +} + +.appLayout.isCollapsed { + /* Include the sidebar border so both modes share the same icon center. */ + grid-template-columns: calc(2 * var(--navigation-icon-center) + 1px) minmax(0, 1fr); +} + +.isCollapsed .sidebarBrand { + justify-content: center; + padding-inline: 0; +} + +.isCollapsed .sidebarNavigation { + overflow-y: auto; +} + +.iconNavigation { + display: flex; + flex-direction: column; + align-items: center; + /* Match SideNav's row spacing (space(6)). */ + gap: 0.375rem; +} + +.iconNavigationLink, +.iconNavigationGroup { + display: flex; + justify-content: center; + align-items: center; + width: 40px; + /* Match SideNav's 32-unit row height, including Spectrum's touch scale. */ + height: calc(2rem * var(--s2-scale, 1)); + flex-shrink: 0; + border-radius: 8px; + color: var(--text); +} + +.iconNavigationLink:hover, +.iconNavigationLink[aria-current="page"], +.iconNavigationGroup.isActive { + background: var(--border); + color: var(--text-h); +} + +.iconNavigationLink:focus-visible { + outline: 2px solid var(--accent); + outline-offset: 2px; +} + +.contentLayout { + display: grid; + grid-template-rows: auto minmax(0, 1fr); + min-width: 0; + min-height: 0; +} + +.skipLink { + position: fixed; + top: 8px; + left: 8px; + z-index: 10; + padding: 8px 16px; + background: var(--bg); + color: var(--accent); + transform: translateY(calc(-100% - 16px)); + + &:focus { + transform: translateY(0); + } +} + +@media (max-width: 640px) { + .appLayout, + .appLayout.isCollapsed { + --navigation-inset: 8px; + grid-template-columns: minmax(0, 1fr); + } + + .sidebar, + .desktopMenuToggle { + display: none; + } + + .sidebarBrand, + .topbar { + padding-inline: 12px; + } +} + +.pageContent { + /* Keep absolutely positioned accessibility helpers inside this scroll area. */ + position: relative; + display: flex; + flex-direction: column; + min-width: 0; + min-height: 0; + overflow: auto; + text-align: center; +} + +.pageContent > * { + flex-shrink: 0; +} -- cgit v1.2.3