-
1
-
2
-
3
-
4
-
5
-
6
-
7
-
8
-
9
-
10
-
11
-
12
-
13
-
14
-
15
-
16
-
17
-
18
-
19
-
20
-
21
-
22
-
23
-
24
-
25
-
26
-
27
-
28
-
29
-
30
-
31
-
32
-
33
-
34
-
35
-
36
-
37
-
38
-
39
-
40
-
41
-
42
-
43
-
44
-
45
-
46
-
47
-
48
-
49
-
50
-
51
-
52
-
53
-
54
-
55
-
56
-
57
-
58
-
59
-
60
-
61
-
62
-
63
-
64
-
65
-
66
-
67
-
68
-
69
-
70
-
71
-
72
-
73
-
74
-
75
-
76
-
77
-
78
-
79
-
80
-
81
-
82
-
83
-
84
-
85
-
86
-
87
-
88
-
89
-
90
-
91
-
92
-
93
-
94
-
95
-
96
-
97
-
98
-
99
-
100
-
101
-
102
-
103
-
104
-
105
-
106
-
107
-
108
-
109
-
110
-
111
-
112
-
113
-
114
-
115
-
116
-
117
-
118
-
119
-
120
-
121
-
122
-
123
-
124
-
125
-
126
-
127
-
128
-
129
-
130
-
131
-
132
-
133
-
134
-
135
-
136
-
137
-
138
-
139
-
140
-
141
-
142
-
143
-
144
-
145
-
146
-
147
-
148
-
149
-
150
-
151
-
152
-
153
-
154
-
155
-
156
-
157
-
158
-
159
-
160
-
161
-
162
-
163
-
164
-
165
/** @jsx h */
import { Fragment, h, withStyles } from "../deps/nano_jsx.ts";
function cx(...classNames: string[]): string {
return classNames.map((className) => `layout__${className}`).join(" ");
}
interface LayoutProps {
navigation: unknown;
toc: unknown;
children: unknown;
siteRoot?: URL;
}
export const Layout = (
{ children, navigation, toc, siteRoot = new URL("https://example.com/") }:
LayoutProps,
) => {
return withStyles(css)(
<Fragment>
<div class={cx("logo-wrapper", "header")}>
<a class={cx("logo")} href={new URL("./", siteRoot).pathname}>
slack<br />message<br />parser
</a>
</div>
<nav class={cx("nav", "header")}>{navigation}</nav>
<div class={cx("header-fill", "header")} />
<aside class={cx("toc")}>{toc}</aside>
<main class={cx("main")}>
{children}
</main>
</Fragment>,
);
};
const css = `
html {
--_scroll-padding-top: 7rem;
scroll-padding-top: var(--_scroll-padding-top);
scroll-behavior: smooth;
}
body {
display: grid;
grid-template-columns: min-content minmax(0, 1fr);
grid-template-rows: min-content max-content minmax(0, 1fr);
grid-template-areas:
"logo nav"
"toc toc"
"main main";
width: 100%;
background-color: hsl(var(--color-neutral));
color: hsl(var(--color-on-neutral));
overflow-y: auto;
}
.${cx("header")} {
position: sticky;
top: 0;
border-bottom: var(--border-width) solid hsl(var(--color-border));
background-color: hsl(var(--color-panel));
z-index: 666;
}
.${cx("logo-wrapper")} {
grid-area: logo;
border-right: var(--border-width) solid hsl(var(--color-border));
display: flex;
justify-content: flex-end;
align-items: center;
padding: var(--gutter-md) var(--gutter-lg);
}
.${cx("logo")} {
display: block;
font-size: var(--font-size-sm);
line-height: 1;
color: inherit;
font-weight: bold;
text-align: right;
text-decoration: none;
}
.${cx("logo")}:hover,
.${cx("logo")}:focus-visible {
outline: none;
text-decoration: underline;
}
.${cx("nav")} {
grid-area: nav;
display: flex;
justify-content: flex-start;
align-items: stretch;
flex-wrap: nowrap;
padding: var(--gutter-sm) var(--gutter-lg);
overflow-x: auto;
}
.${cx("header-fill")} {
grid-area: fill;
display: none;
}
.${cx("toc")} {
grid-area: toc;
display: block;
border-bottom: var(--border-width) solid hsl(var(--color-border));
padding: var(--gutter-md);
}
.${cx("main")} {
grid-area: main;
display: block;
padding: var(--gutter-md);
}
@media (min-width: 800px) {
body {
grid-template-columns: 20rem minmax(0, 1fr);
grid-template-rows: min-content minmax(0, 1fr);
grid-template-areas:
"logo nav"
"toc main";
}
.${cx("toc")} {
align-self: start;
position: sticky;
top: var(--_scroll-padding-top);
display: flex;
justify-content: flex-end;
border: 0;
}
.${cx("main")} {
flex: 1;
padding: var(--gutter-lg);
}
.${cx("nav")} {
justify-content: center;
}
}
@media (min-width: 1100px) {
body {
grid-template-columns: minmax(0, 1fr) 70rem minmax(0, 1fr);
grid-template-areas:
"logo nav fill"
"toc main unused";
}
.${cx("header-fill")} {
display: block;
}
}
`;