Skip to content

Daily RC#508

Merged
softmarshmallow merged 7 commits intomainfrom
canary
Jan 27, 2026
Merged

Daily RC#508
softmarshmallow merged 7 commits intomainfrom
canary

Conversation

@softmarshmallow
Copy link
Copy Markdown
Member

@softmarshmallow softmarshmallow commented Jan 26, 2026

  • emscripten version logging
  • chores on ui usage

Summary by CodeRabbit

  • Documentation

    • Enhanced development setup instructions with build prerequisites and expanded workflow guidance.
  • Refactor

    • Streamlined button and control grouping across editor interface for consistency.
    • Reorganized editor panel tabs for improved layout and interaction stability.
    • Improved list rendering performance with optimized key management.
  • Chores

    • Updated linting configuration to align with framework standards.

✏️ Tip: You can customize this high-level summary in your review settings.

@vercel
Copy link
Copy Markdown

vercel Bot commented Jan 26, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Review Updated (UTC)
docs Ready Ready Preview, Comment Jan 27, 2026 1:46pm
grida Ready Ready Preview, Comment Jan 27, 2026 1:46pm
5 Skipped Deployments
Project Deployment Review Updated (UTC)
code Ignored Ignored Jan 27, 2026 1:46pm
legacy Ignored Ignored Jan 27, 2026 1:46pm
backgrounds Skipped Skipped Jan 27, 2026 1:46pm
blog Skipped Skipped Jan 27, 2026 1:46pm
viewer Skipped Skipped Jan 27, 2026 1:46pm

Request Review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Jan 26, 2026

Walkthrough

This PR consolidates UI component refactoring by migrating ActionGroup to ButtonGroup, refactoring Emscripten build configuration in justfile, updating ESLint rules, improving React list key stability, and adding documentation for Rust/Canvas prerequisites. No new features or altered public APIs.

Changes

Cohort / File(s) Summary
UI Component Refactoring - ButtonGroup Migration
editor/app/(workbench)/[org]/[proj]/(console)/(resources)/customers/page.tsx, editor/app/(workbench)/[org]/[proj]/(console)/(resources)/customers/[uid]/page.tsx, editor/components/preview-button/preview-button.tsx, editor/scaffolds/sidecontrol/controls/ext-align.tsx, editor/scaffolds/sidecontrol/controls/ext-ops.tsx
Replaced ActionGroup/ActionGroupItem with ButtonGroup and ButtonGroupSeparator components; updated imports and styling to use explicit Button components with outline variants
UI Component Refactoring - Internal Changes
editor/app/(workbench)/[org]/[proj]/(console)/(campaign)/campaigns/[campaign]/design/_enterprise/west-referral-duo-001-editor.tsx, editor/components/primitives/contenteditable.tsx
Introduced RightPanelTab wrapper component for modular tab content; added conditional rendering in contenteditable to use children when provided instead of dangerouslySetInnerHTML
Build & Configuration
crates/grida-canvas-wasm/justfile, editor/eslint.config.mjs, editor/empty-module.ts
Consolidated Emscripten environment setup via shared _wasm32_unknown_emscripten_env variable; enabled eslint-config-next/core-web-vitals and mocked rule set; refactored empty module to use named constant
Component Cleanup & Improvements
editor/components/ui-editor/action-group.tsx, editor/scaffolds/data-view-list/list-item.tsx, editor/scaffolds/grid-editor/components/query/xsb/xsb-sql-literal-input.tsx, editor/scaffolds/sidebar/sidebar-menu-group.tsx, editor/theme/templates/kit/components/screen.tsx
Deleted legacy ActionGroup component; stabilized React keys for list rendering; refactored memoized FK search component structure; added ScreenRoot displayName
Documentation
CONTRIBUTING.md
Added Rust/Canvas prerequisites section with ninja installation commands and extended development workflow instructions

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Possibly related PRs

  • #441 — Introduces new UI ButtonGroup and Spinner components, with overlapping ButtonGroup import updates across the same component files
  • #506 — Modifies grida-canvas-wasm Emscripten build configuration (emsdk and justfile adjustments)
  • #504 — Performs overlapping UI component refactors on the same editor files and component usage patterns

Suggested labels

daily, ux

Poem

🐰 Buttons group, ActionGroup fades away,
ButtonGroups shine bright, the refactored way!
Keys keep lists stable, build scripts align,
The canvas wasm toolchain now shines so fine! ✨

🚥 Pre-merge checks | ✅ 1 | ❌ 2
❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title 'Daily RC' is vague and does not clearly convey what changes are included in this pull request. It uses a generic term without meaningful context about the actual modifications. Replace with a descriptive title that summarizes the main changes, such as 'Refactor UI components to use ButtonGroup and add Wasm build improvements' or a more specific summary of the primary objective.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch canary

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 and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 5

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
editor/components/primitives/contenteditable.tsx (1)

50-71: Children rendering is overridden and updates can be skipped.

With the new children path, componentDidUpdate still overwrites DOM with this.props.html, and shouldComponentUpdate ignores children changes. This makes children unreliable (often erased) and can skip legitimate updates. Gate the html sync to the no-children case and allow updates when children change.

🐛 Proposed fix
   render() {
     const { tagName, html, innerRef, ...props } = this.props;
-    const children = this.props.children;
+    const children = this.props.children;
+    const hasChildren = children != null;

     return React.createElement(
       tagName || "div",
       {
         ...props,
         ref:
           typeof innerRef === "function"
             ? (current: HTMLElement) => {
                 innerRef(current);
                 this.el.current = current;
               }
             : innerRef || this.el,
         onInput: this.emitChange,
         onBlur: this.props.onBlur || this.emitChange,
         onKeyUp: this.props.onKeyUp || this.emitChange,
         onKeyDown: this.props.onKeyDown || this.emitChange,
         contentEditable: this.props.contentEditable,
-        ...(children == null ? { dangerouslySetInnerHTML: { __html: html } } : {}),
+        ...(hasChildren ? {} : { dangerouslySetInnerHTML: { __html: html } }),
       },
-      children == null ? undefined : children
+      hasChildren ? children : undefined
     );
   }
   shouldComponentUpdate(nextProps: Props): boolean {
     const { props } = this;
     const el = this.getEl();

     if (!el) return true;

-    if (normalizeHtml(nextProps.html) !== normalizeHtml(el.innerHTML)) {
-      return true;
-    }
+    const hasChildren = props.children != null || nextProps.children != null;
+    if (hasChildren) {
+      if (props.children !== nextProps.children) return true;
+    } else if (normalizeHtml(nextProps.html) !== normalizeHtml(el.innerHTML)) {
+      return true;
+    }

     return (
       props.contentEditable !== nextProps.contentEditable ||
       props.tagName !== nextProps.tagName ||
       props.className !== nextProps.className ||
       props.innerRef !== nextProps.innerRef ||
       !deepEqual(props.style, nextProps.style)
     );
   }

   componentDidUpdate() {
     const el = this.getEl();
     if (!el) return;

-    if (this.props.html !== el.innerHTML) {
-      el.innerHTML = this.props.html;
-    }
-    this.lastHtml = this.props.html;
+    const hasChildren = this.props.children != null;
+    if (!hasChildren && this.props.html !== el.innerHTML) {
+      el.innerHTML = this.props.html;
+    }
+    this.lastHtml = hasChildren ? el.innerHTML : this.props.html;
     replaceCaret(el);
   }
🤖 Fix all issues with AI agents
In `@CONTRIBUTING.md`:
- Around line 24-31: Replace the bold platform labels "**macOS**" and
"**Ubuntu/Debian**" with proper Markdown headings (e.g., "## macOS" and "##
Ubuntu/Debian") so they are treated as section headings rather than emphasized
text; update the surrounding blocks accordingly to maintain spacing and
formatting for the code fences and any subsequent platform-specific
instructions.

In
`@editor/app/`(workbench)/[org]/[proj]/(console)/(campaign)/campaigns/[campaign]/design/_enterprise/west-referral-duo-001-editor.tsx:
- Around line 355-360: The Input's value is reading
values?.components?.referrer?.cta while the onChange calls
props.set("components.referrer-share.cta", ...), causing a mismatch; update the
value binding to the same key used in props.set (e.g., use
values?.components?.["referrer-share"]?.cta) so the Input and props.set target
the same property, ensuring edits are reflected (locate the Input/FieldLabel
block and align the value to the "referrer-share" key).

In `@editor/eslint.config.mjs`:
- Around line 46-47: The config currently turns off critical rules
"react-hooks/rules-of-hooks" and "react-hooks/exhaustive-deps" which risks
runtime bugs; re-enable them instead of blanket "off" by setting them to "error"
or "warn" in eslint.config.mjs (or remove these overrides), then fix existing
violations incrementally in the codebase (or temporarily set to "warn" and
address violations gradually), and if any rule must remain disabled, add an
explicit justification comment in the config and use targeted inline
eslint-disable comments at the specific hook sites referencing rule names to
limit scope.
- Around line 48-55: The listed rules ("react-hooks/set-state-in-effect",
"react-hooks/preserve-manual-memoization", "react-hooks/static-components",
"react-hooks/incompatible-library", "react-hooks/purity",
"react-hooks/immutability", "react-hooks/use-memo", "react-hooks/refs") in
editor/eslint.config.mjs do not exist in eslint-plugin-react-hooks and are
silently ignored; either remove these entries from the rules block or change
their prefix to the correct plugin (react-compiler/) and install that plugin:
update package.json/pnpm-lock to include eslint-plugin-react-compiler, run pnpm
install, and replace each "react-hooks/..." key with "react-compiler/..." (or
simply delete the lines) so the config matches installed plugins and active rule
names.

In `@editor/scaffolds/sidecontrol/controls/ext-ops.tsx`:
- Around line 38-44: The icon-only button rendering <SquaresUniteIcon /> in
ext-ops.tsx lacks an accessible name; update the button element (the one with
onClick={() => onOp?.("union")} and className from buttonVariants) to include an
aria-label describing the action (e.g., "Union" or a more descriptive localized
string) so screen readers can announce its purpose.
🧹 Nitpick comments (3)
editor/components/preview-button/preview-button.tsx (1)

77-77: Consider adding ButtonGroupSeparator for visual consistency.

Other ButtonGroup usages in this PR (e.g., customers/page.tsx) include a ButtonGroupSeparator between the primary action and the dropdown trigger. Consider adding one here for consistency across the codebase, unless the design intentionally omits it for this component.

♻️ Optional: Add separator for consistency
       </Button>
+      <ButtonGroupSeparator />
       <DropdownMenu>

This would require importing ButtonGroupSeparator:

-import { ButtonGroup } from "@/components/ui/button-group";
+import { ButtonGroup, ButtonGroupSeparator } from "@/components/ui/button-group";
editor/scaffolds/sidecontrol/controls/ext-ops.tsx (1)

47-55: Consider using buttonVariants for styling consistency.

The first button uses buttonVariants({ variant: "ghost", size: "icon" }), but the dropdown trigger uses raw CSS classes. For consistency and maintainability, consider using buttonVariants here as well. This also lacks an aria-label for the dropdown trigger.

♻️ Suggested refactor
        <DropdownMenuTrigger asChild>
          <button
            disabled={disabled}
-           className="p-0 px-1 rounded-md focus-visible:outline-none focus-visible:ring-ring/50 focus-visible:ring-[3px]"
+           className={cn(
+             buttonVariants({ variant: "ghost", size: "icon" }),
+             "p-0 px-1"
+           )}
            type="button"
+           aria-label="More boolean operations"
          >
            <CaretDownIcon className="size-3" />
          </button>
        </DropdownMenuTrigger>
editor/eslint.config.mjs (1)

6-7: Config spread order differs from other apps in the codebase.

Other ESLint configs (e.g., apps/backgrounds/eslint.config.mjs, apps/viewer/eslint.config.mjs) spread nextVitals before nextTs. Here the order is reversed. Since later configs override earlier ones, this could lead to different rule precedence. Consider aligning with the existing pattern for consistency:

 const eslintConfig = defineConfig([
-  ...nextTs,
   ...nextVitals,
+  ...nextTs,

Comment thread CONTRIBUTING.md
Comment on lines +24 to +31
**macOS**

```bash
brew install ninja
ninja --version
```

**Ubuntu/Debian**
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Use headings instead of bold for platform labels.

Markdownlint flags macOS / Ubuntu/Debian as emphasis used as headings. Switch to proper heading levels for consistency.

💡 Suggested change
-**macOS**
+### macOS
...
-**Ubuntu/Debian**
+### Ubuntu/Debian
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
**macOS**
```bash
brew install ninja
ninja --version
```
**Ubuntu/Debian**
### macOS
🧰 Tools
🪛 LanguageTool

[grammar] ~31-~31: Ensure spelling is correct
Context: ...all ninja ninja --version **Ubuntu/Debian** bash sudo apt-get update sudo apt-get install -y ninja-build ninja --version ``` Then, install the dependencies and run t...

(QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1)

🪛 markdownlint-cli2 (0.18.1)

24-24: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)


31-31: Emphasis used instead of a heading

(MD036, no-emphasis-as-heading)

🤖 Prompt for AI Agents
In `@CONTRIBUTING.md` around lines 24 - 31, Replace the bold platform labels
"**macOS**" and "**Ubuntu/Debian**" with proper Markdown headings (e.g., "##
macOS" and "## Ubuntu/Debian") so they are treated as section headings rather
than emphasized text; update the surrounding blocks accordingly to maintain
spacing and formatting for the code fences and any subsequent platform-specific
instructions.

Comment on lines +355 to +360
<FieldLabel>Button Text</FieldLabel>
<Input
value={values?.components?.referrer?.cta}
onChange={(e) => {
props.set("components.referrer-share.cta", e.target.value);
}}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Fix CTA binding for “Referrer Share” input.

Line 357 binds the value to referrer.cta while updates write to referrer-share.cta, so the field won’t reflect edits.

🔧 Proposed fix
-                  <Input
-                    value={values?.components?.referrer?.cta}
+                  <Input
+                    value={values?.components?.["referrer-share"]?.cta}
                     onChange={(e) => {
                       props.set("components.referrer-share.cta", e.target.value);
                     }}
🤖 Prompt for AI Agents
In
`@editor/app/`(workbench)/[org]/[proj]/(console)/(campaign)/campaigns/[campaign]/design/_enterprise/west-referral-duo-001-editor.tsx
around lines 355 - 360, The Input's value is reading
values?.components?.referrer?.cta while the onChange calls
props.set("components.referrer-share.cta", ...), causing a mismatch; update the
value binding to the same key used in props.set (e.g., use
values?.components?.["referrer-share"]?.cta) so the Input and props.set target
the same property, ensuring edits are reflected (locate the Input/FieldLabel
block and align the value to the "referrer-share" key).

Comment thread editor/eslint.config.mjs
Comment on lines +46 to +47
"react-hooks/exhaustive-deps": "off",
"react-hooks/rules-of-hooks": "off",
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Disabling critical React Hooks rules carries significant risk.

react-hooks/rules-of-hooks prevents calling hooks inside conditions, loops, or nested functions — violations cause runtime crashes. react-hooks/exhaustive-deps catches stale closure bugs that are notoriously hard to debug.

If these are disabled to silence existing violations, consider fixing the violations incrementally rather than disabling enforcement entirely. At minimum, document why these critical safeguards are being removed.

🤖 Prompt for AI Agents
In `@editor/eslint.config.mjs` around lines 46 - 47, The config currently turns
off critical rules "react-hooks/rules-of-hooks" and
"react-hooks/exhaustive-deps" which risks runtime bugs; re-enable them instead
of blanket "off" by setting them to "error" or "warn" in eslint.config.mjs (or
remove these overrides), then fix existing violations incrementally in the
codebase (or temporarily set to "warn" and address violations gradually), and if
any rule must remain disabled, add an explicit justification comment in the
config and use targeted inline eslint-disable comments at the specific hook
sites referencing rule names to limit scope.

Comment thread editor/eslint.config.mjs
Comment on lines +48 to +55
"react-hooks/set-state-in-effect": "off",
"react-hooks/preserve-manual-memoization": "off",
"react-hooks/static-components": "off",
"react-hooks/incompatible-library": "off",
"react-hooks/purity": "off",
"react-hooks/immutability": "off",
"react-hooks/use-memo": "off",
"react-hooks/refs": "off",
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check for package.json files and their dependencies
echo "=== Looking for package.json files ==="
fd -t f "package.json" . --max-depth 3

echo ""
echo "=== Root package.json dependencies ==="
cat package.json 2>/dev/null | jq '.dependencies, .devDependencies' 2>/dev/null | grep -A2 -B2 "eslint-plugin-react"

echo ""
echo "=== Editor directory package.json (if exists) ==="
if [ -f "editor/package.json" ]; then
  cat editor/package.json | jq '.dependencies, .devDependencies' 2>/dev/null | grep -A2 -B2 "eslint-plugin-react"
fi

echo ""
echo "=== Checking eslint.config.mjs for plugin configuration ==="
cat editor/eslint.config.mjs 2>/dev/null | head -50

Repository: gridaco/grida

Length of output: 3208


🏁 Script executed:

#!/bin/bash
echo "=== editor/package.json ==="
cat editor/package.json

echo ""
echo "=== Full editor/eslint.config.mjs ==="
cat editor/eslint.config.mjs

echo ""
echo "=== Checking for react-compiler references in codebase ==="
rg "react-compiler" editor/ --max-count 5

Repository: gridaco/grida

Length of output: 11334


🏁 Script executed:

#!/bin/bash
echo "=== Checking for eslint-plugin-react-compiler in package-lock or node_modules (if exists) ==="
if [ -d "editor/node_modules" ]; then
  ls -la editor/node_modules | grep -i "react-compiler"
  echo ""
  echo "=== Checking react-compiler specifically ==="
  find editor/node_modules -name "*react-compiler*" -type d 2>/dev/null | head -5
else
  echo "node_modules not available in sandbox"
fi

echo ""
echo "=== Checking eslint-config-next dependencies ==="
cat editor/package-lock.json 2>/dev/null | jq '.dependencies["eslint-config-next"].dependencies' 2>/dev/null | head -50

echo ""
echo "=== Looking for pnpm-lock or similar lock file ==="
ls -la editor/ | grep -E "lock|pnpm"

Repository: gridaco/grida

Length of output: 290


🏁 Script executed:

#!/bin/bash
echo "=== Looking for pnpm-lock.yaml in root ==="
ls -la | grep -E "lock|pnpm"

echo ""
echo "=== Checking root pnpm-lock.yaml for react-compiler ==="
if [ -f "pnpm-lock.yaml" ]; then
  grep -A5 "react-compiler" pnpm-lock.yaml | head -30
fi

echo ""
echo "=== Web search info: Checking what rules eslint-plugin-react-hooks actually provides ==="
echo "Standard eslint-plugin-react-hooks rules: rules-of-hooks, exhaustive-deps"
echo "Questionable rules in config: set-state-in-effect, preserve-manual-memoization, static-components, incompatible-library, purity, immutability, use-memo, refs"

Repository: gridaco/grida

Length of output: 953


🏁 Script executed:

#!/bin/bash
echo "=== Searching for eslint-plugin-react-compiler in pnpm-lock.yaml ==="
grep "eslint-plugin-react-compiler" pnpm-lock.yaml

echo ""
echo "=== Searching for any reference to react-hooks or react-compiler in lock file ==="
grep -i "react.*compiler\|react.*hooks" pnpm-lock.yaml | head -20

echo ""
echo "=== Checking if eslint-config-next includes react-hooks plugin ==="
grep -A20 "eslint-config-next@16.1.3" pnpm-lock.yaml | grep -E "dependencies|react-hooks|react-compiler"

Repository: gridaco/grida

Length of output: 747


🌐 Web query:

eslint-plugin-react-hooks 7.0.1 available rules

💡 Result:

In eslint-plugin-react-hooks@7.0.1, the available ESLint rules exported by the plugin are:

  • react-hooks/rules-of-hooks (aka rules-of-hooks)
  • react-hooks/exhaustive-deps (aka exhaustive-deps)

Sources: the package’s exported rules map for v7.0.1 [1] and React’s Hooks linting docs showing the same two rules [2].


These react-hooks rules do not exist in the installed version and will be silently ignored.

eslint-plugin-react-hooks@7.0.1 (confirmed installed in pnpm-lock.yaml) provides only two rules: rules-of-hooks and exhaustive-deps. The rules on lines 48-55 (set-state-in-effect, preserve-manual-memoization, static-components, incompatible-library, purity, immutability, use-memo, refs) are non-existent and will not be enforced.

These appear to belong to React Compiler's ESLint plugin (eslint-plugin-react-compiler), which is not installed in this project. Either:

  1. Install eslint-plugin-react-compiler and change the prefix to react-compiler/, or
  2. Remove these rules from the configuration
🤖 Prompt for AI Agents
In `@editor/eslint.config.mjs` around lines 48 - 55, The listed rules
("react-hooks/set-state-in-effect", "react-hooks/preserve-manual-memoization",
"react-hooks/static-components", "react-hooks/incompatible-library",
"react-hooks/purity", "react-hooks/immutability", "react-hooks/use-memo",
"react-hooks/refs") in editor/eslint.config.mjs do not exist in
eslint-plugin-react-hooks and are silently ignored; either remove these entries
from the rules block or change their prefix to the correct plugin
(react-compiler/) and install that plugin: update package.json/pnpm-lock to
include eslint-plugin-react-compiler, run pnpm install, and replace each
"react-hooks/..." key with "react-compiler/..." (or simply delete the lines) so
the config matches installed plugins and active rule names.

Comment on lines 38 to 44
<button
disabled={disabled}
className={cn(
buttonVariants({ variant: "ghost", size: "icon" }),
"rounded-r-none"
)}
className={buttonVariants({ variant: "ghost", size: "icon" })}
onClick={() => onOp?.("union")}
>
<SquaresUniteIcon />
</button>
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Add aria-label for accessibility on icon-only button.

The button only contains an icon (<SquaresUniteIcon />) without visible text. Screen reader users won't understand the button's purpose. Consider adding an aria-label to describe the action.

♿ Suggested fix
      <button
        disabled={disabled}
        className={buttonVariants({ variant: "ghost", size: "icon" })}
        onClick={() => onOp?.("union")}
+       aria-label="Union"
      >
        <SquaresUniteIcon />
      </button>
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<button
disabled={disabled}
className={cn(
buttonVariants({ variant: "ghost", size: "icon" }),
"rounded-r-none"
)}
className={buttonVariants({ variant: "ghost", size: "icon" })}
onClick={() => onOp?.("union")}
>
<SquaresUniteIcon />
</button>
<button
disabled={disabled}
className={buttonVariants({ variant: "ghost", size: "icon" })}
onClick={() => onOp?.("union")}
aria-label="Union"
>
<SquaresUniteIcon />
</button>
🤖 Prompt for AI Agents
In `@editor/scaffolds/sidecontrol/controls/ext-ops.tsx` around lines 38 - 44, The
icon-only button rendering <SquaresUniteIcon /> in ext-ops.tsx lacks an
accessible name; update the button element (the one with onClick={() =>
onOp?.("union")} and className from buttonVariants) to include an aria-label
describing the action (e.g., "Union" or a more descriptive localized string) so
screen readers can announce its purpose.

@softmarshmallow softmarshmallow merged commit 2c2ef4d into main Jan 27, 2026
11 of 12 checks passed
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