Skip to content

feat(forms): add .sf-live-validate — opt-in native validation feedback - #604

Merged
jackgranatowski merged 2 commits into
mainfrom
claude/button-size-visibility-issue-40xlwy
Jul 12, 2026
Merged

feat(forms): add .sf-live-validate — opt-in native validation feedback#604
jackgranatowski merged 2 commits into
mainfrom
claude/button-size-visibility-issue-40xlwy

Conversation

@jackgranatowski

@jackgranatowski jackgranatowski commented Jul 12, 2026

Copy link
Copy Markdown
Contributor

Why

Follow-up to #603 (removing unconditional :user-invalid/:user-valid auto-colouring). On reflection, that removal was the right call, but for a more precise reason than originally documented:

:user-invalid fires on simple focus+blur — verified in this PR's own investigation: a real submit-button click reliably triggers it, but a bare focus()/blur() does not, even inside a <form>. In practice this means a still-empty required field gets marked invalid the moment a user tabs past it while filling out a multi-field form — before they've attempted to submit anything. This is a known, named anti-pattern: Bootstrap's own .was-validated class exists specifically to gate validation styling behind an explicit "the user tried to submit" signal, rather than firing from bare native pseudo-classes unconditionally.

So the removal correctly killed the anti-pattern — but it also took away a real, useful zero-JS convenience for consumers who do want native-triggered feedback (very common: "colour the field red once you hit submit").

What

.sf-live-validate is SLASHED's own version of Bootstrap's .was-validated gate — scoped, opt-in, and only active on a real submit attempt:

<form class="sf-live-validate">
  <input type="email" required>
  <button type="submit">Submit</button>
</form>

Within that subtree, :user-invalid/:user-valid on input/select/textarea drive --sf-field-border-color — same token the explicit .sf-is-invalid/.sf-is-valid classes (core/states.css) already set. Outside .sf-live-validate, nothing changes — nothing is scoped, nothing colours automatically.

  • optional/forms.css — the scoped rule pair, in the same spot the unconditional version used to live.
  • docs/token-annotations.json — class description (flows into docs/api-index.{json,md} / docs/classes.md via npm run docs; 293 → verified, +1 class, 329 → 330).
  • docs/migration.md — cross-reference added to the existing forms breaking-change section (this PR itself is additive, not breaking).
  • CHANGELOG.md — Features entry.

Testing note

:user-invalid doesn't reliably match via synthetic focus()/blur() in headless automation — confirmed directly, which is why #603 shipped without a trigger-level test. A real submit-button click is reliable, once the native validation bubble is suppressed via preventDefault() on the invalid event (the standard pairing for custom validation styling — you virtually never want both the native bubble and custom border colouring). tests/forms.spec.js uses exactly this pattern; verified independently in a direct Chromium harness (both themes) before porting into the Playwright spec. Assertion targets --sf-field-border-color directly rather than the rendered border-top-color, which transiently reflects Chromium's own bubble-UI rendering — matching the assertion style already used for this token in tests/states-full.spec.js.

Verification

Full node --test unit suite (109/109) and all 10 CSS gates pass. audit confirms 293 .sf-classes (was 292, +1 = .sf-live-validate); no token-registry drift (no new --sf-* token — reuses --sf-field-border-color).

Notes

🤖 Generated with Claude Code


Generated by Claude Code

Summary by CodeRabbit

  • New Features

    • Added the optional .sf-live-validate class to enable native form validation feedback within a specific form or fieldset.
    • Validation colors now appear after a submit attempt, rather than after focus and blur alone.
    • Existing validation state classes remain available for explicit styling.
  • Documentation

    • Updated the API reference, migration guidance, changelog, and demos to document the new validation option.
  • Tests

    • Added coverage confirming validation feedback is scoped only to forms using .sf-live-validate.

Follow-up to the removal of unconditional :user-invalid/:user-valid
auto-colouring. On reflection the removal was the right call — :user-invalid
fires on simple focus+blur (verified: a real submit-button click is the
reliable trigger; bare focus()/blur() does not fire it reliably even inside a
<form>), so a still-empty required field could be marked invalid mid
multi-field form-fill, before any submit was attempted. This is a known
anti-pattern; Bootstrap's own .was-validated gate exists specifically to avoid
firing validation styling from bare native pseudo-classes.

.sf-live-validate is that same gate, framework-native: apply it to a <form> or
<fieldset> to scope the :user-invalid/:user-valid -> --sf-field-border-color
pivot to that subtree, active only once a submit has actually been attempted.
Restores the zero-JS convenience the removed behaviour offered, without its
premature-feedback failure mode — and without requiring per-field JS the way
the explicit .sf-is-invalid/.sf-is-valid classes do.

- optional/forms.css: new scoped rule pair, right where the unconditional
  version used to live.
- docs/token-annotations.json: class description (flows into
  docs/api-index.{json,md} and docs/classes.md via `npm run docs`).
- docs/migration.md: cross-reference added to the existing forms
  breaking-change section (this PR is additive, not itself breaking).
- CHANGELOG.md: Features entry.
- tests/forms.spec.js: new deterministic Playwright test. :user-invalid does
  not reliably match via synthetic focus()/blur() in headless automation (the
  reason the removal PR shipped without a trigger-level test), but a real
  submit-button click does, reliably, once the native validation bubble is
  suppressed via preventDefault() on the `invalid` event — the standard
  pairing for custom validation styling. Asserts --sf-field-border-color
  directly (not border-top-color, which briefly reflects Chromium's own
  transient bubble-UI rendering) — matching the assertion style already used
  in tests/states-full.spec.js for the same token.

Verified in both themes via a direct Chromium harness before porting into the
Playwright spec. Full node --test unit suite (109/109) and all 10 CSS gates
pass; audit confirms 293 .sf-classes (+1).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

Claude-Session: https://claude.ai/code/session_01GnwqYHgHNAWPbsUJWUeY1w
@coderabbitai

coderabbitai Bot commented Jul 12, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@jackgranatowski, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 51 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: fdc53df2-9f3b-47b6-988f-0d6119943375

📥 Commits

Reviewing files that changed from the base of the PR and between c05447a and b6809da.

📒 Files selected for processing (6)
  • configurator/src/data/classes.generated.json
  • docs/api-index.json
  • docs/api-index.md
  • docs/llm-guide.md
  • optional/forms.css
  • scripts/lib/api-index/extract.js
📝 Walkthrough

Walkthrough

Adds the opt-in .sf-live-validate class for subtree-scoped native form validation styling after submit attempts, with CSS coverage, generated API metadata, documentation, changelog updates, and demo count updates.

Changes

Native validation feedback

Layer / File(s) Summary
Scoped validation styling and test
optional/forms.css, tests/forms.spec.js
Adds .sf-live-validate rules for native valid and invalid states and verifies that styling remains scoped after submission.
Public class metadata and indexes
configurator/src/data/classes.generated.json, docs/api-index.*, docs/classes.md, docs/registry.json, docs/token-annotations.json
Registers and documents the new optional public class across generated datasets and indexes.
Migration and release documentation
docs/migration.md, CHANGELOG.md, demos/full-api-demo*.html
Documents the opt-in behavior, records the release changes, and updates demo class counts.

Estimated code review effort: 2 (Simple) | ~10 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Form
  participant Browser
  participant LiveValidateCSS
  Form->>Browser: Submit required fields
  Browser->>LiveValidateCSS: Apply native validation states
  LiveValidateCSS->>Form: Set field border color within .sf-live-validate
Loading

Possibly related PRs

Suggested labels: codex

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely summarizes the main change: adding the opt-in .sf-live-validate native validation feedback feature.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/button-size-visibility-issue-40xlwy

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot added the codex label Jul 12, 2026
@greptile-apps

greptile-apps Bot commented Jul 12, 2026

Copy link
Copy Markdown

Greptile Summary

This PR adds .sf-live-validate — an opt-in CSS class that restores native :user-invalid/:user-valid--sf-field-border-color feedback within a scoped subtree, following the removal of the unconditional version in #603. It is purely additive with no token changes.

  • optional/forms.css — two scoped rule blocks inside @layer slashed.forms wire up :user-invalid/:user-valid for input, select, and textarea descendants, reusing the existing --sf-field-border-color token.
  • tests/forms.spec.js — new Playwright test covers the positive/negative cases by comparing a plain form and a .sf-live-validate form after a real submit click, correctly suppressing the native validation bubble via preventDefault().
  • Docsapi-index, classes.md, token-annotations.json, registry.json, migration.md, and CHANGELOG.md are all updated; docs/llm-guide.md (mandated by CLAUDE.md for any optional/*.css change) is not included.

Confidence Score: 4/5

Safe to merge; the CSS addition is scoped, purely opt-in, and touches no existing rules.

The CSS implementation is clean: two scoped rule pairs inside the existing @layer slashed.forms, no new tokens, and a well-structured Playwright test that uses a real submit click to reliably trigger :user-invalid. The documentation sweep across api-index, classes.md, registry.json, migration.md, and CHANGELOG.md is thorough. Two minor concerns hold it just below a clean score: docs/llm-guide.md is not updated despite the CLAUDE.md mandatory review requirement for any optional/*.css change, and there is a silent cascade conflict if .sf-is-invalid is applied manually to a field inside .sf-live-validate whose native state disagrees — neither is blocking, but both are worth addressing before the release.

docs/llm-guide.md should be reviewed for a mention of .sf-live-validate in the form-field section (section 9.10).

Important Files Changed

Filename Overview
optional/forms.css Adds two scoped rule blocks (.sf-live-validate input/select/textarea:user-invalid / :user-valid) inside @layer slashed.forms; correctly placed after the autofill stylelint-enable boundary; no new tokens introduced.
tests/forms.spec.js New Playwright test verifies that only the .sf-live-validate-scoped form's input gets --sf-field-border-color set after a real submit click; correctly suppresses the native bubble via preventDefault() and reads the CSS custom property directly.
docs/migration.md Adds a cross-reference under the existing forms breaking-change section documenting .sf-live-validate with an HTML snippet; additive and accurate.
docs/token-annotations.json New entry for sf-live-validate with accurate description; consistent with existing class annotation style.
docs/api-index.json Counts updated correctly (+1 class, +1 PUBLIC, +1 sf_class) and new entry added for sf-live-validate in the correct position; sourceFiles, bundles, and category fields look accurate.
CHANGELOG.md Features entry added above Breaking Changes; cross-reference in the existing forms breaking-change entry updated to mention .sf-live-validate.
configurator/src/data/classes.generated.json New sf-live-validate entry added with correct kind, category, optional, and layer fields; description consistent with other doc artifacts.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[Form submit click] --> B{Form has .sf-live-validate?}
    B -- No --> C[Browser fires :user-invalid on field]
    C --> D[No CSS rule matches — --sf-field-border-color unchanged]
    B -- Yes --> E[Browser fires :user-invalid on field]
    E --> F[.sf-live-validate input:user-invalid sets --sf-field-border-color = --sf-color-danger]
    F --> G[Field border turns danger color]
    H[User types invalid value then blurs] --> B
    style D fill:#f9f9f9,stroke:#ccc
    style G fill:#fde,stroke:#f66
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
flowchart TD
    A[Form submit click] --> B{Form has .sf-live-validate?}
    B -- No --> C[Browser fires :user-invalid on field]
    C --> D[No CSS rule matches — --sf-field-border-color unchanged]
    B -- Yes --> E[Browser fires :user-invalid on field]
    E --> F[.sf-live-validate input:user-invalid sets --sf-field-border-color = --sf-color-danger]
    F --> G[Field border turns danger color]
    H[User types invalid value then blurs] --> B
    style D fill:#f9f9f9,stroke:#ccc
    style G fill:#fde,stroke:#f66
Loading

Reviews (1): Last reviewed commit: "feat(forms): add .sf-live-validate — opt..." | Re-trigger Greptile

Comment thread optional/forms.css
Comment on lines +89 to +107
/* Opt-in native validation feedback. Unconditional :user-invalid/:user-valid
styling was removed in 0.8.0 (see docs/migration.md): it fires on simple
focus+blur, so a still-empty required field could be marked invalid mid
multi-field form-fill, before any submit was attempted — the pattern
Bootstrap's own .was-validated gate exists to avoid. .sf-live-validate is
that same gate: put it on a <form> or <fieldset> to scope the pivot to
that subtree, so it only lights up on a real submit attempt (or explicit
interaction) instead of applying everywhere by default. */
.sf-live-validate input:user-invalid,
.sf-live-validate select:user-invalid,
.sf-live-validate textarea:user-invalid {
--sf-field-border-color: var(--sf-color-danger);
}

.sf-live-validate input:user-valid,
.sf-live-validate select:user-valid,
.sf-live-validate textarea:user-valid {
--sf-field-border-color: var(--sf-color-success);
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 docs/llm-guide.md not updated — CLAUDE.md requirement

CLAUDE.md mandates: "Any PR that touches core/*.css, optional/*.css, or token-registry.json must also review docs/llm-guide.md and update it if needed." This PR touches optional/forms.css but docs/llm-guide.md is not among the changed files. Section 9.10 of the guide documents --sf-field-border-color as the hook set by validation states, but doesn't mention .sf-live-validate as the mechanism to re-enable native-triggered feedback. An LLM consuming the guide to help a user implement form validation would have no way to learn this class exists.

Context Used: CLAUDE.md (source)

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Comment thread optional/forms.css
Comment on lines +97 to +107
.sf-live-validate input:user-invalid,
.sf-live-validate select:user-invalid,
.sf-live-validate textarea:user-invalid {
--sf-field-border-color: var(--sf-color-danger);
}

.sf-live-validate input:user-valid,
.sf-live-validate select:user-valid,
.sf-live-validate textarea:user-valid {
--sf-field-border-color: var(--sf-color-success);
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Interaction with explicit .sf-is-invalid / .sf-is-valid state classes inside .sf-live-validate

The new rules have specificity 0-2-1 (.sf-live-validate + element + pseudo-class), while the explicit .sf-is-invalid / .sf-is-valid state classes live in core/states.css. If a field inside .sf-live-validate has .sf-is-invalid applied for custom/server-side validation but the browser considers it natively valid (:user-valid), the .sf-live-validate input:user-valid rule will set --sf-field-border-color to --sf-color-success, silently overriding the manually-applied invalid styling. This is an edge case, but a silent, non-obvious CSS cascade conflict worth documenting in migration.md or a code comment.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
docs/api-index.json (1)

24890-24890: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Category label "Forms (classless)" is a mismatch for a class-based opt-in.

sf-live-validate is an explicitly applied CSS class (.sf-live-validate on <form>/<fieldset>), not a "classless" enhancement, yet it's filed under the "Forms (classless)" category (also reflected in the by_category counts). This is likely inherited from a category bucket meant for classless form styling defaults; consider a distinct category (e.g., "Forms") for class-based form opt-ins to avoid confusing downstream consumers of this generated index.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/api-index.json` at line 24890, The category assigned to sf-live-validate
is incorrect for its class-based opt-in. Update its entry in the generated API
index to use the appropriate distinct Forms category, and synchronize any
related by_category counts or references so downstream index data consistently
reflects the new category.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs/migration.md`:
- Around line 96-109: Update the forms guidance in llm-guide.md to document that
native :user-invalid/:user-valid feedback is no longer unconditional and is now
enabled opt-in by adding .sf-live-validate to a form or fieldset. Include the
submit-attempt gating and subtree scoping behavior, with an appropriate usage
example consistent with the migration documentation.

---

Nitpick comments:
In `@docs/api-index.json`:
- Line 24890: The category assigned to sf-live-validate is incorrect for its
class-based opt-in. Update its entry in the generated API index to use the
appropriate distinct Forms category, and synchronize any related by_category
counts or references so downstream index data consistently reflects the new
category.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 634dfccb-cef8-42d5-9514-37c8086f9c78

📥 Commits

Reviewing files that changed from the base of the PR and between 2f8a2c8 and c05447a.

📒 Files selected for processing (12)
  • CHANGELOG.md
  • configurator/src/data/classes.generated.json
  • demos/full-api-demo-with-overrides.html
  • demos/full-api-demo.html
  • docs/api-index.json
  • docs/api-index.md
  • docs/classes.md
  • docs/migration.md
  • docs/registry.json
  • docs/token-annotations.json
  • optional/forms.css
  • tests/forms.spec.js

Comment thread docs/migration.md
Comment on lines +96 to +109
**Want the native-triggered feedback back, without writing JS?** Add
`.sf-live-validate` to the `<form>` (or a `<fieldset>`) — it re-enables the
`:user-invalid`/`:user-valid` → `--sf-field-border-color` pivot, scoped to that
subtree, but only once a submit has actually been attempted (not on simple
focus+blur, which is what made the original unconditional behaviour fire
prematurely mid-form-fill):

```html
<form class="sf-live-validate">
<input type="email" required>
<button type="submit">Submit</button>
</form>
```

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Confirm llm-guide.md references the new class / was touched in this PR.
rg -n "sf-live-validate" docs/llm-guide.md
git log --oneline -- docs/llm-guide.md | head -5

Repository: codeslash-dev/SLASHED

Length of output: 655


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n== files ==\n'
git ls-files docs/migration.md docs/llm-guide.md optional/forms.css || true

printf '\n== migration excerpt ==\n'
sed -n '80,130p' docs/migration.md

printf '\n== llm-guide excerpt (search terms) ==\n'
rg -n -C 3 "form|validate|token role|browser support|user-invalid|user-valid|sf-live-validate|border-color" docs/llm-guide.md || true

printf '\n== forms.css excerpt (search terms) ==\n'
rg -n -C 3 "sf-live-validate|user-invalid|user-valid|sf-field-border-color|form|fieldset" optional/forms.css || true

Repository: codeslash-dev/SLASHED

Length of output: 10362


Document .sf-live-validate in docs/llm-guide.md
optional/forms.css now makes native validation feedback opt-in. Add the new .sf-live-validate gate and the removed unconditional :user-invalid/:user-valid behavior to the guide so the forms docs match the shipped behavior.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/migration.md` around lines 96 - 109, Update the forms guidance in
llm-guide.md to document that native :user-invalid/:user-valid feedback is no
longer unconditional and is now enabled opt-in by adding .sf-live-validate to a
form or fieldset. Include the submit-attempt gating and subtree scoping
behavior, with an appropriate usage example consistent with the migration
documentation.

Source: Coding guidelines

…e-safety note

Address CodeRabbit + Greptile review on PR #604:

- docs/llm-guide.md: document .sf-live-validate as the opt-in gate for native
  :user-invalid/:user-valid feedback (CLAUDE.md mandates reviewing this file
  for any optional/*.css change; both reviewers independently flagged the
  omission, even though llm-guide.md was previously 100% token-only).
- scripts/lib/api-index/extract.js: optional/forms.css was hardcoded
  'Forms (classless)' from when the file had zero .sf-* classes; now that
  .sf-live-validate exists, drop the stale qualifier. Regenerated
  docs/api-index.{json,md} + configurator's synced copy.
- optional/forms.css: add a code comment addressing Greptile's cascade
  concern — verified (not just asserted) in Chromium that a manually-applied
  .sf-is-invalid always wins over .sf-live-validate's native-triggered colour,
  regardless of selector specificity, because slashed.states is declared
  AFTER slashed.forms in the layer order (core/layers.css) — cascade layer
  order beats specificity. Greptile's specific claim (specificity 0-2-1 beats
  0-1-0, so the native rule would silently override the manual one) doesn't
  hold once layers are accounted for; documented the real (safe) behaviour
  instead of "fixing" a conflict that doesn't exist.

Full node --test unit suite (109/109) and all 10 CSS gates pass.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

Claude-Session: https://claude.ai/code/session_01GnwqYHgHNAWPbsUJWUeY1w
@jackgranatowski
jackgranatowski merged commit 7371c3f into main Jul 12, 2026
13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants