Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
30 changes: 28 additions & 2 deletions website/src/components/header/header.astro
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,14 @@ const { noLinks } = Astro.props;
.navbar {
display: flex;
align-items: center;
flex-wrap: wrap;
row-gap: 0.25rem;
background-color: var(--colorNeutralBackground3);
padding: 0.5rem 1rem;
margin: 0;
box-shadow: var(--shadow4);
height: var(--header-height);
min-height: var(--header-height);
box-sizing: border-box;
}
#header-drawer-button {
display: flex;
Expand All @@ -28,6 +31,25 @@ const { noLinks } = Astro.props;
border: none;
}

/* On documentation pages Starlight renders its own sidebar menu button in the
same corner. Hide this site menu button there so the two hamburger controls
don't overlap. The site links stay reachable from the Starlight menu (see
Sidebar override). (#10795 Reflow / #10796 Resize Text) */
:global([data-has-sidebar]) #header-drawer-button {
display: none;
}

/* Below 50rem Starlight overlays a fixed sidebar menu button in the top-right
corner. Reserve room for it (mirrors Starlight's own header padding) so it
doesn't overlap the search button. (#10795 Reflow / #10796 Resize Text) */
@media (max-width: 50rem) {
:global([data-has-sidebar]) .navbar {
padding-inline-end: calc(
var(--sl-nav-gap) + var(--sl-nav-pad-x) + var(--sl-menu-button-size)
);
}
}

.nav-content {
display: none;
}
Expand Down Expand Up @@ -143,6 +165,9 @@ const { noLinks } = Astro.props;
.nav-content {
display: flex;
flex: 1;
flex-wrap: wrap;
align-items: center;
gap: 0.25rem 0.5rem;
position: relative;
}

Expand All @@ -158,7 +183,8 @@ const { noLinks } = Astro.props;
.items {
display: flex;
align-items: center;
flex: 1;
flex-wrap: wrap;
flex: 1 1 auto;
min-width: 0;
}

Expand Down
16 changes: 14 additions & 2 deletions website/src/components/release-notification.astro
Original file line number Diff line number Diff line change
Expand Up @@ -37,16 +37,28 @@ import Link from "@typespec/astro-utils/components/link.astro";
.new-version-banner {
border: 1px solid var(--colorBrandBackground);
display: block;
padding: 2px 1rem;
padding: 2px 0.6rem;
border-radius: 2px;
line-height: 24px;
line-height: 22px;
font-size: 0.875rem;
white-space: nowrap;
}
.new-version-banner:hover {
outline: 1px solid var(--colorBrandBackgroundHover);
}
.hide {
display: none;
}

/* In the desktop header the version banner sits inline with the nav links.
Between 1024px and ~1200px there isn't room for it without the header
wrapping to a second row, so hide it in that range. Below 1024px it moves
into the mobile drawer (a vertical list) where it fits fine. (#10794) */
@media (min-width: 1024px) and (max-width: 1200px) {
.new-version-banner {
display: none;
}
}
</style>

<Link
Expand Down
19 changes: 19 additions & 0 deletions website/src/components/starlight-overrides/PageFrame.astro
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,25 @@ import Footer from "../footer/footer.astro";
</div>
</Default>

<script>
// Starlight positions the page content and sidebar using a fixed
// `--sl-nav-height`. The site header can grow taller than that single-row
// height when its content wraps (e.g. under text resize or reflow / zoom),
// which made it overflow and overlap the navigation and content below.
// Keep `--sl-nav-height` in sync with the real header height so everything
// reflows correctly. (Resize Text 1.4.4 & Reflow 1.4.10.)
function setupNavHeightSync() {
const navbar = document.querySelector<HTMLElement>("header.header nav.navbar");
if (!navbar) return;
const sync = () =>
document.documentElement.style.setProperty("--sl-nav-height", `${navbar.offsetHeight}px`);
sync();
new ResizeObserver(sync).observe(navbar);
window.addEventListener("resize", sync);
}
setupNavHeightSync();
</script>

<style>
.footer-wrapper {
position: relative;
Expand Down
54 changes: 54 additions & 0 deletions website/src/components/starlight-overrides/Sidebar.astro
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,24 @@
import MobileMenuFooter from "@astrojs/starlight/components/MobileMenuFooter.astro";
import SidebarPersister from "@astrojs/starlight/components/SidebarPersister.astro";
import SidebarSublist from "@astrojs/starlight/components/SidebarSublist.astro";
import Link from "@typespec/astro-utils/components/link.astro";
import { getCollection } from "astro:content";

// Primary site navigation. On documentation pages the site header's own menu
// button is hidden so it doesn't overlap Starlight's sidebar menu button
// (#10795 / #10796). Surface those links here (mobile menu only) so they stay
// reachable from the single remaining menu button.
const primaryNav = [
{ label: "OpenAPI", href: "/openapi" },
{ label: "Data Validation", href: "/data-validation" },
{ label: "Tooling support", href: "/tooling" },
{ label: "Docs", href: "/docs" },
{ label: "Videos", href: "/videos" },
{ label: "Playground", href: "/playground" },
{ label: "Blog", href: "/blog" },
{ label: "Community", href: "/community" },
];

const { sidebar } = Astro.locals.starlightRoute;
const pathname = Astro.url.pathname;
const base = import.meta.env.BASE_URL;
Expand Down Expand Up @@ -42,10 +58,48 @@ if (isReleaseNotes) {
}
---

<nav class="site-nav md:sl-hidden" aria-label="Site">
<ul>
{
primaryNav.map((entry) => (
<li>
<Link href={entry.href}>{entry.label}</Link>
</li>
))
}
</ul>
</nav>

<SidebarPersister>
<SidebarSublist sublist={filtered} />
</SidebarPersister>

<div class="md:sl-hidden">
<MobileMenuFooter />
</div>

<style>
.site-nav {
border-bottom: 1px solid var(--sl-color-hairline-shade);
padding-bottom: 1rem;
margin-bottom: 0.5rem;
}
.site-nav ul {
list-style: none;
padding: 0;
margin: 0;
display: flex;
flex-direction: column;
gap: 0.25rem;
}
.site-nav a {
display: block;
padding: 0.4rem 0;
color: var(--sl-color-white);
text-decoration: none;
font-weight: 600;
}
.site-nav a:hover {
color: var(--sl-color-text-accent);
}
</style>
49 changes: 35 additions & 14 deletions website/src/components/window-carousel.astro
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
---
import Window from "./window.astro";
const tabs = Object.keys(Astro.slots);
const slug = (name: string) =>
name
.toLowerCase()
.replace(/[^a-z0-9]+/g, "-")
.replace(/^-+|-+$/g, "");
---

<style>
Expand Down Expand Up @@ -50,19 +55,29 @@ const tabs = Object.keys(Astro.slots);
list-style: none;
}

a[role="tab"] {
a[role="tab"],
button[role="tab"] {
display: block;
color: var(--colorNeutralForeground2);
cursor: pointer;
padding-bottom: 3px;
border-bottom: 2px solid transparent;
}
a[role="tab"]:hover {
button[role="tab"] {
background: none;
border-top: none;
border-left: none;
border-right: none;
font: inherit;
}
a[role="tab"]:hover,
button[role="tab"]:hover {
color: var(--colorBrandForeground1);
cursor: pointer;
border-bottom-color: var(--colorBrandForeground1);
}
a[role="tab"][aria-selected="true"] {
a[role="tab"][aria-selected="true"],
button[role="tab"][aria-selected="true"] {
border-bottom-color: var(--colorBrandForeground1);
}
</style>
Expand All @@ -73,25 +88,33 @@ const tabs = Object.keys(Astro.slots);
tabs.map(async (name, i) => {
const render = await Astro.slots.render(name);
return (
<Window class:list={["item", i === 0 && "item-selected"]} role="tabpanel">
<Window
class:list={["item", i === 0 && "item-selected"]}
id={`carousel-panel-${slug(name)}`}
role="tabpanel"
aria-labelledby={`carousel-tab-${slug(name)}`}
tabindex="0"
>
<Fragment set:html={render} />
</Window>
);
})
}
</div>
<ul role="tablist">
<ul role="tablist" aria-label="Sample views">
{
tabs.map((name, i) => (
<li role="presentation" class="tab">
<a
<button
type="button"
role="tab"
id={name}
id={`carousel-tab-${slug(name)}`}
aria-controls={`carousel-panel-${slug(name)}`}
aria-selected={i === 0 ? "true" : "false"}
tabindex={i !== 0 ? -1 : 0}
>
{name}
</a>
</button>
</li>
))
}
Expand All @@ -100,15 +123,14 @@ const tabs = Object.keys(Astro.slots);

<script>
class CarouselTabs extends HTMLElement {
tabs: HTMLAnchorElement[];
tabs: HTMLButtonElement[];
panels: HTMLElement[];

constructor() {
super();
const tablist = this.querySelector<HTMLUListElement>('[role="tablist"]')!;
this.tabs = [...tablist.querySelectorAll<HTMLAnchorElement>('[role="tab"]')];
this.tabs = [...tablist.querySelectorAll<HTMLButtonElement>('[role="tab"]')];
this.panels = [...this.querySelectorAll<HTMLElement>('[role="tabpanel"]')];
console.log("register", this.tabs);

this.panels.forEach((panel, i) => {
panel.addEventListener("click", (e) => {
Expand All @@ -122,7 +144,7 @@ const tabs = Object.keys(Astro.slots);
e.preventDefault();
const currentTab = tablist.querySelector('[aria-selected="true"]');
if (e.currentTarget !== currentTab) {
this.switchTab(e.currentTarget as HTMLAnchorElement, i);
this.switchTab(e.currentTarget as HTMLButtonElement, i);
}
});

Expand Down Expand Up @@ -150,7 +172,7 @@ const tabs = Object.keys(Astro.slots);
});
}

switchTab(newTab: HTMLAnchorElement | null | undefined, index: number, shouldSync = true) {
switchTab(newTab: HTMLButtonElement | null | undefined, index: number, shouldSync = true) {
if (!newTab) return;

// If tabs should be synced, we store the current position so we can restore it after
Expand All @@ -169,7 +191,6 @@ const tabs = Object.keys(Astro.slots);

// Show new panel and mark new tab as selected.
const newPanel = this.panels[index];
console.log("Switch", newPanel, this.panels);
if (newPanel) newPanel.classList.add("item-selected");
// Restore active tab to the default tab order.
newTab.removeAttribute("tabindex");
Expand Down
5 changes: 3 additions & 2 deletions website/src/content.config.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { docsLoader } from "@astrojs/starlight/loaders";
import { docsSchema } from "@astrojs/starlight/schema";
import { docsLoader, i18nLoader } from "@astrojs/starlight/loaders";
import { docsSchema, i18nSchema } from "@astrojs/starlight/schema";
import { llmstxtSchema } from "@typespec/astro-utils/llmstxt/schema";
import { glob } from "astro/loaders";
import { z } from "astro/zod";
Expand Down Expand Up @@ -46,4 +46,5 @@ export const collections = {
authors: z.array(authorSchema).optional(),
}),
}),
i18n: defineCollection({ loader: i18nLoader(), schema: i18nSchema() }),
};
3 changes: 3 additions & 0 deletions website/src/content/i18n/en.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"sidebarNav.accessibleLabel": "Documentation"
}
Loading
Loading