Skip to content

mobile: table view, filters, and row-edit overhaul#1814

Merged
lyubov-voloshko merged 13 commits into
mainfrom
mobile-menu-and-buttons-fixes
Jun 2, 2026
Merged

mobile: table view, filters, and row-edit overhaul#1814
lyubov-voloshko merged 13 commits into
mainfrom
mobile-menu-and-buttons-fixes

Conversation

@karinakharchenko
Copy link
Copy Markdown
Collaborator

@karinakharchenko karinakharchenko commented Jun 1, 2026

Summary

End-to-end mobile pass over the data-grid experience.

  • Table view (db-table-view): rows become cards on ≤600px with dashed separators between fields, checkbox + actions strip non-clickable for preview, action icons unified to outlined symbols. Refresh icon replaced with pull-to-refresh; Add row promoted to an extended FAB; AI and Settings gear moved onto the table-switcher row; sort arrow appended to the active column's data-label.
  • Bottom sheets: table picker (with search + collapsible folders + colored icons), Sort by (per-column expanding asc/desc + pin-icon "Set as default"), Columns (drag-drop checkbox list), Import/Export — all rendered at component root with backdrop-filter scrim so the AI-config banner no longer composites over them.
  • Row preview: bottom-sheet style with drag handle, safe-area padding, related records flattened (per-row chevron to navigate, no accidental teleports). Copy-link snackbar shown at the top so it's not hidden under the sheet. Cell copy buttons hidden on mobile to remove invisible-but-tappable accidental copies.
  • Search & filter: search expanded full-width with a small outlined Filter button below; Filter and Sort by share a row with Columns next to Sort by.
  • Filter dialogs: open as bottom sheets on mobile (rounded top, drag handle, slide-up, safe-area); header restructured to small label over table name; floating labels no longer clip; comparator selects collapse to a single symbol on mobile and widen the panel to fit long options. Saved-filters dialog: per-condition card with name caption, comparator + value on one line, "Quick editing" toggle with the existing info-popup; sticky Save/Cancel.
  • Row edit form: breadcrumbs replaced with a back arrow + two-line title ("Add row" / table name); page-top margin reduced; widget info icon next to fields removed. Save & continue pushed left, primary submit (Save/Add/Edit/Duplicate) right; on mobile the action bar is fixed at viewport bottom with safe-area padding — verified that position: fixed pins to the viewport in mat-sidenav-content (no transformed ancestor), so the long button reflows onto its own row underneath.
  • Connections list logo: short rocket-icon SVG swapped in on mobile via <picture>.
  • Misc: number cells left-aligned on mobile; foreign-key filter no longer artificially tall; success snackbar gets an optional verticalPosition so the preview's copy-link toast shows above the sheet.

Test plan

  • Open table view on mobile (≤600px): tap table name → bottom sheet with search + folders; long-press scroll triggers pull-to-refresh.
  • Tap a row card → preview opens as bottom sheet with backdrop; tap related record's chevron, then back, then close.
  • Apply a column filter, then a fast filter; open Sort by, expand a column, pick Descending and "Set as default".
  • Open Add row → form scrolls, Save / Save & continue / Back arrow all reachable above the keyboard; safe-area padding visible on iPhone with home indicator.
  • Confirm desktop view of the same pages is unchanged.

🤖 Generated with Claude Code

Summary by CodeRabbit

Release Notes

  • New Features

    • Added pull-to-refresh functionality for mobile devices
    • Introduced mobile-optimized bottom-sheet dialogs for filters, sorting, and column management
    • Added table switcher with search capability on mobile
  • Improvements

    • Redesigned filter UI with card-based condition layout for better clarity
    • Enhanced responsive design across dashboard, forms, and table views
    • Improved mobile navigation with dedicated header controls
    • Optimized form and button layouts for smaller screens

karinakharchenko and others added 7 commits May 21, 2026 17:07
…s cleanup

- Table view: card-style rows on mobile (rounded border, dashed inter-cell
  separators, label/value centered between dashes, checkbox+actions strip
  non-clickable for preview), unified icon button styling, mobile-only Sort
  button on the saved-filters row.
- Saved filters: combined dropdown trigger on mobile (active filter shown
  with check + bold name, "New fast filter" entry at the bottom); desktop
  chip layout preserved. Applied-filter details get a soft background and
  no longer trigger horizontal overflow.
- Row preview: bottom sheet on mobile with backdrop scrim, drag handle,
  safe-area padding. Related records flattened (outer expansion removed)
  and per-row navigation moved to an explicit chevron button to prevent
  accidental teleports.
- Mobile actions: icon-only with tooltips, unified outlined symbol set,
  count badge hidden when label collapses.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Empty-filter state: card-style placeholder with icon + tailored copy
  for fast filters vs column filters; separate from the empty-table CTA.
- Select all: moved from settings menu into the bulk-actions toolbar so
  it appears after the first row is selected.
- Search: collapsed pill (40x40 with search icon) that expands on focus
  or when filled — saves room next to the action buttons.
- Action icons: unified to material-symbols-outlined and bumped to 22px
  with stronger color to match the checkbox weight on cards.
- Saved filters menu: fixed nested-button alignment by replacing the
  per-row trigger button with a span; check icon kept in flow via
  visibility toggle so labels stay vertically centered.
- Filter dialog: opens as a bottom sheet on mobile via panelClass with
  rounded top corners, drag handle, slide-up animation, safe-area pad.
- Comparator selects: narrowed (max 116px) and dropdown panel widened
  to its content (max 100vw - 32px) so long options stay readable.
- Foreign-key filter: subscript wrapper hidden globally so the field is
  no longer artificially tall.
- Number cell: left-aligned in mobile cards (copy button moved back to
  the right edge) so values line up with the rest.
- Logo: short rocketadmin icon swapped in on mobile via <picture>.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…s on mobile

- Floating labels in filter form fields: removed max-width / overflow
  clip on .mdc-notched-outline__notch and .mdc-floating-label so the
  text isn't truncated when the field is narrow; .filters-container
  switched from overflow: hidden to overflow-x: clip / overflow-y:
  visible to stop vertical clipping of the rising label.
- Filter dialog on mobile: each filter row now stacks column name
  above the inputs as a small caption (12px, 600, .6 opacity) via
  grid-template-areas instead of a 3-column inline layout.
- Filter dialog spacing: added breathing room between the "Filters for
  [table]" header and the first "Add filter by..." field so its
  floating label no longer collides with the title (both desktop and
  bottom-sheet mobile variant).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Each filter condition is now a stacked block with column name caption,
  comparator + value on one row, and a "Quick editing" toggle below;
  conditions are separated by a dashed line (matching the table card
  style) instead of a gray background.
- Comparator dropdown collapses to a single-symbol trigger (=, >, ≥, etc.
  for numbers; a…, …a, ∋, ∌, ∅ for text) and is locked to 56px with
  inner Material padding/min-width / subscript-wrapper all stripped, so
  the value field can take the rest of the row.
- Value input wrapped in .condition-card__value to ensure the dynamic
  filter component (ndc-dynamic host) stretches to fill remaining
  space — eliminates the dead gap between comparator and value field.
- Dialog header restructured: small "New fast filter" / "Edit fast
  filter" label above a smaller table name; mat-dialog-title's MDC
  baseline ::before spacer disabled so the heading height matches the
  regular filter dialog.
- Dialog actions (Save / Cancel) are sticky at the bottom; surface uses
  overflow: hidden with a scrollable .filters-content area so buttons
  stay in view instead of scrolling off.
- info_outline help icon (with the existing animated quick-edit
  explanation menu) is rendered next to the per-condition toggle; the
  global "Quick edit" header block was removed and the mat-menu hoisted
  out of *ngIf so the per-row triggers resolve it.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Table switcher: replaced the mat-menu (whose search overlapped the
  trigger and caused misclicks) with a bottom sheet — search pill,
  collapsible folders with colored folder icons (dehaze for All tables),
  active table checkmark, slide-up + scrim. Rendered at the component
  root with backdrop-filter/translateZ so the AI-config banner's
  backdrop-filter no longer composites over it.
- Sort by: bottom sheet listing sortable columns; per-column asc/desc
  icon buttons (active highlighted) plus a lock toggle for set/remove
  default — replaces the awkward nested submenu.
- Columns: opens the same drag-drop checkbox list as a bottom sheet on
  mobile (isMobileView nulls the matMenuTriggerFor) while desktop keeps
  the dropdown menu.
- Comparator selects in filter dialogs show full text on desktop and a
  single symbol on mobile; table-name shown as "Table: <name>" in both
  filter dialog headers.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ctions

- Table view: removed the refresh icon on mobile in favor of pull-to-
  refresh (touch handlers trigger loadRowsPage past a 70px pull with a
  spinner indicator); Import/Export opens as a bottom sheet on mobile
  while desktop keeps the dropdown menu.
- Row preview: wider 20px side padding, header trailing icons aligned,
  copy-link snackbar shown at the top so it isn't hidden under the sheet.
- Cell copy buttons hidden on mobile — they were invisible (no hover)
  but still tappable, causing accidental copies instead of opening the
  row preview.
- Row edit form: action bar (Back / Save / Save and continue editing)
  fixed to the viewport bottom on mobile so it no longer scrolls off the
  page; the form scroll container is mat-drawer-content and position:
  fixed correctly pins (verified — no transformed ancestor), so a flex
  static footer is NOT used. Buttons reflow: Back+Save in a row, the
  long continue button on its own line; safe-area padding at the bottom.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…it form

- Table view header on mobile: a 12px gap separates the table-switcher
  row from the search; the AI icon and Settings gear moved to the
  table-switcher row (far right) so the actions row stays uncluttered.
- Filter actions split out of the icon-only actions row: Filter is a
  small outlined button under a full-width search field; Add row turned
  into an extended FAB (icon + label) pinned to the bottom-right, shown
  whenever the user has add permission (no longer hidden on empty
  tables) so it never disappears behind the empty-state CTA.
- Columns moved next to Sort by in the saved-filters row, with the
  saved-filters-row switched from absolute Sort to a flex layout so
  Columns + Sort sit side-by-side at the right; both are icon-only on
  mobile (Columns view_week, Sort by gets a leading swap_vert icon).
  The actions-row originals are hidden on mobile.
- Sort bottom sheet redesigned: tapping a column expands inline buttons
  for Ascending / Descending and a Set/Remove default action with a
  pin icon; an active sort arrow is appended to the column data-label
  in row cards.
- Import/Export consolidated into the Settings menu on mobile (with a
  divider) so the separate swap_vert button can be hidden.
- Filter dialog: autoFocus disabled so the "Add filter by..." input
  doesn't auto-open the column dropdown; settings icon explicitly
  pushed to the right via margin-left:auto.
- Row edit form: breadcrumbs replaced with a back arrow and a two-line
  title (page mode + table name); page top margin reduced and empty
  app-alert collapsed so the title sits higher; widget info icon next
  to fields removed. Action bar reworked — Back removed entirely (the
  header arrow handles it); Save & continue pushed left, primary
  submit (Save / Add / Edit / Duplicate) right; on mobile the bar is a
  fixed bottom bar with safe-area padding and the buttons reflow with
  Save & continue on its own full-width row.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@CLAassistant
Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Jun 1, 2026

Review Change Stack

📝 Walkthrough

Walkthrough

This PR introduces a comprehensive mobile-first redesign of the frontend dashboard and data management interfaces. The changes span responsive layouts, touch interactions, sheet-based dialogs, and responsive typography across the table view, filters, row editing, and supporting components, targeting viewports ≤600px with safe-area awareness and bottom-sheet pattern adoption.

Changes

Mobile-first Dashboard and Data Management UI

Layer / File(s) Summary
Global mobile styling foundation and service enhancements
frontend/src/styles.scss, frontend/src/app/services/notifications.service.ts
Establishes CDK overlay bottom-sheet dialog positioning (fixed, full-width, safe-area padding, drag handle, slide-up animation) and Material select/form-field responsive sizing for mobile. Extends NotificationsService.showSuccessSnackbar to accept optional verticalPosition parameter ('top' | 'bottom', default 'bottom').
Logo responsive rendering
frontend/src/app/app.component.css, frontend/src/app/app.component.html
Adds responsive picture element with srcset for logo selection on mobile/desktop; inline-flex container styling and mobile-specific height (28px) and margin adjustments.
Table view comprehensive mobile transformation
frontend/src/app/components/dashboard/db-table-view/db-table-view.component.css, frontend/src/app/components/dashboard/db-table-view/db-table-view.component.html, frontend/src/app/components/dashboard/db-table-view/db-table-view.component.ts
Introduces pull-to-refresh interaction via touch event handlers, table-switcher button with search filtering across categorized/uncategorized tables and folder collapse state. Adds multiple bottom-sheet layouts (sort, columns, transfer). Restructures header with labeled actions, search-row with filter button, saved-filters row integration. Updates table grid with transparent backgrounds, dashed cell separators, data-label rendering via ::before pseudo-element, and responsive empty-state card styling.
Saved filters dialog and panel mobile UI
frontend/src/app/components/dashboard/db-table-view/saved-filters-panel/saved-filters-dialog/saved-filters-dialog.component.css, frontend/src/app/components/dashboard/db-table-view/saved-filters-panel/saved-filters-dialog/saved-filters-dialog.component.html, frontend/src/app/components/dashboard/db-table-view/saved-filters-panel/saved-filters-panel.component.css, frontend/src/app/components/dashboard/db-table-view/saved-filters-panel/saved-filters-panel.component.html, frontend/src/app/components/dashboard/db-table-view/saved-filters-panel/saved-filters-panel.component.ts
Redesigns dialog with condition-card layout and quick-edit help menu; adds per-card footer with enable/disable toggle. Panel adds mobile-only dropdown trigger menu showing current filter name with fallback. Updates responsive filters-container, dynamic-column-editor, and applies mobile-bottom-sheet panelClass to both dialog and panel.
Filters dialog mobile optimization
frontend/src/app/components/dashboard/db-table-view/db-table-filters-dialog/db-table-filters-dialog.component.css, frontend/src/app/components/dashboard/db-table-view/db-table-filters-dialog/db-table-filters-dialog.component.html, frontend/src/app/components/dashboard/dashboard.component.ts
Restructures dialog header with separate label and table-name display spans. Updates filter-line CSS to hide Material subscript and use responsive grid with named areas (column-name, field, delete) for mobile. Adds mobile-bottom-sheet panelClass and disables autoFocus on dialog open.
Row preview sidebar mobile layout
frontend/src/app/components/dashboard/db-table-view/db-table-row-view/db-table-row-view.component.css, frontend/src/app/components/dashboard/db-table-view/db-table-row-view/db-table-row-view.component.html, frontend/src/app/components/dashboard/db-table-view/db-table-row-view/db-table-row-view.component.ts
Converts sidebar to fixed full-width mobile layout with safe-area padding, rounded top corners, slide-up animation, and backdrop. Changes related-records from mat-nav-list to mat-list with action in meta area. Adds related-records-section wrapper with uppercase title styling and related-record__open color states. Updates snackbar position to 'top'.
Row edit page mobile layout
frontend/src/app/components/db-table-row-edit/db-table-row-edit.component.css, frontend/src/app/components/db-table-row-edit/db-table-row-edit.component.html, frontend/src/app/components/db-table-row-edit/db-table-row-edit.component.ts
Replaces breadcrumbs with dedicated header containing back icon, title, and subtitle. Restructures actions to use flex-end justification and adds mobile fixed bottom positioning with safe-area insets. Removes widget info icon and standalone back button. Updates button label to "Save & continue" and adds pageTitle getter.
Field display components mobile optimization
frontend/src/app/components/ui-components/filter-fields/foreign-key/foreign-key.component.css, frontend/src/app/components/ui-components/filter-fields/foreign-key/foreign-key.component.html, frontend/src/app/components/ui-components/table-display-fields/base-table-display-field/base-table-display-field.component.css, frontend/src/app/components/ui-components/table-display-fields/number/number.component.css
Hides copy buttons on mobile using display:none !important across base and number components. Reverses number component text alignment and copy-button positioning for mobile. Hides foreign-key subscript wrapper and removes hint text.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Suggested reviewers

  • lyubov-voloshko
  • gugu

🐰 A dashboard redesigned for the mobile screen,
With swipe and tap where once there scrolled a dream,
Pull-to-refresh now dances at your finger's peak,
Bottom sheets slide up so silky, smooth, and sleek! 📱✨

🚥 Pre-merge checks | ✅ 6
✅ Passed checks (6 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'mobile: table view, filters, and row-edit overhaul' directly and accurately describes the main changes across the PR, highlighting the three primary affected areas.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Security Check ✅ Passed PR follows OWASP security guidelines: no XSS vulnerabilities, no code injection risks, proper input validation, no hardcoded credentials, permission checks maintained, and safe event handling.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch mobile-menu-and-buttons-fixes

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.

@coderabbitai coderabbitai Bot requested review from gugu and lyubov-voloshko June 1, 2026 11:28
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 15

🧹 Nitpick comments (2)
frontend/src/app/services/notifications.service.ts (1)

21-27: 💤 Low value

Add an explicit return type to the method.

The signature change to add an optional verticalPosition with a default is backward compatible with existing callers. Per the TS guideline, add a : void return annotation.

📝 Proposed fix
-	showSuccessSnackbar(message: string, verticalPosition: 'top' | 'bottom' = 'bottom') {
+	showSuccessSnackbar(message: string, verticalPosition: 'top' | 'bottom' = 'bottom'): void {

As per coding guidelines: "Always add type annotations to function parameters and return types in TypeScript".

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/src/app/services/notifications.service.ts` around lines 21 - 27, The
method showSuccessSnackbar in notifications.service.ts is missing an explicit
return type; update its signature to include a void return annotation (e.g.,
change the declaration of showSuccessSnackbar(message: string, verticalPosition:
'top' | 'bottom' = 'bottom') to include : void) so it conforms to the TypeScript
guidelines requiring explicit function return types.
frontend/src/styles.scss (1)

126-126: 💤 Low value

Reference palette CSS variables instead of hardcoding colors.

The box-shadow (Line 126) and drag-handle backgrounds (Lines 156, 163) use hardcoded rgba(...) values. Consider sourcing these from the generated palette so they stay theme-consistent.

As per coding guidelines: "Only use colors from generated palettes defined in src/main.ts (colorConfig). Do not hardcode arbitrary color values; reference palette CSS variables from @brumeilde/ngx-theme".

Also applies to: 156-156, 163-163

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/src/styles.scss` at line 126, Replace the hardcoded rgba(...) values
in styles.scss (the box-shadow declaration and the drag-handle background
declarations) with the generated palette CSS variables produced by your
colorConfig in src/main.ts and exposed by `@brumeilde/ngx-theme`; locate the
box-shadow line and the drag-handle rules (background properties) and swap the
rgba literals for the appropriate palette variables (e.g.,
var(--palette-<color>-<shade>) or whatever naming your build emits), ensuring
you reference the same generated variable names used by `@brumeilde/ngx-theme` so
the shadow and handle colors follow the active theme.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@frontend/src/app/components/dashboard/db-table-view/db-table-row-view/db-table-row-view.component.css`:
- Around line 84-91: The `@keyframes` name rowPreviewSlideUp uses camelCase and
breaks the configured keyframes-name-pattern; rename it to kebab-case (e.g.,
row-preview-slide-up) and update all corresponding usages (animation,
animation-name, and any JS/TS references) to the new identifier; repeat the same
change for the other keyframes defined at 93-100 (rename to a kebab-case
equivalent) so stylelint passes and all animations still reference the updated
names (check CSS selectors, inline styles, and component templates).

In
`@frontend/src/app/components/dashboard/db-table-view/db-table-row-view/db-table-row-view.component.html`:
- Around line 1-4: The template still uses legacy structural directives (*ngIf,
*ngFor, *ngSwitch) in newly edited blocks (e.g., the div with class
"row-preview-backdrop" that binds to selectedRow and calls handleClose()), which
violates the Angular 19 control-flow guideline; update those instances to use
the built-in control-flow syntax (`@if`, `@for`, `@switch`) — for example replace the
*ngIf usage on the preview/backdrop and any other occurrences (including the
blocks referenced around the row rendering and switch logic) with
`@if`="selectedRow" and convert any *ngFor/*ngSwitch blocks to `@for/`@switch
equivalents while keeping existing event handlers and classes (e.g.,
handleClose, selectedRow, row-preview-backdrop) intact.
- Around line 73-80: The icon-only anchor with class "related-record__open" (the
<a matListItemMeta mat-icon-button ...> that navigates using [routerLink] and
calls handleClose()) needs an explicit accessible label; add an aria-label (or
[attr.aria-label] bound) to that anchor — e.g. a static "Open record" or a
dynamic label like `Open record for {{ referencedTable.table_name }}` or
including the referenced record id from
referencedRecords[referencedTable.table_name]?.links[i] — so screen readers get
a clear action name while preserving the existing routerLink, [queryParams], and
(click)="handleClose()".

In
`@frontend/src/app/components/dashboard/db-table-view/db-table-view.component.css`:
- Line 33: Rename the camelCase keyframe name pullRefreshSpin to a kebab-case
name (e.g., pull-refresh-spin) and update all usages accordingly; locate the
`@keyframes` declaration for pullRefreshSpin and change its identifier, then find
any animation, animation-name, or shorthand references (the occurrences
currently at the other two locations reported) and replace pullRefreshSpin with
the new kebab-case identifier so linting passes.
- Line 1113: In db-table-view.component.css replace the deprecated grid-gap
property usage with the modern gap property (i.e., change the rule that
currently sets "grid-gap: 2px 12px;" to use "gap: 2px 12px;") so the CSS uses
current syntax and satisfies lint rules; update any identical occurrences of
grid-gap in the same file or component stylesheet (search for "grid-gap" to
locate all instances).

In
`@frontend/src/app/components/dashboard/db-table-view/db-table-view.component.html`:
- Around line 1-9: The template uses legacy structural directives; replace all
*ngIf/*ngFor/*ngSwitch usages in this component with Angular 19 built-in
control-flow directives (`@if`, `@for`, `@switch`). Concretely, update the
pull-to-refresh indicator markup to use `@if/`@for patterns where conditional
rendering depends on pullDistance and pullRefreshing (the div with class
pull-refresh-indicator and the mat-icon), and apply the same conversion for the
table switcher sheet, sort sheet, columns sheet, and transfer sheet (the
sections referenced in the review). Keep the existing bindings (e.g.,
[class.pull-refresh-indicator_active], [style.height.px], [style.transform])
intact while replacing the structural directives, and run template linting to
ensure the new `@if/`@for/@switch syntax is used consistently.

In
`@frontend/src/app/components/dashboard/db-table-view/db-table-view.component.ts`:
- Line 315: Convert the listed component state fields into Angular signals:
replace the plain fields tableSwitcherSearch, tableSwitcherOpen,
collapsedFolders, sortSheetOpen, sortExpandedColumn, columnsSheetOpen,
transferSheetOpen, pullDistance, and pullRefreshing with protected or private
readonly signals initialized via signal(...) (e.g., protected readonly
tableSwitcherSearch = signal('') or appropriate initial values). Update all
writes to these states to use .set(...) (e.g., tableSwitcherSearch.set(...)) and
update reads in methods and templates to use signal reads (call the signal or
use its value per your project convention). Ensure the symbol names remain
identical and update any usages in methods like anyTableSwitching handlers,
folder toggles, sort/column sheet handlers, transfer sheet logic, and
pull-to-refresh handlers to use the new signal API.
- Around line 356-358: The isMobileView getter directly reads window.innerWidth
which risks SSR hydration issues; update the component to perform a proper
platform check using Angular's PLATFORM_ID and isPlatformBrowser (inject
PLATFORM_ID into the component constructor and call
isPlatformBrowser(this.platformId) before accessing window) or switch to Angular
CDK's BreakpointObserver/responsive service to determine mobile state without
touching window during server render; modify the isMobileView getter (or replace
it with a boolean property updated by BreakpointObserver) so any window access
is gated by isPlatformBrowser(this.platformId) and ensure the constructor
injects PLATFORM_ID (and BreakpointObserver if used).

In
`@frontend/src/app/components/dashboard/db-table-view/saved-filters-panel/saved-filters-dialog/saved-filters-dialog.component.css`:
- Line 876: Replace the deprecated CSS property "grid-row-gap" with the standard
"row-gap" in the saved filters dialog stylesheet: find the rule that sets
"grid-row-gap: 0 !important;" (in saved-filters-dialog.component.css) and change
it to use "row-gap: 0 !important;" so stylelint no longer flags the deprecated
property.

In
`@frontend/src/app/components/dashboard/db-table-view/saved-filters-panel/saved-filters-dialog/saved-filters-dialog.component.html`:
- Around line 81-238: The template uses structural directives (*ngFor, *ngIf) —
replace them with Angular 19 control-flow syntax: convert the outer loop over
tableRowFieldsShown (currently on the div with class "condition-card") to
`@for`="let value of tableRowFieldsShown | keyvalue; trackBy: trackByFn", and
replace each *ngIf (checks calling getComparatorType(getInputType(value.key)),
isWidget(value.key), and the type-specific comparator checks) with `@if`
expressions and `@else` references that preserve the existing ng-template
fallbacks (defaultTableField and comparableFilterInputs). Ensure the ndc-dynamic
usages, bindings to tableRowFieldsShown/tableRowFieldsComparator, and event
handlers (updateField, updateComparatorFromComponent, updateComparator) remain
unchanged, and keep the quickEditHelpMenu/ toggleDynamicColumn logic intact.

In
`@frontend/src/app/components/dashboard/db-table-view/saved-filters-panel/saved-filters-panel.component.html`:
- Around line 44-81: Replace the new template usages of structural directives
with Angular 19 control-flow syntax: wrap the menu trigger block that currently
uses *ngIf="savedFilterData.length !== 0" in an <ng-container> using `@if` with
the same condition; change the *ngFor on the menu item to an <ng-container>
using `@for`="let filter of savedFilterData" (keeping the same bindings inside the
generated button), and replace the other *ngIf (canEditConnection()) with `@if` on
an <ng-container> so canEditConnection(), selectFiltersSet(filter.id),
setCurrentFilter(filter), selectedFilterSetId, savedFilterMap and
handleOpenSavedFiltersDialog() continue to be referenced unchanged; ensure you
stopPropagation() where you did before and preserve matMenuTriggerFor bindings
and classes.
- Around line 64-69: Replace the clickable <span> used as the per-row menu
trigger with a real <button> (e.g., mat-icon-button) to restore keyboard
accessibility and correct semantics: locate the template block that calls
canEditConnection() and uses [matMenuTriggerFor]="filterMenu" and
(click)="$event.stopPropagation(); setCurrentFilter(filter)" (the
saved-filters-menu__row-menu element) and change it to a button element, keep
the matMenuTriggerFor binding and the click handler (including stopPropagation
and setCurrentFilter(filter)), add type="button" and an appropriate aria-label,
and preserve the mat-icon and CSS class so styling/behavior remain the same.

In
`@frontend/src/app/components/db-table-row-edit/db-table-row-edit.component.html`:
- Around line 24-30: The back link element (anchor with class
"row-edit-header__back" and data-testid "record-back-to-table-button") is
icon-only and needs an accessible name; add an aria-label (e.g.,
aria-label="Back to table" or use a localized label) to the anchor so screen
readers announce its purpose, keeping the existing routerLink, [queryParams],
matTooltip and mat-icon intact.

In `@frontend/src/styles.scss`:
- Around line 118-120: Insert a blank line between the custom-property
declaration --mdc-dialog-container-shape and the subsequent declaration
max-height to satisfy Stylelint's declaration-empty-line-before rule; locate the
rule block containing --mdc-dialog-container-shape, max-height, and
padding-bottom and add a single empty line before the max-height declaration so
the sequence is: --mdc-dialog-container-shape, (blank line), max-height,
padding-bottom.
- Around line 167-174: The keyframes identifier mobileBottomSheetSlideUp must be
renamed to kebab-case (e.g., mobile-bottom-sheet-slide-up) and every reference
to it in the stylesheet updated accordingly; specifically rename the `@keyframes`
declaration name and update any animation/animation-name/shorthand properties
that currently reference mobileBottomSheetSlideUp so they use the new kebab-case
name (ensure exact string match for shorthand usages).

---

Nitpick comments:
In `@frontend/src/app/services/notifications.service.ts`:
- Around line 21-27: The method showSuccessSnackbar in notifications.service.ts
is missing an explicit return type; update its signature to include a void
return annotation (e.g., change the declaration of showSuccessSnackbar(message:
string, verticalPosition: 'top' | 'bottom' = 'bottom') to include : void) so it
conforms to the TypeScript guidelines requiring explicit function return types.

In `@frontend/src/styles.scss`:
- Line 126: Replace the hardcoded rgba(...) values in styles.scss (the
box-shadow declaration and the drag-handle background declarations) with the
generated palette CSS variables produced by your colorConfig in src/main.ts and
exposed by `@brumeilde/ngx-theme`; locate the box-shadow line and the drag-handle
rules (background properties) and swap the rgba literals for the appropriate
palette variables (e.g., var(--palette-<color>-<shade>) or whatever naming your
build emits), ensuring you reference the same generated variable names used by
`@brumeilde/ngx-theme` so the shadow and handle colors follow the active theme.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 213eb3f2-a173-4804-ac1e-c742d8b1b75c

📥 Commits

Reviewing files that changed from the base of the PR and between 9c031e4 and d58cda9.

📒 Files selected for processing (25)
  • frontend/src/app/app.component.css
  • frontend/src/app/app.component.html
  • frontend/src/app/components/dashboard/dashboard.component.ts
  • frontend/src/app/components/dashboard/db-table-view/db-table-filters-dialog/db-table-filters-dialog.component.css
  • frontend/src/app/components/dashboard/db-table-view/db-table-filters-dialog/db-table-filters-dialog.component.html
  • frontend/src/app/components/dashboard/db-table-view/db-table-row-view/db-table-row-view.component.css
  • frontend/src/app/components/dashboard/db-table-view/db-table-row-view/db-table-row-view.component.html
  • frontend/src/app/components/dashboard/db-table-view/db-table-row-view/db-table-row-view.component.ts
  • frontend/src/app/components/dashboard/db-table-view/db-table-view.component.css
  • frontend/src/app/components/dashboard/db-table-view/db-table-view.component.html
  • frontend/src/app/components/dashboard/db-table-view/db-table-view.component.ts
  • frontend/src/app/components/dashboard/db-table-view/saved-filters-panel/saved-filters-dialog/saved-filters-dialog.component.css
  • frontend/src/app/components/dashboard/db-table-view/saved-filters-panel/saved-filters-dialog/saved-filters-dialog.component.html
  • frontend/src/app/components/dashboard/db-table-view/saved-filters-panel/saved-filters-panel.component.css
  • frontend/src/app/components/dashboard/db-table-view/saved-filters-panel/saved-filters-panel.component.html
  • frontend/src/app/components/dashboard/db-table-view/saved-filters-panel/saved-filters-panel.component.ts
  • frontend/src/app/components/db-table-row-edit/db-table-row-edit.component.css
  • frontend/src/app/components/db-table-row-edit/db-table-row-edit.component.html
  • frontend/src/app/components/db-table-row-edit/db-table-row-edit.component.ts
  • frontend/src/app/components/ui-components/filter-fields/foreign-key/foreign-key.component.css
  • frontend/src/app/components/ui-components/filter-fields/foreign-key/foreign-key.component.html
  • frontend/src/app/components/ui-components/table-display-fields/base-table-display-field/base-table-display-field.component.css
  • frontend/src/app/components/ui-components/table-display-fields/number/number.component.css
  • frontend/src/app/services/notifications.service.ts
  • frontend/src/styles.scss
💤 Files with no reviewable changes (1)
  • frontend/src/app/components/ui-components/filter-fields/foreign-key/foreign-key.component.html

Comment on lines +84 to +91
@keyframes rowPreviewSlideUp {
from {
transform: translateY(100%);
}
to {
transform: translateY(0);
}
}
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 | ⚡ Quick win

Rename keyframes to kebab-case to satisfy stylelint.

The new animation names violate the configured keyframes-name-pattern and can fail lint checks.

Suggested fix
-		animation: rowPreviewSlideUp 240ms cubic-bezier(0.2, 0.8, 0.2, 1);
+		animation: row-preview-slide-up 240ms cubic-bezier(0.2, 0.8, 0.2, 1);
...
-		animation: rowPreviewBackdropFadeIn 240ms ease-out;
+		animation: row-preview-backdrop-fade-in 240ms ease-out;
...
-@keyframes rowPreviewSlideUp {
+@keyframes row-preview-slide-up {
...
-@keyframes rowPreviewBackdropFadeIn {
+@keyframes row-preview-backdrop-fade-in {

Also applies to: 93-100

🧰 Tools
🪛 Stylelint (17.12.0)

[error] 84-84: Expected keyframe name "rowPreviewSlideUp" to be kebab-case (keyframes-name-pattern)

(keyframes-name-pattern)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@frontend/src/app/components/dashboard/db-table-view/db-table-row-view/db-table-row-view.component.css`
around lines 84 - 91, The `@keyframes` name rowPreviewSlideUp uses camelCase and
breaks the configured keyframes-name-pattern; rename it to kebab-case (e.g.,
row-preview-slide-up) and update all corresponding usages (animation,
animation-name, and any JS/TS references) to the new identifier; repeat the same
change for the other keyframes defined at 93-100 (rename to a kebab-case
equivalent) so stylelint passes and all animations still reference the updated
names (check CSS selectors, inline styles, and component templates).

Comment on lines +1 to 4
<div *ngIf="selectedRow"
class="row-preview-backdrop"
(click)="handleClose()"></div>
<div *ngIf="selectedRow"
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion | 🟠 Major | 🏗️ Heavy lift

Migrate newly touched structural directives to Angular built-in control flow.

The changed template still uses *ngIf/*ngFor in newly modified blocks; this conflicts with the frontend template standard for new code.

As per coding guidelines, "Use Angular 19's built-in control flow (@if, @for, @switch) instead of structural directives (*ngIf, *ngFor, *ngSwitch) in all new code".

Also applies to: 30-35, 57-59

🧰 Tools
🪛 HTMLHint (1.9.2)

[error] 1-1: Doctype must be declared before any non-comment content.

(doctype-first)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@frontend/src/app/components/dashboard/db-table-view/db-table-row-view/db-table-row-view.component.html`
around lines 1 - 4, The template still uses legacy structural directives (*ngIf,
*ngFor, *ngSwitch) in newly edited blocks (e.g., the div with class
"row-preview-backdrop" that binds to selectedRow and calls handleClose()), which
violates the Angular 19 control-flow guideline; update those instances to use
the built-in control-flow syntax (`@if`, `@for`, `@switch`) — for example replace the
*ngIf usage on the preview/backdrop and any other occurrences (including the
blocks referenced around the row rendering and switch logic) with
`@if`="selectedRow" and convert any *ngFor/*ngSwitch blocks to `@for/`@switch
equivalents while keeping existing event handlers and classes (e.g.,
handleClose, selectedRow, row-preview-backdrop) intact.

Comment on lines +73 to +80
<a matListItemMeta mat-icon-button
class="related-record__open"
matTooltip="Open record"
[routerLink]="['/dashboard', selectedRow.connectionID, referencedTable.table_name, 'entry']"
[queryParams]="referencedRecords[referencedTable.table_name]?.links[i]"
(click)="handleClose()">
<mat-icon>chevron_right</mat-icon>
</a>
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 | ⚡ Quick win

Add an explicit accessible label to the icon-only “open record” action.

This anchor is icon-only; add aria-label so screen-reader users get a clear action name.

Suggested fix
-                        <a matListItemMeta mat-icon-button
+                        <a matListItemMeta mat-icon-button
+                            aria-label="Open related record"
                             class="related-record__open"
                             matTooltip="Open record"
📝 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
<a matListItemMeta mat-icon-button
class="related-record__open"
matTooltip="Open record"
[routerLink]="['/dashboard', selectedRow.connectionID, referencedTable.table_name, 'entry']"
[queryParams]="referencedRecords[referencedTable.table_name]?.links[i]"
(click)="handleClose()">
<mat-icon>chevron_right</mat-icon>
</a>
<a matListItemMeta mat-icon-button
aria-label="Open related record"
class="related-record__open"
matTooltip="Open record"
[routerLink]="['/dashboard', selectedRow.connectionID, referencedTable.table_name, 'entry']"
[queryParams]="referencedRecords[referencedTable.table_name]?.links[i]"
(click)="handleClose()">
<mat-icon>chevron_right</mat-icon>
</a>
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@frontend/src/app/components/dashboard/db-table-view/db-table-row-view/db-table-row-view.component.html`
around lines 73 - 80, The icon-only anchor with class "related-record__open"
(the <a matListItemMeta mat-icon-button ...> that navigates using [routerLink]
and calls handleClose()) needs an explicit accessible label; add an aria-label
(or [attr.aria-label] bound) to that anchor — e.g. a static "Open record" or a
dynamic label like `Open record for {{ referencedTable.table_name }}` or
including the referenced record id from
referencedRecords[referencedTable.table_name]?.links[i] — so screen readers get
a clear action name while preserving the existing routerLink, [queryParams], and
(click)="handleClose()".

}
}

@keyframes pullRefreshSpin {
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 | ⚡ Quick win

Rename keyframes to kebab-case to satisfy stylelint

Line 33, Line 510, and Line 519 use camelCase keyframe names, which violates the configured keyframe naming rule and can fail linting.

Suggested patch
-@keyframes pullRefreshSpin {
+@keyframes pull-refresh-spin {
@@
-	.pull-refresh-indicator__icon_spinning {
-		animation: pullRefreshSpin 700ms linear infinite;
+	.pull-refresh-indicator__icon_spinning {
+		animation: pull-refresh-spin 700ms linear infinite;
 	}
-@keyframes tableSheetSlideUp {
+@keyframes table-sheet-slide-up {
@@
-@keyframes tableSheetFadeIn {
+@keyframes table-sheet-fade-in {
@@
-.table-sheet-backdrop {
+.table-sheet-backdrop {
 	...
-	animation: tableSheetFadeIn 200ms ease-out;
+	animation: table-sheet-fade-in 200ms ease-out;
 }
@@
-.table-sheet {
+.table-sheet {
 	...
-	animation: tableSheetSlideUp 260ms cubic-bezier(0.2, 0.8, 0.2, 1);
+	animation: table-sheet-slide-up 260ms cubic-bezier(0.2, 0.8, 0.2, 1);
 }

Also applies to: 510-510, 519-519

🧰 Tools
🪛 Stylelint (17.12.0)

[error] 33-33: Expected keyframe name "pullRefreshSpin" to be kebab-case (keyframes-name-pattern)

(keyframes-name-pattern)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@frontend/src/app/components/dashboard/db-table-view/db-table-view.component.css`
at line 33, Rename the camelCase keyframe name pullRefreshSpin to a kebab-case
name (e.g., pull-refresh-spin) and update all usages accordingly; locate the
`@keyframes` declaration for pullRefreshSpin and change its identifier, then find
any animation, animation-name, or shorthand references (the occurrences
currently at the other two locations reported) and replace pullRefreshSpin with
the new kebab-case identifier so linting passes.

border-bottom-color: var(--mat-table-row-item-outline-color, rgba(0, 0, 0, 0.12));
border-bottom-width: var(--mat-table-row-item-outline-width, 1px);
border-bottom-style: solid;
grid-gap: 2px 12px;
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 | ⚡ Quick win

Replace deprecated grid-gap with gap

Line 1113 uses deprecated grid-gap; switch to gap to satisfy lint rules and modern CSS usage.

Suggested patch
-		grid-gap: 2px 12px;
+		gap: 2px 12px;
📝 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
grid-gap: 2px 12px;
gap: 2px 12px;
🧰 Tools
🪛 Stylelint (17.12.0)

[error] 1113-1113: Expected "grid-gap" to be "gap" (property-no-deprecated)

(property-no-deprecated)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@frontend/src/app/components/dashboard/db-table-view/db-table-view.component.css`
at line 1113, In db-table-view.component.css replace the deprecated grid-gap
property usage with the modern gap property (i.e., change the rule that
currently sets "grid-gap: 2px 12px;" to use "gap: 2px 12px;") so the CSS uses
current syntax and satisfies lint rules; update any identical occurrences of
grid-gap in the same file or component stylesheet (search for "grid-gap" to
locate all instances).

Comment on lines +44 to +81
<button *ngIf="savedFilterData.length !== 0"
mat-stroked-button type="button"
class="saved-filters-trigger"
[class.saved-filters-trigger_active]="selectedFilterSetId"
[matMenuTriggerFor]="filtersMenu">
<mat-icon fontSet="material-symbols-outlined" class="saved-filters-trigger__icon">tune</mat-icon>
<span class="saved-filters-trigger__label">
{{ savedFilterMap[selectedFilterSetId]?.name || 'Fast filters' }}
</span>
<mat-icon iconPositionEnd class="saved-filters-trigger__chevron">arrow_drop_down</mat-icon>
</button>

<mat-menu #filtersMenu="matMenu" class="saved-filters-menu">
<button mat-menu-item type="button"
*ngFor="let filter of savedFilterData"
[class.saved-filters-menu__item_active]="filter.id === selectedFilterSetId"
(click)="selectFiltersSet(filter.id)">
<mat-icon class="saved-filters-menu__check"
[class.saved-filters-menu__check_visible]="filter.id === selectedFilterSetId">check</mat-icon>
<span class="saved-filters-menu__name">{{ filter.name }}</span>
<span *ngIf="canEditConnection()"
class="saved-filters-menu__row-menu"
[matMenuTriggerFor]="filterMenu"
(click)="$event.stopPropagation(); setCurrentFilter(filter)">
<mat-icon>more_vert</mat-icon>
</span>
</button>

<button *ngIf="canEditConnection()"
mat-menu-item type="button"
class="saved-filters-menu__create"
angulartics2On="click"
angularticsAction="Saved filters: create new filter is clicked"
(click)="handleOpenSavedFiltersDialog(); posthog.capture('Saved filters: create new filter is clicked')">
<mat-icon>bookmark_add</mat-icon>
<span>New fast filter</span>
</button>
</mat-menu>
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion | 🟠 Major | 🏗️ Heavy lift

Use Angular built-in control flow in the new mobile menu block

The added mobile section still uses structural directives (*ngIf, *ngFor) in new code (Line 44, Line 58, Line 72). Please migrate these to @if/@for.

As per coding guidelines, "Use Angular 19's built-in control flow (@if, @for, @switch) instead of structural directives (*ngIf, *ngFor, *ngSwitch) in all new code".

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@frontend/src/app/components/dashboard/db-table-view/saved-filters-panel/saved-filters-panel.component.html`
around lines 44 - 81, Replace the new template usages of structural directives
with Angular 19 control-flow syntax: wrap the menu trigger block that currently
uses *ngIf="savedFilterData.length !== 0" in an <ng-container> using `@if` with
the same condition; change the *ngFor on the menu item to an <ng-container>
using `@for`="let filter of savedFilterData" (keeping the same bindings inside the
generated button), and replace the other *ngIf (canEditConnection()) with `@if` on
an <ng-container> so canEditConnection(), selectFiltersSet(filter.id),
setCurrentFilter(filter), selectedFilterSetId, savedFilterMap and
handleOpenSavedFiltersDialog() continue to be referenced unchanged; ensure you
stopPropagation() where you did before and preserve matMenuTriggerFor bindings
and classes.

Comment on lines +64 to +69
<span *ngIf="canEditConnection()"
class="saved-filters-menu__row-menu"
[matMenuTriggerFor]="filterMenu"
(click)="$event.stopPropagation(); setCurrentFilter(filter)">
<mat-icon>more_vert</mat-icon>
</span>
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 | ⚡ Quick win

Use a real button for the per-row menu trigger

Line 64-69 uses a clickable <span> as an action target. That’s not reliably keyboard-accessible and weakens semantics for assistive tech. Use a button (e.g., mat-icon-button) for this trigger.

Suggested patch
-                <span *ngIf="canEditConnection()"
-                    class="saved-filters-menu__row-menu"
-                    [matMenuTriggerFor]="filterMenu"
-                    (click)="$event.stopPropagation(); setCurrentFilter(filter)">
+                <button *ngIf="canEditConnection()"
+                    mat-icon-button
+                    type="button"
+                    class="saved-filters-menu__row-menu"
+                    aria-label="Filter options"
+                    [matMenuTriggerFor]="filterMenu"
+                    (click)="$event.stopPropagation(); setCurrentFilter(filter)">
                     <mat-icon>more_vert</mat-icon>
-                </span>
+                </button>
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@frontend/src/app/components/dashboard/db-table-view/saved-filters-panel/saved-filters-panel.component.html`
around lines 64 - 69, Replace the clickable <span> used as the per-row menu
trigger with a real <button> (e.g., mat-icon-button) to restore keyboard
accessibility and correct semantics: locate the template block that calls
canEditConnection() and uses [matMenuTriggerFor]="filterMenu" and
(click)="$event.stopPropagation(); setCurrentFilter(filter)" (the
saved-filters-menu__row-menu element) and change it to a button element, keep
the matMenuTriggerFor binding and the click handler (including stopPropagation
and setCurrentFilter(filter)), add type="button" and an appropriate aria-label,
and preserve the mat-icon and CSS class so styling/behavior remain the same.

Comment on lines +24 to +30
<a mat-icon-button class="row-edit-header__back"
routerLink="/dashboard/{{connectionID}}/{{tableName}}"
[queryParams]="backUrlParams"
matTooltip="Back to table"
data-testid="record-back-to-table-button">
<mat-icon>arrow_back</mat-icon>
</a>
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 | ⚡ Quick win

Add an accessible name to the icon-only back action.

The control is icon-only; add aria-label to ensure reliable screen-reader output.

Suggested fix
                 <a mat-icon-button class="row-edit-header__back"
+                    aria-label="Back to table"
                     routerLink="/dashboard/{{connectionID}}/{{tableName}}"
                     [queryParams]="backUrlParams"
                     matTooltip="Back to table"
📝 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
<a mat-icon-button class="row-edit-header__back"
routerLink="/dashboard/{{connectionID}}/{{tableName}}"
[queryParams]="backUrlParams"
matTooltip="Back to table"
data-testid="record-back-to-table-button">
<mat-icon>arrow_back</mat-icon>
</a>
<a mat-icon-button class="row-edit-header__back"
aria-label="Back to table"
routerLink="/dashboard/{{connectionID}}/{{tableName}}"
[queryParams]="backUrlParams"
matTooltip="Back to table"
data-testid="record-back-to-table-button">
<mat-icon>arrow_back</mat-icon>
</a>
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@frontend/src/app/components/db-table-row-edit/db-table-row-edit.component.html`
around lines 24 - 30, The back link element (anchor with class
"row-edit-header__back" and data-testid "record-back-to-table-button") is
icon-only and needs an accessible name; add an aria-label (e.g.,
aria-label="Back to table" or use a localized label) to the anchor so screen
readers announce its purpose, keeping the existing routerLink, [queryParams],
matTooltip and mat-icon intact.

Comment thread frontend/src/styles.scss
Comment on lines +118 to +120
--mdc-dialog-container-shape: 16px 16px 0 0;
max-height: 85vh;
padding-bottom: env(safe-area-inset-bottom, 0px);
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 | ⚡ Quick win

Add the blank line before max-height to satisfy Stylelint.

Stylelint reports declaration-empty-line-before at Line 119 because a declaration follows a custom-property declaration without a separating blank line. This may fail CI lint.

🎨 Proposed fix
     .mobile-bottom-sheet-dialog .mat-mdc-dialog-container {
         --mdc-dialog-container-shape: 16px 16px 0 0;
+
         max-height: 85vh;
         padding-bottom: env(safe-area-inset-bottom, 0px);
     }
📝 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
--mdc-dialog-container-shape: 16px 16px 0 0;
max-height: 85vh;
padding-bottom: env(safe-area-inset-bottom, 0px);
--mdc-dialog-container-shape: 16px 16px 0 0;
max-height: 85vh;
padding-bottom: env(safe-area-inset-bottom, 0px);
🧰 Tools
🪛 Stylelint (17.12.0)

[error] 119-119: Expected empty line before declaration (declaration-empty-line-before)

(declaration-empty-line-before)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/src/styles.scss` around lines 118 - 120, Insert a blank line between
the custom-property declaration --mdc-dialog-container-shape and the subsequent
declaration max-height to satisfy Stylelint's declaration-empty-line-before
rule; locate the rule block containing --mdc-dialog-container-shape, max-height,
and padding-bottom and add a single empty line before the max-height declaration
so the sequence is: --mdc-dialog-container-shape, (blank line), max-height,
padding-bottom.

Comment thread frontend/src/styles.scss
Comment on lines +167 to +174
@keyframes mobileBottomSheetSlideUp {
from {
transform: translateY(100%);
}
to {
transform: translateY(0);
}
}
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 | ⚡ Quick win

Rename keyframes to kebab-case and update the reference.

Stylelint reports keyframes-name-pattern at Line 167 — mobileBottomSheetSlideUp should be kebab-case. Remember to also update the animation reference at Line 114 so the animation still resolves.

🎨 Proposed fix
-        animation: mobileBottomSheetSlideUp 260ms cubic-bezier(0.2, 0.8, 0.2, 1);
+        animation: mobile-bottom-sheet-slide-up 260ms cubic-bezier(0.2, 0.8, 0.2, 1);
-@keyframes mobileBottomSheetSlideUp {
+@keyframes mobile-bottom-sheet-slide-up {
     from {
         transform: translateY(100%);
     }
     to {
         transform: translateY(0);
     }
 }
📝 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
@keyframes mobileBottomSheetSlideUp {
from {
transform: translateY(100%);
}
to {
transform: translateY(0);
}
}
`@keyframes` mobile-bottom-sheet-slide-up {
from {
transform: translateY(100%);
}
to {
transform: translateY(0);
}
}
🧰 Tools
🪛 Stylelint (17.12.0)

[error] 167-167: Expected keyframe name "mobileBottomSheetSlideUp" to be kebab-case (keyframes-name-pattern)

(keyframes-name-pattern)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/src/styles.scss` around lines 167 - 174, The keyframes identifier
mobileBottomSheetSlideUp must be renamed to kebab-case (e.g.,
mobile-bottom-sheet-slide-up) and every reference to it in the stylesheet
updated accordingly; specifically rename the `@keyframes` declaration name and
update any animation/animation-name/shorthand properties that currently
reference mobileBottomSheetSlideUp so they use the new kebab-case name (ensure
exact string match for shorthand usages).

@lyubov-voloshko lyubov-voloshko enabled auto-merge June 2, 2026 19:02
@lyubov-voloshko lyubov-voloshko merged commit 1bf3da0 into main Jun 2, 2026
11 of 15 checks passed
@lyubov-voloshko lyubov-voloshko deleted the mobile-menu-and-buttons-fixes branch June 2, 2026 19:05
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.

3 participants