Repository: Solvro/mobile-topwr
Pull request #733: feat: add accessibility to parkings view
Author: login: mmzek
Labels: name: size/L
Created: 2025-05-18T00:08:50Z | Merged: 2025-05-27T19:45:44Z

Hi, I have a few questions about this.
Starting with the map, right now I excluded markers when it comes to semantics, because in my opinion it's the only thing that makes sense. Map doesn't have originally any semantics.  I looked at Google Maps app, with TalkBack on, they exclude map completely, only allowing to tap search button etc. and imo it's the way we should do it but maybe you have different opinion.
 What to do with the chart? Should it read labels etc or just one general info that it's a chart and currently there are x free spaces?
<!-- ELLIPSIS_HIDDEN -->


----

> [!IMPORTANT]
> Enhance accessibility in map and parking views by adding semantic labels and excluding non-essential elements from screen readers.
> 
>   - **Accessibility Enhancements**:
>     - Add `semanticsLabel` to `MapView` and `MapWidget` for better screen reader descriptions.
>     - Exclude map markers and certain UI elements from semantics in `ParkingsView` and `MapWidget`.
>     - Add semantic labels to `MyLocationButton` and `FavouriteIcon` for screen reader support.
>     - Update `ParkingChart` and `ChartWidget` to include semantic labels for chart data.
>   - **Localization**:
>     - Add new localization strings in `app_en.arb` and `app_pl.arb` for accessibility labels.
>   - **UI Adjustments**:
>     - Adjust text scaling and padding in `ParkingWideTileCard` and `ReversedLabel` for better accessibility.
>     - Modify `SearchBox` to exclude semantics and improve focus handling.
> 
> <sup>This description was created by </sup>[<img alt="Ellipsis" src="https://img.shields.io/badge/Ellipsis-blue?color=175173">](https://www.ellipsis.dev?ref=Solvro%2Fmobile-topwr&utm_source=github&utm_medium=referral)<sup> for b56f573e2856b1c7dc5302962e4bdeb71a319a4d. You can [customize](https://app.ellipsis.dev/Solvro/settings/summaries) this summary. It will automatically update as commits are pushed.</sup>


<!-- ELLIPSIS_HIDDEN -->


Diff:
diff --git a/lib/features/buildings_view/buildings_view.dart b/lib/features/buildings_view/buildings_view.dart
index a24e61b26..471e51f7b 100644
--- a/lib/features/buildings_view/buildings_view.dart
+++ b/lib/features/buildings_view/buildings_view.dart
@@ -39,6 +39,7 @@ class BuildingsView extends ConsumerWidget {
               ),
             ),
           ),
+      semanticsLabel: context.localize.map_view_description,
     );
   }
 }
diff --git a/lib/features/map_view/map_view.dart b/lib/features/map_view/map_view.dart
index e67195e95..c727b61e5 100644
--- a/lib/features/map_view/map_view.dart
+++ b/lib/features/map_view/map_view.dart
@@ -21,6 +21,7 @@ class MapView<T extends GoogleNavigable> extends ConsumerWidget {
     required this.markerBuilder,
     required this.mapTileBuilder,
     required this.mapSheetSize,
+    required this.semanticsLabel,
     this.animateListTiles = false,
     this.initialActiveItemId,
     super.key,
@@ -32,6 +33,7 @@ class MapView<T extends GoogleNavigable> extends ConsumerWidget {
   final MapSheetSize mapSheetSize;
   final bool animateListTiles;
   final String? initialActiveItemId;
+  final String semanticsLabel;
 
   @override
   Widget build(BuildContext context, WidgetRef ref) {
@@ -55,8 +57,8 @@ class MapView<T extends GoogleNavigable> extends ConsumerWidget {
           backgroundColor: context.colorTheme.whiteSoap,
           body:
               kIsWeb || isBigScreen
-                  ? _HorizontalWebLayout<T>()
-                  : Stack(children: [MapWidget<T>(), BottomScrollSheet<T>()]),
+                  ? _HorizontalWebLayout<T>(semanticsLabel: semanticsLabel)
+                  : Stack(children: [MapWidget<T>(semanticsLabel), BottomScrollSheet<T>()]),
         ),
       ),
     );
@@ -64,7 +66,8 @@ class MapView<T extends GoogleNavigable> extends ConsumerWidget {
 }
 
 class _HorizontalWebLayout<T extends GoogleNavigable> extends StatelessWidget {
-  const _HorizontalWebLayout({super.key});
+  final String semanticsLabel;
+  const _HorizontalWebLayout({super.key, required this.semanticsLabel});
 
   @override
   Widget build(BuildContext context) {
@@ -72,7 +75,10 @@ class _HorizontalWebLayout<T extends GoogleNavigable> extends StatelessWidget {
     return MapViewPopBehaviour<T>(
       screenHeight: MediaQuery.sizeOf(context).height,
       child: Row(
-        children: [SizedBox(width: panelWidth, child: SheetLayoutScheme<T>()), Expanded(child: MapWidget<T>())],
+        children: [
+          SizedBox(width: panelWidth, child: SheetLayoutScheme<T>()),
+          Expanded(child: MapWidget<T>(semanticsLabel)),
+        ],
       ),
     );
   }
diff --git a/lib/features/map_view/widgets/map_widget.dart b/lib/features/map_view/widgets/map_widget.dart
index 8372a9403..fea474349 100644
--- a/lib/features/map_view/widgets/map_widget.dart
+++ b/lib/features/map_view/widgets/map_widget.dart
@@ -6,7 +6,6 @@ import "package:hooks_riverpod/hooks_riverpod.dart";
 
 import "../../../config/map_view_config.dart";
 import "../../../theme/app_theme.dart";
-import "../../../utils/context_extensions.dart";
 import "../../my_location_button/presentation/is_following_controller.dart";
 import "../../my_location_button/presentation/my_loc_layer.dart";
 import "../controllers/controllers_set.dart";
@@ -18,8 +17,8 @@ import "markers_layer.dart";
 import "toolbar.dart";
 
 class MapWidget<T extends GoogleNavigable> extends HookConsumerWidget {
-  const MapWidget();
-
+  final String semanticsLabel;
+  const MapWidget(this.semanticsLabel, {super.key});
   @override
   Widget build(BuildContext context, WidgetRef ref) {
     return LoadAnimationMapController<T>(
@@ -42,7 +41,7 @@ class MapWidget<T extends GoogleNavigable> extends HookConsumerWidget {
           ),
           mapController: controller.mapController,
           children: [
-            Semantics(label: context.localize.map_view_description, child: const MapTileLayer()),
+            Semantics(label: semanticsLabel, child: const MapTileLayer()),
             ExcludeSemantics(child: MarkersConsumerLayer<T>()),
             const ExcludeSemantics(child: MyLocationLayer()),
             const Toolbar(),
diff --git a/lib/features/my_location_button/presentation/my_loc_button.dart b/lib/features/my_location_button/presentation/my_loc_button.dart
index 834fe0abb..a13691cb5 100644
--- a/lib/features/my_location_button/presentation/my_loc_button.dart
+++ b/lib/features/my_location_button/presentation/my_loc_button.dart
@@ -11,10 +11,13 @@ class MyLocationButton extends ConsumerWidget {
   @override
   Widget build(BuildContext context, WidgetRef ref) {
     return FloatingActionButton.small(
-      tooltip: context.localize.my_location_button_tooltip,
       backgroundColor: context.colorTheme.whiteSoap,
       onPressed: ref.watch(isFollowingCurrentLocationControllerProvider.notifier).buttonClicked,
-      child: Icon(Icons.my_location, color: context.colorTheme.orangePomegranade, size: 24),
+      child: Icon(
+        semanticLabel: context.localize.my_location,
+        Icons.my_location,
+        color: context.colorTheme.orangePomegranade,
+      ),
     );
   }
 }
diff --git a/lib/features/parkings/parking_chart/chart_elements/labels_bottom.dart b/lib/features/parkings/parking_chart/chart_elements/labels_bottom.dart
index ec2df80c7..d5d7f5fd2 100644
--- a/lib/features/parkings/parking_chart/chart_elements/labels_bottom.dart
+++ b/lib/features/parkings/parking_chart/chart_elements/labels_bottom.dart
@@ -3,6 +3,7 @@ import "package:flutter/widgets.dart";
 
 import "../../../../theme/app_theme.dart";
 import "../../../../utils/angles.dart";
+import "../../../../utils/context_extensions.dart";
 import "../utils/chart_utils.dart";
 
 const double rotationAngle = -45;
@@ -12,7 +13,7 @@ class BottomLabels extends AxisTitles {
     : super(
         sideTitles: SideTitles(
           showTitles: true,
-          interval: 1,
+          interval: context.isTextScaledDown ? 1 : 3,
           reservedSize: 48,
           getTitlesWidget:
               (double val, TitleMeta meta) => Padding(
diff --git a/lib/features/parkings/parking_chart/chart_elements/labels_left.dart b/lib/features/parkings/parking_chart/chart_elements/labels_left.dart
index 07d43f66d..a674ff36d 100644
--- a/lib/features/parkings/parking_chart/chart_elements/labels_left.dart
+++ b/lib/features/parkings/parking_chart/chart_elements/labels_left.dart
@@ -2,6 +2,7 @@ import "package:fl_chart/fl_chart.dart";
 import "package:flutter/widgets.dart";
 
 import "../../../../theme/app_theme.dart";
+import "../../../../utils/context_extensions.dart";
 
 extension WillMaxLabelOverlapX on TitleMeta {
   bool get isMaxLabelOverlapping {
@@ -21,7 +22,7 @@ class LeftLabels extends AxisTitles {
             }
             return SideTitleWidget(
               meta: meta,
-              space: 10,
+              space: context.isTextScaledDown ? 10 : 1,
               child: Text(meta.formattedValue, style: context.iParkingTheme.chart),
             );
           },
diff --git a/lib/features/parkings/parking_chart/parking_chart.dart b/lib/features/parkings/parking_chart/parking_chart.dart
index 5eb6c04b2..92870f9a3 100644
--- a/lib/features/parkings/parking_chart/parking_chart.dart
+++ b/lib/features/parkings/parking_chart/parking_chart.dart
@@ -20,6 +20,7 @@ class ParkingChart extends ConsumerWidget {
 
   @override
   Widget build(BuildContext context, WidgetRef ref) {
+    final scaler = context.textScaler.clamp(maxScaleFactor: 0.1);
     final chartData = ref.watch(chartRepositoryProvider(parking));
     return switch (chartData) {
       AsyncError(:final error) => Material(
@@ -33,11 +34,16 @@ class ParkingChart extends ConsumerWidget {
               child: Text(context.localize.noChartData, style: context.iParkingTheme.subtitleLight.withoutShadows),
             )
             : Padding(
-              padding: const EdgeInsets.only(top: 14, right: 25, bottom: 9),
+              padding: EdgeInsets.only(top: scaler.scale(14), right: scaler.scale(25), bottom: scaler.scale(9)),
               child: ChartWidget(value, parking),
             ),
       _ => Padding(
-        padding: const EdgeInsets.only(top: 18, left: 8, right: 8, bottom: 10),
+        padding: EdgeInsets.only(
+          top: scaler.scale(18),
+          left: scaler.scale(8),
+          right: scaler.scale(8),
+          bottom: scaler.scale(10),
+        ),
         child: PreviewCardLoading(
           height: double.infinity,
           width: double.infinity,
diff --git a/lib/features/parkings/parking_chart/widgets/chart_widget.dart b/lib/features/parkings/parking_chart/widgets/chart_widget.dart
index afd289800..400efb552 100644
--- a/lib/features/parkings/parking_chart/widgets/chart_widget.dart
+++ b/lib/features/parkings/parking_chart/widgets/chart_widget.dart
@@ -4,6 +4,7 @@ import "package:flutter/material.dart";
 
 import "../../../../config/ui_config.dart";
 import "../../../../theme/app_theme.dart";
+import "../../../../utils/context_extensions.dart";
 import "../../../../widgets/charts/hide_labels.dart";
 import "../../parkings_view/models/parking.dart";
 import "../chart_elements/chart_border.dart";
@@ -24,53 +25,63 @@ class ChartWidget extends StatelessWidget {
 
   @override
   Widget build(BuildContext context) {
-    return Row(
-      children: [
-        const ReversedLabel(),
-        Expanded(
-          child: LineChart(
-            LineChartData(
-              borderData: ChartBorder(context),
-              gridData: ChartGrid(context),
-              titlesData: FlTitlesData(
-                rightTitles: const HideLabels(),
-                topTitles: const HideLabels(),
-                bottomTitles: BottomLabels(context),
-                leftTitles: LeftLabels(context),
-              ),
-              lineBarsData: [ChartLine(context, chartData)],
-              minX: chartData.minX,
-              maxX: chartData.maxX,
-              maxY: chartData.maxY(parking),
-              minY: 0,
-              lineTouchData: LineTouchData(
-                touchTooltipData: LineTouchTooltipData(
-                  getTooltipItems: (touchedSpots) {
-                    return touchedSpots.map((touchedSpot) {
-                      final hour = HourLabel(touchedSpot.x).toStringRepr();
-                      final value = touchedSpot.y.toInt().toString();
-                      return LineTooltipItem(
-                        "$value\n",
-                        TextStyle(
-                          color: context.colorTheme.whiteSoap,
-                          fontWeight: FontWeight.bold,
-                          fontSize: ParkingChartConfig.labelFontSize,
-                        ),
-                        children: [
-                          TextSpan(
-                            text: hour,
-                            style: TextStyle(color: context.colorTheme.greyLight, fontWeight: FontWeight.normal),
-                          ),
-                        ],
-                      );
-                    }).toList();
-                  },
+    return Semantics(
+      label:
+          "${context.localize.parking_chart_max_today_screen_reader_label} ${chartData.reduce((a, b) => a.y > b.y ? a : b).y.toInt()}",
+      child: Row(
+        children: [
+          const ReversedLabel(),
+          Expanded(
+            child: ExcludeSemantics(
+              child: LineChart(
+                LineChartData(
+                  borderData: ChartBorder(context),
+                  gridData: ChartGrid(context),
+                  titlesData: FlTitlesData(
+                    rightTitles: const HideLabels(),
+                    topTitles: const HideLabels(),
+                    bottomTitles: BottomLabels(context),
+                    leftTitles: LeftLabels(context),
+                  ),
+                  lineBarsData: [ChartLine(context, chartData)],
+                  minX: chartData.minX,
+                  maxX: chartData.maxX,
+                  maxY: chartData.maxY(parking),
+                  minY: 0,
+                  lineTouchData: LineTouchData(
+                    touchTooltipData: LineTouchTooltipData(
+                      getTooltipItems: (touchedSpots) {
+                        return touchedSpots.map((touchedSpot) {
+                          final hour = HourLabel(touchedSpot.x).toStringRepr();
+                          final value = touchedSpot.y.toInt().toString();
+                          return LineTooltipItem(
+                            "$value\n",
+                            TextStyle(
+                              color: context.colorTheme.whiteSoap,
+                              fontWeight: FontWeight.bold,
+                              fontSize: ParkingChartConfig.labelFontSize,
+                            ),
+                            children: [
+                              TextSpan(
+                                text: hour,
+                                style: TextStyle(
+                                  color: context.colorTheme.greyLight,
+                                  fontWeight: FontWeight.normal,
+                                  fontSize: ParkingChartConfig.labelFontSize,
+                                ),
+                              ),
+                            ],
+                          );
+                        }).toList();
+                      },
+                    ),
+                  ),
                 ),
               ),
             ),
           ),
-        ),
-      ],
+        ],
+      ),
     );
   }
 }
diff --git a/lib/features/parkings/parking_chart/widgets/reversed_label.dart b/lib/features/parkings/parking_chart/widgets/reversed_label.dart
index 8a12f9165..1f89754fe 100644
--- a/lib/features/parkings/parking_chart/widgets/reversed_label.dart
+++ b/lib/features/parkings/parking_chart/widgets/reversed_label.dart
@@ -8,11 +8,14 @@ class ReversedLabel extends StatelessWidget {
 
   @override
   Widget build(BuildContext context) {
+    final scaler = context.textScaler.clamp(maxScaleFactor: 0.1);
     return Padding(
-      padding: const EdgeInsets.only(bottom: 25, right: 2),
+      padding: EdgeInsets.only(bottom: scaler.scale(25), right: scaler.scale(2)),
       child: RotatedBox(
         quarterTurns: -1,
-        child: Text(context.localize.freePlaces, style: context.iParkingTheme.chart, textAlign: TextAlign.start),
+        child: ExcludeSemantics(
+          child: Text(context.localize.freePlaces, style: context.iParkingTheme.chart, textAlign: TextAlign.start),
+        ),
       ),
     );
   }
diff --git a/lib/features/parkings/parkings_view/parkings_view.dart b/lib/features/parkings/parkings_view/parkings_view.dart
index 222718622..137e47bda 100644
--- a/lib/features/parkings/parkings_view/parkings_view.dart
+++ b/lib/features/parkings/parkings_view/parkings_view.dart
@@ -29,18 +29,21 @@ class ParkingsView extends ConsumerWidget {
       markerBuilder:
           (item, ref, {required bool isActive}) => Marker(
             alignment: Alignment.topCenter,
-            child: GestureDetector(
-              onTap: () {
-                unawaited(ref.read(parkingsMapControllerProvider).onMarkerTap(item));
-              },
-              child: Image.asset(
-                isActive
-                    ? Assets.png.mapMarkers.activeParkingMapMarker.path
-                    : Assets.png.mapMarkers.parkingMapMarker.path,
+            child: ExcludeSemantics(
+              child: GestureDetector(
+                onTap: () {
+                  unawaited(ref.read(parkingsMapControllerProvider).onMarkerTap(item));
+                },
+                child: Image.asset(
+                  isActive
+                      ? Assets.png.mapMarkers.activeParkingMapMarker.path
+                      : Assets.png.mapMarkers.parkingMapMarker.path,
+                ),
               ),
             ),
             point: item.location,
           ),
+      semanticsLabel: context.localize.parking_map_description,
     );
   }
 }
diff --git a/lib/features/parkings/parkings_view/widgets/parking_favourite.dart b/lib/features/parkings/parkings_view/widgets/parking_favourite.dart
index 17c0a6663..5a4cc3ebf 100644
--- a/lib/features/parkings/parkings_view/widgets/parking_favourite.dart
+++ b/lib/features/parkings/parkings_view/widgets/parking_favourite.dart
@@ -3,6 +3,7 @@ import "package:flutter_riverpod/flutter_riverpod.dart";
 
 import "../../../../theme/app_theme.dart";
 import "../../../../theme/iparking_theme.dart";
+import "../../../../utils/context_extensions.dart";
 import "../models/parking.dart";
 import "../repository/local_fav_parking_repository.dart";
 
@@ -36,6 +37,11 @@ class FavouriteIcon extends StatelessWidget {
 
   @override
   Widget build(BuildContext context) {
-    return Icon(icon, color: color, size: 22, shadows: iparkingShadows);
+    final scaler = context.textScaler.clamp(maxScaleFactor: 2);
+    return Semantics(
+      button: true,
+      label: context.localize.favourite_button,
+      child: Icon(icon, color: color, size: scaler.scale(22), shadows: iparkingShadows),
+    );
   }
 }
diff --git a/lib/features/parkings/parkings_view/widgets/parking_wide_tile_card.dart b/lib/features/parkings/parkings_view/widgets/parking_wide_tile_card.dart
index bb9a4bf35..178285883 100644
--- a/lib/features/parkings/parkings_view/widgets/parking_wide_tile_card.dart
+++ b/lib/features/parkings/parkings_view/widgets/parking_wide_tile_card.dart
@@ -18,10 +18,11 @@ class ParkingWideTileCard extends StatelessWidget {
 
   @override
   Widget build(BuildContext context) {
+    final scaler = context.textScaler.clamp(maxScaleFactor: 2);
     return GestureDetector(
       onTap: isActive ? null : onTap,
       child: Container(
-        height: isActive ? 300 : WideTileCardConfig.imageSize,
+        height: isActive ? scaler.scale(300) : scaler.scale(WideTileCardConfig.imageSize),
         decoration: BoxDecoration(
           borderRadius: const BorderRadius.all(WideTileCardConfig.radius),
           image: DecorationImage(fit: BoxFit.cover, image: NetworkImage(parking.iParkPhotoUrl)),
@@ -49,7 +50,11 @@ class ParkingWideTileCard extends StatelessWidget {
                 child: IconButton(
                   padding: EdgeInsets.zero,
                   onPressed: onTap,
-                  icon: Icon(Icons.close, color: context.colorTheme.whiteSoap, size: 22),
+                  icon: Semantics(
+                    button: true,
+                    label: context.localize.close,
+                    child: Icon(Icons.close, color: context.colorTheme.whiteSoap, size: scaler.scale(22)),
+                  ),
                 ),
               ),
           ],
@@ -67,31 +72,43 @@ class _LeftColumn extends StatelessWidget {
 
   @override
   Widget build(BuildContext context) {
-    return Column(
-      crossAxisAlignment: CrossAxisAlignment.stretch,
-      children: [
-        Text(
-          parking.symbol,
-          style: isActive ? context.iParkingTheme.title.withoutShadows : context.iParkingTheme.title,
-        ),
-        Padding(
-          padding: ParkingsConfig.extraIndentPadd,
-          child:
-              isActive
-                  ? Text(
-                    "${context.localize.street_abbreviation} ${parking.addressFormatted}",
-                    style: context.iParkingTheme.subtitleLight.withoutShadows,
-                  )
-                  : Text(parking.nameNormalized, style: context.iParkingTheme.subtitle),
-        ),
-        const SizedBox(height: 2),
-        if (!isActive)
+    return Semantics(
+      label:
+          isActive
+              ? context.localize.parking_chart_title_screen_reader_label +
+                  context.localize.parking_address_screen_reader_label
+              : context.localize.parking_address_screen_reader_label,
+      child: Column(
+        crossAxisAlignment: CrossAxisAlignment.stretch,
+        children: [
+          Flexible(
+            child: Text(
+              parking.symbol,
+              style: isActive ? context.iParkingTheme.title.withoutShadows : context.iParkingTheme.title,
+            ),
+          ),
           Padding(
             padding: ParkingsConfig.extraIndentPadd,
-            child: Text(parking.openingHours, style: context.iParkingTheme.small),
+            child:
+                isActive
+                    ? Text(
+                      "${context.localize.street_abbreviation} ${parking.addressFormatted}",
+                      style: context.iParkingTheme.subtitleLight.withoutShadows,
+                    )
+                    : Text(parking.nameNormalized, style: context.iParkingTheme.subtitle),
           ),
-        if (isActive) Expanded(child: Center(child: ParkingChart(parking))),
-      ],
+          const SizedBox(height: 2),
+          if (!isActive)
+            Padding(
+              padding: ParkingsConfig.extraIndentPadd,
+              child: Semantics(
+                label: context.localize.parking_opening_hours_reader_label,
+                child: Flexible(child: Text(parking.openingHours, style: context.iParkingTheme.small)),
+              ),
+            ),
+          if (isActive) Expanded(child: Center(child: ParkingChart(parking))),
+        ],
+      ),
     );
   }
 }
@@ -104,29 +121,36 @@ class _RightColumn extends StatelessWidget {
 
   @override
   Widget build(BuildContext context) {
+    final scaler = context.textScaler.clamp(maxScaleFactor: 2);
     return Column(
       crossAxisAlignment: CrossAxisAlignment.end,
       mainAxisAlignment: MainAxisAlignment.end,
       children: [
         const Spacer(),
-        Row(
-          mainAxisAlignment: MainAxisAlignment.end,
-          children: [
-            MyTooltip(
-              message: context.localize.places_currently_available,
-              child: Text(
-                parking.parsedNumberOfPlaces,
-                style: isActive ? context.iParkingTheme.title.withoutShadows : context.iParkingTheme.title,
+        Semantics(
+          label:
+              "${context.localize.parking_people_live_screen_reader_label} ${parking.parsedNumberOfPlaces} ${context.localize.sks_people_live_screen_reader_label_trend}${localizedName(parking.trend, context)}",
+          child: Row(
+            mainAxisAlignment: MainAxisAlignment.end,
+            children: [
+              ExcludeSemantics(
+                child: MyTooltip(
+                  message: context.localize.places_currently_available,
+                  child: Text(
+                    parking.parsedNumberOfPlaces,
+                    style: isActive ? context.iParkingTheme.title.withoutShadows : context.iParkingTheme.title,
+                  ),
+                ),
               ),
-            ),
-            const SizedBox(width: 4),
-            Icon(
-              parking.trend.arrowIcon,
-              color: isActive ? arrowColor(parking.trend, context) : context.colorTheme.whiteSoap,
-              size: 21,
-              shadows: iparkingShadows,
-            ),
-          ],
+              SizedBox(width: scaler.scale(4)),
+              Icon(
+                parking.trend.arrowIcon,
+                color: isActive ? arrowColor(parking.trend, context) : context.colorTheme.whiteSoap,
+                size: scaler.scale(21),
+                shadows: iparkingShadows,
+              ),
+            ],
+          ),
         ),
       ],
     );
@@ -143,3 +167,14 @@ Color arrowColor(String trend, BuildContext context) {
       return context.colorTheme.whiteSoap;
   }
 }
+
+String localizedName(String trend, BuildContext context) {
+  switch (trend) {
+    case "1":
+      return context.localize.sks_people_live_screen_reader_label_trend_increasing;
+    case "-1":
+      return context.localize.sks_people_live_screen_reader_label_trend_decreasing;
+    default:
+      return context.localize.sks_people_live_screen_reader_label_trend_stable;
+  }
+}
diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb
index d4e0f80cd..6b6952c42 100644
--- a/lib/l10n/app_en.arb
+++ b/lib/l10n/app_en.arb
@@ -42,6 +42,8 @@
   "study_circles": "Student organizations",
   "days": "days",
   "to_start_session": "until the session starts",
+  "my_location": "My location",
+  "favourite_button": "Add to favourite",
   "map_button": "Map",
   "meet_our_team": "Meet us!",
   "sections": "Faculties",
@@ -531,6 +533,12 @@
   "clear_search": "Clear search",
   "my_location_button_tooltip": "My location",
   "map_view_description": "Map view with buildings markers. You have bottom sheet with a list of buildings. Scroll up to expand it.",
+  "parking_map_description": "Map view with parkings markers. You have bottom sheet with a list of parkings. Scroll up to expand it.",
+  "parking_chart_title_screen_reader_label": "Parkings occupancy chart.",
+  "parking_address_screen_reader_label": "Nearby building name and parking address is:",
+  "parking_people_live_screen_reader_label": "Current number of free spaces:",
+  "parking_opening_hours_reader_label": "Parking opening hours:",
+  "parking_chart_max_today_screen_reader_label": "Maximum number of free spaces:",
   "bottom_scroll_sheet_description_collapsed": "Bottom scroll sheet. Scroll down to collapse it.",
   "bottom_scroll_sheet_description_expanded": "Bottom scroll sheet. Scroll up to collapse it.",
   "building_tile_selected": "Selected",
diff --git a/lib/l10n/app_pl.arb b/lib/l10n/app_pl.arb
index b1ed16b1c..af2948a83 100644
--- a/lib/l10n/app_pl.arb
+++ b/lib/l10n/app_pl.arb
@@ -169,6 +169,14 @@
   "@map_button": {
     "description": "Label for map navigation button"
   },
+  "my_location": "Moja lokalizacja",
+  "@my_location":{
+    "description": "Button to allow user current location"
+  },
+  "favourite_button": "Dodaj do ulubionych",
+  "@favourite_button":{
+    "description": "Button add to favourite"
+  },
   "meet_our_team": "Poznaj nas!",
   "@meet_our_team": {
     "description": "Title for team introduction section"
@@ -3243,6 +3251,30 @@
   "@map_view_description": {
     "description": "Text read for map view description"
   },
+  "parking_map_description": "Widok mapy ze znacznikami parkingów. U dołu znajduje się lista parkingów. Przewiń w górę, aby ją rozwinąć.",
+  "@parking_map_description": {
+    "description": "Text read for parking map view description"
+  },
+  "parking_chart_title_screen_reader_label": "Wykres obłożenia parkingów.",
+  "@parking_chart_title_screen_reader_label": {
+    "description": "Text read for parking chart title"
+  },
+  "parking_address_screen_reader_label": "Nazwa sąsiedniego budynku i lokalizacja parkingu to: ",
+  "@parking_address_screen_reader_label": {
+    "description": "Text read for parking address"
+  },
+  "parking_people_live_screen_reader_label": "Aktualna liczba wolnych miejsc to",
+  "@parking_people_live_screen_reader_label": {
+    "description": "Text read for parking live button by screen reader"
+  },
+  "parking_opening_hours_reader_label": "Godziny otwarcia parkingu:",
+  "@parking_opening_hours_reader_label": {
+    "description": "Text read for parking opening hours"
+  },
+  "parking_chart_max_today_screen_reader_label": "Maksymalna liczba wolnych miejsc dzisiejszego dnia wynosi: ",
+  "@parking_chart_max_today_screen_reader_label": {
+    "description": "Text read for parking chart max today"
+  },
   "bottom_scroll_sheet_description_collapsed": "Szuflada dolna z listą. Przewiń w górę, aby ją rozwinąć.",
   "@bottom_scroll_sheet_description_collapsed": {
     "description": "Text read for bottom scroll sheet description when it's collapsed"
diff --git a/lib/widgets/search_box.dart b/lib/widgets/search_box.dart
index cccbe75be..5c26e89b3 100644
--- a/lib/widgets/search_box.dart
+++ b/lib/widgets/search_box.dart
@@ -38,31 +38,33 @@ class SearchBox extends HookWidget {
 
     final color = context.colorTheme.blackMirage.withValues(alpha: 0.48);
 
-    return TextField(
-      controller: controller,
-      focusNode: focusNode,
-      onTap: onTap,
-      onTapOutside: onTapOutside,
-      onChanged: onChanged,
-      decoration: InputDecoration(
-        constraints: BoxConstraints(maxHeight: context.textScaler.scale(SearchBoxConfig.height)),
-        contentPadding: context.isTextScaledUp ? const EdgeInsets.symmetric(vertical: 4) : EdgeInsets.zero,
-        filled: true,
-        fillColor: context.colorTheme.greyLight,
-        hintText: "${searchText ?? context.localize.search}...",
-        hintStyle: context.textTheme.lightTitle.copyWith(color: color),
-        border: OutlineInputBorder(borderRadius: BorderRadius.circular(8), borderSide: BorderSide.none),
-        prefixIcon: ExcludeSemantics(
-          child: Padding(padding: const EdgeInsets.all(10), child: SvgPicture.asset(Assets.svg.searchBox.vectorsearch)),
+    return ExcludeSemantics(
+      child: TextField(
+        controller: controller,
+        focusNode: focusNode,
+        onTap: onTap,
+        onTapOutside: onTapOutside,
+        onChanged: onChanged,
+        decoration: InputDecoration(
+          constraints: const BoxConstraints(maxHeight: SearchBoxConfig.height),
+          contentPadding: EdgeInsets.zero,
+          filled: true,
+          fillColor: context.colorTheme.greyLight,
+          hintText: "${searchText ?? context.localize.search}...",
+          hintStyle: context.textTheme.lightTitle.copyWith(color: color),
+          border: OutlineInputBorder(borderRadius: BorderRadius.circular(8), borderSide: BorderSide.none),
+          prefixIcon: Padding(
+            padding: const EdgeInsets.all(10),
+            child: SvgPicture.asset(Assets.svg.searchBox.vectorsearch),
+          ),
+          suffixIcon:
+              showCloseIcon.value
+                  ? IconButton(
+                    icon: Icon(Icons.cancel, color: context.colorTheme.blackMirage, size: 19),
+                    onPressed: onSuffixPressed,
+                  )
+                  : null,
         ),
-        suffixIcon:
-            showCloseIcon.value
-                ? IconButton(
-                  tooltip: context.localize.clear_search,
-                  icon: Icon(Icons.cancel, color: context.colorTheme.blackMirage, size: context.textScaler.scale(19)),
-                  onPressed: onSuffixPressed,
-                )
-                : null,
       ),
     );
   }
diff --git a/lib/widgets/search_box_app_bar.dart b/lib/widgets/search_box_app_bar.dart
index 9b82adb14..30053c42a 100644
--- a/lib/widgets/search_box_app_bar.dart
+++ b/lib/widgets/search_box_app_bar.dart
@@ -46,7 +46,12 @@ class SearchBoxAppBar extends AppBar {
                left: defaultHorizontalPadding,
                right: defaultHorizontalPadding,
              ),
-             child: SearchBox(onQueryChanged: onQueryChanged, onTap: onSearchBoxTap),
+
+             child: Semantics(
+               button: true,
+               label: context.localize.search,
+               child: SearchBox(onQueryChanged: onQueryChanged, onTap: onSearchBoxTap),
+             ),
            ),
          ),
        );


Reviews:
user: login: ellipsis-dev[bot]
body: > [!CAUTION]
> **Changes requested  :x:**
> <details>
> <summary>Reviewed everything up to b09f7b509c58f7ddbe4aefbf225bf6873f309286 in <ellipsistime>2 minutes and 3 seconds</ellipsistime>. Click for details.</summary> 
> 
> - Reviewed `215` lines of code in `8` files
> - Skipped `0` files when reviewing.
> - Skipped posting `4` draft comments. View those below.
> - Modify your [settings](https://app.ellipsis.dev/Solvro/settings/code-review) and [rules](https://app.ellipsis.dev/Solvro/code-review/rules) to customize what types of comments Ellipsis leaves. And don't forget to react with :+1: or :-1: to teach Ellipsis.
> 
> <details>
> <summary>1. <code>lib/widgets/search_box_app_bar.dart:48</code></summary>
> 
> - **Draft comment:** 
> Wrapping the SearchBox in a Semantics widget with 'button: true' assigns it a button role. Verify that this is intentional because a search text field typically expects text input. If this search box is meant to launch a dedicated search view rather than being directly typed into, this may be acceptable.
> - **Reason this comment was not posted:**
> Comment looked like it was already resolved.
> 
> 
> </details>
> 
> <details>
> <summary>2. <code>lib/features/my_location_button/presentation/my_loc_button.dart:19</code></summary>
> 
> - **Draft comment:** 
> Typo detected: The color property uses `orangePomegranade`, which might be a misspelling. Consider renaming it to `orangePomegranate` if that was the intent.
> - **Reason this comment was not posted:**
> Comment was on unchanged code.
> 
> 
> </details>
> 
> <details>
> <summary>3. <code>lib/l10n/app_pl.arb:174</code></summary>
> 
> - **Draft comment:** 
> Typographical issue: The description text "Button to allow user current location" seems a bit awkward. Consider revising it to something like "Button to allow user's current location" or similar for clarity.
> - **Reason this comment was not posted:**
> Decided after close inspection that this draft comment was likely wrong and/or not actionable: usefulness confidence = 10% vs. threshold = 50% This is a minor grammatical fix that adds a possessive 's to make the description more grammatically correct in English. While technically correct, this kind of minor text change in a description field doesn't meaningfully impact functionality or user experience. The current text is still understandable. The change would make the text more grammatically correct. Description fields should ideally have proper grammar since they may be used in documentation or UI. However, this is an extremely minor issue in a description field that doesn't affect functionality. The rules state not to make purely informative comments or comments about obvious/unimportant issues. This comment should be deleted as it addresses a very minor grammatical issue that doesn't meaningfully impact the code or user experience.
> 
> 
> </details>
> 
> <details>
> <summary>4. <code>lib/l10n/app_pl.arb:178</code></summary>
> 
> - **Draft comment:** 
> Typographical issue: The description text "Button add to favourite" appears to be missing a word. Consider revising it to "Button to add to favourite" for better readability.
> - **Reason this comment was not posted:**
> Decided after close inspection that this draft comment was likely wrong and/or not actionable: usefulness confidence = 10% vs. threshold = 50% 1. The comment is about a changed line in the diff (new translation entry). 2. It's a very minor grammatical suggestion. 3. The description field is just metadata, not user-facing text. 4. The current text is understandable even if not perfectly grammatical. 5. The rules say not to make obvious or unimportant comments. The grammar could be technically incorrect, and consistency in documentation is valuable. Maybe this is worth fixing for maintainability. While technically correct, this is an extremely minor issue in a metadata field that doesn't impact functionality or user experience. The rules specifically say to avoid obvious/unimportant comments. Delete this comment as it's too minor of an issue and relates to non-user-facing metadata text.
> 
> 
> </details>
> 
> 
> Workflow ID: <workflowid>`wflow_WFO3U9kxNcPwPPc3`</workflowid>
> </details>
> 
> <sup>You can customize </sup>[<img alt="Ellipsis" src="https://img.shields.io/badge/Ellipsis-blue?color=175173">](https://www.ellipsis.dev?ref=Solvro%2Fmobile-topwr&utm_source=github&utm_medium=referral)<sup> by changing your [verbosity settings](https://app.ellipsis.dev/Solvro/settings/code-review), reacting with :+1: or :-1:, [replying to comments](https://docs.ellipsis.dev/features/code-review#teaching-ellipsis), or adding [code review rules](https://app.ellipsis.dev/Solvro/code-review/rules).</sup>
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-18T00:10:57Z
user: login: mikolaj-jalocha
body: Hi! 

Regarding charts: imo info about max and free spaces is enough. Maybe sth about trend. 

I've got few questions:

1. Suppose I want to know how many places there's on some parking spot, does screen reader handle that? 
2. Why excluding search box? 
3. How everything is working with exceptionally large and small fonts and icons? 
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-05-20T12:15:23Z
user: login: mmzek
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-05-24T12:08:09Z
user: login: ellipsis-dev[bot]
body: > [!IMPORTANT]
> **Looks good to me!  :+1:**
> <details>
> <summary>Reviewed 04d97b9597aced865787ff723a409377fc04111a in <ellipsistime>1 minute and 43 seconds</ellipsistime>. Click for details.</summary> 
> 
> - Reviewed `136` lines of code in `6` files
> - Skipped `0` files when reviewing.
> - Skipped posting `4` draft comments. View those below.
> - Modify your [settings](https://app.ellipsis.dev/Solvro/settings/code-review) and [rules](https://app.ellipsis.dev/Solvro/code-review/rules) to customize what types of comments Ellipsis leaves. And don't forget to react with :+1: or :-1: to teach Ellipsis.
> 
> <details>
> <summary>1. <code>lib/l10n/app_pl.arb:1429</code></summary>
> 
> - **Draft comment:** 
> Typo detected: The key 'floor_list' has an extra trailing 'L' in its value ('Liczba pięterL'). Please remove the extra 'L'.
> - **Reason this comment was not posted:**
> Comment was not on a location in the diff, so it can't be submitted as a review comment.
> 
> 
> </details>
> 
> <details>
> <summary>2. <code>lib/l10n/app_pl.arb:3254</code></summary>
> 
> - **Draft comment:** 
> Ensure new semantic translation keys (e.g. 'parking_map_description') match across all localization files for consistency.
> - **Reason this comment was not posted:**
> Comment did not seem useful. Confidence is useful = `0%` <= threshold `50%` The comment is asking the author to ensure consistency across localization files, which is similar to asking them to double-check or verify something. This violates the rule against asking the author to ensure or verify things.
> 
> 
> </details>
> 
> <details>
> <summary>3. <code>lib/features/map_view/widgets/map_widget.dart:48</code></summary>
> 
> - **Draft comment:** 
> Potential typo: 'OpenMapAtrribution' might be intended as 'OpenMapAttribution'.
> - **Reason this comment was not posted:**
> Comment was not on a location in the diff, so it can't be submitted as a review comment.
> 
> 
> </details>
> 
> <details>
> <summary>4. <code>lib/l10n/app_en.arb:536</code></summary>
> 
> - **Draft comment:** 
> Typo suggestion: The phrase "parkings markers" (and similarly "list of parkings") in the new string might be intended to be "parking markers" (and "list of parking"). Consider revising for clarity and consistency.
> - **Reason this comment was not posted:**
> Decided after close inspection that this draft comment was likely wrong and/or not actionable: usefulness confidence = 10% vs. threshold = 50% Looking at the file, it uses "parkings" in other places like "parkings_title" and "parkings_not_found". This suggests "parkings" is the intentional terminology used throughout the app. Changing just this one instance would create inconsistency. The current wording, while perhaps not perfect English, is consistent with the app's terminology. The comment correctly identifies that "parking markers" is more standard English than "parkings markers". In isolation, the suggestion would improve the English. However, consistency within the app is more important than perfect English grammar. The app consistently uses "parkings" as a countable noun throughout its strings. Delete the comment because changing this string would create inconsistency with the app's established terminology, where "parkings" is used throughout.
> 
> 
> </details>
> 
> 
> Workflow ID: <workflowid>`wflow_XGtd8DybrmnjEixJ`</workflowid>
> </details>
> 
> <sup>You can customize </sup>[<img alt="Ellipsis" src="https://img.shields.io/badge/Ellipsis-blue?color=175173">](https://www.ellipsis.dev?ref=Solvro%2Fmobile-topwr&utm_source=github&utm_medium=referral)<sup> by changing your [verbosity settings](https://app.ellipsis.dev/Solvro/settings/code-review), reacting with :+1: or :-1:, [replying to comments](https://docs.ellipsis.dev/features/code-review#teaching-ellipsis), or adding [code review rules](https://app.ellipsis.dev/Solvro/code-review/rules).</sup>
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-24T12:50:47Z
user: login: ellipsis-dev[bot]
body: > [!CAUTION]
> **Changes requested  :x:**
> <details>
> <summary>Reviewed c187141061df4479d5810179c009c28c20ce95fa in <ellipsistime>1 minute and 48 seconds</ellipsistime>. Click for details.</summary> 
> 
> - Reviewed `308` lines of code in `5` files
> - Skipped `0` files when reviewing.
> - Skipped posting `4` draft comments. View those below.
> - Modify your [settings](https://app.ellipsis.dev/Solvro/settings/code-review) and [rules](https://app.ellipsis.dev/Solvro/code-review/rules) to customize what types of comments Ellipsis leaves. And don't forget to react with :+1: or :-1: to teach Ellipsis.
> 
> <details>
> <summary>1. <code>lib/features/parkings/parking_chart/widgets/chart_widget.dart:28</code></summary>
> 
> - **Draft comment:** 
> chartData.reduce() may throw if chartData is empty. Consider adding a check to handle an empty list.
> - **Reason this comment was not posted:**
> Decided after close inspection that this draft comment was likely wrong and/or not actionable: usefulness confidence = 20% vs. threshold = 50% Looking at the code, chartData is of type IList<ChartPoint> and is a required constructor parameter. The same chartData is used throughout the widget for other operations like minX, maxX, maxY, and ChartLine. If chartData was empty, those would likely fail too. This suggests chartData being non-empty is likely a precondition for this widget. I could be wrong about the precondition - maybe the chart should handle empty data gracefully. Also, defensive programming against null/empty collections is generally good practice. While defensive programming is good, this widget appears to fundamentally require data to work. Adding checks here would just mask a higher-level issue if empty data is passed in. The comment should be deleted as it suggests adding defensive code in a widget that requires data to function. If empty data handling is needed, it should be handled at a higher level.
> 
> 
> </details>
> 
> <details>
> <summary>2. <code>lib/l10n/app_pl.arb:1429</code></summary>
> 
> - **Draft comment:** 
> Typo detected: 'Liczba pięterL' appears to have an unwanted trailing 'L'.
> - **Reason this comment was not posted:**
> Comment was not on a location in the diff, so it can't be submitted as a review comment.
> 
> 
> </details>
> 
> <details>
> <summary>3. <code>lib/l10n/app_en.arb:94</code></summary>
> 
> - **Draft comment:** 
> Possible typo in key 'scientific_cirlces' – consider renaming to 'scientific_circles' for clarity.
> - **Reason this comment was not posted:**
> Comment was not on a location in the diff, so it can't be submitted as a review comment.
> 
> 
> </details>
> 
> <details>
> <summary>4. <code>lib/features/parkings/parkings_view/widgets/parking_wide_tile_card.dart:128</code></summary>
> 
> - **Draft comment:** 
> The concatenated string for the semantic label might be missing a space between the value from 'context.localize.sks_people_live_screen_reader_label_trend' and the result of 'localizedName(parking.trend, context)'. Please ensure that the intended spacing is applied if a separator is needed.
> - **Reason this comment was not posted:**
> Decided after close inspection that this draft comment was likely wrong and/or not actionable: usefulness confidence = 10% vs. threshold = 50% Without seeing the actual localized strings, it's impossible to know if a space is needed. The localized strings themselves might already include appropriate spacing. Additionally, this is a pure UI/accessibility concern without any functional impact on the logic. Per the rules, we should not comment on pure UI changes. The comment could be valid if the screen reader output is actually running words together, making it hard to understand. This is an accessibility issue that could impact users. While accessibility is important, we don't have enough context about the localized strings to know if there's really an issue. The strings themselves likely handle spacing appropriately. Delete the comment since it's a UI/accessibility suggestion without clear evidence of an actual problem, and we can't verify if it's needed without seeing the localized strings.
> 
> 
> </details>
> 
> 
> Workflow ID: <workflowid>`wflow_my8VEVrIRb4ee3GT`</workflowid>
> </details>
> 
> <sup>You can customize </sup>[<img alt="Ellipsis" src="https://img.shields.io/badge/Ellipsis-blue?color=175173">](https://www.ellipsis.dev?ref=Solvro%2Fmobile-topwr&utm_source=github&utm_medium=referral)<sup> by changing your [verbosity settings](https://app.ellipsis.dev/Solvro/settings/code-review), reacting with :+1: or :-1:, [replying to comments](https://docs.ellipsis.dev/features/code-review#teaching-ellipsis), or adding [code review rules](https://app.ellipsis.dev/Solvro/code-review/rules).</sup>
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-24T14:58:56Z
user: login: ellipsis-dev[bot]
body: > [!IMPORTANT]
> **Looks good to me!  :+1:**
> <details>
> <summary>Reviewed b56f573e2856b1c7dc5302962e4bdeb71a319a4d in <ellipsistime>2 minutes and 5 seconds</ellipsistime>. Click for details.</summary> 
> 
> - Reviewed `194` lines of code in `7` files
> - Skipped `0` files when reviewing.
> - Skipped posting `8` draft comments. View those below.
> - Modify your [settings](https://app.ellipsis.dev/Solvro/settings/code-review) and [rules](https://app.ellipsis.dev/Solvro/code-review/rules) to customize what types of comments Ellipsis leaves. And don't forget to react with :+1: or :-1: to teach Ellipsis.
> 
> <details>
> <summary>1. <code>lib/features/parkings/parking_chart/chart_elements/labels_bottom.dart:16</code></summary>
> 
> - **Draft comment:** 
> Add a comment explaining why 'context.isTextScaledDown' determines the interval value.
> - **Reason this comment was not posted:**
> Confidence changes required: `33%` <= threshold `50%` None
> 
> 
> </details>
> 
> <details>
> <summary>2. <code>lib/features/parkings/parking_chart/chart_elements/labels_left.dart:25</code></summary>
> 
> - **Draft comment:** 
> Document the rationale for using 'context.isTextScaledDown ? 10 : 1' for the space value.
> - **Reason this comment was not posted:**
> Confidence changes required: `33%` <= threshold `50%` None
> 
> 
> </details>
> 
> <details>
> <summary>3. <code>lib/features/parkings/parking_chart/parking_chart.dart:23</code></summary>
> 
> - **Draft comment:** 
> Verify that clamping the textScaler with maxScaleFactor: 0.1 yields the intended (small) scale for chart padding.
> - **Reason this comment was not posted:**
> Comment did not seem useful. Confidence is useful = `0%` <= threshold `50%` The comment is asking the PR author to verify the behavior of clamping the `textScaler` with a specific `maxScaleFactor`. This falls under asking the author to confirm their intention or ensure the behavior is intended, which is against the rules.
> 
> 
> </details>
> 
> <details>
> <summary>4. <code>lib/features/parkings/parking_chart/widgets/reversed_label.dart:11</code></summary>
> 
> - **Draft comment:** 
> Ensure that using clamp(maxScaleFactor: 0.1) for the reversed label produces optimal sizing.
> - **Reason this comment was not posted:**
> Confidence changes required: `33%` <= threshold `50%` None
> 
> 
> </details>
> 
> <details>
> <summary>5. <code>lib/features/parkings/parkings_view/widgets/parking_wide_tile_card.dart:21</code></summary>
> 
> - **Draft comment:** 
> Confirm that using clamp(maxScaleFactor: 2) here (in contrast to 0.1 elsewhere) is intentional for these elements.
> - **Reason this comment was not posted:**
> Confidence changes required: `33%` <= threshold `50%` None
> 
> 
> </details>
> 
> <details>
> <summary>6. <code>lib/features/parkings/parkings_view/widgets/parking_wide_tile_card.dart:75</code></summary>
> 
> - **Draft comment:** 
> Consider adding a separator (e.g., a space) between the concatenated semantic labels in _LeftColumn for clarity.
> - **Reason this comment was not posted:**
> Confidence changes required: `33%` <= threshold `50%` None
> 
> 
> </details>
> 
> <details>
> <summary>7. <code>lib/features/parkings/parkings_view/widgets/parking_wide_tile_card.dart:131</code></summary>
> 
> - **Draft comment:** 
> Verify if a separator is needed between the trend descriptor and trend name in the semantics label for screen reader clarity.
> - **Reason this comment was not posted:**
> Confidence changes required: `33%` <= threshold `50%` None
> 
> 
> </details>
> 
> <details>
> <summary>8. <code>lib/features/parkings/parking_chart/parking_chart.dart:23</code></summary>
> 
> - **Draft comment:** 
> Typographical note: In line 23, you use 'context.textScaler'. If this was intended to use Flutter's standard text scale factor, it is typically spelled 'textScaleFactor'. Please verify whether 'textScaler' is correct or a typo.
> - **Reason this comment was not posted:**
> Decided after close inspection that this draft comment was likely wrong and/or not actionable: usefulness confidence = 10% vs. threshold = 50% 1. The code is using `context.textScaler` which comes from an extension method. 2. The API seems intentional since it has additional functionality (clamp). 3. This could be a legitimate Flutter API or custom implementation. 4. Without seeing context_extensions.dart, we can't be certain if this is wrong. 5. The comment is speculative and asking for verification rather than pointing out a clear issue. I might be wrong about the extension method - it could be a typo. Also, if textScaleFactor is the only correct Flutter API, this would be important to fix. Even if it were a typo, the code compiles and the pattern is used consistently. More importantly, we don't have enough context to be certain this is incorrect, and the comment is asking for verification rather than stating a clear issue. Delete the comment because it's speculative, asks for verification, and we don't have strong evidence that textScaler is incorrect.
> 
> 
> </details>
> 
> 
> Workflow ID: <workflowid>`wflow_AwaNlBMo0cJ1gclb`</workflowid>
> </details>
> 
> <sup>You can customize </sup>[<img alt="Ellipsis" src="https://img.shields.io/badge/Ellipsis-blue?color=175173">](https://www.ellipsis.dev?ref=Solvro%2Fmobile-topwr&utm_source=github&utm_medium=referral)<sup> by changing your [verbosity settings](https://app.ellipsis.dev/Solvro/settings/code-review), reacting with :+1: or :-1:, [replying to comments](https://docs.ellipsis.dev/features/code-review#teaching-ellipsis), or adding [code review rules](https://app.ellipsis.dev/Solvro/code-review/rules).</sup>
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-24T17:07:54Z

Review comments:
diff_hunk: @@ -38,31 +38,33 @@ class SearchBox extends HookWidget {
 
     final color = context.colorTheme.blackMirage.withValues(alpha: 0.48);
 
-    return TextField(
-      controller: controller,
-      focusNode: focusNode,
-      onTap: onTap,
-      onTapOutside: onTapOutside,
-      onChanged: onChanged,
-      decoration: InputDecoration(
-        constraints: const BoxConstraints(maxHeight: SearchBoxConfig.height),
-        contentPadding: EdgeInsets.zero,
-        filled: true,
-        fillColor: context.colorTheme.greyLight,
-        hintText: "${searchText ?? context.localize.search}...",
-        hintStyle: context.textTheme.lightTitle.copyWith(color: color),
-        border: OutlineInputBorder(borderRadius: BorderRadius.circular(8), borderSide: BorderSide.none),
-        prefixIcon: Padding(
-          padding: const EdgeInsets.all(10),
-          child: SvgPicture.asset(Assets.svg.searchBox.vectorsearch),
+    return ExcludeSemantics(
path: lib/widgets/search_box.dart
user: login: ellipsis-dev[bot]
body: Review the use of `ExcludeSemantics` wrapping the `TextField`. If the text field is interactive, ensure that necessary semantic information (such as label and value) is provided elsewhere so screen readers aren’t left without context.

created_at: 2025-05-18T00:10:57Z
author_association: CONTRIBUTOR
diff_hunk: @@ -38,31 +38,33 @@ class SearchBox extends HookWidget {
 
     final color = context.colorTheme.blackMirage.withValues(alpha: 0.48);
 
-    return TextField(
-      controller: controller,
-      focusNode: focusNode,
-      onTap: onTap,
-      onTapOutside: onTapOutside,
-      onChanged: onChanged,
-      decoration: InputDecoration(
-        constraints: const BoxConstraints(maxHeight: SearchBoxConfig.height),
-        contentPadding: EdgeInsets.zero,
-        filled: true,
-        fillColor: context.colorTheme.greyLight,
-        hintText: "${searchText ?? context.localize.search}...",
-        hintStyle: context.textTheme.lightTitle.copyWith(color: color),
-        border: OutlineInputBorder(borderRadius: BorderRadius.circular(8), borderSide: BorderSide.none),
-        prefixIcon: Padding(
-          padding: const EdgeInsets.all(10),
-          child: SvgPicture.asset(Assets.svg.searchBox.vectorsearch),
+    return ExcludeSemantics(
path: lib/widgets/search_box.dart
user: login: mikolaj-jalocha
body: Why excluding this?
created_at: 2025-05-20T12:14:14Z
author_association: MEMBER
diff_hunk: @@ -38,31 +38,33 @@ class SearchBox extends HookWidget {
 
     final color = context.colorTheme.blackMirage.withValues(alpha: 0.48);
 
-    return TextField(
-      controller: controller,
-      focusNode: focusNode,
-      onTap: onTap,
-      onTapOutside: onTapOutside,
-      onChanged: onChanged,
-      decoration: InputDecoration(
-        constraints: const BoxConstraints(maxHeight: SearchBoxConfig.height),
-        contentPadding: EdgeInsets.zero,
-        filled: true,
-        fillColor: context.colorTheme.greyLight,
-        hintText: "${searchText ?? context.localize.search}...",
-        hintStyle: context.textTheme.lightTitle.copyWith(color: color),
-        border: OutlineInputBorder(borderRadius: BorderRadius.circular(8), borderSide: BorderSide.none),
-        prefixIcon: Padding(
-          padding: const EdgeInsets.all(10),
-          child: SvgPicture.asset(Assets.svg.searchBox.vectorsearch),
+    return ExcludeSemantics(
path: lib/widgets/search_box.dart
user: login: mmzek
body: before the readed text was "unlabeled button search" now label is "search" so it says "search button" without excluding it would be "search button search"

created_at: 2025-05-24T12:08:09Z
author_association: MEMBER
diff_hunk: @@ -67,31 +71,41 @@ class _LeftColumn extends StatelessWidget {
 
   @override
   Widget build(BuildContext context) {
-    return Column(
-      crossAxisAlignment: CrossAxisAlignment.stretch,
-      children: [
-        Text(
-          parking.symbol,
-          style: isActive ? context.iParkingTheme.title.withoutShadows : context.iParkingTheme.title,
-        ),
-        Padding(
-          padding: ParkingsConfig.extraIndentPadd,
-          child:
-              isActive
-                  ? Text(
-                    "${context.localize.street_abbreviation} ${parking.addressFormatted}",
-                    style: context.iParkingTheme.subtitleLight.withoutShadows,
-                  )
-                  : Text(parking.nameNormalized, style: context.iParkingTheme.subtitle),
-        ),
-        const SizedBox(height: 2),
-        if (!isActive)
+    return Semantics(
+      label:
+          isActive
+              ? context.localize.parking_chart_title_screen_reader_label +
path: lib/features/parkings/parkings_view/widgets/parking_wide_tile_card.dart
user: login: ellipsis-dev[bot]
body: When concatenating the two localization strings for the Semantics label in `_LeftColumn`, add a space or punctuation to separate them for clarity.

created_at: 2025-05-24T14:58:56Z
author_association: CONTRIBUTOR
diff_hunk: @@ -109,24 +123,30 @@
       mainAxisAlignment: MainAxisAlignment.end,
       children: [
         const Spacer(),
-        Row(
-          mainAxisAlignment: MainAxisAlignment.end,
-          children: [
-            MyTooltip(
-              message: context.localize.places_currently_available,
-              child: Text(
-                parking.parsedNumberOfPlaces,
-                style: isActive ? context.iParkingTheme.title.withoutShadows : context.iParkingTheme.title,
+        Semantics(
+          label:
+              "${context.localize.parking_people_live_screen_reader_label} ${parking.parsedNumberOfPlaces} ${context.localize.sks_people_live_screen_reader_label_trend}${localizedName(parking.trend, context)}",
path: lib/features/parkings/parkings_view/widgets/parking_wide_tile_card.dart
user: login: ellipsis-dev[bot]
body: Include a space after the trend label in the Semantics label of `_RightColumn` to ensure proper separation before the localized trend description.
```suggestion
              "${context.localize.parking_people_live_screen_reader_label} ${parking.parsedNumberOfPlaces} ${context.localize.sks_people_live_screen_reader_label_trend} ${localizedName(parking.trend, context)}",
```

created_at: 2025-05-24T14:58:56Z
author_association: CONTRIBUTOR

PR comments:
user: login: simon-the-shark
created_at: 2025-05-19T21:51:40Z
body: @mmzek I've added few map/bottom sheet related things to my PR https://github.com/Solvro/mobile-topwr/pull/735 so you can rebase on top of it and check how they work with your changes (parkings and buildings have some common widgets)
author_association: MEMBER
user: login: simon-the-shark
created_at: 2025-05-23T15:02:39Z
body: what's the status here?
author_association: MEMBER
user: login: mmzek
created_at: 2025-05-24T17:10:49Z
body: ![image](https://github.com/user-attachments/assets/8b4c4714-5f31-43c7-b353-6520e6434c2e)
![image](https://github.com/user-attachments/assets/dcf534f7-e070-441e-b690-21914c7d29cf)

author_association: MEMBER