Skip to content

Cluster pages: the diagram as the way in, linked reading lists, one colour per cluster - #1137

Open
LukasWallrich wants to merge 14 commits into
rebrand-doorsfrom
rebrand/clusters-round
Open

LukasWallrich wants to merge 14 commits into
rebrand-doorsfrom
rebrand/clusters-round

Conversation

@LukasWallrich

@LukasWallrich LukasWallrich commented Nov 13, 2026 •

Copy link
Copy Markdown
Contributor

The cluster pages had become hard to use for reaching a resource. Sol and Opus scored them 6 and 4 in the first round under the design guide (#1135). The problems they found:

  • The titles in a cluster's reading lists weren't links. Reaching a paper meant a citation button, then a pop-up.
  • Nothing on /clusters/ linked to the eleven cluster pages.
  • The diagram's labels were about 9 px.
  • The filters took half of a phone screen.
  • The 258-item topic lists had no search.
  • The clusters took turns using the four area colours.

What changes for visitors:

  • The diagram is the way in on desktop. Each cluster name in it links to its cluster page and can be reached with Tab. Pointing at a cluster, or tabbing to it, highlights it and shows its name, first sentence and counts in a bar at the foot of the window. Cluster names are now about 16 px at 1440 px. Below 1256 px the names would be too small, so the page shows the small hub and a linked list, as on phones; "Open full size" still gives the whole drawing.
  • "The 11 clusters" is a list of links to each cluster page, each numbered in its colour. On phones it replaces the eleven full-width coloured bars. Each cluster's heading further down also links to its page.
  • Titles in reading lists link to the resource. The author–year button still opens the citation pop-up. "Overview · Paper" is plain text instead of teal and magenta chips, also in the pop-up.
  • Filters on phones sit behind a closed "Filters" button that counts the active filters. Buttons and search are 44 px tall on touch screens.
  • Feedback when filtering: if a filter leaves nothing, the page says "No resources match" and offers Clear filters. Counts read "25 of 27 shown", and the specialist checkbox says those resources stay hidden until it is ticked.
  • The citation pop-up takes keyboard focus, keeps Tab inside, and returns focus when closed.
  • Topic lists (/forrt_clusters/<term>/) get a one-line explanation, a search with a live count, and underlined titles in two columns on wide screens.
  • The desktop side list underlines cluster names, marks the current cluster, scrolls it into view, and shows shadows where the list scrolls.
  • Colours: each cluster has its own colour, together spanning the spectrum (--cl1…--cl11 in tokens.css). The diagram, panels, side list and numbers all use them. The strong colours meet 4.5:1 contrast against the page.

Decisions to review

  • Diagram for keyboard users: the cluster names in the diagram are real Tab stops, named "Cluster N: name". The ring segments and sub-cluster boxes are hidden from screen readers, because the text list repeats them. A separate list as the keyboard route scrolled the diagram off screen, so the highlight didn't work. Check 21 in check_seo_html.py and its tests now require named Tab stops instead of a hidden diagram.
  • The introduction ("Teaching Open and Reproducible Science shouldn't require…") moves below the diagram and the list, under "About the clusters".
  • Colours:
    • clusters 9 to 11 look fairly similar;
    • the pale backgrounds of clusters 6 and 7 read close to beige, which the guide rules out. The existing community background is already close to that.
  • The sub-cluster boxes in the diagram are still about 9 px at 1440 px. They are in the text list and the full-size view.
  • Search drop-down on cluster pages is removed, because it counted differently from the filtered list. /disciplines/ keeps it.
  • Topic lists can't link to a pre-filtered resources directory. They use the older cluster names, and the directory filters by the current eleven.
  • Resource titles open doi.org in a new tab without saying so. The guide asks links leaving the site to say where they go; this is for a follow-up.
  • The share image content/clusters/FORRT_Clusters.webp is re-rendered with scripts/render_clusters_share_image.py, because the diagram changed.

Checks:

  • check_seo_html.py passes, including the rewritten check 21 and the FLoRA check.
  • The source rules and the unit tests (146) pass.
  • The cluster parts of check_design.py pass: the clusters diagram, specialist resources, panel width, floating controls, 200% text and phone reading.
  • axe finds only the site-wide skip-link "region" note.
  • The page audit is clean on the cluster pages and /forrt_clusters/preregistration/, apart from issues that were already there: a hidden 11.6 px count, and small badges on /disciplines/.

Overview, desktop: the diagram leads. It is in the cluster colours, with larger names, and a bar at the foot shows the pointed cluster.

Clusters overview, desktop: before and after

Overview, phone: a small hub, then a linked list of the eleven clusters instead of full-width coloured bars

Clusters overview, phone: before and after

Cluster page, phone: search plus a closed "Filters" button instead of the full filter panel

Cluster page, phone: before and after

Reading list, desktop: linked titles, plain "Overview · Book" labels, "4 of 4 shown", and the cluster's own colour

Open reading list, desktop: before and after

Topic list, desktop: an explanation, search with a count, and underlined titles in two columns

Topic list, desktop: before and after

Created with Claude Opus 5.5 in Claude Code; reviewed by GPT-6.1 Sol and Claude Opus 5.5.

🤖 Generated with Claude Code


Summary by cubic

Overhauls the cluster pages so reaching a resource takes a single click: the diagram on /clusters/ links to every cluster page, each reading-list title opens its paper, and the filters collapse on phones. Each of the 11 clusters also gets its own colour across the spectrum (--cl1–--cl11 in tokens.css), replacing the rotation of the four area colours.

Navigation

  • Cluster names in the diagram link to their pages and are tab stops (named "Cluster N: name"); pointing at or tabbing to one highlights the cluster and describes it in a bar at the foot of the window. Names read at about 16 px at a 1440 px viewport; below 1256 px the page shows the hub and a linked list instead, with "Open full size" still available.
  • /clusters/ gains "The 11 clusters", a numbered linked list that also replaces the full-width coloured bars on phones; each cluster's heading further down links to its page.
  • The side list underlines cluster names, marks the current cluster, and opens scrolled to it; shadows at the list's edges show when it scrolls. The introduction moves below the diagram and list, under "About the clusters".

Resources, filters and feedback

  • Reading-list titles are underlined links to the resource's DOI; the author–year button still opens the citation. "Overview · Paper" reads as quiet sentence-case text instead of teal-and-magenta chips, in the cards and in the citation pop-up, which now keeps focus inside and returns it to the opening button when closed.
  • On phones the Focus, Type and specialist controls sit behind a closed "Filters" button that counts the active filters; search, buttons and checkboxes are 44 px tall on touch screens.
  • Filtering reports "X of Y resources shown" and "No resources match" with a Clear filters button when nothing does; the search drop-down on cluster pages is gone because it counted differently from the filtered list (/disciplines/ keeps it).
  • /forrt_clusters/<term>/ pages get an explanation, a search with a live count, and underlined titles in two columns on wide screens.
  • Owner decisions to review: clusters 9–11 read fairly similar, and the pale backgrounds of 6 and 7 sit close to beige, which the design guide rules out. Resource titles open doi.org in a new tab without announcing it; that is flagged as a follow-up.

Written for commit 6c1701f. Summary will update on new commits.

View guided diff Turn on auto-fix

LukasWallrich and others added 14 commits November 13, 2026 00:06
Each sub-cluster card's title now links to the resource (its DOI), underlined as a link; the
author-year button stays as the secondary reference action, now named as such for screen readers.
Focus and type read as quiet sentence-case text ("Overview · Paper") on the cards and in the
reference dialog instead of filled teal and magenta chips in capitals.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Opening a reference moves focus to the dialog's Close button, Tab and Shift+Tab cycle through its
controls, and closing (Escape, Close or the backdrop) returns focus to the button that opened it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ng matches

- Phones: the search fills the width and Focus, Type and the specialist toggle sit in a closed
  Filters disclosure whose label counts the active filters; from 761 px the disclosure is open
  and its summary hidden. Filter buttons, search and toggles are at least 44 px tall on phones
  and touch screens, and the filter buttons expose aria-pressed in labelled groups.
- Sub-cluster counts read "25 of 27 shown", and a line under the specialist toggle says that
  specialist resources stay hidden until it is ticked.
- A status line under the bar gives the number of resources shown while a filter or search is
  set and says "No resources match." with a Clear filters button when none is; it is a live
  region. The drop-down of search hits is gone from cluster pages: it counted differently from
  the filtered list and announced a second result. /disciplines/ keeps it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Owner decision: the clusters no longer rotate the four area colours. tokens.css defines --cl1 to
--cl11 (equal OKLCH lightness, hues 33 degrees apart starting from blue, each at least 4.5:1 on the
page, on white and on its own pale background) and --cl1-bg to --cl11-bg for the cluster panels.
clusters/colors.html hands them out in cluster order, so the panels, sidebar arrows and the
/clusters/ diagram agree.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- After the filters, "The 11 clusters" lists each cluster as a link to /clusters/cluster-N/,
  numbered in its colour, with the first sentence of its description (two lines at most; left
  out for cluster 7, whose only sentence counts its sub-clusters) and its counts. On phones it
  replaces the eleven full-width coloured bars, which are gone.
- The introduction and the diagram follow under "How the clusters fit together", with Open full
  size and the text list kept; the diagram's clusters and sub-clusters, and the text list, now
  link to the cluster pages. Every cluster in full follows under its own heading, and each
  panel's heading links to its page.
- check_design.py's phone check counts the new list's links instead of the bars.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…nt cluster

Cluster and sub-cluster names in the side list are underlined; the current cluster is marked by
weight and aria-current instead. On a cluster page the desktop list, which scrolls in its own box,
opens scrolled to the current cluster without moving the page, and soft shadows at the top and foot
of the box show when there is more to scroll.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
/forrt_clusters/<term>/ pages (e.g. 258 resources tagged Preregistration) open with one line on
what the list is, with a link to the clusters page, then the site's list search (the markup of
shortcodes/list_filter.html, with its live count) over one column of underlined titles, each with
its type as plain text, instead of three hairline-ruled columns. The link to the unfiltered
resources directory is gone: the directory's cluster filter uses the current clusters, not these
tags, so it cannot open on this list.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The lighter weight for side-list names applies only to the cluster list, whose names are underlined.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Owner decision: the diagram leads /clusters/ again and works as navigation.
- Cluster names in the diagram are drawn at 32 units, about 16-17 px at 1440 px (were about 11).
- Each cluster name is a link and a tab stop named "Cluster N: name", in cluster order, with a
  visible focus ring; the ring segments and sub-cluster pills stay out of the tab order and hidden
  from assistive technology (the pills are in the text list and on the cluster pages).
- Pointing at a cluster or focusing its name lights it up and describes it (number, name, first
  sentence, counts) in a line under the diagram that sticks to the foot of the window.
- The linked list of the 11 clusters follows the diagram (on phones, the small hub and this list),
  then the introduction, then every cluster in full with the filters directly above it.
- check_seo_html.py check 21 and its tests now require named tab stops and hidden repeats instead
  of a drawing hidden as a whole.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Cluster panel numbers are coloured only where the panel has a cluster colour, so /disciplines/
  keeps its grey badges, and they are 15 px.
- Raw links in reference-only cards use the site's link colour (were 4.2:1).
- The forrt_clusters explanation keeps under 80 characters a line, and the list box spans the
  width (its rows keep to the reading measure), as the directory-width check expects.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…labels

Made with scripts/render_clusters_share_image.py from a build of this branch, as map.html asks
after the diagram changes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
At 1440 px the cluster names in the drawing are about 16.6 px and at 1280 px 15.3 px, but at 1024 px
only 12.4 px. Below 1256 px the page now shows the hub and the linked list of clusters, as phones do;
the full drawing stays one click away under Open full size. The forrt_clusters search placeholder no
longer suggests a preregistration term on every term page.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ters-round

# Conflicts:
#	scripts/check_seo_html.py
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@LukasWallrich
LukasWallrich requested a review from a team as a code owner November 13, 2026 01:04
@github-actions

Copy link
Copy Markdown
Contributor

👍 All image files/references (if any) are in webp format, in line with our policy.

@github-actions

Copy link
Copy Markdown
Contributor

📝 Spell Check Results

Found 4 potential spelling issue(s) when checking 20 changed file(s):

📄 static/js/clusters-page.js

Line Issue
79 tabEl ==> table
80 tabEl ==> table
82 tabEl ==> table
84 tabEl ==> table

ℹ️ How to address these issues:

  1. Fix the typo: If it's a genuine typo, please correct it.
  2. Add to whitelist: If it's a valid word (e.g., a name, technical term), add it to .codespell-ignore.txt
  3. False positive: If this is a false positive, please report it in the PR comments.

🤖 This check was performed by codespell

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

13 issues found across 24 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="layouts/partials/clusters/overview_list.html">

<violation number="1" location="layouts/partials/clusters/overview_list.html:4">
P2: `.data.clusters` is read without a guard, unlike `map.html` and the count in `intro.html`, which both wrap `hugo.Data.clusters_v4` in `with`. If the JSON is missing, this partial fails the build rather than omitting the list. Wrap the lookup in `with`.</violation>
</file>

<file name="layouts/partials/clusters/card_head.html">

<violation number="1" location="layouts/partials/clusters/card_head.html:8">
P3: The new DOI title link opens a new tab without telling users. Add a visible external-link cue and screen-reader text such as “opens in a new tab.”</violation>
</file>

<file name="static/js/clusters-page.js">

<violation number="1" location="static/js/clusters-page.js:448">
P3: The sidebar alignment runs only once, so resizing or rotating from phone width to desktop leaves the active cluster at the old scroll position. Re-run the alignment after the responsive breakpoint changes.</violation>
</file>

<file name="layouts/partials/clusters/all_clusters.html">

<violation number="1" location="layouts/partials/clusters/all_clusters.html:16">
P3: This new section heading is an `h2`, the same level as every cluster title it introduces. Screen-reader heading navigation then shows a flat outline. Either demote the cluster titles to `h3` in `cluster_section.html`, or render this as a non-heading element that keeps the `clusters-section-heading` class. The `id` is unused, so remove it unless something needs to reference it.</violation>
</file>

<file name="layouts/partials/clusters/map.html">

<violation number="1" location="layouts/partials/clusters/map.html:255">
P3: Moving the pointer off a cluster clears the info line even when that cluster's name still has keyboard focus. Only clear it when the focused element is not this cluster's name.</violation>
</file>

<file name="layouts/_default/list.html">

<violation number="1" location="layouts/_default/list.html:27">
P3: This change removes the only link from the cluster resource list to the resources directory, which offers the full search and filter. Keep a link to `/resources` in the intro so readers can reach the directory's filters from here.</violation>
</file>

<file name="layouts/partials/clusters/intro.html">

<violation number="1" location="layouts/partials/clusters/intro.html:7">
P2: The linked cluster list renders at all widths, not only below 1256px. On desktop this duplicates the diagram's 11 cluster links, so keyboard users get 22 tab stops and screen readers announce each cluster twice. The list should be hidden at min-width 1256px to match the map's compact-hub breakpoint, or the duplication should be confirmed as intended.</violation>
</file>

<file name="layouts/partials/clusters/clusters_controls.html">

<violation number="1" location="layouts/partials/clusters/clusters_controls.html:53">
P2: This live region is hidden with `:empty{display:none}` in clusters.css. It appears only when its text is inserted, and some screen readers skip announcing a region that was hidden when its content changed. Keep the region rendered and collapse it with `min-height: 0` or visually-hidden styling instead of `display:none`, so the message is announced on each filter change.</violation>
</file>

<file name="scripts/check_seo_html.py">

<violation number="1" location="scripts/check_seo_html.py:666">
P2: A cluster-name link with `aria-hidden="true"` still passes this check, yet it stays in the tab order. Keyboard focus would land on a control that screen readers never announce. Fail any tab stop in the illustration that carries aria-hidden.</violation>
</file>

<file name="assets/css/doors/clusters.css">

<violation number="1" location="assets/css/doors/clusters.css:984">
P3: This readability breakpoint uses pixels even though it protects a text-size constraint, so text-only zoom can enlarge labels without switching away from the full diagram. Use an equivalent `em` breakpoint so the compact layout responds to text zoom.</violation>
</file>

<file name="assets/css/doors/lists.css">

<violation number="1" location="assets/css/doors/lists.css:104">
P3: This new breakpoint uses fixed pixels, so text-only zoom can leave enlarged titles in cramped columns. Use an `em` breakpoint for this content-width switch.

(Based on your team's feedback about text-only zoom breakpoints.) [2daf6c82-7918-4f44-b822-fcb49f7bf681]</violation>
</file>

<file name="static/js/featured-resources.js">

<violation number="1" location="static/js/featured-resources.js:847">
P2: Checking “Show specialist resources” marks one active filter, but `isFiltered` excludes `showNarrow`; Clear filters and the live count stay hidden. Include `showNarrow` in `isFiltered`.</violation>

<violation number="2" location="static/js/featured-resources.js:892">
P3: A query found only in a cluster or sub-cluster heading hides every card and announces “No resources match,” despite the label promising cluster search. Label it “Search resources.”</violation>
</file>

Reply with feedback, questions, or to request a fix.

View guided diff | Turn on auto-fix | Re-trigger cubic

{{/* /clusters/: the eleven clusters as a plain linked list, each with its number in its colour, the first
sentence of its description (left out where that sentence only counts sub-clusters) and its counts.
Expects dict: data (clusters_v4), arrowColors. */}}
{{ $clusters := .data.clusters }}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: .data.clusters is read without a guard, unlike map.html and the count in intro.html, which both wrap hugo.Data.clusters_v4 in with. If the JSON is missing, this partial fails the build rather than omitting the list. Wrap the lookup in with.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At layouts/partials/clusters/overview_list.html, line 4:

<comment>`.data.clusters` is read without a guard, unlike `map.html` and the count in `intro.html`, which both wrap `hugo.Data.clusters_v4` in `with`. If the JSON is missing, this partial fails the build rather than omitting the list. Wrap the lookup in `with`.</comment>

<file context>
@@ -0,0 +1,25 @@
+{{/* /clusters/: the eleven clusters as a plain linked list, each with its number in its colour, the first
+     sentence of its description (left out where that sentence only counts sub-clusters) and its counts.
+     Expects dict: data (clusters_v4), arrowColors. */}}
+{{ $clusters := .data.clusters }}
+{{ $marks := .arrowColors }}
+<section class="clusters-overview" aria-labelledby="clusters-overview-heading">
</file context>

{{ $palette := partial "clusters/colors.html" }}
<div class="clusters-intro">
{{ partial "clusters/map.html" (dict "link_mode" "subpath") }}
{{ partial "clusters/overview_list.html" (dict "data" hugo.Data.clusters_v4 "arrowColors" $palette.arrowColors) }}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: The linked cluster list renders at all widths, not only below 1256px. On desktop this duplicates the diagram's 11 cluster links, so keyboard users get 22 tab stops and screen readers announce each cluster twice. The list should be hidden at min-width 1256px to match the map's compact-hub breakpoint, or the duplication should be confirmed as intended.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At layouts/partials/clusters/intro.html, line 7:

<comment>The linked cluster list renders at all widths, not only below 1256px. On desktop this duplicates the diagram's 11 cluster links, so keyboard users get 22 tab stops and screen readers announce each cluster twice. The list should be hidden at min-width 1256px to match the map's compact-hub breakpoint, or the duplication should be confirmed as intended.</comment>

<file context>
@@ -1,7 +1,12 @@
+{{ $palette := partial "clusters/colors.html" }}
 <div class="clusters-intro">
+  {{ partial "clusters/map.html" (dict "link_mode" "subpath") }}
+  {{ partial "clusters/overview_list.html" (dict "data" hugo.Data.clusters_v4 "arrowColors" $palette.arrowColors) }}
+  <h2 class="clusters-section-heading" id="clusters-about-heading">About the clusters</h2>
   <p class="intro-paragraph">
</file context>

resources in place, so the old drop-down of search hits (clusters-page.js, still used on
/disciplines/) is not on these pages: it counted differently and announced a second result. */}}
<div class="fr-filter-result" id="fr-filter-result">
<p class="fr-filter-status" id="fr-filter-status" role="status" aria-live="polite"></p>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: This live region is hidden with :empty{display:none} in clusters.css. It appears only when its text is inserted, and some screen readers skip announcing a region that was hidden when its content changed. Keep the region rendered and collapse it with min-height: 0 or visually-hidden styling instead of display:none, so the message is announced on each filter change.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At layouts/partials/clusters/clusters_controls.html, line 53:

<comment>This live region is hidden with `:empty{display:none}` in clusters.css. It appears only when its text is inserted, and some screen readers skip announcing a region that was hidden when its content changed. Keep the region rendered and collapse it with `min-height: 0` or visually-hidden styling instead of `display:none`, so the message is announced on each filter change.</comment>

<file context>
@@ -1,45 +1,58 @@
+       resources in place, so the old drop-down of search hits (clusters-page.js, still used on
+       /disciplines/) is not on these pages: it counted differently and announced a second result. */}}
+  <div class="fr-filter-result" id="fr-filter-result">
+    <p class="fr-filter-status" id="fr-filter-status" role="status" aria-live="polite"></p>
+    <a class="fr-filter-result__go" id="fr-filter-result-go" href="#" hidden>Go to the first match</a>
+    <button type="button" class="fr-filter-result__clear" id="fr-filter-result-clear" hidden>Clear filters</button>
</file context>

Comment thread scripts/check_seo_html.py
Comment on lines +666 to +668
unnamed = [a.get("href", "") for a in stops if not (a.get("aria-label") or "").strip() or not (a.get("href") or "").strip()]
if unnamed:
failures.append("clusters/index.html: %d tab stops in the illustration lack a name or target, e.g. %s" % (len(unnamed), unnamed[0]))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: A cluster-name link with aria-hidden="true" still passes this check, yet it stays in the tab order. Keyboard focus would land on a control that screen readers never announce. Fail any tab stop in the illustration that carries aria-hidden.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At scripts/check_seo_html.py, line 666:

<comment>A cluster-name link with `aria-hidden="true"` still passes this check, yet it stays in the tab order. Keyboard focus would land on a control that screen readers never announce. Fail any tab stop in the illustration that carries aria-hidden.</comment>

<file context>
@@ -655,11 +656,20 @@ def check_clusters_map(public_dir):
-        failures.append("clusters/index.html: %d links in the illustration are tab stops, e.g. %s" % (len(stops), stops[0]))
+        failures += ["clusters/index.html: the illustration has tab stops but is aria-hidden"
+                     for art in parser.arts if art.get("aria-hidden") == "true"]
+    unnamed = [a.get("href", "") for a in stops if not (a.get("aria-label") or "").strip() or not (a.get("href") or "").strip()]
+    if unnamed:
+        failures.append("clusters/index.html: %d tab stops in the illustration lack a name or target, e.g. %s" % (len(unnamed), unnamed[0]))
</file context>
Suggested change
unnamed = [a.get("href", "") for a in stops if not (a.get("aria-label") or "").strip() or not (a.get("href") or "").strip()]
if unnamed:
failures.append("clusters/index.html: %d tab stops in the illustration lack a name or target, e.g. %s" % (len(unnamed), unnamed[0]))
unnamed = [a.get("href", "") for a in stops if not (a.get("aria-label") or "").strip() or not (a.get("href") or "").strip() or a.get("aria-hidden") == "true"]
if unnamed:
failures.append("clusters/index.html: %d tab stops in the illustration are unnamed, lack a target or are aria-hidden, e.g. %s" % (len(unnamed), unnamed[0]))

if (clearBtn) clearBtn.hidden = !isFiltered;
/* The Filters summary counts the choices that differ from the start: a focus, a type, specialist shown. */
var active = (activeFocus !== 'all' ? 1 : 0) + (activeType !== 'all' ? 1 : 0) + (showNarrow ? 1 : 0);
if (activeLabel) activeLabel.textContent = active ? ' (' + active + ' active)' : '';

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Checking “Show specialist resources” marks one active filter, but isFiltered excludes showNarrow; Clear filters and the live count stay hidden. Include showNarrow in isFiltered.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At static/js/featured-resources.js, line 847:

<comment>Checking “Show specialist resources” marks one active filter, but `isFiltered` excludes `showNarrow`; Clear filters and the live count stay hidden. Include `showNarrow` in `isFiltered`.</comment>

<file context>
@@ -790,6 +842,9 @@
       if (clearBtn) clearBtn.hidden = !isFiltered;
+      /* The Filters summary counts the choices that differ from the start: a focus, a type, specialist shown. */
+      var active = (activeFocus !== 'all' ? 1 : 0) + (activeType !== 'all' ? 1 : 0) + (showNarrow ? 1 : 0);
+      if (activeLabel) activeLabel.textContent = active ? ' (' + active + ' active)' : '';
 
       // --- Pass 1: compute visibility from cached data (no DOM reads) ---
</file context>

art.querySelectorAll('.clusters-map__cluster').forEach(function (g) {
var n = g.getAttribute('data-cluster'), name = g.querySelector('.clusters-map__label');
g.addEventListener('mouseenter', function () { show(n); });
g.addEventListener('mouseleave', function () { show(null); });

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3: Moving the pointer off a cluster clears the info line even when that cluster's name still has keyboard focus. Only clear it when the focused element is not this cluster's name.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At layouts/partials/clusters/map.html, line 255:

<comment>Moving the pointer off a cluster clears the info line even when that cluster's name still has keyboard focus. Only clear it when the focused element is not this cluster's name.</comment>

<file context>
@@ -215,6 +222,51 @@
+    art.querySelectorAll('.clusters-map__cluster').forEach(function (g) {
+      var n = g.getAttribute('data-cluster'), name = g.querySelector('.clusters-map__label');
+      g.addEventListener('mouseenter', function () { show(n); });
+      g.addEventListener('mouseleave', function () { show(null); });
+      if (name) {
+        name.addEventListener('focus', function () { show(n); light(n); });
</file context>
Suggested change
g.addEventListener('mouseleave', function () { show(null); });
g.addEventListener('mouseleave', function () { show(name && document.activeElement === name ? n : null); });

shortcodes/list_filter.html (same markup; site.js filters the list items after the h2 that
follows it and keeps the count). The directory's cluster filter uses the current clusters
(forrt_clusters_new), not these tags, so there is no pre-filtered link to it. */}}
<p class="cluster-resources-intro">Resources in the FORRT database tagged with this cluster. The eleven current clusters, with their sub-clusters and references, are on the <a href="{{ relref . "/clusters" }}">clusters page</a>.</p>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3: This change removes the only link from the cluster resource list to the resources directory, which offers the full search and filter. Keep a link to /resources in the intro so readers can reach the directory's filters from here.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At layouts/_default/list.html, line 27:

<comment>This change removes the only link from the cluster resource list to the resources directory, which offers the full search and filter. Keep a link to `/resources` in the intro so readers can reach the directory's filters from here.</comment>

<file context>
@@ -20,11 +20,22 @@ <h1>{{ .Title }}</h1>
+             shortcodes/list_filter.html (same markup; site.js filters the list items after the h2 that
+             follows it and keeps the count). The directory's cluster filter uses the current clusters
+             (forrt_clusters_new), not these tags, so there is no pre-filtered link to it. */}}
+        <p class="cluster-resources-intro">Resources in the FORRT database tagged with this cluster. The eleven current clusters, with their sub-clusters and references, are on the <a href="{{ relref . "/clusters" }}">clusters page</a>.</p>
+        <div class="article-style cluster-resources-list">
+          <div class="list-filter" data-noun="resources" hidden>
</file context>
Suggested change
<p class="cluster-resources-intro">Resources in the FORRT database tagged with this cluster. The eleven current clusters, with their sub-clusters and references, are on the <a href="{{ relref . "/clusters" }}">clusters page</a>.</p>
<p class="cluster-resources-intro">Resources in the FORRT database tagged with this cluster. Search them here, or use the <a href="{{ relref . "/resources" }}">resources directory</a> to filter them. The current clusters, with their sub-clusters and references, are on the <a href="{{ relref . "/clusters" }}">clusters page</a>.</p>

@media (max-width: 760px) {
/* Below 1256 px the full drawing would set cluster names under 15 px, so phones, tablets and small laptops get
the hub, and the clusters in the linked list after it; the pills are in the text list and the full-size view. */
@media (max-width: 1255px) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3: This readability breakpoint uses pixels even though it protects a text-size constraint, so text-only zoom can enlarge labels without switching away from the full diagram. Use an equivalent em breakpoint so the compact layout responds to text zoom.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At assets/css/doors/clusters.css, line 984:

<comment>This readability breakpoint uses pixels even though it protects a text-size constraint, so text-only zoom can enlarge labels without switching away from the full diagram. Use an equivalent `em` breakpoint so the compact layout responds to text zoom.</comment>

<file context>
@@ -979,22 +979,15 @@
-@media (max-width: 760px) {
+/* Below 1256 px the full drawing would set cluster names under 15 px, so phones, tablets and small laptops get
+   the hub, and the clusters in the linked list after it; the pills are in the text list and the full-size view. */
+@media (max-width: 1255px) {
   .clusters-map__frame { display: none; }
   .clusters-map__compact { display: block; }
</file context>
Suggested change
@media (max-width: 1255px) {
@media (max-width: 78.4375em) {

.cluster-resources__type{color:var(--soft);font-size:16px}
.cluster-resources-list h2{margin:24px 0 4px}
/* Wide screens: two columns, so the list does not leave half the screen empty. */
@media(min-width:1001px){.article-style.cluster-resources-list{max-width:none}.article-style .cluster-resources{columns:2;column-gap:48px;max-width:1080px}.article-style .list-filter~ul.cluster-resources>li{break-inside:avoid}.cluster-resources-list .list-filter{max-width:520px}}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3: This new breakpoint uses fixed pixels, so text-only zoom can leave enlarged titles in cramped columns. Use an em breakpoint for this content-width switch.

(Based on your team's feedback about text-only zoom breakpoints.) [2daf6c82-7918-4f44-b822-fcb49f7bf681]

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At assets/css/doors/lists.css, line 104:

<comment>This new breakpoint uses fixed pixels, so text-only zoom can leave enlarged titles in cramped columns. Use an `em` breakpoint for this content-width switch.

(Based on your team's feedback about text-only zoom breakpoints.) [2daf6c82-7918-4f44-b822-fcb49f7bf681]</comment>

<file context>
@@ -91,11 +91,17 @@
+.cluster-resources__type{color:var(--soft);font-size:16px}
+.cluster-resources-list h2{margin:24px 0 4px}
+/* Wide screens: two columns, so the list does not leave half the screen empty. */
+@media(min-width:1001px){.article-style.cluster-resources-list{max-width:none}.article-style .cluster-resources{columns:2;column-gap:48px;max-width:1080px}.article-style .list-filter~ul.cluster-resources>li{break-inside:avoid}.cluster-resources-list .list-filter{max-width:520px}}
 .tag-find{max-width:520px;margin:20px 0 6px}
 .tag-find label{display:block;margin:0 0 6px;font:600 17px/1.3 var(--text)}
</file context>
Suggested change
@media(min-width:1001px){.article-style.cluster-resources-list{max-width:none}.article-style .cluster-resources{columns:2;column-gap:48px;max-width:1080px}.article-style .list-filter~ul.cluster-resources>li{break-inside:avoid}.cluster-resources-list .list-filter{max-width:520px}}
@media(min-width:62.5625em){.article-style.cluster-resources-list{max-width:none}.article-style .cluster-resources{columns:2;column-gap:48px;max-width:1080px}.article-style .list-filter~ul.cluster-resources>li{break-inside:avoid}.cluster-resources-list .list-filter{max-width:520px}}

if (statusEl) {
var message = '';
if (isFiltered && shownCards === 0) message = 'No resources match.';
else if (isFiltered) message = shownCards + ' of ' + allCards + ' resources shown' + (onHub ? ' in the clusters below.' : '.');

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3: A query found only in a cluster or sub-cluster heading hides every card and announces “No resources match,” despite the label promising cluster search. Label it “Search resources.”

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At static/js/featured-resources.js, line 892:

<comment>A query found only in a cluster or sub-cluster heading hides every card and announces “No resources match,” despite the label promising cluster search. Label it “Search resources.”</comment>

<file context>
@@ -825,6 +880,32 @@
+      if (statusEl) {
+        var message = '';
+        if (isFiltered && shownCards === 0) message = 'No resources match.';
+        else if (isFiltered) message = shownCards + ' of ' + allCards + ' resources shown' + (onHub ? ' in the clusters below.' : '.');
+        if (statusEl.textContent !== message) statusEl.textContent = message;
+        var none = isFiltered && shownCards === 0;
</file context>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant