Skip to main content

ImageViewer toolbar optimizations (DES-130)

Version: 0.3.1 · Type: 🐛 Bug Fix

Problem

The ImageViewer bottom toolbar had three areas for improvement:

  1. Navigation still shown for a single image: With a single image (or an empty list), the previous / next buttons were still rendered and merely grayed out — a meaningless placeholder for the user.
  2. Wrong cursor on disabled icons: When disabled at a boundary, hovering the icon area still showed a pointer cursor instead of not-allowed.
  3. Missing zoom accessibility: Zoom in / zoom out only had aria-label; zoom-level changes were not perceivable to screen readers.

Root Cause (Problem 2)

The button text color disabled:text-(--Labels-Disabled) itself worked (correctly inherited by the icon via currentColor, so the color was fine); the cursor failure was because the injected icon SVG carries its own cursor-pointer (e.g. design-site IconSvg's ICON_BASE_CLASS), whose selector overrode the button's disabled:cursor-not-allowed. Verified in a real browser: .btn:disabled svg { cursor: not-allowed } (specificity 0,2,1) can override the icon's .cursor-pointer (0,1,0).

Changed Files

  • packages/design/src/components/ImageViewer/ImageViewer.tsx
  • packages/design/src/components/ImageViewer/styles.ts
  • packages/design/src/components/ImageViewer/__tests__/ImageViewer.test.tsx
  • packages/design/src/components/ImageViewer/ImageViewerDesignSpec.md
  • packages/design-site/docs/components/patterns/image-viewer.mdx (Chinese i18n synced)

Changes

  • Hide navigation for a single image: Added a derived showNav = total > 1 state; the previous / next buttons and the divider after them are only rendered when there are multiple images. The single-image toolbar collapses to [zoom out] [zoom in] | [delete]* | [export] | [collapse].
  • Disabled icon cursor: IMAGE_VIEWER_TOOLBAR_BUTTON_CLASS now appends disabled:[&_svg]:cursor-not-allowed, explicitly setting the icon SVG cursor back to not-allowed in the disabled state without depending on the injected icon's implementation details.
  • Zoom accessibility: Added a visually-hidden region with role="status" and aria-live="polite" that announces the current percentage when zoom changes (Zoomed to 150%).
  • Keyboard zoom: handleKeyDown now handles + / = to zoom in and - to zoom out (previously it only handled / , so the keyboard could not zoom). zoomIn / zoomOut clamp at the boundaries themselves so they do not exceed limits; + / - with Cmd / Ctrl are let through and not intercepted, to avoid hijacking the browser's native page zoom (preserving page-zoom accessibility for low-vision users).
  • Added unit tests: navigation hidden for a single image / shown for multiple images, disabled buttons include disabled:[&_svg]:cursor-not-allowed, the zoom live region announces the percentage, and + / - with Cmd / Ctrl do not take over zoom.
  • Synced the "single image" section in DesignSpec and on the documentation site to "hide navigation", and added notes about zoom announcements and the disabled icon cursor.

Notes

  • pnpm test:run 1151 passing
  • pnpm lint (including tsc) passing

Linear: