Skip to content
160 linesCodeBlameRaw
1---
2// The docs header: the wordmark, search in the middle and links on the
3// right, with the tabs that divide the docs beneath it.
4//
5// Its own layout, not Starlight's: Starlight lines the search up with the
6// page's text column, which moves when a page has an "On this page" list
7// and when it does not. Here the row is three columns, the outer two always
8// the same width, so the search sits at the header's centre on every page.
9import Search from '@astrojs/starlight/components/Search.astro';
10// Auto, Light or Dark, kept in this browser; Auto follows the system.
11// On tablets and phones it is at the foot of the menu instead.
12import ThemeSelect from '@astrojs/starlight/components/ThemeSelect.astro';
13
14import { TABS, tabFor } from '../tabs';
15import SiteTitle from './SiteTitle.astro';
16import SocialIcons from './SocialIcons.astro';
17
18const current = tabFor(Astro.locals.starlightRoute.id);
19---
20
21<div class="g1t-header">
22 <div class="g1t-header-top">
23 <div class="g1t-header-title"><SiteTitle /></div>
24 <div class="g1t-header-search print:hidden"><Search /></div>
25 <div class="g1t-header-links print:hidden">
26 <SocialIcons />
27 <div class="g1t-header-theme"><ThemeSelect /></div>
28 </div>
29 </div>
30 <nav class="g1t-tabs" aria-label="Sections">
31 {
32 TABS.map((tab) => (
33 <a href={tab.href} aria-current={tab === current ? 'page' : undefined}>
34 {tab.label}
35 </a>
36 ))
37 }
38 </nav>
39</div>
40
41<style>
42 .g1t-header {
43 display: flex;
44 flex-direction: column;
45 height: 100%;
46 }
47 /* The same bar as the app's: 3.5rem, and a line under it. */
48 .g1t-header-top {
49 /* Each side column is at least as wide as the widest thing that goes
50 in either, so the two stay equal and the search stays centred. */
51 --g1t-header-side: 13.5rem;
52 box-sizing: border-box;
53 display: grid;
54 grid-template-columns:
55 minmax(var(--g1t-header-side), 1fr)
56 minmax(0, 26rem)
57 minmax(var(--g1t-header-side), 1fr);
58 align-items: center;
59 gap: 1rem;
60 height: 3.5rem;
61 flex-shrink: 0;
62 padding: 0 var(--sl-nav-pad-x);
63 border-bottom: 1px solid var(--g1t-line);
64 }
65 .g1t-header-title {
66 display: flex;
67 min-width: 0;
68 /* Room for the link's focus ring. */
69 padding: 0.25rem;
70 margin: -0.25rem;
71 }
72 .g1t-header-search {
73 display: flex;
74 justify-content: center;
75 min-width: 0;
76 }
77 .g1t-header-links {
78 display: flex;
79 align-items: center;
80 justify-content: flex-end;
81 gap: 0.75rem;
82 min-width: 0;
83 }
84 .g1t-header-theme {
85 display: flex;
86 align-items: center;
87 padding-inline-start: 0.75rem;
88 border-inline-start: 1px solid var(--g1t-line);
89 height: 1.25rem;
90 }
91 /* Desktop: the links and the theme select together are wider. On a
92 narrow desktop the select shows only its icon (styles/g1t.css), so the
93 search keeps its room. */
94 @media (min-width: 50rem) {
95 .g1t-header-top {
96 --g1t-header-side: 17.5rem;
97 }
98 }
99 @media (min-width: 64rem) {
100 .g1t-header-top {
101 --g1t-header-side: 21rem;
102 }
103 }
104 /* Tablets and phones: the theme select is at the foot of the menu. */
105 @media (max-width: 49.99rem) {
106 .g1t-header-theme {
107 display: none;
108 }
109 }
110 /* Tablets: the sidebar is a menu, and its button (fixed in place by
111 Starlight) takes the row's end. The right column makes room for it
112 inside itself, so the two columns stay equal and the search centred. */
113 @media (max-width: 49.99rem) {
114 .g1t-header-top {
115 --g1t-header-side: 13rem;
116 }
117 :global([data-has-sidebar]) .g1t-header-links {
118 padding-inline-end: calc(var(--sl-menu-button-size) + 0.5rem);
119 }
120 }
121 /* Phones: the wordmark on the left; search, the links and the menu
122 button together on the right. */
123 @media (max-width: 44.99rem) {
124 .g1t-header-top {
125 grid-template-columns: minmax(0, 1fr) auto auto;
126 gap: 0.25rem;
127 }
128 }
129 .g1t-tabs {
130 display: flex;
131 gap: 1.5rem;
132 height: 2.75rem;
133 padding: 0 var(--sl-nav-pad-x);
134 overflow-x: auto;
135 overscroll-behavior-x: contain;
136 scrollbar-width: none;
137 }
138 .g1t-tabs::-webkit-scrollbar {
139 display: none;
140 }
141 .g1t-tabs a {
142 display: flex;
143 flex-shrink: 0;
144 align-items: center;
145 border-bottom: 1.5px solid transparent;
146 font-size: 0.875rem;
147 font-weight: 500;
148 white-space: nowrap;
149 color: var(--g1t-muted);
150 text-decoration: none;
151 transition: color 0.15s;
152 }
153 .g1t-tabs a:hover {
154 color: var(--g1t-fg);
155 }
156 .g1t-tabs a[aria-current='page'] {
157 border-color: var(--g1t-fg);
158 color: var(--g1t-fg);
159 }
160</style>