UI design - HULKs/labello GitHub Wiki

Labello UI and design guidelines

Use these criteria for shared UI changes. UI implementation defines state and async boundaries; annotation and review explains the user workflow.

Product rules

Use the product glossary for every application-provided action and concept. Reuse catalog labels in visible and accessible text. Context may qualify a term; compact synonyms must be listed in the glossary.

  • Keep the image and current task central. The canvas stays dark, low-noise, and shadow-free; metadata and secondary panels yield space first.
  • Build hierarchy with typography and spacing. Use teal for primary intent, amber for attention, and elevation only for floating content.
  • Reuse semantic tokens, typography, geometry, and helpers from crates/labello-ui/src/theme.rs. Do not add local styling when an existing intent covers it.
  • Use primary, standard secondary, quiet, and danger actions. A region normally has one primary action. Preserve native hover, press, focus, open, selected, and disabled states instead of applying direct fills.
  • Embedded button shortcuts use theme::button_shortcut so their foreground follows the button's visual state. Semantic helpers and selected placement buttons use the shared button renderer, which scopes weak-text styling and disabled opacity to that button and restores the surrounding style. Disabled buttons retain disabled semantics and a faded appearance with enough text contrast; supporting text keeps the normal weak-text token. Danger button labels use the readable text foreground, with danger conveyed by fill/stroke.
  • Use standard egui controls. Add a shared helper only for a repeated Labello-specific pattern. Add no theme, icon set, widget library, table dependency, or screenshot framework without a concrete unmet need.
  • Create hierarchy before adding borders or cards. Avoid nested cards and shadows on ordinary content.
  • Use sentence case and human labels. Use monospace for IDs, paths, dimensions, geometry, and aligned numbers.

Layout

  • Reuse LayoutMode: Compact below 600 points, Medium from 600 through 1287, and Wide from 1288. Heights below 480 points are short viewports.
  • Validate width and height together. Long content and larger text must not collapse siblings or push primary controls offscreen.
  • Keep global identity, dataset, navigation, status, and account controls in the app shell. The second bar owns image identity, workflow context and canvas controls. Dataset inspection keeps image names beneath the navigator thumbnails and uses the second bar only for canvas navigation and panel controls. The bottom bar owns workflow commands in every layout, including annotation, review, correction and every migration phase.
  • When every global destination, action, and account element cannot fit in the app bar, replace all of them with one modal left-drawer trigger. The drawer owns its dismiss action, closes after navigation, and restores focus to its trigger when dismissed without navigation. In the collapsed header, keep the dataset pill in the space left after the navigation trigger, streak, connection dot, and workspace presence. Bound avatar overflow so it cannot consume the dataset's share; let the pill expand and retain its full name in a tooltip and accessible label. At very narrow effective widths such as 200% mobile browser zoom, move the streak into the drawer to preserve presence, connection, and navigation targets. Drawer destinations retain their wide-bar order. Utilities read Statistics, Settings, contextual Tutorial, Admin, then Setup, subject to access. Account identity and Sign out come last. Use aligned icon/label rows with shared selection and focus states. Inspect uses stacked image frames with landscape details in both the bar and drawer.
  • Collapsed navigation places its menu button on the left. Dataset pills use available space up to the natural text width plus padding; truncate only when the name does not fit.
  • The second bar measures progress and its controls before stacking. Keep six-point vertical frame padding at every width, including stacked compact bars. Use one control row when the summary fits between the edge panel toggles and canvas controls. Compact item progress uses 3 / 12; complete item/phase wording stays in the accessible description and tooltip. Use the shared task-type icon beside progress and workflow identity at every width; keep the full task-type name in the tooltip and accessible description. Keep workflow/type/class context and review attribution in the summary. Stack only when progress, attribution, or enlarged text needs more room; retain every control and its 44-point target. If the control group cannot fit between the panel toggles, put it beneath them. On short compact workspaces, use six-point outer canvas gutters vertically to retain image space.
  • Render each action once per layout. Keep primary work actions visible and move secondary actions to overflow when space is limited.
  • Wide work views use workflow, canvas, and inspector panes; Medium and Compact use center-left Workflow and center-right Inspector drawers. Workflow actions stay in the bottom bar at every width.
  • Use aligned rows or grids for desktop comparison. Use 44-point, touch-friendly cards and stacked fields on Compact layouts. Keep forms and pages bounded.
  • Truncate or wrap long content deliberately; expose the complete value by tooltip or accessibility text.
  • Dataset inspector filter menus use compact 32-point choices inside standard 44-point triggers. Workflow-type icons, class-color markers and status symbols support the full accessible choice names; truncated labels retain tooltips. Menus use the available viewport height instead of an arbitrary fixed height, and scroll only when their contents cannot fit. This density exception applies to the inspector's workflow, class and status choices. The Images and Overlays status menus share these triggers and icon rows; Overlays keeps independent selected states for each visible status.

State and safety

  • Each remote region shows one base state: initial loading, loaded, empty, initial failure with Retry, loaded while refreshing, or loaded and stale after refresh failure.
  • Keep loaded data visible during refresh. View-specific bars start blank with their layout space reserved. Within the same view and workflow, retain their last loaded contents during image navigation and disable retained controls. Loading feedback is visible only on initial view entry. Subsequent image loads retain the previous canvas and inspector at their normal opacity until the replacement is ready. Next/previous navigation must not dim the application or show a save spinner merely because assignment release shares a busy guard; routine background reads keep loaded data visible without refresh indicators. Never show zero placeholders after failure or present retained contents as newly loaded data. The global top bar stays visible and keeps its layout during loads. Inspect publishes replacement image pixels, identity and annotation state together, including refreshes of the same image. Failed replacements keep the previous coherent display with failure feedback and a retry action. Admin, Export, About and import status reads retain loaded content without refresh spinners; explicit saves, model checks, uploads, imports and exports still show operation progress.
  • Put validation and failures in the affected field, section, or page. Reserve global notices for cross-screen events.
  • Hide account-scoped content while authentication is unresolved. Clear stale state when endpoint or session identity changes, and ignore responses owned by obsolete requests, workspaces, or datasets.
  • Keep drafts transactional. Failed saves leave drafts editable. Block navigation, dataset changes, and sign-out until staged edits are saved or explicitly discarded.
  • Roll back loading ownership when work cannot be queued; local failure must not leave controls permanently busy.

Interaction and accessibility

  • Use native egui::Modal for blocking decisions. Only the highest-priority overlay is active; it blocks background input, and Escape reaches it first.
  • Constrain overlays to the viewport and keep decisions reachable by scrolling the whole surface on short screens. Blocking drawers follow the same rules.
  • In compact shortcut settings, place action labels above binding controls and wrap long bindings. Keep the save/cancel row at its content height.
  • Popup menus and drawers suppress workspace shortcuts. Consume captured keyboard events before other controls process them.
  • Use a danger action plus concise confirmation for destructive work. Never use double-click as confirmation.
  • Preserve 44-point targets, except for the inspector menu choices and compact saved-feedback disclosure specified here. Preserve visible focus, tooltips, associated field labels, and complete, contextual AccessKit names.
  • Expose selected, open, disabled, loading, and modal states semantically. Never rely on color alone; retain text, stroke, pattern, thickness, handle, or shape cues.
  • Match cursors to create, move, resize, pan, and disabled behavior. Keep gestures and shortcuts discoverable through controls or concise hints.
  • Pen-tip annotation must track movement before release and commit each action once, including when the browser also emits compatibility mouse or stylus touch events. Two-finger navigation must coexist with pen editing in either contact order. After pen detection, finger contacts on the canvas must not annotate, and pen drags over controls must not scroll their contents. Follow the stylus contract and physical procedure for cancellation, mixed input, and iPadOS Safari/Firefox acceptance. Desktop WebKit and Chromium pen emulation do not certify an iPad or Android device.

Measurable accessibility criteria

  • Normal text and text rendered into controls must have a contrast ratio of at least 4.5:1 against its background. Text at least 18 points, or at least 14 points and bold, may use 3:1.
  • Control boundaries, annotation handles, focus indicators, and meaningful non-text states must have at least 3:1 contrast against adjacent colors. Focus must remain visible on every interactive control and cannot be represented by color alone.
  • Browser zoom from 100% through 200% must preserve access to every primary action and all non-canvas content. Reflow may switch LayoutMode; it must not create page-level horizontal scrolling except for a deliberately scrollable data region.
  • Long labels and browser or OS text enlargement must wrap, truncate with an accessible full value, or expand their region without covering adjacent controls. A clipped visual label still requires a complete accessible name.
  • Keyboard-only users must be able to sign in, choose a dataset and task, claim and release work, create/edit/delete annotations, submit or skip an assignment, complete review decisions, edit and save administration forms, operate import decisions, open settings/help, and dismiss or confirm every modal. Canvas-only spatial placement may require a pointer, but all surrounding commands and any non-spatial alternative must remain keyboard reachable.
  • Tab order follows the visual and task order. Overlays trap focus while open, restore it to the invoking control when closed, and expose an accessible name and modal state. Escape closes only the highest-priority dismissible overlay.
  • Every icon-only action has a contextual accessible name and tooltip. Dynamic loading, error, selection, expanded, disabled, and completion states must be represented in the accessibility tree, not only painted.

Labello does not currently claim certification for a specific screen-reader/browser pair. AccessKit labels and the Chromium accessibility tree are the supported semantic verification surfaces. A release must not claim screen-reader support until its critical workflows have also been exercised with named browser, operating-system, and screen-reader versions and the result has been recorded.

Screen patterns

  • Login and setup: keep sign-in focused and hide methods until session discovery completes. Provide About without authentication and put endpoint editing in Advanced connection. Use a bounded sign-in column with the primary action before secondary navigation. Center the signed-out icon and name vertically in the app bar. Give the sole enabled login method primary emphasis; when both are enabled, keep local development secondary to GitHub. Collapse excess top spacing on short screens and scroll keyboard-focused actions into view. After sign-in, feature one valid next dataset action, list all datasets separately, and keep creation secondary. Use a home glyph for the setup navigation action while retaining its destination-based accessible name and tooltip. Keep the authenticated section selector visible in every Setup section, with About last. Each section owns its heading; do not repeat a dataset-specific welcome banner above unrelated sections. Signed-out secondary navigation also puts About last.
  • Workspace: keep the primary submit, save-and-advance, or confirm action at the bottom right in annotation, migration, and review, including compact layouts. Placed objects remain editable; expose placed-keypoint Visible/Occluded controls when allowed by the task. Migration overview uses canvas clicks to create and select objects; omit separate inspector Add missing object and Edit added object mode buttons. Preserve tested canvas geometry and gestures; keep Pan and Fit visible, with Refocus for review and migration. Omit explicit zoom buttons and percentage displays; keep configurable zoom actions and wheel, touchpad, and pinch instructions in Settings. Review opens each focused item for direct editing. Primary drag edits the item; modifier-drag and middle-drag remain available for panning. Omit the Pan button in review; place review phase near the canvas; prefer compact object summaries over coordinate-heavy labels. Show source images without a grid overlay in annotation, review, and migration canvases.
  • Image overlays: use filled circles for visible keypoints and hollow diamonds for occluded keypoints in saved annotations, active drafts, reviewer corrections, and migration. Not-present keypoints have no image marker or incident edge. Suggestions retain hollow markers and their prelabel color; visible suggestions use circles and occluded suggestions use diamonds. Ordinary bounding boxes use Labello annotation teal, including the active box outline and resize-handle outlines. Selection remains visible through the stronger outline, fill and white handle centers. Explicit review/migration warning and error styles retain their semantic colors; skeletons retain class colors. Use a single one-point contrasting halo on boxes, edges, keypoints, selection handles, and focus indicators. Choose black for light class colors and white for dark ones, keeping at least 4.5:1 between the color and its halo. Inspect legibility on light, dark, and textured images; this does not guarantee contrast against every image pixel. Keep context guides, drafts, and box suggestions dashed, with gaps wide enough to separate the outlined dashes. Give every dashed box corner a continuous L-shaped dash and distribute edge gaps evenly between corner dashes. For unfocused migration context boxes, scale dash length and gap with viewport zoom so both shrink when zooming out. Keep stroke width fixed in screen space. Expose keypoint names, states, and marker descriptions on the canvas's accessibility node without encoding image coordinates.
  • Review context: use the same exact-target projection in every layout. Identify workflow, class, geometry type, position, and persisted target version. Final checks say "Final check / Full image" and omit object-only fields; excluded migration targets use disposition versions. Actual edits show base version and unsaved input. Opening an item alone is not a correction. The passive second-bar summary leads with position or Image overview and the submission author's profile avatar. Inspector starts closed. The second bar places Workflow at its left edge and Inspector at its right edge, matching the sides where their panels open. Center the remaining summary and canvas controls between these toggles in both Annotation and Review. Annotation uses the same two-line hierarchy: current-image progress or phase, then annotation type and workflow/class. Image identity and dimensions remain available in hover and accessible details. Reuse cached avatars with initials or unknown-author fallback, and expose submitter identity in hover and accessible text. Size the summary to measured text/avatar width. Lead its second line with annotation type and truncate long workflow identity with full accessible details. The shell reserves their actual height. Same-view image loads retain the complete previous bar presentation, including control placement and summary dimensions. Identity, phase and actions update together when the next image is ready. First load and changes of view, workflow, dataset or account show blank reserved bars. Empty or failed loads discard retained presentation; preview failure remains separate from valid target context. Never pair old identity with a new phase. The global header keeps its navigation, utilities and layout during loads. The dataset inspector reserves its context row during initial gallery loading and retains fixed controls across image loads. On Compact, center the summary above a control row with Workflow at the left edge, canvas controls centered, and Inspector at the right edge. Apply this ordering to both Annotation and Review. Keep this region compact enough to retain usable canvas height on short screens. The passive summary is not a keyboard focus stop; Inspector receives focus back after its drawer closes. Keep Previous, Discard changes, and Skip reachable beside the current item's decision. Added migration objects also expose Remove item. Icon fallback retains full names/tooltips. Short empty states scroll. Use Approve for unchanged items and Submit correction for valid edits. Space and Y/N follow the same review flow. Reset requires another decision. Objects submits its correction immediately; Overview submits the image's corrections together. Navigation saves unfinished proposals without confirming them. Incomplete additions block submission. Failed requests preserve exact retry identity. Reviewed keypoints have no extra selection circle. Revisions keep a visible Revising indication in the identity line and distinguish effective decisions from staged replacements without a redundant notice. Previous follows retained item history across images; Skip saves partial work, releases the item and prefers another available item. Historical whole-image revisions retain their audited revisit/discard rules. Measure secondary actions with actual fonts, icons, and shortcuts. Show the longest prefix that fits, trying icons before overflow. Required controls wrap and remain visible. Moving a focused action to overflow transfers focus to its trigger without dispatch; menu labels/shortcuts stack and scroll. Compact availability feedback uses the truncatable identity line without displacing type/phase or adding a row. Short viewports retain identity, phase, and useful canvas height; migration bars remove spare padding.
  • Saved reasons: show only feedback matching the active image and workflow, independent of the workflow-change notice. Lead with the event and explanation at a four-point gap; keep the 44-point dismiss target beside the content so it cannot inflate that gap. Use eight-point grouping gaps, existing text roles and quiet borders. Keep workflow and status visible, then a 24-point avatar with the GitHub username immediately to its right. Reuse cached avatars and initials fallback; unavailable identity reads Unknown author. Align Additional info to the right of that same 24-point author row. Keep eight-point gaps above and below the row, without extra vertical button padding. When expanded, object IDs and UTC timestamps use the full content width below the row. The explanation itself never requires expansion. Show message counts at the bottom. Keep earlier/replaced feedback explicit and newest messages first. Wrap long explanations in a bounded scroll area; at short heights the event title opens full feedback in a bounded non-modal window. Use amber only for current rejection/exclusion feedback. Revisiting a completed review alone creates no notice. Dismissal applies to the opened context. Object and submission reason inputs retain their scope, validation and input-preservation behavior.
  • Skeleton outcomes: present Visible and Occluded as selected coordinate-placement modes with one concise dynamic instruction. Present Not present as a coordinate-free outcome for one optional keypoint. Keep whole-object exclusion in a separate, always-visible Exclude object section. Explain the keypoint-level versus object-level distinction there, and reserve danger styling for the final exclusion action.
  • Admin: use a shield icon beside Statistics in the app bar's right-side utility group, with a 44-point target, an Open admin accessible name, and a tooltip. Show it only when the existing Admin access check allows the view; keep a labeled Admin action in the collapsed drawer. Organize by Overview, People, Images, Schema, Automation, and Snapshots, and Export; preserve staged edits between destinations; use wide rows and compact cards; retain validation and role protections.
  • Statistics: use a bar-chart icon in the app bar's right-side utility group, with a 44-point target, an Open statistics accessible name, and a tooltip. Keep a labeled Statistics action in the collapsed navigation drawer. Open a statistics modal above the current workspace or Setup, including when no dataset has been opened. Place a bounded, keyboard-accessible Statistics for selector in the fixed modal header, offering individual authorized datasets and All accessible datasets. Scope selection preserves the work dataset and assignment. Group aggregate task/class breakdowns by source dataset; keep balance and scoring-focus information in individual dataset views. Opening, refreshing, and closing it preserve the assignment, image, draft, selection, canvas transform, and workspace epoch. Continue legitimate in-flight workflow results and expose recovery when ownership becomes invalid. Block background input, provide Close and Escape dismissal, restore focus to the invoking control, and constrain the content to a scrollable viewport. Refresh silently without a refresh button or routine update timestamp; retain loading, failure, and retry states. Keep real data visible during refresh, order columns by the workflow, align numeric comparisons, and expose an accessible value for every chart item. Lead with the full-width score podium and rankings, then Daily activity, dataset totals, assignment balance, task/class breakdowns, and throughput. Keep Score first in metric choices and its podium expanded on mobile. Put other highlights below Rankings in a disclosure; stack chart cards below 850 content points, retaining values, units, and empty states. Put the Leaderboard heading and Leaderboard/History graph switch on one row, with the period selector aligned right. Omit the visible Period label and date range caption; retain the selector's accessible name and UTC tooltip. Wrap these controls on narrow screens. Activity and rankings share the selected period. Provide a keyboard- and touch-operated Activity day selector and Previous/Next day buttons with visible counts, alongside calendar hover details. At enlarged browser zoom, stack the modal header controls. Compact rankings use a bounded sort picker, a 44-point direction button, and wrapping score-first summaries. Keep flame and day count beside each contributor. Keep history comparison controls below the metric choices and selected names in bounded rows. Show acceptance as a percentage with review counts. Show avatars beside names with initials fallback, and preserve keyboard access and full accessible names when truncating.

Verification

  • Read the complete interaction and async flow, reuse current patterns, and add the smallest egui_kittest regression for behavior, geometry, or AccessKit semantics. Include long content and failure states when relevant.
  • Inspect relevant states at 320x568, 390x844, 600x800, 1288x820, 1440x1000, and a short size such as 320x320. Exercise each applicable size at device pixel ratios 1 and 2; test 390x844 at DPR 3 for a high-density mobile case.
  • Repeat critical browser workflows at 200% browser zoom and with the platform's larger-text setting where Chromium exposes it. Record any unsupported platform behavior instead of silently reducing the test matrix.
  • Use native inspector presets for shared rendering and accessibility checks. Use Chromium for WASM startup, scaling, browser input, and desktop/mobile rendering and inspect the browser accessibility tree. The native inspector does not prove browser behavior, zoom reflow, or screen-reader output.
  • Run a keyboard-only pass for every changed critical workflow. For modal, focus, or semantic changes, record the initial focus, tab sequence, accessible name/state, Escape behavior, and restored focus.
  • Run focused UI tests, formatting, and Clippy. Run the WASM check and trunk build --release --locked when browser or shared rendering changes.

Build information and mismatch

Setup > About is reachable before and after sign-in. It separates Web app and Server identities, shows release tags with twelve-character source commits, and gives each row a complete accessible label and full-value tooltip. Missing release metadata is explicitly development; missing commits are unavailable. About uses a bounded content column and groups each component's release and commit together. Web app and Server appear side by side when space permits and stack at narrow widths. Copy build information is the primary action; server refresh or retry is secondary. Complete selectable text is available in a keyboard-accessible manual-copy disclosure that opens automatically when copying fails or is unavailable. Server loading, unavailable and retry states are local to About. Clipboard feedback is an accessible polite status and success requires the platform copy operation to succeed.

In the browser, a confirmed mismatch automatically prepares an update and reloads when current operations and browser draft writes have finished. About shows a polite status explaining preparation, pending work or storage, and failure. Failed or already-attempted recovery offers a 44-point Retry app update action alongside the build details. It rechecks server identity before retrying. These controls wrap within About's existing scrollable content at compact and short sizes.

Routine identity values stay in About. Only two complete differing release identities produce the persistent lower-right bottom-bar warning, Web app and server builds differ. Use the existing amber warning intent, a small warning icon and quiet button interaction/focus states, without a filled alert banner. The accessible action name also says it opens About. Keep its 44-point target and lower-right position in wide, medium, compact and short layouts; nearby future activity content must condense or reflow. Existing assignment transition confirmation and cancellation apply to this navigation.

Availability fallback feedback

Automatic selection shows a dismissible, nonmodal notice naming the destination and why it changed. Keep it visible across the following item load. It must not consume a confirmation shortcut or require acknowledgment. Use a 44-point close control and an accessible status label. Saved partial work and reservation cleanup follow the same path as explicit workflow switching.

Current workflow marker

The committed selected workflow has a small bright dot. A reason icon indicates restricted, checking, or unable-to-check states. Annotation and review activities center these cues together below the label. Available unselected workflows have no status cue. Pending candidates, hover and keyboard focus never acquire the dot.

Use line icons with short tooltips available on disabled cards and equivalent AccessKit descriptions on the existing workflow button. Markers add no focus stops or accessible names. Keep the selected fill/border and semantic selection. Every disabled workflow pass cell has a reason icon, including saving, session/dataset/image loading, sign-out, migration updates, transitions, modal blocks, assignment-resolution barriers, migration phases, and unavailable work. Saving precedes loading, migration updates, transitions and modal blocks, then activity-phase and availability restrictions. Same-view assignment release and reopen requests retain the loaded view at normal opacity and use a static transition reason on disabled workflows, without a false save or loading spinner. Background availability refreshes remain silent when they do not block interaction. Retained known restrictions remain visible during refresh. Unknown or failed availability alone never disables selection. A static segmented spinner avoids continuous animation. Specific server reasons require a supported workflow-wide result; mixed restrictions remain generic. Panel and drawer use the same renderer. The automatic workflow-change notice remains independent of these markers.

Measured workspace action buttons use the same state-dependent shortcut foreground both inline and in wrapped overflow menus. Moving an action into More changes only its placement; its shortcut contrast and accessible command identity remain the same.

Responsive workspace checks must also resize through the viewport matrix while running only requested frames. Compact action panels must settle without a later pointer or keyboard event; forced extra frames can conceal a cached-height gap.

Workspace presence

Presence belongs in the existing top header, with compact circular GitHub profile photos and a small semantic-color connection dot. Right-align the avatars and dot immediately before the navigation action icons. The signed-in account has no separate username label; qualifying active leases include it in presence. Navigation icons run right to left: Logout, Home/Setup, authorized Admin, shortcut settings, and statistics. Keep the dataset pill centered when space permits; with collapsed navigation it uses the remaining space beside bounded presence. Preserve one header row, primary action targets, canvas space and keyboard focus through resizing.

Avatars are 28 points inside a single focusable target at least 44 points high and wide. Show as many as fit, then +N for the remaining users. Missing, pending or failed photos use initials. The shared statistics/presence loader caches public GitHub photos and failures; it sends no browser credentials. Full @githubLogin handles and active datasets remain available on hover, activation and through the control's accessible name. Missing logins use the internal user ID in those details. Counts include the current user under the same active-lease rules. Avatars and initials stay static; the former text highlight is removed.

A successful empty sample reads "No active labellers". Keep the existing loading, temporary failure and unavailable states. Do not add a presence bar, daily-count footer, extra row or lease-duration explanation. Reserve a 44-point focusable target for the connection dot while painting only a 9-point circle. Color is accompanied by textual status in its accessible name and details.

Check one and many users, overflow, long handles and dataset names, missing and failed photos, initial loading, connection loss/recovery, saving/unsaved work, application errors, and keyboard activation.

Shortcut editor

Show that shortcuts apply to all datasets. Offer explicit selection of preserved legacy settings before the first global save. Group each shortcut category once. Match ordinary button vocabulary and expose context-dependent button names in searchable help. Keep current binding and reset controls visually separate from bounded, wrapping text; stack them below text when columns would crowd. Long key combinations must wrap without obscuring names or descriptions. Keep compact footer decisions adjacent rather than distributing them through the available height. Conflict feedback names the other action and workspace context, with a filter to locate the affected rows. Verify text/control non-intersection and scroll reachability as well as viewport containment.

Annotation and review class groups

Annotation and review workflow panels and drawers list workflows by class. Each class starts with a left-aligned 15-point heading followed by a thin rule; classes are separated by eight points, with no card frame. Each configured activity is one row with a 24-point type icon, an eight-point gap, and a 14-point label. Order activities top to bottom: bounding boxes, migration, then direct skeleton annotation. Omit unconfigured activities.

Objects and Overview are two right-aligned pass columns shared by every row, named once in a 12-point header above the scroll area. The header is omitted when no workflow is split. Cells are 64 points wide, six points apart, and at least 44 points tall. They contain no text: a muted ring marks an available pass, a filled dot marks the selected pass, and the existing reason icon marks a blocked pass. A selected blocked pass shows the dot beside the reason icon. Cells have no frame until hovered, focused or selected. Unsplit workflows work on the complete image and use only the Overview cell; their accessible name ends in Annotate or Review.

When one activity has several workflows, its icon and label form a heading row and each workflow follows as an indented row with its 13-point wrapped name and its own pass cells. Do not open a separate chooser. Review groups bounding-box and skeleton review workflows, including migrated skeletons, without exposing annotation migration actions. Show no explanatory text beside or beneath cells; reasons belong in state icons, tooltips, and accessible descriptions. Accessible names and tooltips carry the class, activity, workflow, and pass. Configured workflows that are temporarily blocked remain visible with a reason icon and state-only tooltip and accessible description. Do not present migration as active on images that support only direct skeleton annotation.

The selected marker follows the chosen task and Objects/Overview variant. Overview never skips prerequisite Objects work. Size both panels to the widest unwrapped class, activity or workflow name, between 240 and 360 logical points, cap drawers to the viewport, wrap class headings and retain complete accessible names. Focused pass cells scroll into view; long text must not widen the canvas. Closing a drawer restores keyboard focus to its trigger.

Rows use two-point vertical gaps. The seven HSLVision classes should fit a 1920 × 1080 desktop viewport without scrolling at default text size. Shorter screens and larger text retain scrolling. Availability failures retain a compact Retry availability button above the classes. A boosted annotation workflow has a soft amber glow and inner rim on each of its pass cells. A brief shimmer runs when the boost appears or the button receives hover or keyboard focus; it then settles to the persistent highlight. Reduced-motion and disabled controls keep the highlight static. Native selection, focus, and availability remain distinct. Tooltips and accessible descriptions identify the boosted workflow without a percentage, countdown, focus label, or footer. Expired or unreliable boost data removes the highlight.