Skip to content

Commit 66e2f78

Browse files
committed
Improve PageTitle layout, scaling and mobile responsiveness
- Added automatic font-size scaling for long page titles to prevent layout overflow - Improved mobile and tablet layout: badge now moves below the title on small screens - Ensured stable desktop behavior with non-wrapping titles and dynamic scaling - Refactored logic for cleaner, more predictable layout handling - Removed unnecessary wrapper elements and simplified structure around StarlightPage
1 parent da4524a commit 66e2f78

3 files changed

Lines changed: 98 additions & 104 deletions

File tree

web/src/overrides/PageTitle.astro

Lines changed: 91 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -1,149 +1,139 @@
11
---
22
import { functionTypePrettyName } from "@src/utils/functions";
3+
const funcType = (Astro.locals.funcType ?? 'shared') as 'client' | 'server' | 'shared';
34
---
45

5-
<div class="page-title-container">
6+
<div class={`page-title-container type-${funcType}`}>
67
<h1 class="page-title">{Astro.locals.starlightRoute.entry.data.title}</h1>
78

8-
<div data-pagefind-ignore class="type-badge type-badge--client">
9-
{functionTypePrettyName["client"]}
10-
</div>
11-
<div data-pagefind-ignore class="type-badge type-badge--server">
12-
{functionTypePrettyName["server"]}
13-
</div>
14-
<div data-pagefind-ignore class="type-badge type-badge--shared">
15-
{functionTypePrettyName["shared"]}
9+
<div class={`type-badge type-badge-${funcType}`}>
10+
{functionTypePrettyName[funcType]}
1611
</div>
1712
</div>
1813

19-
<style is:global>
20-
.show-type-badge-client {
14+
<style>
15+
.page-title-container {
16+
display: flex;
17+
align-items: center;
18+
justify-content: space-between;
19+
border-bottom: 1px solid var(--selected-type-color);
20+
margin-bottom: -1.5rem; /* .content-panel */
21+
padding-bottom: 1.5rem;
22+
}
23+
24+
.page-title-container.type-client {
2125
--selected-type-color: var(--color-type-client);
2226
}
23-
.show-type-badge-server {
27+
28+
.page-title-container.type-server {
2429
--selected-type-color: var(--color-type-server);
2530
}
26-
.show-type-badge-shared {
31+
32+
.page-title-container.type-shared {
2733
--selected-type-color: var(--color-type-shared);
2834
}
2935

30-
.show-type-badge-client .type-badge--client {
31-
display: block;
32-
}
33-
.show-type-badge-server .type-badge--server {
34-
display: block;
35-
}
36-
.show-type-badge-shared .type-badge--shared {
37-
display: block;
36+
.page-title {
37+
max-width: 100%;
38+
font-size: var(--sl-text-h1);
39+
line-height: var(--sl-line-height-headings);
40+
font-weight: bold;
41+
color: var(--sl-color-white);
3842
}
39-
</style>
4043

41-
<style>
4244
.type-badge {
43-
font-size: 12px;
45+
flex-shrink: 0;
46+
padding: 0.15rem 1.5rem;
4447
border-radius: 0.25rem;
4548
text-transform: uppercase;
4649
font-weight: bold;
47-
display: none;
4850
}
4951

50-
.type-badge.type-badge--client {
52+
.type-badge.type-badge-client {
5153
color: var(--color-type-client);
52-
}
53-
.type-badge.type-badge--server {
54-
color: var(--color-type-server);
55-
}
56-
.type-badge.type-badge--shared {
57-
color: var(--color-type-shared);
58-
}
59-
60-
.page-title-container {
61-
display: flex;
62-
justify-content: flex-start;
63-
align-items: flex-start;
64-
flex-direction: column;
65-
border-bottom: 1px solid var(--selected-type-color);
66-
padding-bottom: 1.5rem;
67-
margin-bottom: calc(-1.5rem - 1px);
68-
position: relative;
69-
}
70-
71-
.page-title {
72-
font-size: var(--sl-text-h1);
73-
line-height: var(--sl-line-height-headings);
74-
font-weight: 600;
75-
color: var(--sl-color-white);
76-
}
77-
78-
.page-title.size-h2 {
79-
font-size: var(--sl-text-h2);
54+
background-color: var(--color-type-client-background);
55+
border: 1px solid var(--color-type-client);
8056
}
8157

82-
.page-title.size-h3 {
83-
font-size: var(--sl-text-h3);
58+
.type-badge.type-badge-server {
59+
color: var(--color-type-server);
60+
background-color: var(--color-type-server-background);
61+
border: 1px solid var(--color-type-server);
8462
}
8563

86-
.page-title.size-h4 {
87-
font-size: var(--sl-text-h4);
64+
.type-badge.type-badge-shared {
65+
color: var(--color-type-shared);
66+
background-color: var(--color-type-shared-background);
67+
border: 1px solid var(--color-type-shared);
8868
}
8969

90-
@media (width >= 48rem) {
91-
.type-badge {
92-
font-size: initial;
93-
padding: 0.15rem 1.5rem;
70+
@media (max-width: 768px) {
71+
.page-title-container {
72+
align-items: flex-start;
73+
gap: 0.75rem;
9474
}
9575

96-
.type-badge.type-badge--client {
97-
background-color: var(--color-type-client-background);
98-
border: 1px solid var(--color-type-client);
99-
}
100-
.type-badge.type-badge--server {
101-
background-color: var(--color-type-server-background);
102-
border: 1px solid var(--color-type-server);
103-
}
104-
.type-badge.type-badge--shared {
105-
background-color: var(--color-type-shared-background);
106-
border: 1px solid var(--color-type-shared);
76+
.page-title {
77+
font-size: var(--sl-text-h3);
10778
}
10879

109-
.page-title-container {
110-
justify-content: space-between;
111-
align-items: center;
112-
flex-direction: row;
113-
margin-top: 1rem;
80+
.type-badge {
81+
align-self: flex-end;
82+
margin-top: 0.25rem;
11483
}
11584
}
11685
</style>
11786

11887
<script>
119-
document.addEventListener("DOMContentLoaded", () => {
120-
const title = document.querySelector(".page-title");
121-
const sizeClasses = ["size-h2", "size-h3", "size-h4"];
122-
123-
function adjustTitle() {
124-
if (!title) return;
125-
126-
title.classList.remove(...sizeClasses);
127-
128-
requestAnimationFrame(() => {
129-
const lineHeight = parseFloat(getComputedStyle(title).lineHeight);
130-
let lines = Math.round(title.scrollHeight / lineHeight);
131-
132-
if (lines <= 1) return;
88+
window.addEventListener("load", () => {
89+
const title = document.querySelector(".page-title") as HTMLElement;;
90+
const badge = document.querySelector(".type-badge") as HTMLElement;
91+
const container = document.querySelector(".page-title-container") as HTMLElement;
92+
93+
if (!title || !badge || !container) return;
94+
95+
const sizes = [
96+
"var(--sl-text-h1)",
97+
"var(--sl-text-h2)",
98+
"var(--sl-text-h3)",
99+
"var(--sl-text-h4)",
100+
"var(--sl-text-h5)",
101+
"var(--sl-text-xl)",
102+
"var(--sl-text-lg)",
103+
"var(--sl-text-base)",
104+
"var(--sl-text-sm)",
105+
"var(--sl-text-xs)",
106+
"var(--sl-text-2xs)"
107+
];
108+
109+
const MIN_GAP = 10;
110+
111+
function gap() {
112+
const t = title.getBoundingClientRect();
113+
const b = badge.getBoundingClientRect();
114+
return b.left - t.right;
115+
}
133116

134-
for (const sizeClass of sizeClasses) {
135-
title.classList.remove(...sizeClasses);
136-
title.classList.add(sizeClass);
117+
function adjust() {
118+
for (const size of sizes) {
119+
title.style.fontSize = size;
120+
if (container.style.flexDirection == "column" || gap() >= MIN_GAP) break;
121+
}
137122

138-
lines = Math.round(title.scrollHeight / lineHeight);
123+
if (badge.getBoundingClientRect().right > container.getBoundingClientRect().right)
124+
{
125+
container.style.flexDirection = "column";
126+
badge.style.alignSelf = "flex-start";
127+
}
128+
}
139129

140-
if (lines <= 1) break;
141-
}
142-
});
130+
if (document.fonts) {
131+
document.fonts.ready.then(adjust);
132+
} else {
133+
adjust();
143134
}
144135

145-
adjustTitle();
146-
window.addEventListener("resize", adjustTitle);
136+
new ResizeObserver(adjust).observe(container);
147137
});
148138
</script>
149139

web/src/pages/reference/[func].astro

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ const funcType = funcInfo.type;
4040
const funcPair = funcInfo.pair;
4141
const funcPath = path.dirname(func.filePath ?? "");
4242
43+
Astro.locals.funcType = funcType;
44+
4345
// Join shared, client, and server examples
4446
let funcExamples: any[] = [];
4547
@@ -87,8 +89,6 @@ let funcSyntaxes = parseFunctionSyntaxes(func.id, func.data);
8789
8890
const oopList = Array.isArray(funcInfo.oop) ? funcInfo.oop : funcInfo.oop ? [funcInfo.oop]: [];
8991
---
90-
91-
<div class={`show-type-badge-${funcType}`}>
9292
<StarlightPage
9393
frontmatter={{
9494
template: 'doc',
@@ -340,4 +340,3 @@ const oopList = Array.isArray(funcInfo.oop) ? funcInfo.oop : funcInfo.oop ? [fun
340340

341341
<SeeAlsoSection seeAlsoLinks={getSeeAlsoLinksForItem(func)} currentId={func.id} />
342342
</StarlightPage>
343-
</div>

web/src/utils/globals_locals.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
declare namespace App {
2+
interface Locals {
3+
funcType: 'client' | 'server' | 'shared';
4+
}
5+
}

0 commit comments

Comments
 (0)