@half-built/astro 0.3.0 → 0.3.1

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@half-built/astro",
3
- "version": "0.3.0",
3
+ "version": "0.3.1",
4
4
  "description": "Astro components, islands, and pure helpers for the half-built design system.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -66,7 +66,7 @@ const year = new Date().getFullYear();
66
66
  {ecosystem.map((entry) => (
67
67
  <li>
68
68
  {entry.key === ecosystemSelf ? (
69
- <span class="footer-sitemap-self">{entry.label}</span>
69
+ <span class="footer-sitemap-self" aria-current="page">{entry.label}</span>
70
70
  ) : entry.href !== null ? (
71
71
  <a href={entry.href}>{entry.label}</a>
72
72
  ) : (
@@ -215,10 +215,31 @@ export interface EcosystemOptions {
215
215
  cacheKey?: string;
216
216
  }
217
217
 
218
+ /* Astro compiles a component's scoped rules to `.cls[data-astro-cid-x]`,
219
+ and it stamps that attribute at build time on markup it renders. An
220
+ element built here with createElement never gets stamped, so it
221
+ matches none of Footer.astro's scoped rules: the self entry loses its
222
+ bold, a pending entry loses its dimming, and every link falls back to
223
+ the browser's default underline. The server-rendered list is stamped,
224
+ so the fix is to read the attribute off it and carry it onto whatever
225
+ we create. Read rather than hardcoded, because the hash changes
226
+ whenever the component's styles change. Consumers who render the
227
+ footer unscoped simply have nothing to copy, and the loop is a no-op. */
228
+ function scopeOf(list: Element): string | null {
229
+ for (const { name } of list.attributes) {
230
+ if (name.startsWith("data-astro-cid-")) return name;
231
+ }
232
+ return null;
233
+ }
234
+
218
235
  function entryNode(doc: Document, entry: EcosystemDocEntry, selfKey: string): HTMLElement {
219
236
  if (entry.key === selfKey) {
220
237
  const self = doc.createElement("span");
221
238
  self.className = "footer-sitemap-self";
239
+ /* The bold is the visual "you are here"; this is the same statement
240
+ for a screen reader, which cannot see weight. Without it the self
241
+ entry is announced exactly like an undeployed one. */
242
+ self.setAttribute("aria-current", "page");
222
243
  self.textContent = entry.label;
223
244
  return self;
224
245
  }
@@ -263,10 +284,16 @@ export async function mountEcosystem(root: Document, opts: EcosystemOptions): Pr
263
284
  const entries = sortEntries(document_.entries, selfKey, limit);
264
285
  if (!entries || entries.length === 0) return;
265
286
 
287
+ const scope = scopeOf(list);
266
288
  const fragment = root.createDocumentFragment();
267
289
  for (const entry of entries) {
268
290
  const item = root.createElement("li");
269
- item.append(entryNode(root, entry, selfKey));
291
+ const node = entryNode(root, entry, selfKey);
292
+ if (scope !== null) {
293
+ item.setAttribute(scope, "");
294
+ node.setAttribute(scope, "");
295
+ }
296
+ item.append(node);
270
297
  fragment.append(item);
271
298
  }
272
299
  list.replaceChildren(fragment);