@casoon/pages-theme 0.12.12 → 0.12.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -41,7 +41,18 @@ const nav = [
41
41
  }
42
42
  </ul>
43
43
  <span class="sep" aria-hidden="true"></span>
44
- {config.repo && <a class="cta" href={`https://github.com/${config.repo}`}>GitHub</a>}
44
+ {
45
+ config.repo && (
46
+ <a class="cta" href={`https://github.com/${config.repo}`}>
47
+ GitHub
48
+ <span class="arrow" aria-hidden="true">
49
+ <svg viewBox="0 0 24 24" width="15" height="15">
50
+ <path d="M5 12h14M13 6l6 6-6 6" />
51
+ </svg>
52
+ </span>
53
+ </a>
54
+ )
55
+ }
45
56
  </nav>
46
57
  </div>
47
58
  <button class="theme" type="button" data-theme-toggle aria-label={s.darkTheme} aria-pressed="false" hidden>
@@ -58,7 +69,7 @@ const nav = [
58
69
  </header>
59
70
 
60
71
  <style>
61
- /* Floating white pill over the page. */
72
+ /* Floating white pill over the page, as wide as the hero. */
62
73
  .header {
63
74
  position: sticky;
64
75
  top: 0;
@@ -70,13 +81,14 @@ const nav = [
70
81
  display: flex;
71
82
  align-items: center;
72
83
  gap: 20px;
73
- max-width: 1000px;
84
+ max-width: 1240px;
74
85
  height: var(--header-h);
75
86
  margin: 0 auto;
76
- padding: 0 10px 0 24px;
87
+ padding: 0 8px 0 24px;
88
+ border: 1px solid var(--border);
77
89
  border-radius: 40px;
78
90
  background: var(--surface);
79
- box-shadow: 0 1px 2px rgb(0 0 0 / 0.25);
91
+ box-shadow: 0 16px 56px rgb(18 20 15 / 0.1);
80
92
  pointer-events: auto;
81
93
  }
82
94
  .home {
@@ -134,25 +146,56 @@ const nav = [
134
146
  list-style: none;
135
147
  }
136
148
  nav a {
137
- display: block;
138
- padding: 7px 14px;
149
+ display: grid;
150
+ place-items: center;
151
+ min-height: 44px;
152
+ padding: 0 14px;
139
153
  border-radius: 999px;
140
154
  color: var(--heading);
141
- font-size: 15px;
155
+ font-size: 14.5px;
142
156
  font-weight: 500;
157
+ letter-spacing: -0.012em;
143
158
  white-space: nowrap;
159
+ transition: background-color 0.2s;
144
160
  }
145
- nav a:hover {
146
- color: var(--accent);
147
- }
161
+ nav a:hover,
148
162
  nav a[aria-current='page'] {
163
+ background: color-mix(in srgb, var(--heading) 6%, transparent);
149
164
  color: var(--heading);
150
- font-weight: 600;
151
165
  }
166
+ /* Pill with the arrow in its own white circle on the right. */
152
167
  nav a.cta {
153
- padding: 8px 18px;
168
+ display: flex;
169
+ gap: 12px;
170
+ min-height: 46px;
171
+ padding: 0 4px 0 18px;
154
172
  background: linear-gradient(180deg, var(--accent-top) 0%, var(--accent-fill) 25%, var(--accent-fill) 100%);
155
173
  color: #fff;
174
+ font-weight: 600;
175
+ }
176
+ nav a.cta:hover {
177
+ background: var(--accent);
178
+ color: #fff;
179
+ }
180
+ .arrow {
181
+ display: grid;
182
+ place-items: center;
183
+ width: 38px;
184
+ height: 38px;
185
+ border-radius: 999px;
186
+ background: #fff;
187
+ color: var(--accent-fill);
188
+ transition: transform 0.3s;
189
+ }
190
+ nav a.cta:hover .arrow {
191
+ transform: translateX(2px);
192
+ }
193
+ .arrow svg {
194
+ fill: none;
195
+ stroke: currentColor;
196
+ stroke-width: 2;
197
+ stroke-linecap: round;
198
+ stroke-linejoin: round;
156
199
  }
157
200
  .sep {
158
201
  width: 1px;
@@ -235,7 +278,17 @@ const nav = [
235
278
  display: none;
236
279
  }
237
280
  nav a {
238
- padding: 7px 8px;
281
+ min-height: 36px;
282
+ padding: 0 10px;
283
+ }
284
+ nav a.cta {
285
+ gap: 8px;
286
+ min-height: 36px;
287
+ padding: 0 3px 0 12px;
288
+ }
289
+ .arrow {
290
+ width: 30px;
291
+ height: 30px;
239
292
  }
240
293
  }
241
294
  @media (max-width: 900px) {
@@ -272,7 +325,17 @@ const nav = [
272
325
  display: none;
273
326
  }
274
327
  [data-wide] nav a {
275
- padding: 7px 8px;
328
+ min-height: 36px;
329
+ padding: 0 10px;
330
+ }
331
+ [data-wide] nav a.cta {
332
+ gap: 8px;
333
+ min-height: 36px;
334
+ padding: 0 3px 0 12px;
335
+ }
336
+ [data-wide] .arrow {
337
+ width: 30px;
338
+ height: 30px;
276
339
  }
277
340
  }
278
341
  </style>
@@ -28,6 +28,9 @@ const {
28
28
  tone = 'plain',
29
29
  } = Astro.props;
30
30
  const hasSource = Astro.slots.has('source');
31
+ // An eyebrow that starts with "CASOON" marks the project as one of the family: it is set as a
32
+ // badge with the logo mark, and the rest ("Open Source", "Proof of Concept") follows it.
33
+ const family = eyebrow.match(/^CASOON\b\s*(?:·\s*)?(.*)$/);
31
34
  ---
32
35
 
33
36
  <section class:list={['hero', `is-${layout}`, tone === 'invert' && 'invert']}>
@@ -35,7 +38,21 @@ const hasSource = Astro.slots.has('source');
35
38
  layout === 'split' && (
36
39
  <div class="inner">
37
40
  <div>
38
- <p class="eyebrow">{eyebrow}</p>
41
+ <p class:list={['eyebrow', family && 'family']}>
42
+ {family ? (
43
+ <>
44
+ <span class="mark" aria-hidden="true">
45
+ <svg viewBox="110 92 280 316">
46
+ <path d="M169.49,108.38c-13.22,7.76-23.78,18.14-31.69,31.15-7.9,13.01-11.85,27.49-11.85,43.44v135.58c0,15.52,3.95,29.71,11.85,42.57,7.9,12.86,18.47,23.1,31.69,30.72,13.22,7.62,27.88,11.42,43.97,11.42h160.59v-45.48h-160.59c-11.64,0-21.55-3.91-29.75-11.74-8.19-7.83-12.28-17.21-12.28-28.13v-134.93c0-11.35,4.09-21.01,12.28-28.99,8.19-7.98,18.11-11.96,29.75-11.96h160.59v-45.26h-160.59c-16.09,0-30.75,3.88-43.97,11.64Z" />
47
+ </svg>
48
+ </span>
49
+ <span class="name">CASOON</span>
50
+ {family[1] && <span class="rest">{family[1]}</span>}
51
+ </>
52
+ ) : (
53
+ eyebrow
54
+ )}
55
+ </p>
39
56
  <h1>{title}</h1>
40
57
  <p class="lead">{lead}</p>
41
58
  <slot />
@@ -53,7 +70,21 @@ const hasSource = Astro.slots.has('source');
53
70
  layout === 'stack' && (
54
71
  <div class="inner">
55
72
  <div class="head">
56
- <p class="eyebrow">{eyebrow}</p>
73
+ <p class:list={['eyebrow', family && 'family']}>
74
+ {family ? (
75
+ <>
76
+ <span class="mark" aria-hidden="true">
77
+ <svg viewBox="110 92 280 316">
78
+ <path d="M169.49,108.38c-13.22,7.76-23.78,18.14-31.69,31.15-7.9,13.01-11.85,27.49-11.85,43.44v135.58c0,15.52,3.95,29.71,11.85,42.57,7.9,12.86,18.47,23.1,31.69,30.72,13.22,7.62,27.88,11.42,43.97,11.42h160.59v-45.48h-160.59c-11.64,0-21.55-3.91-29.75-11.74-8.19-7.83-12.28-17.21-12.28-28.13v-134.93c0-11.35,4.09-21.01,12.28-28.99,8.19-7.98,18.11-11.96,29.75-11.96h160.59v-45.26h-160.59c-16.09,0-30.75,3.88-43.97,11.64Z" />
79
+ </svg>
80
+ </span>
81
+ <span class="name">CASOON</span>
82
+ {family[1] && <span class="rest">{family[1]}</span>}
83
+ </>
84
+ ) : (
85
+ eyebrow
86
+ )}
87
+ </p>
57
88
  <h1>{title}</h1>
58
89
  <p class="lead">{lead}</p>
59
90
  </div>
@@ -85,7 +116,21 @@ const hasSource = Astro.slots.has('source');
85
116
  {
86
117
  layout === 'editorial' && (
87
118
  <div class="inner">
88
- <p class="eyebrow">{eyebrow}</p>
119
+ <p class:list={['eyebrow', family && 'family']}>
120
+ {family ? (
121
+ <>
122
+ <span class="mark" aria-hidden="true">
123
+ <svg viewBox="110 92 280 316">
124
+ <path d="M169.49,108.38c-13.22,7.76-23.78,18.14-31.69,31.15-7.9,13.01-11.85,27.49-11.85,43.44v135.58c0,15.52,3.95,29.71,11.85,42.57,7.9,12.86,18.47,23.1,31.69,30.72,13.22,7.62,27.88,11.42,43.97,11.42h160.59v-45.48h-160.59c-11.64,0-21.55-3.91-29.75-11.74-8.19-7.83-12.28-17.21-12.28-28.13v-134.93c0-11.35,4.09-21.01,12.28-28.99,8.19-7.98,18.11-11.96,29.75-11.96h160.59v-45.26h-160.59c-16.09,0-30.75,3.88-43.97,11.64Z" />
125
+ </svg>
126
+ </span>
127
+ <span class="name">CASOON</span>
128
+ {family[1] && <span class="rest">{family[1]}</span>}
129
+ </>
130
+ ) : (
131
+ eyebrow
132
+ )}
133
+ </p>
89
134
  <h1>{title}</h1>
90
135
  <div class="row">
91
136
  <p class="lead">{lead}</p>
@@ -133,6 +178,72 @@ const hasSource = Astro.slots.has('source');
133
178
  border-radius: 50%;
134
179
  background: var(--accent-fill);
135
180
  }
181
+ /* Family badge: logo mark, the name in wide caps, then the rest after a hairline. A slow
182
+ sheen crosses it now and then. */
183
+ .eyebrow.family {
184
+ position: relative;
185
+ display: inline-flex;
186
+ gap: 0;
187
+ padding: 3px 12px 3px 3px;
188
+ overflow: hidden;
189
+ border: 1px solid var(--border);
190
+ border-radius: 999px;
191
+ background: color-mix(in srgb, var(--surface) 60%, transparent);
192
+ font-size: 11px;
193
+ letter-spacing: 0.06em;
194
+ line-height: 1;
195
+ }
196
+ .eyebrow.family::before {
197
+ content: none;
198
+ }
199
+ .eyebrow.family::after {
200
+ content: '';
201
+ position: absolute;
202
+ inset: 0;
203
+ background: linear-gradient(105deg, transparent 35%, rgb(255 255 255 / 0.3) 50%, transparent 65%);
204
+ translate: -100% 0;
205
+ animation: family-sheen 7s ease-in-out 1.5s infinite;
206
+ pointer-events: none;
207
+ }
208
+ @keyframes family-sheen {
209
+ 0% {
210
+ translate: -100% 0;
211
+ }
212
+ 25%,
213
+ 100% {
214
+ translate: 100% 0;
215
+ }
216
+ }
217
+ @media (prefers-reduced-motion: reduce) {
218
+ .eyebrow.family::after {
219
+ content: none;
220
+ }
221
+ }
222
+ .mark {
223
+ display: grid;
224
+ place-items: center;
225
+ width: 20px;
226
+ height: 20px;
227
+ border-radius: 50%;
228
+ background: #028baa;
229
+ }
230
+ .mark svg {
231
+ width: 9px;
232
+ height: 9px;
233
+ fill: #fff;
234
+ }
235
+ .name {
236
+ margin-left: 8px;
237
+ font-weight: 600;
238
+ letter-spacing: 0.14em;
239
+ }
240
+ .rest {
241
+ margin-left: 9px;
242
+ padding-left: 9px;
243
+ border-left: 1px solid var(--border);
244
+ color: var(--muted);
245
+ font-weight: 500;
246
+ }
136
247
  h1 {
137
248
  margin: 0 0 28px;
138
249
  color: var(--heading);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@casoon/pages-theme",
3
- "version": "0.12.12",
3
+ "version": "0.12.14",
4
4
  "description": "Shared Astro theme for the GitHub Pages sites of CASOON open-source projects",
5
5
  "type": "module",
6
6
  "license": "MIT",
package/styles/base.css CHANGED
@@ -305,3 +305,10 @@ h2.cp-label::before {
305
305
  border: 0;
306
306
  border-top: 1px solid var(--border);
307
307
  }
308
+
309
+ /* Space between the hero's sand ground and whatever a site places right after it. The theme
310
+ sections listed here bring their own top padding; everything else — a site's own aside, card
311
+ or section, and Spotlight — would otherwise sit flush against the hero's lower edge. */
312
+ main > .hero + :not(.facts, .features, .anchor-grid, .faq, .flow, .integrations) {
313
+ margin-top: clamp(40px, 6vw, 72px);
314
+ }
package/styles/tokens.css CHANGED
@@ -39,7 +39,7 @@
39
39
 
40
40
  --font-sans: Inter, -apple-system, "Segoe UI", Roboto, sans-serif;
41
41
  --font-mono: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
42
- --header-h: 62px;
42
+ --header-h: 66px;
43
43
  --max: 1100px;
44
44
 
45
45
  /* Terminal surface: dark in both themes. */