Skip to content

Assistant - #4

Merged
thomasgallagher merged 46 commits into
mainfrom
assistant
Feb 27, 2026
Merged

Assistant#4
thomasgallagher merged 46 commits into
mainfrom
assistant

Conversation

@thomasgallagher

Copy link
Copy Markdown
Collaborator

No description provided.

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 554581c719

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

const main = document.querySelector("main")
const panel = document.querySelector(".l-ui-container--panel")
if (main) main.removeAttribute("inert")
if (panel) panel.removeAttribute("inert")

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Preserve panel inert state when closing mobile nav

This always removes inert from .l-ui-container--panel when the mobile menu closes, even if the panel is still closed. On mobile, a user can open and close navigation once and end up with an off-canvas panel that is aria-hidden but no longer inert, so its hidden controls are reachable via keyboard focus. Please only clear inert when the panel is actually open (or restore it when closed).

Useful? React with 👍 / 👎.

if (this.previousActiveElement && typeof this.previousActiveElement.focus === "function") {
this.previousActiveElement.focus()
}
this.announce("Dialog closed")

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 Badge Avoid duplicate dialog-closed announcements

The close event handler now announces "Dialog closed", but close() already announces the same message after calling dialogTarget.close(). Since HTMLDialogElement.close() emits the close event, normal close-button flows now send two live-region updates, which can make screen readers announce the closure twice. Keep the announcement in only one of these paths.

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: d64ee0d13b

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

// Restore background content tabbability
const main = document.querySelector("main")
const panel = document.querySelector(".l-ui-container--panel")
if (main) main.removeAttribute("inert")

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Keep main inert while panel remains open

closeNavigation() always calls main.removeAttribute("inert"), but l-ui--panel#open now sets main to inert on mobile to keep background content out of the tab order while the panel is open. If a user opens the panel, then opens and closes mobile navigation, this line clears inert even though the panel is still open, so hidden background controls become reachable again. Recompute inert state from both UI states (nav + panel) before removing it.

Useful? React with 👍 / 👎.

Comment on lines +125 to +128
if (this.isMobile()) {
const main = document.querySelector("main")
if (main) main.setAttribute("inert", "")
}

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 Badge Clear mobile inert state when viewport becomes desktop

open() applies inert to <main> on mobile, but there is no matching removal path when the viewport crosses to desktop while the panel stays open. Because handleWindowResize() only updates width/margins, rotating/resizing from <768px to desktop leaves main content inert and non-interactive until the panel is manually closed. The resize path should explicitly drop inert for the desktop-open panel case.

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: d6c4118b3a

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

data-action="click->l-ui--panel#toggle"
title="Toggle panel (Ctrl+i / ⌘i) - drag to move"
data-controller="l-ui--panel-button"
data-action="click->l-ui--panel#toggle mousedown->l-ui--panel-button#startDrag touchstart:passive->l-ui--panel-button#startDrag"

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 Badge Fix touch drag action descriptor syntax

The data-action token touchstart:passive->l-ui--panel-button#startDrag is not valid Stimulus option syntax, so on touch devices the handler is bound to a non-existent touchstart:passive event instead of touchstart. That means startDrag never runs for taps/drags on mobile, and the new draggable panel button cannot be repositioned there. Use Stimulus’s option placement (touchstart->...:passive) so the touch listener is actually registered.

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 72dc90002c

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".


try { localStorage.setItem("panelOpen", "false") } catch (e) { /* localStorage unavailable */ }
const main = document.querySelector("main")
if (main) main.removeAttribute("inert")

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 Badge Keep main inert while mobile navigation is still open

openNavigation() now sets main to inert, but close() always calls main.removeAttribute("inert") without checking whether the mobile menu is currently open. On mobile, if both overlays are active and the panel is closed via the keyboard shortcut (Ctrl/⌘+i), the navigation remains open while background content becomes tabbable again, which breaks the modal-like focus isolation introduced in mobile_navigation_controller.

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 9a51fdd054

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

const main = document.querySelector("main")
const panel = document.querySelector(".l-ui-container--panel")
if (main) main.removeAttribute("inert")
if (panel) panel.removeAttribute("inert")

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Preserve panel inert state in desktop resize handler

The desktop branch of handleResize() always runs panel.removeAttribute("inert"), which makes a closed off-canvas panel keyboard-focusable after any resize event (for example, resizing a desktop browser window while the panel is closed). This bypasses the panel controller’s closed-state focus isolation and allows hidden controls inside the panel to re-enter the tab order.

Useful? React with 👍 / 👎.

Comment on lines +85 to +87
if (this.isMobile()) {
const main = document.querySelector("main")
if (main) main.setAttribute("inert", "")

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 Badge Apply mobile inert state after desktop-to-mobile resize

The panel only sets <main> inert at open time when isMobile() is already true, so if a user opens the panel on desktop and then shrinks the viewport below 768px, background content stays tabbable behind the now-mobile overlay. This breaks the intended modal-like focus isolation on mobile until the panel is explicitly closed and reopened.

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e28e7fc026

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +179 to +181
this.element.removeEventListener("click", suppressClick, true)
}
this.element.addEventListener("click", suppressClick, true)

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 Badge Clear drag click-suppression even when no click fires

The drag-end path adds a capture-phase click suppressor but only removes it from inside that same click handler. If no click is emitted after mouseup (for example, when release happens outside the button after edge clamping, or on touch flows where preventDefault() suppresses the synthetic click), the suppressor stays attached and the next real tap/click on the panel button is swallowed. This makes the toggle appear unresponsive until an extra click and should be cleaned up even when no click arrives.

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 39944cd26d

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

this.actionButtonTarget.disabled = false
this.actionButtonTarget.setAttribute("aria-expanded", "false")
this.actionButtonTarget.removeAttribute("aria-hidden")
this.actionButtonTarget.setAttribute("tabindex", "-1")

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Keep panel toggle button in the tab order when closed

Setting the action button to tabindex="-1" in the close path makes the visible "Open panel" control unreachable for keyboard-only users after any close (including initial load, because connect() calls close(false)). In this state, users who do not know the Ctrl/⌘+i shortcut cannot reopen the panel at all, which is a functional accessibility regression from the previous behaviour where the button was tabbable.

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 0c3bad12eb

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +76 to +79
clearTimeout(this.toggleTimeout)
this.toggleTimeout = setTimeout(() => {
this.dispatch("toggle", { bubbles: true })
}, TOGGLE_DELAY)

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 Badge Keep click-to-toggle delay above double-click latency

queueToggle fires the panel toggle after a fixed 220ms timeout, but the timeout is only cancelled in cycleCorner (the dblclick handler). Any valid double-click whose second click lands after 220ms (still within the browser/OS double-click window) will trigger a panel toggle before the corner-cycle path can cancel it, so users trying to reposition the button can unintentionally open/close the panel first.

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 273d092055

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".


connect() {
this.previousActiveElement = null
this.isOpen = false

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 Badge Derive initial mobile nav state from current DOM

Setting this.isOpen to false on every connect can desynchronise controller state from the actual DOM state after Turbo snapshot restoration (Turbo is enabled in test/dummy/app/javascript/application.js). If a page is restored while the menu/backdrop still have the open class, close() becomes a no-op because it gates on this.isOpen, leaving a visibly open backdrop/menu that cannot be dismissed with outside click or Escape until users toggle twice. Initialise isOpen from the existing .open class (or normalise classes during connect) to keep state consistent.

Useful? React with 👍 / 👎.

@chatgpt-codex-connector

Copy link
Copy Markdown

💡 Codex Review

*,
*::before,
*::after {

P2 Badge Limit reduced-motion reset to layered-ui scope

This selector change applies the reduced-motion override to * across the whole document, so importing layered-ui-rails now suppresses animations/transitions for all host-app UI (not just layered-ui components) whenever prefers-reduced-motion: reduce is set. The previous implementation was scoped to [data-l-ui-reduce-motion], so this introduces cross-app side effects and can break host flows that depend on transition/animation timing. Please keep the reset scoped to layered-ui containers.

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 367856bd06

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +126 to +127
const hasModifier = event.metaKey || event.ctrlKey
if (!hasModifier || !event.altKey) return

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 Badge Ignore AltGr key combos in global corner shortcut handler

This handler treats any Ctrl/⌘ + Alt + 1..4 keydown as a panel-button command and always calls preventDefault(), but on many non-US Windows layouts the AltGr key reports as ctrlKey + altKey. In those environments, typing AltGr+digit in form fields (or any focused editable control) will be intercepted and the character input is blocked while the floating button moves unexpectedly. Please ignore AltGraph/editable-input contexts before consuming the event.

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 29a49b6876

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +7 to +8
<%= 'role="alert"' if error_message.present? %>
<%= 'hidden aria-hidden="true"' unless error_message.present? %>

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 Badge Emit valid ARIA attributes for field error element

The dynamic attribute strings are rendered via <%= ... %>, so Rails escapes the embedded quotes and outputs values like role=&quot;alert&quot; and aria-hidden=&quot;true&quot;; HTML parsers treat those as literal values ("alert", "true") rather than valid ARIA tokens. In validation flows, this can stop assistive tech from reliably announcing field-level errors and from correctly interpreting the hidden state. Build these attributes with tag helpers or unescaped attribute values instead of interpolated escaped strings.

Useful? React with 👍 / 👎.

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 84f8ce82c7

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

d="M12 3v1m0 16v1m9-9h-1M4 12H3m15.364 6.364l-.707-.707M6.343 6.343l-.707-.707m12.728 0l-.707.707M6.343 17.657l-.707.707M16 12a4 4 0 11-8 0 4 4 0 018 0z"
></path>
</svg>
<%= image_tag "layered_ui/icon_moon.svg", alt: "", class: "l-ui-icon--sm l-ui-theme-toggle__icon--light", aria: { hidden: true } %>

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 Badge Render currentColor icons inline instead of image tags

The new header control icons are now rendered with image_tag, but the SVG assets still rely on stroke="currentColor"; when an SVG is loaded through <img>, it no longer inherits the button text colour from .l-ui-button--icon/.l-ui-button--mobile-navigation, so these icons render with a fixed colour (and only a coarse dark:invert fallback) instead of following theme/token colours. This causes visible contrast/theming regressions in dark mode and custom colour schemes where control icons are expected to track foreground tokens.

Useful? React with 👍 / 👎.

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@thomasgallagher
thomasgallagher merged commit bf6090e into main Feb 27, 2026
2 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