Skip to content

fix(styles): resolve bottom navbar button positioning and layout jump issues #5019

Open
FussuChalice wants to merge 10 commits intosws2apps:mainfrom
FussuChalice:fix-new-ui-page-buttons
Open

fix(styles): resolve bottom navbar button positioning and layout jump issues #5019
FussuChalice wants to merge 10 commits intosws2apps:mainfrom
FussuChalice:fix-new-ui-page-buttons

Conversation

@FussuChalice
Copy link
Copy Markdown
Contributor

@FussuChalice FussuChalice commented Feb 17, 2026

Description

  • Fixed bottom button not moving into bottom navbar on Add Person page
  • Prevented layout shift when clicking certain action buttons
  • Auto set right button as main

Type of change

  • Bug fix (non-breaking change which fixes an issue)

Checklist:

  • My code follows the style guidelines of this project
  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings
  • Any dependent changes have been merged and published in downstream modules

@vercel
Copy link
Copy Markdown

vercel bot commented Feb 17, 2026

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

Project Deployment Actions Updated (UTC)
staging-organized-app Ready Ready Preview Feb 27, 2026 10:06pm
test-organized-app Ready Ready Preview Feb 27, 2026 10:06pm

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Feb 17, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9ea4b80 and 08c7b70.

📒 Files selected for processing (1)
  • src/components/nav_bar_button/index.types.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/components/nav_bar_button/index.types.ts

Walkthrough

Refactors NavBarButton (icon-only rendering, accessibility, styling, keyboard activation), updates hook signatures (useBreakpoints exposes tablet688Up; useCurrentUser no longer returns isPersonEditor), changes NavBarOptionsType.buttons to ReactNode, adds markLastNavBarButton to useNavbar and uses it when rendering navbar buttons, and updates several page usages accordingly.

Changes

Cohort / File(s) Summary
NavBarButton Component
src/components/nav_bar_button/index.tsx, src/components/nav_bar_button/index.types.ts
Always renders icon-only button container; adds aria-disabled, tabIndex, Enter/Space key handling, conditional onClick guard, updated padding/hover/focus styles, removes ripple block; adds JSDoc note on main prop.
Navbar Hook & Layout
src/layouts/navbar/useNavbar.tsx, src/layouts/navbar/index.tsx
Adds markLastNavBarButton(children: ReactNode) that finds/clones the last NavBarButton to inject main: true; exposes it from useNavbar and applies it when rendering navBar buttons (main bar and BottomMenu).
Type Updates
src/definition/app.ts
Changes NavBarOptionsType.buttons type from ReactElement to ReactNode and updates the import accordingly.
Page-level Adjustments
src/pages/persons/person_details/index.tsx, src/pages/meetings/midweek/index.tsx, src/pages/meetings/weekend/index.tsx
person_details: uses tablet688Up (replacing laptopUp) and useCurrentUser now only exposes isAdmin; layout padding and button rendering adjusted. midweek: removed main prop from Publish NavBarButton. weekend: added main={!isConnected} to Autif fill NavBarButton.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested labels

released

Suggested reviewers

  • ux-git
  • rhahao
🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main objectives of the PR: fixing bottom navbar button positioning, preventing layout shifts, and implementing auto-setting of the right button as main.
Description check ✅ Passed The description clearly relates to the changeset, covering the three main issues addressed: bottom button navbar positioning, layout shift prevention, and auto-setting the right button as main.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • 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

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

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: 4

🧹 Nitpick comments (1)
src/components/nav_bar_button/index.tsx (1)

60-63: MuiTouchRipple selectors are dead CSS on a plain Box.

A Box renders a <div> and does not include MUI's ripple effect. These selectors will never match any child elements. Consider removing them to avoid confusion, or switch to ButtonBase if you want ripple.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/nav_bar_button/index.tsx` around lines 60 - 63, The CSS rules
targeting '.MuiTouchRipple-ripple .MuiTouchRipple-child' are dead because
NavBarButton renders a plain Box (no MUI ripple DOM); remove those
ripple-specific selectors from the style block in the NavBarButton component, or
if you intend to keep the ripple effect replace the root Box with MUI's
ButtonBase (or Button) so the ripple DOM exists and update styles to target the
component's ripple classes; update the code paths around the NavBarButton export
and any usages of the component accordingly.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/components/nav_bar_button/index.tsx`:
- Line 74: The onClick prop currently sets onClick={!disabled && props.onClick},
which can pass false and is type-unsafe; change the logic to conditionally pass
undefined when disabled (e.g., use a ternary or logical check to set onClick to
undefined when disabled, otherwise props.onClick) and ensure the onClick prop
type of the component (props.onClick / NavBarButton's prop interface) allows
undefined (React.MouseEventHandler | undefined) so TypeScript strict checks
pass.
- Around line 48-77: The icon-only Box (role="button") is not
keyboard-accessible; update the Box component to include tabIndex={0} when not
disabled, an onKeyDown handler that triggers props.onClick for Enter (key ===
'Enter') and Space (key === ' ' or key === 'Spacebar') while preventing
activation when disabled, and add aria-disabled={disabled} to expose state to
assistive tech; also add cursor: 'pointer' when enabled and cursor: 'default'
when disabled in the sx styles so the visual affordance matches (refer to the
Box with role="button", props.onClick, and disabled), ensuring you still guard
calls to props.onClick so they never fire when disabled.

In `@src/features/persons/export_persons/index.tsx`:
- Around line 13-23: The NavBarButton is still clickable during processing
because disabled={isProcessing} was removed and handleExport has no re-entry
guard; restore disabled={isProcessing} on the NavBarButton (the element
rendering IconLoading/IconExport) and update handleExport to immediately return
if isProcessing is true (or otherwise guard/set a local lock) before setting
isProcessing to true so duplicate exports are prevented.

In `@src/pages/persons/person_details/index.tsx`:
- Line 41: The buttons prop is using a redundant ternary that renders the same
component in both branches; locate the JSX where buttons={laptopUp ?
<PersonButtonActions /> : <PersonButtonActions />} and replace the ternary with
a single component instance (buttons={<PersonButtonActions />}) so the code is
simpler and clearer while preserving behavior.

---

Nitpick comments:
In `@src/components/nav_bar_button/index.tsx`:
- Around line 60-63: The CSS rules targeting '.MuiTouchRipple-ripple
.MuiTouchRipple-child' are dead because NavBarButton renders a plain Box (no MUI
ripple DOM); remove those ripple-specific selectors from the style block in the
NavBarButton component, or if you intend to keep the ripple effect replace the
root Box with MUI's ButtonBase (or Button) so the ripple DOM exists and update
styles to target the component's ripple classes; update the code paths around
the NavBarButton export and any usages of the component accordingly.

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.

🧹 Nitpick comments (1)
src/pages/persons/person_details/index.tsx (1)

31-37: Consider extracting the 60px magic number into a shared constant or CSS variable.

The 60px bottom padding is presumably tied to the bottom navbar height. If the navbar height changes, this value will silently go out of sync. A shared constant (e.g., BOTTOM_NAVBAR_HEIGHT) or a CSS custom property would keep these coupled.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/pages/persons/person_details/index.tsx` around lines 31 - 37, Extract the
hard-coded '60px' used in the Box's paddingBottom (when computing paddingBottom
with tablet688Up) into a shared constant or CSS custom property (e.g.,
BOTTOM_NAVBAR_HEIGHT) and use that constant instead of the literal string;
update the Box usage in this file to reference BOTTOM_NAVBAR_HEIGHT and add the
constant to a shared UI constants module or theme (so the bottom navbar height
stays in sync across components using paddingBottom and the navbar component
itself).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@src/pages/persons/person_details/index.tsx`:
- Around line 31-37: Extract the hard-coded '60px' used in the Box's
paddingBottom (when computing paddingBottom with tablet688Up) into a shared
constant or CSS custom property (e.g., BOTTOM_NAVBAR_HEIGHT) and use that
constant instead of the literal string; update the Box usage in this file to
reference BOTTOM_NAVBAR_HEIGHT and add the constant to a shared UI constants
module or theme (so the bottom navbar height stays in sync across components
using paddingBottom and the navbar component itself).

coderabbitai[bot]
coderabbitai bot previously approved these changes Feb 17, 2026
@FussuChalice FussuChalice changed the title fix(ui): resolve bottom navbar button positioning and layout jump issues fix(styles): resolve bottom navbar button positioning and layout jump issues Feb 24, 2026
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.

♻️ Duplicate comments (1)
src/components/nav_bar_button/index.tsx (1)

48-84: ⚠️ Potential issue | 🟡 Minor

Avoid passing null to onClick in strict TS.

Line 83 assigns null when disabled, which is not assignable to MouseEventHandler | undefined under strictNullChecks. Prefer undefined to keep typings strict-safe.

✅ Proposed fix
-      onClick={!disabled ? props.onClick : null}
+      onClick={!disabled ? props.onClick : undefined}
#!/bin/bash
# Check whether strictNullChecks is enabled in any tsconfig file.
fd -t f 'tsconfig.*\.json' -E node_modules -E dist -E build | while read -r f; do
  echo "## $f"
  rg -n '"strictNullChecks"|\"strict\"' "$f" || true
done
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/nav_bar_button/index.tsx` around lines 48 - 84, The onClick
assignment on the Box currently uses onClick={!disabled ? props.onClick : null},
which breaks strict TypeScript because null isn't assignable to
MouseEventHandler | undefined; update the conditional to return undefined
instead of null so the type remains MouseEventHandler | undefined (i.e., set
onClick to !disabled ? props.onClick : undefined), and ensure the handler
references the component prop name props.onClick and the local disabled flag in
the nav_bar_button component.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@src/components/nav_bar_button/index.tsx`:
- Around line 48-84: The onClick assignment on the Box currently uses
onClick={!disabled ? props.onClick : null}, which breaks strict TypeScript
because null isn't assignable to MouseEventHandler | undefined; update the
conditional to return undefined instead of null so the type remains
MouseEventHandler | undefined (i.e., set onClick to !disabled ? props.onClick :
undefined), and ensure the handler references the component prop name
props.onClick and the local disabled flag in the nav_bar_button component.

ℹ️ Review info

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b552e21 and 984cef8.

📒 Files selected for processing (4)
  • src/components/nav_bar_button/index.tsx
  • src/features/persons/export_persons/index.tsx
  • src/pages/meetings/midweek/index.tsx
  • src/pages/meetings/weekend/index.tsx
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/features/persons/export_persons/index.tsx

coderabbitai[bot]
coderabbitai bot previously approved these changes Feb 24, 2026
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.

🧹 Nitpick comments (1)
src/layouts/navbar/useNavbar.tsx (1)

158-174: Normalize main prop to ensure single primary button per group.

The markLastNavBarButton function sets main: true on the resolved last button but doesn't clear main from other NavBarButton instances. Multiple buttons in the rendered group may retain pre-existing main attributes, creating ambiguous primary state. Recommend explicitly setting main: false on all non-final buttons to enforce single-primary semantics.

Normalization approach
- if (lastChildIndex === null && child.type === NavBarButton) {
-   return cloneElement(child as ReactElement<NavBarButtonProps>, {
-     main: true,
-   });
- }
+ if (lastChildIndex === null && child.type === NavBarButton) {
+   return cloneElement(child as ReactElement<NavBarButtonProps>, {
+     main: true,
+   });
+ }
+
+ if (child.type === NavBarButton) {
+   return cloneElement(child as ReactElement<NavBarButtonProps>, {
+     main: false,
+   });
+ }

...
- const updatedNested = nested.map((nestedChild, j) =>
+ const updatedNested = nested.map((nestedChild, j) =>
    isValidElement(nestedChild) &&
    nestedChild.type === NavBarButton &&
    j === lastChildIndex
      ? cloneElement(nestedChild as ReactElement<NavBarButtonProps>, {
          main: true,
        })
+     : isValidElement(nestedChild) && nestedChild.type === NavBarButton
+       ? cloneElement(nestedChild as ReactElement<NavBarButtonProps>, {
+           main: false,
+         })
      : nestedChild
  );
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/layouts/navbar/useNavbar.tsx` around lines 158 - 174, The
markLastNavBarButton logic currently only sets main: true for the last
NavBarButton but doesn't clear main on others; update the mapping that processes
children and nested children (the blocks that check child.type === NavBarButton
and the nested.map creating updatedNested) to always clone NavBarButton elements
with an explicit main property: set main: true when index === lastChildIndex and
set main: false for all other NavBarButton clones (use cloneElement on
NavBarButton instances in both the top-level child handling and nested.map),
ensuring only the final button retains main: true.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@src/layouts/navbar/useNavbar.tsx`:
- Around line 158-174: The markLastNavBarButton logic currently only sets main:
true for the last NavBarButton but doesn't clear main on others; update the
mapping that processes children and nested children (the blocks that check
child.type === NavBarButton and the nested.map creating updatedNested) to always
clone NavBarButton elements with an explicit main property: set main: true when
index === lastChildIndex and set main: false for all other NavBarButton clones
(use cloneElement on NavBarButton instances in both the top-level child handling
and nested.map), ensuring only the final button retains main: true.

ℹ️ Review info

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 984cef8 and 9ea4b80.

📒 Files selected for processing (5)
  • src/components/nav_bar_button/index.types.ts
  • src/definition/app.ts
  • src/layouts/navbar/index.tsx
  • src/layouts/navbar/useNavbar.tsx
  • src/pages/meetings/midweek/index.tsx
💤 Files with no reviewable changes (1)
  • src/pages/meetings/midweek/index.tsx

coderabbitai[bot]
coderabbitai bot previously approved these changes Feb 25, 2026
@rhahao
Copy link
Copy Markdown
Member

rhahao commented Feb 25, 2026

@FussuChalice: will the deprecated props removed later or should be part of this PR too?

@FussuChalice
Copy link
Copy Markdown
Contributor Author

@FussuChalice: will the deprecated props removed later or should be part of this PR too?

The "main" parameter should remain, as it allows you to adjust it manually.

Or do you want me to clean the buttons on all pages?

@rhahao
Copy link
Copy Markdown
Member

rhahao commented Feb 25, 2026

If so then no problem. It could be that JSDoc comment could be misleading. It would be best to remove that deprecated line.

@FussuChalice
Copy link
Copy Markdown
Contributor Author

If so then no problem. It could be that JSDoc comment could be misleading. It would be best to remove that deprecated line.

I did it.

@sonarqubecloud
Copy link
Copy Markdown

❌ The last analysis has failed.

See analysis details on SonarQube Cloud

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.

2 participants