Feature/custom bottom navigation - #1
Conversation
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
📝 WalkthroughWalkthroughThis 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
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
Estimated Code Review Effort🎯 3 (Moderate) | ⏱️ ~22 minutes Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
There was a problem hiding this comment.
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
📒 Files selected for processing (11)
.coderabbit.yaml.github/workflows/flutter-android.yml.github/workflows/flutter-ios.ymlios/Runner.xcodeproj/project.pbxprojlib/core/routing/route_paths.dartlib/core/routing/router.dartlib/core/styles/color_styles.dartlib/main.dartlib/presentation/dummy/dummy_screen.dartlib/presentation/mypage/mypage_screen.dartlib/presentation/navigation/bottom_navigation.dart
💤 Files with no reviewable changes (1)
- ios/Runner.xcodeproj/project.pbxproj
| # 요약/리뷰를 "친근한 말투"로 유도 (요약 커스터마이징) | ||
| high_level_summary_instructions: | | ||
| 한국어로 친근하고 짧게 요약해줘. | ||
| 아래 형식으로 작성해줘: | ||
| - 변경 요약(1~3줄) | ||
| - 주요 변경점(불릿 3~7개) | ||
| - 주의/리스크(있으면 1~3개) | ||
| - 다음 액션(있으면 1~3개) |
There was a problem hiding this comment.
🧩 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 -20Repository: 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 -5Repository: 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 3Repository: DearLook/frontend
Length of output: 43
🏁 Script executed:
# View the .coderabbit.yaml file to see the current configuration
cat .coderabbit.yamlRepository: 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.
| - 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- |
There was a problem hiding this comment.
🧩 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/cachewill fail if you don’t upgrade, and specifically recommends upgrading toactions/cache@v4or@v3before that date—using at leastv4.2.0orv3.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/cacherelease (or because of Node runtime deprecations). For example, many projects moved toactions/cache@v4because 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 toactions/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-hitoutput is set on cache miss; deprecated thesave-alwaysinput. [1] - 4.1.1: Restored original behavior of
cache-hitoutput. [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/cachedependency 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 likev3.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.
| - 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.
| - name: Analyze code | ||
| run: flutter analyze --no-fatal-warnings || echo "Analysis completed with warnings" | ||
| continue-on-error: false |
There was a problem hiding this comment.
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.
| - name: Analyze code | ||
| run: flutter analyze --no-fatal-warnings || echo "Analysis completed with warnings" | ||
| continue-on-error: false |
There was a problem hiding this comment.
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.
| - 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).
| 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), |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
cd /repo && find . -name "bottom_navigation.dart" -type fRepository: DearLook/frontend
Length of output: 116
🏁 Script executed:
cat -n lib/presentation/navigation/bottom_navigation.dart | head -150Repository: DearLook/frontend
Length of output: 5399
🏁 Script executed:
wc -l lib/presentation/navigation/bottom_navigation.dartRepository: 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.
| 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, | ||
| ), | ||
| ), | ||
| ), |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
# First, check if the file exists and get its structure
fd "bottom_navigation.dart" --type fRepository: 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"
fiRepository: 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"
fiRepository: 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"
fiRepository: 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 -50Repository: 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 -50Repository: 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 -20Repository: 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 -80Repository: 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 30Repository: 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 -20Repository: 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.
| 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.
반영 브랜치
작업 이미지