Skip to content

Feature/custom bottom navigation - #1

Merged
JEON-SEUNGBHIN merged 5 commits into
developfrom
feature/custom-bottom-navigation
Mar 8, 2026
Merged

Feature/custom bottom navigation#1
JEON-SEUNGBHIN merged 5 commits into
developfrom
feature/custom-bottom-navigation

Conversation

@wsw0922

@wsw0922 wsw0922 commented Mar 7, 2026

Copy link
Copy Markdown
Contributor

반영 브랜치

develop < feature/custom-bottom-navigation

작업 이미지

image

@coderabbitai

coderabbitai Bot commented Mar 7, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 85182278-579e-40a3-8d4c-298c2394eba5

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

This PR introduces bottom navigation with persistent state across multiple screens, adds automated CI/CD workflows for Flutter Android and iOS builds, establishes routing infrastructure with route constants, and updates the design system with new color variants and point colors.

Changes

Cohort / File(s) Summary
Configuration & Automation
.coderabbit.yaml, .github/workflows/flutter-android.yml, .github/workflows/flutter-ios.yml
Added CodeRabbit configuration for automated Korean-language reviews with custom formatting. Introduced two GitHub Actions CI/CD workflows that build Flutter Android (debug APK) and iOS (Runner.app) on PRs to develop, including secrets decoding, dependency installation, code analysis, artifact builds, and uploads.
Routing & Navigation
lib/core/routing/route_paths.dart, lib/core/routing/router.dart, lib/presentation/navigation/bottom_navigation.dart
Established route path constants (home, dummy, mypage). Restructured router from direct GoRoute to StatefulShellRoute with IndexedStack-based bottom navigation, wiring branch switching via BottomNavigation widget. Created BottomNavigation component with custom nav items and floating action button linking to dummy screen.
Screen Components
lib/presentation/dummy/dummy_screen.dart, lib/presentation/mypage/mypage_screen.dart
Added two new simple screen widgets: DummyScreen and MypageScreen, both rendering centered text with styled typography on white background scaffolds.
Design System
lib/core/styles/color_styles.dart, lib/main.dart
Removed grayA3 color, added five new gray variants (grayF3, grayB8, gray72, gray6B, gray46) and two point colors (pointC9, pointE5). Updated white color value. Modified text selection theme colors in main app to use updated color constant.
iOS Build Configuration
ios/Runner.xcodeproj/project.pbxproj
Removed empty inputPaths and outputPaths arrays from Embed Pods Frameworks shell script phase.

Sequence Diagram(s)

sequenceDiagram
    actor User
    participant BottomNav as BottomNavigation
    participant Router as GoRouter
    participant Shell as StatefulShellRoute
    participant Screen as Screen Widget

    User->>BottomNav: Tap home/mypage
    activate BottomNav
    BottomNav->>BottomNav: Update currentPageIndex
    BottomNav->>Router: onChangeIndex(newIndex)
    deactivate BottomNav
    
    activate Router
    Router->>Shell: Switch branch based on index
    deactivate Router
    
    activate Shell
    Shell->>Screen: Display selected screen
    deactivate Shell
    Screen-->>User: Render screen content
    
    User->>BottomNav: Tap floating action button
    activate BottomNav
    BottomNav->>Router: Navigate to dummy route
    deactivate BottomNav
    activate Router
    Router->>Screen: Display DummyScreen
    deactivate Router
Loading

Estimated Code Review Effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Poem

🐰 Hoppy new routes with colors so bright,
Navigation branches left and right,
Bottom tabs dance, the dummy hops through,
CI/CD pipelines build it all true! 🚀

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Feature/custom bottom navigation' directly and concisely describes the primary change, which is the addition of a custom bottom navigation feature across multiple files.
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
  • Commit unit tests in branch feature/custom-bottom-navigation

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.

@wsw0922

wsw0922 commented Mar 7, 2026

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Mar 7, 2026

Copy link
Copy Markdown
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 6

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.coderabbit.yaml:
- Around line 11-18: The config puts the friendly tone inside
reviews.high_level_summary_instructions so it only affects summaries; add a
top-level tone_instructions key (e.g., tone_instructions: "한국어로 친근하고 짧게 말해줘.")
and keep reviews.high_level_summary_instructions strictly as the summary format;
update .coderabbit.yaml by adding tone_instructions and removing the tone text
from high_level_summary_instructions to ensure tone applies to all reviews and
chat.

In @.github/workflows/flutter-android.yml:
- Around line 80-82: The workflow step named "Analyze code" currently masks
analyzer failures by appending `|| echo "Analysis completed with warnings"` to
the `flutter analyze --no-fatal-warnings` command; remove that fallback so
analyzer exit codes propagate (keep `--no-fatal-warnings` to allow warnings but
not silence errors) and ensure `continue-on-error: false` remains to let the job
fail on actual analyzer errors.
- Around line 17-22: The workflow uses actions/cache@v3 in the job step named
"Cache Flutter pub packages"; update the step to use actions/cache@v4 by
changing the uses reference from actions/cache@v3 to actions/cache@v4 and ensure
the existing inputs (path, key, restore-keys) remain unchanged and still valid
for v4; run a quick workflow lint/validation to confirm no breaking input
changes after switching to actions/cache@v4.

In @.github/workflows/flutter-ios.yml:
- Around line 78-80: The workflow step named "Analyze code" currently masks
analyzer failures by appending `|| echo "Analysis completed with warnings"` to
the `run` command; remove that fallback and make the `run` command simply
`flutter analyze --no-fatal-warnings` so real analyzer errors fail the job (keep
`continue-on-error: false` or remove it if redundant).

In `@lib/presentation/navigation/bottom_navigation.dart`:
- Around line 51-69: Add accessibility semantics to the tab items and center
action: extend the _BottomNavItem API to accept a semanticLabel string and wrap
its tappable widget in a Semantics widget using semanticsLabel: semanticLabel
and selected: isSelected (use the existing isSelected prop), so screen readers
announce the label and active state; update the places creating _BottomNavItem
(home and profile) to pass meaningful labels like "Home" and "Profile". For the
center action (the GestureDetector-wrapped icon), wrap the GestureDetector (or
replace with an InkWell) with Semantics(button: true, label: "Magic search") so
assistive tech announces it as a button with that label. Ensure the Semantics
widgets are used where onTap handlers (onChangeIndex / center action) are
defined so the selected and button states are accurate.
- Around line 77-94: The center floating action uses a raw GestureDetector
(Positioned -> GestureDetector -> Container) which lacks semantics and focus;
replace that widget subtree with a Material widget containing an InkWell (or
InkResponse) wrapped in Semantics to provide an accessible label and semantics,
mirror the visual layout (width/height, circular BoxDecoration, color, Icon) and
use onTap to call context.push(RoutePaths.dummy); ensure the Semantics label
matches the real feature name (not a generic description), and verify the button
participates in keyboard focus/activation similar to the existing _BottomNavItem
pattern.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: e99321a3-4dca-4967-bad7-ae551df5e68c

📥 Commits

Reviewing files that changed from the base of the PR and between 63870ce and 36fcec1.

📒 Files selected for processing (11)
  • .coderabbit.yaml
  • .github/workflows/flutter-android.yml
  • .github/workflows/flutter-ios.yml
  • ios/Runner.xcodeproj/project.pbxproj
  • lib/core/routing/route_paths.dart
  • lib/core/routing/router.dart
  • lib/core/styles/color_styles.dart
  • lib/main.dart
  • lib/presentation/dummy/dummy_screen.dart
  • lib/presentation/mypage/mypage_screen.dart
  • lib/presentation/navigation/bottom_navigation.dart
💤 Files with no reviewable changes (1)
  • ios/Runner.xcodeproj/project.pbxproj

Comment thread .coderabbit.yaml
Comment on lines +11 to +18
# 요약/리뷰를 "친근한 말투"로 유도 (요약 커스터마이징)
high_level_summary_instructions: |
한국어로 친근하고 짧게 요약해줘.
아래 형식으로 작성해줘:
- 변경 요약(1~3줄)
- 주요 변경점(불릿 3~7개)
- 주의/리스크(있으면 1~3개)
- 다음 액션(있으면 1~3개)

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

🧩 Analysis chain

🏁 Script executed:

# Search for coderabbit schema or documentation files
find . -type f \( -name "*schema*" -o -name "*coderabbit*" -o -name "*.md" \) | grep -E "(schema|coderabbit|README)" | head -20

Repository: DearLook/frontend

Length of output: 151


🏁 Script executed:

# Look for the full .coderabbit.yaml file to understand context
find . -name ".coderabbit.yaml" -o -name "coderabbit.yaml" | head -5

Repository: DearLook/frontend

Length of output: 79


🏁 Script executed:

# Search for documentation about tone_instructions and high_level_summary_instructions
rg "tone_instructions|high_level_summary_instructions" -A 3 -B 3

Repository: DearLook/frontend

Length of output: 43


🏁 Script executed:

# View the .coderabbit.yaml file to see the current configuration
cat .coderabbit.yaml

Repository: DearLook/frontend

Length of output: 647


🌐 Web query:

CodeRabbit configuration tone_instructions high_level_summary_instructions

💡 Result:

In CodeRabbit, these are .coderabbit.yaml settings:

  • tone_instructions (top-level): Free-form text describing the voice/tone CodeRabbit should use in review comments (e.g., concise, supportive, strict, etc.). Defaults to empty string. [1][2]
  • reviews.high_level_summary_instructions: Free-form text telling CodeRabbit what to include and how to format the PR’s high-level summary (sections, bullets, tables, length constraints, etc.). Defaults to empty string. [3][4]

Example:

tone_instructions: |
  Be concise, technical, and direct. Avoid praise/pleasantries. Prefer actionable bullets.

reviews:
  high_level_summary_instructions: |
    Write 5–8 bullet release notes.
    Then add a short "Risk" section (max 3 bullets).
    Keep total under 120 words.

Sources: CodeRabbit configuration reference (tone) [1], YAML template showing tone_instructions placement [2], summary docs and how high_level_summary_instructions works [3][4].


Use tone_instructions for friendly tone across all reviews and chat.

Line 11 intends to set a friendly tone, but reviews.high_level_summary_instructions only controls the summary format. To apply friendly tone to inline reviews and chat as well, use the top-level tone_instructions field instead.

Suggested config split
tone_instructions: "한국어로 친근하고 짧게 말해줘."

reviews:
  high_level_summary_instructions: |
    아래 형식으로 작성해줘:
    - 변경 요약(1~3줄)
    - 주요 변경점(불릿 3~7개)
    - 주의/리스크(있으면 1~3개)
    - 다음 액션(있으면 1~3개)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.coderabbit.yaml around lines 11 - 18, The config puts the friendly tone
inside reviews.high_level_summary_instructions so it only affects summaries; add
a top-level tone_instructions key (e.g., tone_instructions: "한국어로 친근하고 짧게 말해줘.")
and keep reviews.high_level_summary_instructions strictly as the summary format;
update .coderabbit.yaml by adding tone_instructions and removing the tone text
from high_level_summary_instructions to ensure tone applies to all reviews and
chat.

Comment on lines +17 to +22
- name: Cache Flutter pub packages
uses: actions/cache@v3
with:
path: ~/.pub-cache
key: pubcache-${{ runner.os }}-stable-3.35.4-${{ hashFiles('pubspec.lock') }}
restore-keys: pubcache-${{ runner.os }}-stable-3.35.4-

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

🌐 Web query:

actions/cache v3 deprecated unsupported GitHub Actions 2025

💡 Result:

actions/cache@v3 itself was not broadly deprecated/unsupported in 2025—but some older releases/tags were.

  • GitHub rewrote the cache backend (“cache service v2”) and began migrating on February 1, 2025, sunsetting the legacy service the same day. GitHub warns that workflow runs using deprecated versions of actions/cache will fail if you don’t upgrade, and specifically recommends upgrading to actions/cache@v4 or @v3 before that date—using at least v4.2.0 or v3.4.0 (or the SHAs for those versions). [1]
  • If you’re seeing “deprecated/unsupported” errors or warnings, it’s often because you (or another action you use) is pulling an older cache implementation or an older actions/cache release (or because of Node runtime deprecations). For example, many projects moved to actions/cache@v4 because it runs on Node 20 (whereas v3 is on Node 16). [1][2]

What to do

  • Update your workflows to: uses: actions/cache@v4 (or newer), or at minimum pin to actions/cache@v3.4.0+. [1]
  • If you’re on self-hosted runners, ensure your runner is new enough for the new cache service (GitHub calls out runner >= 2.231.0 in the migration notes). [1]

Sources: GitHub actions/cache README/migration notes [1], upstream issue discussing Node16→Node20 motivation for moving from cache v3→v4 [2].


🌐 Web query:

actions/cache v4 release notes GitHub Actions

💡 Result:

actions/cache@v4 — release notes (highlights)

  • 4.0.0: Updated minimum runner support Node 12 → Node 20. [1]
  • 4.1.0: Ensures cache-hit output is set on cache miss; deprecated the save-always input. [1]
  • 4.1.1: Restored original behavior of cache-hit output. [1]
  • 4.2.0: Integrated with the new cache service (v2) APIs; GitHub began rolling out the new service around Feb 1, 2025 and deprecated older cache-action versions as part of that migration. [1][2]
  • 4.2.1 / 4.2.2 / 4.2.3 / 4.2.4: Dependency bumps of @actions/cache (notably 4.2.3 obfuscates SAS tokens in debug logs for cache entries). [1]
  • 4.3.0: Bumped @actions/cache dependency to v4.1.0. [1]

Sources: actions/cache repo RELEASES.md (v4 changelog) [1], repo README (“What’s New” / v4 overview) [2].


🌐 Web query:

actionlint actions/cache version warning

💡 Result:

actionlint warns about the version of actions/cache when your workflow references an outdated/deprecated major (typically @v1/@v2) or a known-bad tag. This matters because GitHub migrated JavaScript actions to Node.js 20, and older action releases (and older cache backends) have been deprecated/sunset. [2]

What to do:

  • Prefer actions/cache@v4 (current major) to avoid deprecation/back-end issues. [1]
  • If you must stay on v3, don’t use actions/cache@v3.4.1 (it was incorrectly released); use @v3 (floating) or a fixed good patch like v3.4.2. [3]

Example fix:

- uses: actions/cache@v4
  with:
    path: ~/.npm
    key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }}

Sources: GitHub Actions Node20 enforcement guidance [2], GitHub’s cache deprecation/upgrade notice [1], v3.4.1 tag warning [3].


Upgrade actions/cache to v4.

While actions/cache@v3 is not deprecated if using v3.4.0+, upgrading to v4 is recommended: it aligns with GitHub's current major version, runs on Node 20 (v3 uses Node 16, which is being phased out), and ensures full compatibility with the new cache backend rolled out in February 2025.

Suggested fix
       - name: Cache Flutter pub packages
-        uses: actions/cache@v3
+        uses: actions/cache@v4
📝 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
- name: Cache Flutter pub packages
uses: actions/cache@v3
with:
path: ~/.pub-cache
key: pubcache-${{ runner.os }}-stable-3.35.4-${{ hashFiles('pubspec.lock') }}
restore-keys: pubcache-${{ runner.os }}-stable-3.35.4-
- name: Cache Flutter pub packages
uses: actions/cache@v4
with:
path: ~/.pub-cache
key: pubcache-${{ runner.os }}-stable-3.35.4-${{ hashFiles('pubspec.lock') }}
restore-keys: pubcache-${{ runner.os }}-stable-3.35.4-
🧰 Tools
🪛 actionlint (1.7.11)

[error] 18-18: the runner of "actions/cache@v3" action is too old to run on GitHub Actions. update the action's version to fix this issue

(action)

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

In @.github/workflows/flutter-android.yml around lines 17 - 22, The workflow
uses actions/cache@v3 in the job step named "Cache Flutter pub packages"; update
the step to use actions/cache@v4 by changing the uses reference from
actions/cache@v3 to actions/cache@v4 and ensure the existing inputs (path, key,
restore-keys) remain unchanged and still valid for v4; run a quick workflow
lint/validation to confirm no breaking input changes after switching to
actions/cache@v4.

Comment on lines +80 to +82
- name: Analyze code
run: flutter analyze --no-fatal-warnings || echo "Analysis completed with warnings"
continue-on-error: 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.

⚠️ Potential issue | 🟠 Major

Don't mask analyzer failures.

Line 81 turns flutter analyze errors into a successful step. --no-fatal-warnings already keeps warnings non-fatal, so the fallback echo removes the last failing guard here.

Suggested fix
       - name: Analyze code
-        run: flutter analyze --no-fatal-warnings || echo "Analysis completed with warnings"
+        run: flutter analyze --no-fatal-warnings
         continue-on-error: false
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/flutter-android.yml around lines 80 - 82, The workflow
step named "Analyze code" currently masks analyzer failures by appending `||
echo "Analysis completed with warnings"` to the `flutter analyze
--no-fatal-warnings` command; remove that fallback so analyzer exit codes
propagate (keep `--no-fatal-warnings` to allow warnings but not silence errors)
and ensure `continue-on-error: false` remains to let the job fail on actual
analyzer errors.

Comment on lines +78 to +80
- name: Analyze code
run: flutter analyze --no-fatal-warnings || echo "Analysis completed with warnings"
continue-on-error: 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.

⚠️ Potential issue | 🟠 Major

Let analyzer errors fail the job.

Line 79 swallows real flutter analyze failures. With --no-fatal-warnings already in place, warnings stay non-blocking without needing the || echo ... fallback.

Suggested fix
       - name: Analyze code
-        run: flutter analyze --no-fatal-warnings || echo "Analysis completed with warnings"
+        run: flutter analyze --no-fatal-warnings
         continue-on-error: false
📝 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
- name: Analyze code
run: flutter analyze --no-fatal-warnings || echo "Analysis completed with warnings"
continue-on-error: false
- name: Analyze code
run: flutter analyze --no-fatal-warnings
continue-on-error: false
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/flutter-ios.yml around lines 78 - 80, The workflow step
named "Analyze code" currently masks analyzer failures by appending `|| echo
"Analysis completed with warnings"` to the `run` command; remove that fallback
and make the `run` command simply `flutter analyze --no-fatal-warnings` so real
analyzer errors fail the job (keep `continue-on-error: false` or remove it if
redundant).

Comment on lines +51 to +69
child: _BottomNavItem(
icon: Icons.home_rounded,
isSelected: currentPageIndex == 0,
selectedColor: ColorStyles.gray46,
unselectedColor: ColorStyles.grayB8,
onTap: () => onChangeIndex(0),
),
),
),
const SizedBox(width: 80),
Expanded(
child: Align(
alignment: Alignment.centerRight,
child: _BottomNavItem(
icon: Icons.person_rounded,
isSelected: currentPageIndex == 1,
selectedColor: ColorStyles.gray46,
unselectedColor: ColorStyles.grayB8,
onTap: () => onChangeIndex(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.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

cd /repo && find . -name "bottom_navigation.dart" -type f

Repository: DearLook/frontend

Length of output: 116


🏁 Script executed:

cat -n lib/presentation/navigation/bottom_navigation.dart | head -150

Repository: DearLook/frontend

Length of output: 5399


🏁 Script executed:

wc -l lib/presentation/navigation/bottom_navigation.dart

Repository: DearLook/frontend

Length of output: 115


Expose accessible labels and selected state for the tab buttons.

The tabs are icon-only and currently communicate state only through color, so assistive tech won't reliably announce which destination is which or which tab is active. Add a semanticLabel prop to _BottomNavItem and wrap the button with Semantics to surface the selected state.

♿ Suggested change
                         child: _BottomNavItem(
                           icon: Icons.home_rounded,
+                          semanticLabel: 'Home',
                           isSelected: currentPageIndex == 0,
                           selectedColor: ColorStyles.gray46,
                           unselectedColor: ColorStyles.grayB8,
                           onTap: () => onChangeIndex(0),
                         ),
@@
                         child: _BottomNavItem(
                           icon: Icons.person_rounded,
+                          semanticLabel: 'My page',
                           isSelected: currentPageIndex == 1,
                           selectedColor: ColorStyles.gray46,
                           unselectedColor: ColorStyles.grayB8,
                           onTap: () => onChangeIndex(1),
                         ),
@@
 class _BottomNavItem extends StatelessWidget {
   final IconData icon;
+  final String semanticLabel;
   final bool isSelected;
   final Color selectedColor;
   final Color unselectedColor;
   final VoidCallback onTap;
@@
   const _BottomNavItem({
     required this.icon,
+    required this.semanticLabel,
     required this.isSelected,
     required this.selectedColor,
     required this.unselectedColor,
     required this.onTap,
   });
@@
     return SizedBox(
       width: 44,
       height: 44,
-      child: Material(
-        color: Colors.transparent,
-        child: InkWell(
-          splashColor: Colors.transparent,
-          highlightColor: Colors.transparent,
-          onTap: onTap,
-          child: Padding(
-            padding: const EdgeInsets.all(8),
-            child: Icon(
-              icon,
-              size: 24,
-              color: isSelected ? selectedColor : unselectedColor,
-            ),
-          ),
-        ),
+      child: Semantics(
+        button: true,
+        selected: isSelected,
+        label: semanticLabel,
+        child: Material(
+          color: Colors.transparent,
+          child: InkWell(
+            splashColor: Colors.transparent,
+            highlightColor: Colors.transparent,
+            onTap: onTap,
+            child: Padding(
+              padding: const EdgeInsets.all(8),
+              child: Icon(
+                icon,
+                size: 24,
+                color: isSelected ? selectedColor : unselectedColor,
+              ),
+            ),
+          ),
+        ),
       ),
     );
   }
 }

Also add semantic labeling to the center action button (line 79–94) with a GestureDetector wrapping an icon. It should announce as a button with label "Magic search" or similar.

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

In `@lib/presentation/navigation/bottom_navigation.dart` around lines 51 - 69, Add
accessibility semantics to the tab items and center action: extend the
_BottomNavItem API to accept a semanticLabel string and wrap its tappable widget
in a Semantics widget using semanticsLabel: semanticLabel and selected:
isSelected (use the existing isSelected prop), so screen readers announce the
label and active state; update the places creating _BottomNavItem (home and
profile) to pass meaningful labels like "Home" and "Profile". For the center
action (the GestureDetector-wrapped icon), wrap the GestureDetector (or replace
with an InkWell) with Semantics(button: true, label: "Magic search") so
assistive tech announces it as a button with that label. Ensure the Semantics
widgets are used where onTap handlers (onChangeIndex / center action) are
defined so the selected and button states are accurate.

Comment on lines +77 to +94
Positioned(
top: 0,
child: GestureDetector(
onTap: () => context.push(RoutePaths.dummy),
child: Container(
width: 64,
height: 64,
decoration: BoxDecoration(
color: ColorStyles.pointE5,
shape: BoxShape.circle,
),
child: const Icon(
Icons.auto_awesome,
color: Colors.white,
size: 24,
),
),
),

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:

# First, check if the file exists and get its structure
fd "bottom_navigation.dart" --type f

Repository: DearLook/frontend

Length of output: 111


🏁 Script executed:

# Read the specific lines mentioned (77-94)
if [ -f "lib/presentation/navigation/bottom_navigation.dart" ]; then
  wc -l "lib/presentation/navigation/bottom_navigation.dart"
fi

Repository: DearLook/frontend

Length of output: 115


🏁 Script executed:

# Get the full context around lines 77-94
if [ -f "lib/presentation/navigation/bottom_navigation.dart" ]; then
  sed -n '60,110p' "lib/presentation/navigation/bottom_navigation.dart"
fi

Repository: DearLook/frontend

Length of output: 1607


🏁 Script executed:

# Search for other GestureDetector usage patterns in this file
if [ -f "lib/presentation/navigation/bottom_navigation.dart" ]; then
  grep -n "GestureDetector" "lib/presentation/navigation/bottom_navigation.dart"
fi

Repository: DearLook/frontend

Length of output: 103


🏁 Script executed:

# Search for Semantics usage in the codebase to understand accessibility patterns
rg "Semantics\(" --type dart -A 3 | head -50

Repository: DearLook/frontend

Length of output: 43


🏁 Script executed:

# Search for Material + InkWell patterns to see if suggested approach is used elsewhere
rg "Material\(" --type dart -A 3 | head -50

Repository: DearLook/frontend

Length of output: 389


🏁 Script executed:

# Check if there are any accessibility-related tests or documentation
find . -type f \( -name "*accessibility*" -o -name "*a11y*" -o -name "*semantic*" \) | head -20

Repository: DearLook/frontend

Length of output: 43


🏁 Script executed:

# Get broader context of the bottom_navigation.dart file to understand the widget structure
head -80 "lib/presentation/navigation/bottom_navigation.dart"

Repository: DearLook/frontend

Length of output: 2908


🏁 Script executed:

# Search for InkWell usage to understand the pattern better
rg "InkWell\(" --type dart -B 2 -A 5 | head -80

Repository: DearLook/frontend

Length of output: 735


🏁 Script executed:

# Check if there's a _BottomNavItem implementation to see how it handles accessibility
rg "class _BottomNavItem" --type dart -A 30

Repository: DearLook/frontend

Length of output: 2447


🏁 Script executed:

# Search for any custom button implementations or icon button patterns
rg "IconButton\|ElevatedButton\|TextButton" --type dart | head -20

Repository: DearLook/frontend

Length of output: 43


Promote the center action to a Material button for consistency and accessibility.

This icon-only GestureDetector lacks semantic information and keyboard focus behavior, and it's inconsistent with the _BottomNavItem pattern used for other navigation actions. Replace it with Material + InkWell wrapped in Semantics to provide accessible label and standard button behavior.

Suggested change
               Positioned(
                 top: 0,
-                child: GestureDetector(
-                  onTap: () => context.push(RoutePaths.dummy),
-                  child: Container(
-                    width: 64,
-                    height: 64,
-                    decoration: BoxDecoration(
-                      color: ColorStyles.pointE5,
-                      shape: BoxShape.circle,
-                    ),
-                    child: const Icon(
-                      Icons.auto_awesome,
-                      color: Colors.white,
-                      size: 24,
-                    ),
-                  ),
+                child: Semantics(
+                  button: true,
+                  label: 'Open feature',
+                  child: Material(
+                    color: ColorStyles.pointE5,
+                    shape: const CircleBorder(),
+                    child: InkWell(
+                      customBorder: const CircleBorder(),
+                      onTap: () => context.push(RoutePaths.dummy),
+                      child: const SizedBox(
+                        width: 64,
+                        height: 64,
+                        child: Icon(
+                          Icons.auto_awesome,
+                          color: Colors.white,
+                          size: 24,
+                        ),
+                      ),
+                    ),
+                  ),
                 ),
               ),

Update the semantic label to match the actual feature name, and test with screen readers and keyboard navigation on supported platforms.

📝 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
Positioned(
top: 0,
child: GestureDetector(
onTap: () => context.push(RoutePaths.dummy),
child: Container(
width: 64,
height: 64,
decoration: BoxDecoration(
color: ColorStyles.pointE5,
shape: BoxShape.circle,
),
child: const Icon(
Icons.auto_awesome,
color: Colors.white,
size: 24,
),
),
),
Positioned(
top: 0,
child: Semantics(
button: true,
label: 'Open feature',
child: Material(
color: ColorStyles.pointE5,
shape: const CircleBorder(),
child: InkWell(
customBorder: const CircleBorder(),
onTap: () => context.push(RoutePaths.dummy),
child: const SizedBox(
width: 64,
height: 64,
child: Icon(
Icons.auto_awesome,
color: Colors.white,
size: 24,
),
),
),
),
),
),
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lib/presentation/navigation/bottom_navigation.dart` around lines 77 - 94, The
center floating action uses a raw GestureDetector (Positioned -> GestureDetector
-> Container) which lacks semantics and focus; replace that widget subtree with
a Material widget containing an InkWell (or InkResponse) wrapped in Semantics to
provide an accessible label and semantics, mirror the visual layout
(width/height, circular BoxDecoration, color, Icon) and use onTap to call
context.push(RoutePaths.dummy); ensure the Semantics label matches the real
feature name (not a generic description), and verify the button participates in
keyboard focus/activation similar to the existing _BottomNavItem pattern.

@JEON-SEUNGBHIN
JEON-SEUNGBHIN merged commit d727979 into develop Mar 8, 2026
3 checks passed
@JEON-SEUNGBHIN
JEON-SEUNGBHIN deleted the feature/custom-bottom-navigation branch March 8, 2026 09:45
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