Skip to content

Frontend/safari fixes#995

Merged
isabeleliassen merged 7 commits intocsg-org:developmentfrom
InspiringApps:frontend/ios-safari-fixes
Aug 13, 2025
Merged

Frontend/safari fixes#995
isabeleliassen merged 7 commits intocsg-org:developmentfrom
InspiringApps:frontend/ios-safari-fixes

Conversation

@jsandoval81
Copy link
Copy Markdown
Collaborator

@jsandoval81 jsandoval81 commented Aug 6, 2025

Requirements List

  • yarn install --ignore-engines

Description List

  • Updated vue-responsiveness dependency
  • Adjust payment popup keyboard nav
  • Adjust side nav bottom padding on mobile safari
  • Fix input position on email confirmation modal on safari

Testing List

  • yarn test:unit:all should run without errors or warnings
  • yarn serve should run without errors or warnings
  • yarn build should run without errors or warnings
  • Code review
  • Testing
    • Login as licensee user who can purchase privileges
    • Start the purchase workflow and continue to the "Payment Summary" screen
    • Complete the form to launch the authorize .net popup
    • Confirm that the popup is focused and keyboard tab nav begins near the first focusable item in the popup
    • Confirm that tab navigation is focus-trapped reasonably in the popup
      • There might be slight variations between browsers, but in general focus trapping should now be a thing for this popup
    • In safari, navigate to the Account page and initiate an email address change, prompting the modal with the code
    • Confirm all of the content in the modal is centered
      • No need to actually finish the email change
    • In mobile safari (iphone or xcode simulator) expand the side navigation
    • Confirm the Logout link is completely visible and not obscured by the bottom URL bar, even when the bottom URL bar expands upwards
    • In mobile safari (ipad or xcode simulator) confirm that the side navigation is touch compatible

Closes #898
Close #967

Summary by CodeRabbit

  • Accessibility Improvements

    • Better keyboard navigation and focus handling for the payment details flow, improving use of embedded payment UI.
  • Bug Fixes

    • Prevented iPhone Safari’s URL bar from obscuring navigation by adding targeted spacing.
  • Style

    • Improved modal and action-button layout for email confirmation across screen sizes.
    • Scoped navigation/header styles to hover-capable tablet devices for visual consistency.
  • New Features / Enhancements

    • Navigation and header now adapt behavior for touch vs. pointer devices; menu collapse after navigation refined.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Aug 6, 2025

Walkthrough

Adds device/browser detection to adjust navigation rendering and styles (including iPhone Safari and touch devices), refines media queries to target hover-capable tablets, adds keyboard focus-trap handling for the payment iframe, and tweaks modal and layout styles for responsiveness.

Changes

Cohort / File(s) Change Summary
Page navigation detection & styles
webroot/src/components/Page/PageMainNav/PageMainNav.ts, webroot/src/components/Page/PageMainNav/PageMainNav.vue, webroot/src/components/Page/PageMainNav/PageMainNav.less
Adds computed getters isTouchDevice, isIphoneSafari, isMenuTouchToggle; switches event/visibility logic to use isMenuTouchToggle; adds conditional classes touch-device and iphone-safari and adjusts nav CSS (including additional padding rules and flex growth).
Page container & header adjustments
webroot/src/components/Page/PageContainer/PageContainer.ts, webroot/src/components/Page/PageContainer/PageContainer.less, webroot/src/components/Page/PageHeader/PageHeader.ts, webroot/src/components/Page/PageHeader/PageHeader.vue, webroot/src/components/Page/PageHeader/PageHeader.less
Renames/expands isPhoneisMenuTouchToggle; updates include/header rendering to use isMenuTouchToggle; refines several tablet media queries to require (hover: hover) so styles apply only to hover-capable tablet-width devices.
Payment iframe accessibility
webroot/src/components/PrivilegePurchaseAcceptUI/PrivilegePurchaseAcceptUI.ts, webroot/src/components/PrivilegePurchaseAcceptUI/PrivilegePurchaseAcceptUI.vue
Adds focus-trap handling: new properties, focusTrap(), removeFocusTrapHandling(), detectIframeClose(), handleIframeClosed(); sets iframe title and focuses the container; adds id="payment-init" to submit button.
Modal layout tweaks
webroot/src/components/UserAccount/UserAccount.less
Updates .confirm-email-modal .modal-content to flex column/center and adjusts .action-button-row widths, margins, and desktop layout to improve responsiveness.
Router menu collapse behavior
webroot/src/router/index.ts
Expands condition in router.afterEach to also collapse nav when device matches (hover: hover) and (pointer: fine) in addition to small window width.
TypeScript shim
webroot/src/shims-vue-responsiveness.d.ts
Adds module augmentation for @vue/runtime-core to type $matches from vue-responsiveness.

Sequence Diagram(s)

Payment popup keyboard focus trap flow

sequenceDiagram
    participant User
    participant Browser
    participant PrivilegePurchaseAcceptUI

    User->>Browser: Open payment flow
    Browser->>PrivilegePurchaseAcceptUI: Render iframe + container
    PrivilegePurchaseAcceptUI->>PrivilegePurchaseAcceptUI: create trap element, set title, focus container, attach keydown handlers
    User->>PrivilegePurchaseAcceptUI: press Tab / Shift+Tab
    PrivilegePurchaseAcceptUI->>PrivilegePurchaseAcceptUI: focusTrap() cycles focus between container and trapper
    PrivilegePurchaseAcceptUI->>PrivilegePurchaseAcceptUI: detectIframeClose() -> handleIframeClosed() -> cleanup
Loading

Navigation detection and style application (high level)

sequenceDiagram
    participant Browser
    participant PageMainNav
    participant CSS

    Browser->>PageMainNav: instantiate component
    PageMainNav->>PageMainNav: compute isTouchDevice, isIphoneSafari, isMenuTouchToggle
    PageMainNav->>PageMainNav: add conditional classes to nav (`touch-device`, `iphone-safari`) and adjust handlers
    PageMainNav->>CSS: CSS rules apply based on classes & refined media queries
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~18 minutes

Assessment against linked issues

Objective Addressed Explanation
Move logout button up the screen on mobile to prevent access issue (#898) No changes move or reposition the logout button; nav rendering changes don't explicitly adjust logout placement.
Safari: Account page email verification modal code input not centered (#967)
Safari: Payment credit card popup not focused for keyboard nav like on other browsers (#967)

Assessment against linked issues: Out-of-scope changes

Code Change Explanation
Expanded router collapse condition to (hover: hover) and (pointer: fine) (webroot/src/router/index.ts) Not referenced in linked issues; this broadens collapse behavior beyond Safari fixes or logout placement and appears unrelated to those objectives.
Addition of $matches TypeScript shim (webroot/src/shims-vue-responsiveness.d.ts) Typing addition is infrastructure/typing support and not required by the linked issues' functional objectives.

Possibly related PRs

Suggested reviewers

  • jlkravitz
  • rmolinares
  • isabeleliassen

Poem

"I nudged a nav, I trapped a tab,
I padded bottoms where Safari drab.
A modal centered, buttons neat,
Focus finds forms with tiny feet.
Hopgingly helpful — 🐇✨"


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between be1c43c and 091d655.

📒 Files selected for processing (1)
  • webroot/src/components/PrivilegePurchaseAcceptUI/PrivilegePurchaseAcceptUI.ts (3 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • webroot/src/components/PrivilegePurchaseAcceptUI/PrivilegePurchaseAcceptUI.ts
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: CheckWebroot
✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai generate unit tests to generate unit tests for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Copy Markdown
Contributor

@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: 0

🧹 Nitpick comments (1)
webroot/src/components/PrivilegePurchaseAcceptUI/PrivilegePurchaseAcceptUI.ts (1)

141-178: Focus trap setup looks good with a minor suggestion.

The implementation correctly sets up focus trap elements and event listeners. The accessibility improvement with the iframe title is also good.

Consider using requestAnimationFrame or nextTick instead of setTimeout for more deterministic focus timing:

-            window.setTimeout(() => { acceptUiContainer.focus(); }, 100);
+            this.$nextTick(() => { acceptUiContainer.focus(); });
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 94c24ff and f98dded.

📒 Files selected for processing (5)
  • webroot/src/components/Page/PageMainNav/PageMainNav.less (1 hunks)
  • webroot/src/components/Page/PageMainNav/PageMainNav.ts (1 hunks)
  • webroot/src/components/Page/PageMainNav/PageMainNav.vue (1 hunks)
  • webroot/src/components/PrivilegePurchaseAcceptUI/PrivilegePurchaseAcceptUI.ts (3 hunks)
  • webroot/src/components/UserAccount/UserAccount.less (2 hunks)
🧰 Additional context used
🧠 Learnings (8)
📓 Common learnings
Learnt from: jsandoval81
PR: csg-org/CompactConnect#799
File: webroot/src/pages/LicenseeProof/LicenseeProof.less:144-168
Timestamp: 2025-05-07T18:15:17.462Z
Learning: In the CompactConnect project, print layouts for footers are designed to use fixed positioning (position: fixed) in Chrome and Firefox while using a fallback to relative positioning for Safari (detected via supports (font: -apple-system-body)). This approach is intentional and aligns with the design requirements, as Safari doesn't handle fixed elements correctly in print layouts.
Learnt from: jsandoval81
PR: csg-org/CompactConnect#922
File: webroot/src/components/UserAccount/UserAccount.ts:0-0
Timestamp: 2025-07-10T19:50:56.745Z
Learning: In the UserAccount component (webroot/src/components/UserAccount/UserAccount.ts), the email field should be disabled for staff users (`isDisabled: this.isStaff`) to maintain existing restrictions, while licensees should be able to change their email address through the new verification process. This is the intended behavior per PR #922 requirements.
Learnt from: jsandoval81
PR: csg-org/CompactConnect#873
File: webroot/src/styles.common/_inputs.less:115-118
Timestamp: 2025-06-24T00:17:31.188Z
Learning: The team intentionally uses broad CSS selectors like `.dp__input_wrap div { position: static; }` to fix styling issues with the Vue Date-Picker library. They have experience with these styles working well, keep the library version pinned in yarn.lock, and have established processes to re-test everything when updating the library version. This approach is acceptable given their testing discipline and version control.
📚 Learning: in the useraccount component (webroot/src/components/useraccount/useraccount.ts), the email field sh...
Learnt from: jsandoval81
PR: csg-org/CompactConnect#922
File: webroot/src/components/UserAccount/UserAccount.ts:0-0
Timestamp: 2025-07-10T19:50:56.745Z
Learning: In the UserAccount component (webroot/src/components/UserAccount/UserAccount.ts), the email field should be disabled for staff users (`isDisabled: this.isStaff`) to maintain existing restrictions, while licensees should be able to change their email address through the new verification process. This is the intended behavior per PR #922 requirements.

Applied to files:

  • webroot/src/components/UserAccount/UserAccount.less
📚 Learning: the `.add-email-help` element in the inputemaillist component (webroot/src/components/forms/inputema...
Learnt from: jsandoval81
PR: csg-org/CompactConnect#822
File: webroot/src/components/Forms/InputEmailList/InputEmailList.less:17-26
Timestamp: 2025-05-28T16:10:55.628Z
Learning: The `.add-email-help` element in the InputEmailList component (webroot/src/components/Forms/InputEmailList/InputEmailList.less) is display-only and not meant to handle interaction states like hover or focus. It should not have cursor: pointer or interactive styling.

Applied to files:

  • webroot/src/components/UserAccount/UserAccount.less
📚 Learning: in the compactconnect project, print layouts for footers are designed to use fixed positioning (posi...
Learnt from: jsandoval81
PR: csg-org/CompactConnect#799
File: webroot/src/pages/LicenseeProof/LicenseeProof.less:144-168
Timestamp: 2025-05-07T18:15:17.462Z
Learning: In the CompactConnect project, print layouts for footers are designed to use fixed positioning (position: fixed) in Chrome and Firefox while using a fallback to relative positioning for Safari (detected via supports (font: -apple-system-body)). This approach is intentional and aligns with the design requirements, as Safari doesn't handle fixed elements correctly in print layouts.

Applied to files:

  • webroot/src/components/Page/PageMainNav/PageMainNav.less
📚 Learning: in privilegepurchaseacceptui, the team requires that the acceptui script be appended only to the ele...
Learnt from: jsandoval81
PR: csg-org/CompactConnect#847
File: webroot/src/components/PrivilegePurchaseAcceptUI/PrivilegePurchaseAcceptUI.ts:91-109
Timestamp: 2025-06-11T18:47:17.329Z
Learning: In PrivilegePurchaseAcceptUI, the team requires that the AcceptUI script be appended only to the element with id `finalize-privilege-purchase-container`; falling back to `document.body` is not acceptable.

Applied to files:

  • webroot/src/components/PrivilegePurchaseAcceptUI/PrivilegePurchaseAcceptUI.ts
📚 Learning: `privilegepurchaseacceptui` publishes payment results via `"success"` / `"error"` events; the visual...
Learnt from: jsandoval81
PR: csg-org/CompactConnect#847
File: webroot/src/components/PrivilegePurchaseAcceptUI/PrivilegePurchaseAcceptUI.ts:141-155
Timestamp: 2025-06-11T18:49:14.626Z
Learning: `PrivilegePurchaseAcceptUI` publishes payment results via `"success"` / `"error"` events; the visual feedback is rendered by the parent component (`PrivilegePurchaseFinalize.ts`), so the child intentionally does not set its own `errorMessage` / `successMessage`.

Applied to files:

  • webroot/src/components/PrivilegePurchaseAcceptUI/PrivilegePurchaseAcceptUI.ts
📚 Learning: in licensecard component's clickunencumberitem method (webroot/src/components/licensecard/licensecar...
Learnt from: jsandoval81
PR: csg-org/CompactConnect#873
File: webroot/src/components/LicenseCard/LicenseCard.ts:414-443
Timestamp: 2025-06-24T00:02:39.944Z
Learning: In LicenseCard component's clickUnencumberItem method (webroot/src/components/LicenseCard/LicenseCard.ts), complex event handling for checkbox interactions is intentionally designed to ensure consistent behavior across checkbox input, wrapper label, and outer selection parent elements for custom UI requirements. This complexity should be preserved rather than simplified.

Applied to files:

  • webroot/src/components/PrivilegePurchaseAcceptUI/PrivilegePurchaseAcceptUI.ts
📚 Learning: in focus trap implementations for modals, when there's only one focusable element (like in a success...
Learnt from: jsandoval81
PR: csg-org/CompactConnect#922
File: webroot/src/components/UserAccount/UserAccount.ts:250-267
Timestamp: 2025-07-10T19:52:40.366Z
Learning: In focus trap implementations for modals, when there's only one focusable element (like in a success state), it's correct for both firstTabIndex and lastTabIndex to reference the same element. This keeps focus appropriately trapped on that single element. Optional chaining operators (?.focus()) provide adequate null safety for DOM element access in focus management code.

Applied to files:

  • webroot/src/components/PrivilegePurchaseAcceptUI/PrivilegePurchaseAcceptUI.ts
🔇 Additional comments (8)
webroot/src/components/PrivilegePurchaseAcceptUI/PrivilegePurchaseAcceptUI.ts (3)

54-55: LGTM! Properties for focus trap management.

The new properties appropriately store references to DOM elements needed for focus trap functionality.


118-129: Good cleanup implementation.

The method properly removes event listeners and DOM elements to prevent memory leaks.


180-197: Well-implemented focus trap logic.

The method correctly handles Tab and Shift+Tab navigation, cycling focus within the payment popup when visible. This addresses the Safari keyboard navigation issue mentioned in the PR objectives.

webroot/src/components/Page/PageMainNav/PageMainNav.vue (1)

75-75: Correct implementation of dynamic class binding.

The conditional class binding for iPhone Safari is properly implemented and will work with the corresponding CSS rules to address mobile Safari viewport issues.

webroot/src/components/Page/PageMainNav/PageMainNav.less (1)

58-62: Good Safari-specific fix for navigation visibility.

The 8.4rem padding addresses the iPhone Safari URL bar issue effectively. This approach is consistent with your team's established pattern for handling Safari-specific layout issues.

webroot/src/components/Page/PageMainNav/PageMainNav.ts (1)

145-152: Comprehensive iPhone Safari detection.

The browser detection correctly identifies iPhone Safari while excluding other iOS browsers. The implementation properly addresses the requirement to apply Safari-specific fixes only where needed.

webroot/src/components/UserAccount/UserAccount.less (2)

50-53: Effective fix for Safari modal centering.

The flexbox layout with centered alignment properly addresses the email verification modal centering issue on Safari mentioned in the PR objectives.


115-126: Good responsive design for action buttons.

The width adjustments (100% on mobile, auto on desktop) improve the modal's responsive behavior across different screen sizes.

@jsandoval81 jsandoval81 requested a review from rmolinares August 7, 2025 14:27
Copy link
Copy Markdown
Collaborator

@rmolinares rmolinares left a comment

Choose a reason for hiding this comment

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

Nice job 👍! I did notice a few things:

  1. When I close the authorize.net frame using the keyboard, it goes away but I'm not able to continue tabbing on the "Payment summary" screen. I can shift+tab, but it appears that once I reach a certain point, I'm not longer able to cycle forward with just tab
  2. Not necessarily part of this initial scope, but when testing on Xcode simulators, I noticed the logout section is cut off a little on iPad devices. I don't know if it makes sense to add a computed prop that checks for Safari on iPad similar to the one for phone, or to just increase the margin-bottom for ul.nav on PageMainNav.less.

iPad Pro (12.9 inch) 5th generation
image

iPad Mini 6th generation
image

Copy link
Copy Markdown
Contributor

@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: 2

🧹 Nitpick comments (6)
webroot/src/components/Page/PageHeader/PageHeader.less (1)

25-27: Align media query with pointer capability for consistency with router logic

Router now gates behavior on (hover: hover) and (pointer: fine). To avoid divergence and accidental styling on hover-capable but coarse pointers, mirror that here.

Proposed diff:

-    @media @tabletWidth and (hover: hover) {
+    @media @tabletWidth and (hover: hover) and (pointer: fine) {
         background-color: transparent;
     }

Please verify intended Safari targets support both hover and pointer media features. If you need to support older Safari versions lacking pointer, consider a graceful fallback.

webroot/src/components/Page/PageHeader/PageHeader.ts (1)

22-26: LGTM: Unified touch-toggle detection

isMenuTouchToggle cleanly captures phone-only or no-hover contexts and aligns with related components.

To prevent logic drift across components, consider centralizing this in a small composable (e.g., useDeviceCapabilities.ts) that exposes isMenuTouchToggle, isTouchDevice, etc. This keeps one source of truth when future heuristics evolve (e.g., fold in any-hover handling).

webroot/src/components/Page/PageHeader/PageHeader.vue (2)

10-21: Minor a11y: Support Space key on logo “button”

For div/img with role="button", Space should activate the control as well as Enter.

Proposed diff:

             <img
                 src="@assets/logos/compact-connect-logo-white.svg"
                 :alt="$t('common.appName')"
                 class="logo"
                 @click="logoClick"
-                @keyup.enter="logoClick"
+                @keyup.enter="logoClick"
+                @keyup.space.prevent="logoClick"
                 role="button"
                 tabindex="0"
                 :aria-label="$t('common.appName')"
             />
``` <!-- review_comment_end -->

---

`23-33`: **A11y: Use semantic button or add aria-expanded and Space key handling**

Prefer a <button> for the toggle. If keeping a div, expose state via `aria-expanded` and support Space to activate.



Proposed diff:
```diff
-            <div
+            <div
                 class="nav-toggle"
                 :class="{ expanded: $store.state.isNavExpanded }"
                 @click="navToggle"
-                @keyup.enter="navToggle"
+                @keyup.enter="navToggle"
+                @keyup.space.prevent="navToggle"
                 role="button"
                 tabindex="0"
-                :aria-label="$t('common.toggleNav')"
+                :aria-label="$t('common.toggleNav')"
+                :aria-expanded="$store.state.isNavExpanded.toString()"
             >
``` <!-- review_comment_end -->

</blockquote></details>
<details>
<summary>webroot/src/components/Page/PageContainer/PageContainer.ts (1)</summary><blockquote>

`43-47`: **LGTM: Expanded device heuristic**

Switching from `isPhone` to `isMenuTouchToggle` broadens inclusion to non-hover devices (e.g., mobile Safari, touch tablets), matching the PR goals.



- Consider centralizing this logic in a composable to keep it consistent with `PageHeader`/`PageMainNav`.
- Verify header visibility on iPad with/without trackpad; `hover` can change dynamically with pointer devices. If needed, you can listen for `change` on the MediaQueryList to react to accessory attachment. <!-- review_comment_end -->

</blockquote></details>
<details>
<summary>webroot/src/components/Page/PageMainNav/PageMainNav.ts (1)</summary><blockquote>

`158-160`: **Verify broadened toggle condition on hybrid devices**

`isMenuTouchToggle` now triggers for any touch device (not just phone breakpoint). This likely improves tablet behavior (goal), but please verify on hybrid laptops/convertibles (e.g., Surface, Pixelbook) to ensure menu behavior isn’t unintentionally “touch-optimized” when a hover-capable pointer is primary.


Suggested manual checks:
- Windows Surface (tablet + keyboard/mouse): hover/expand/collapse behavior should remain desktop-like.
- iPad (no external pointing device): should use touch toggle.
- iPad + trackpad: confirm it behaves desktop-like (hover-capable => not touch toggle).

If issues arise, consider narrowing to “coarse pointer” in addition to `hover: none` if supported by your `$matches` plugin (e.g., `$matches.pointer === 'coarse'`).

</blockquote></details>

</blockquote></details>

<details>
<summary>📜 Review details</summary>

**Configuration used: CodeRabbit UI**
**Review profile: CHILL**
**Plan: Pro**


<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between f98dded172faec2319b607895d8021bb8c08d8fc and 2dd0eaf8865fedcd80d44cd36e1a0c8def3e428a.

</details>

<details>
<summary>⛔ Files ignored due to path filters (1)</summary>

* `webroot/yarn.lock` is excluded by `!**/yarn.lock`, `!**/*.lock`

</details>

<details>
<summary>📒 Files selected for processing (12)</summary>

* `webroot/src/components/Page/PageContainer/PageContainer.less` (3 hunks)
* `webroot/src/components/Page/PageContainer/PageContainer.ts` (2 hunks)
* `webroot/src/components/Page/PageHeader/PageHeader.less` (1 hunks)
* `webroot/src/components/Page/PageHeader/PageHeader.ts` (1 hunks)
* `webroot/src/components/Page/PageHeader/PageHeader.vue` (2 hunks)
* `webroot/src/components/Page/PageMainNav/PageMainNav.less` (3 hunks)
* `webroot/src/components/Page/PageMainNav/PageMainNav.ts` (1 hunks)
* `webroot/src/components/Page/PageMainNav/PageMainNav.vue` (2 hunks)
* `webroot/src/components/PrivilegePurchaseAcceptUI/PrivilegePurchaseAcceptUI.ts` (3 hunks)
* `webroot/src/components/PrivilegePurchaseAcceptUI/PrivilegePurchaseAcceptUI.vue` (1 hunks)
* `webroot/src/router/index.ts` (1 hunks)
* `webroot/src/shims-vue-responsiveness.d.ts` (1 hunks)

</details>

<details>
<summary>✅ Files skipped from review due to trivial changes (3)</summary>

* webroot/src/components/PrivilegePurchaseAcceptUI/PrivilegePurchaseAcceptUI.vue
* webroot/src/components/Page/PageContainer/PageContainer.less
* webroot/src/shims-vue-responsiveness.d.ts

</details>

<details>
<summary>🚧 Files skipped from review as they are similar to previous changes (3)</summary>

* webroot/src/components/Page/PageMainNav/PageMainNav.vue
* webroot/src/components/PrivilegePurchaseAcceptUI/PrivilegePurchaseAcceptUI.ts
* webroot/src/components/Page/PageMainNav/PageMainNav.less

</details>

<details>
<summary>🧰 Additional context used</summary>

<details>
<summary>🧠 Learnings (3)</summary>

<details>
<summary>📓 Common learnings</summary>

Learnt from: jsandoval81
PR: #873
File: webroot/src/styles.common/_inputs.less:115-118
Timestamp: 2025-06-24T00:17:31.188Z
Learning: The team intentionally uses broad CSS selectors like .dp__input_wrap div { position: static; } to fix styling issues with the Vue Date-Picker library. They have experience with these styles working well, keep the library version pinned in yarn.lock, and have established processes to re-test everything when updating the library version. This approach is acceptable given their testing discipline and version control.


Learnt from: jsandoval81
PR: #922
File: webroot/src/components/UserAccount/UserAccount.ts:0-0
Timestamp: 2025-07-10T19:50:56.745Z
Learning: In the UserAccount component (webroot/src/components/UserAccount/UserAccount.ts), the email field should be disabled for staff users (isDisabled: this.isStaff) to maintain existing restrictions, while licensees should be able to change their email address through the new verification process. This is the intended behavior per PR #922 requirements.


Learnt from: jsandoval81
PR: #799
File: webroot/src/pages/LicenseeProof/LicenseeProof.less:144-168
Timestamp: 2025-05-07T18:15:17.462Z
Learning: In the CompactConnect project, print layouts for footers are designed to use fixed positioning (position: fixed) in Chrome and Firefox while using a fallback to relative positioning for Safari (detected via supports (font: -apple-system-body)). This approach is intentional and aligns with the design requirements, as Safari doesn't handle fixed elements correctly in print layouts.


Learnt from: jsandoval81
PR: #922
File: webroot/src/components/UserAccount/UserAccount.ts:250-267
Timestamp: 2025-07-10T19:52:40.366Z
Learning: In focus trap implementations for modals, when there's only one focusable element (like in a success state), it's correct for both firstTabIndex and lastTabIndex to reference the same element. This keeps focus appropriately trapped on that single element. Optional chaining operators (?.focus()) provide adequate null safety for DOM element access in focus management code.


</details>
<details>
<summary>📚 Learning: 2025-05-28T16:12:31.310Z</summary>

Learnt from: jsandoval81
PR: #822
File: webroot/src/router/routes.ts:96-99
Timestamp: 2025-05-28T16:12:31.310Z
Learning: In webroot/src/router/routes.ts, the team prefers to keep router logic simple and handle route parameter validation (like state abbreviations) in the page components themselves based on user permissions, rather than adding validation at the router level.


**Applied to files:**
- `webroot/src/router/index.ts`

</details>
<details>
<summary>📚 Learning: 2025-07-03T15:35:57.893Z</summary>

Learnt from: rmolinares
PR: #905
File: webroot/src/components/UpdateHomeJurisdiction/UpdateHomeJurisdiction.vue:32-41
Timestamp: 2025-07-03T15:35:57.893Z
Learning: In the CompactConnect frontend codebase, the team prefers to keep non-dynamic text directly in Vue templates rather than moving it to computed properties in TypeScript modules, as this approach prevents cluttering the TS files with template labels.


**Applied to files:**
- `webroot/src/components/Page/PageHeader/PageHeader.vue`

</details>

</details>

</details>

<details>
<summary>⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)</summary>

* GitHub Check: CheckWebroot

</details>

<details>
<summary>🔇 Additional comments (2)</summary><blockquote>

<details>
<summary>webroot/src/components/Page/PageContainer/PageContainer.ts (1)</summary>

`55-56`: **Behavior check: Header inclusion now depends on no-hover OR phone**

Confirm that this intendedly shows the header on larger touch-only devices (tablets) and hides it on hover-capable tablets with keyboards/trackpads.



If that’s desired, great. If not, consider incorporating `(pointer: coarse)` alongside `hover === 'none'` to target finger-first tablets explicitly. <!-- review_comment_end -->

</details>
<details>
<summary>webroot/src/components/Page/PageMainNav/PageMainNav.ts (1)</summary>

`145-147`: **LGTM: media-query–based touch heuristic is appropriate**

Using `$matches.hover === 'none'` is a solid, reactive signal for touch-first contexts via the media query. No changes needed.

</details>

</blockquote></details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->

Comment thread webroot/src/components/Page/PageMainNav/PageMainNav.ts Outdated
Comment thread webroot/src/router/index.ts Outdated
@jsandoval81 jsandoval81 requested a review from rmolinares August 8, 2025 20:59
Copy link
Copy Markdown
Collaborator

@rmolinares rmolinares left a comment

Choose a reason for hiding this comment

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

Nice work on the iPad navigation. Looks much better / as expected in every simulator device I've tested.

Regarding the tabbing after the payment modal has been closed, I am now able to tab a few times (cycling through the form buttons) but it the focus eventually gets lost again and am unable to cycle through in a loop fashion the way I am with shift+tab. With shift+tab I can infinitely cycle through, but not with just tab only. Your fix may be suffice for closing this ticket, but figured I'd bring it up in case we wanted to get that to function as normal. Thoughts on this?

@jsandoval81 jsandoval81 requested a review from rmolinares August 11, 2025 17:05
@jsandoval81
Copy link
Copy Markdown
Collaborator Author

@jlkravitz This is ready for your review.

Copy link
Copy Markdown
Collaborator

@jlkravitz jlkravitz left a comment

Choose a reason for hiding this comment

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

Couple small items but generally looks great. Thanks for taking the time to dive into the nitty-gritty of Safari / mobile!

Comment thread webroot/src/components/Page/PageContainer/PageContainer.less
Comment thread webroot/src/components/Page/PageContainer/PageContainer.less
Copy link
Copy Markdown
Collaborator

@jlkravitz jlkravitz left a comment

Choose a reason for hiding this comment

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

@isabeleliassen good to merge!

@isabeleliassen isabeleliassen merged commit 2690067 into csg-org:development Aug 13, 2025
2 checks passed
@jsandoval81 jsandoval81 deleted the frontend/ios-safari-fixes branch September 15, 2025 15:51
@coderabbitai coderabbitai Bot mentioned this pull request Sep 26, 2025
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.

Safari fixes move logout button up the screen on mobile to prevent access issue

4 participants