# Driftwood UI/UX Overhaul Design ## Context Driftwood is a GTK4/libadwaita AppImage manager. The current UI is functional but visually plain - cards look like basic boxes, the list view resembles a settings page, and the detail view is a wall of ActionRows with no hierarchy. This design overhauls all three views plus adds a right-click context menu to make Driftwood feel like a first-class GNOME app. ## Design Principles - Use libadwaita's built-in style classes wherever possible instead of custom CSS - Follow GNOME HIG spacing (6px grid, 12px padding baseline, 14px grid gaps) - Only show the most important information at each level (card -> list -> detail = progressive disclosure) - Actions belong in context menus and detail headers, not crammed into cards --- ## 1. Card View (Grid) ### Current State - 180px wide cards with 64px icons - All badges shown (Wayland, FUSE, Update, Integration) - Custom `.app-card` CSS duplicating libadwaita's `.card` behavior - FlowBox allows up to 6 columns (cards get too small) ### New Design ``` +----------------------------------+ | | | [72px icon] | | (icon-dropshadow) | | | | App Name | | (.title-3) | | | | 1.2.3 - 45 MiB | | (.caption .dimmed .numeric) | | | | [single most important badge] | +----------------------------------+ 200px wide, 14px internal padding ``` ### Changes - **Card width: 200px** (from 180px) for better breathing room - **Icon size: 72px** (from 64px) with `.icon-dropshadow` class - **App name: `.title-3`** (from `.heading`) for more visual weight - **Version + size on one combined line** using `.caption .dimmed .numeric` - **Single badge only** - show the most important status using priority: Update > FUSE issue > Wayland issue. Integration is already shown via the icon corner emblem - **Replace custom `.app-card` CSS with libadwaita `.card` + `.activatable`** - native hover, active, dark mode, and contrast states for free - **FlowBox max 4 columns** (from 6) so cards stay readable - **14px row and column spacing** (matching GNOME Software) - **Right-click context menu** on each card (see Section 5) ### Files Modified - `src/ui/app_card.rs` - card construction, badge logic, CSS classes - `data/resources/style.css` - remove `.app-card` rules, add new sizing - `src/ui/library_view.rs` - FlowBox max_children_per_line, context menu wiring --- ## 2. List View ### Current State - 40px icons, standard ActionRow - Subtitle mashes version + size + description into one hyphenated string - All badges shown in a suffix box - Standard ListBox (no `.rich-list`) ### New Design ``` +--[48px icon]--+--Title--------------------------+--[badge]--[>]--+ | (rounded | App Name | | | 8px clip) | Description or path (.dimmed) | [Update] | | | 1.2.3 - 45 MiB (.caption) | | +---------------+----------------------------------+---------------+ ``` ### Changes - **Icon size: 48px** (from 40px) with `border-radius: 8px` and `overflow: hidden` for rounded clipping - **Subtitle structured as two lines:** - Line 1: Description snippet or file path (dimmed) - Line 2: Version + size (caption, dimmed, numeric) - Use `subtitle-lines(2)` on ActionRow to allow the two-line subtitle - **`.rich-list` style class** on the ListBox for taller rows - **Single badge suffix** - same priority logic as cards - **Remove integration badge from suffix** - redundant with icon emblem - **Right-click context menu** - same menu as card view - **Navigate arrow stays** as rightmost suffix ### Files Modified - `src/ui/library_view.rs` - list row construction, ListBox class, context menu - `data/resources/style.css` - icon rounding class --- ## 3. Detail View (Tabbed) ### Current State - 64px icon in banner - Single scrolling page with 3 PreferencesGroups - 20+ rows all visible at once - No visual hierarchy between sections ### New Design ``` +--[< back]------- App Name --------[Update][Launch]--+ | | | +--[96px icon]---+ App Name (.title-1) | | | (icon- | 1.2.3 - x86_64 (.dimmed) | | | dropshadow) | Short description (.body) | | +----------------+ [Integrated] [Native Wayland] | | | | +---[Overview]--[System]--[Security]--[Storage]--+ | | | | | | | (active tab content below) | | | | | | | + + | +------------------------------------------------------+ ``` ### Hero Banner - **96px icon** (from 64px) with `.icon-dropshadow` - **App name in `.title-1`** (stays as-is) - **Subtle gradient background:** `linear-gradient(to bottom, alpha(@accent_bg_color, 0.08), transparent)` behind the banner area - **Key badges inline** (stays as-is) ### Tab System - **`adw::ViewStack`** contains four pages - **`adw::ViewSwitcher`** with `.inline` style, placed between the banner and tab content (not in the header bar) - Header bar stays clean with just back button, app name title, Update button, Launch button ### Tab 1: Overview (default) Shows the most commonly needed information at a glance. - Update method (update type or "no automatic updates") - Update status (available/up-to-date) with version info - Last checked date - Total launches + last launched - AppImage type + executable status - File path with copy + open folder buttons - First seen / last scanned dates - Notes (if any) ### Tab 2: System All system integration and compatibility information. - Desktop integration switch - Desktop file path (if integrated) - Wayland compatibility row + badge - Analyze toolkit button - Runtime display protocol (if available) - FUSE status + badge - Launch method - Firejail sandbox switch + install hint ### Tab 3: Security Vulnerability scanning and integrity. - Bundled libraries count - Vulnerability summary with severity badge - Scan button (with busy state) - SHA256 checksum with copy button ### Tab 4: Storage Disk usage and data discovery. - AppImage file size - Total disk footprint (if discovered) - Discover data paths button - Individual discovered paths with type icons, confidence badges, sizes ### Files Modified - `src/ui/detail_view.rs` - major restructure: banner upgrade, ViewStack/ViewSwitcher, redistribute rows across 4 tab pages - `data/resources/style.css` - banner gradient, ViewSwitcher positioning --- ## 4. CSS & Visual Polish ### Remove - `.app-card` and `.app-card:hover` and `.app-card:active` rules (replaced by libadwaita `.card`) - Dark mode `.app-card` overrides (handled by `.card` automatically) - High contrast `.app-card` overrides (handled by `.card` automatically) ### Add ```css /* Rounded icon clipping for list view */ .icon-rounded { border-radius: 8px; overflow: hidden; } /* Detail banner gradient wash */ .detail-banner { padding: 18px 0; background-image: linear-gradient( to bottom, alpha(@accent_bg_color, 0.08), transparent ); border-radius: 12px; margin-bottom: 6px; } ``` ### Keep (unchanged) - All status badge styling - Integration emblem styling - Letter-circle fallback icons - All WCAG AAA styles (focus indicators, high contrast, reduced motion, target sizes) - Compatibility warning banner - Quick action pill styling ### Style Classes Used (libadwaita built-in) - `.card` + `.activatable` on FlowBoxChild card boxes - `.icon-dropshadow` on icons 48px+ - `.rich-list` on list view ListBox - `.numeric` on version/size labels - `.title-3` on card app names - `.inline` on the detail ViewSwitcher - `.property` on key-value ActionRows where subtitle is the main content (path, SHA256) --- ## 5. Right-Click Context Menu ### Design A `GtkPopoverMenu` built from a `gio::Menu` model, attached to each FlowBoxChild (card) and ListBox row. Triggered by secondary click (button 3) or long-press on touch. ``` +---------------------------+ | Launch | +---------------------------+ | Check for Updates | | Scan for Vulnerabilities | +---------------------------+ | Integrate / Remove | | Open Containing Folder | +---------------------------+ | Copy Path | +---------------------------+ ``` ### Menu Items | Label | Action | Notes | |-------|--------|-------| | Launch | `app.launch-appimage(id)` | Launches the AppImage | | Check for Updates | `app.check-update(id)` | Triggers update check, shows toast with result | | Scan for Vulnerabilities | `app.scan-security(id)` | Triggers security scan, shows toast | | Integrate / Remove Integration | `app.toggle-integration(id)` | Label changes based on current state | | Open Containing Folder | `app.open-folder(id)` | Opens file manager to the directory | | Copy Path | `app.copy-path(id)` | Copies full path, shows toast | ### Implementation Approach - Define actions at the window level with the record ID as parameter - Build a `gio::Menu` with sections (separators between groups) - Attach `GtkPopoverMenu` to each card/row - Wire `GtkGestureClick` for button 3 (right-click) and `GtkGestureLongPress` for touch - Update the "Integrate/Remove" label dynamically based on `record.integrated` ### Files Modified - `src/window.rs` - define parameterized actions - `src/ui/library_view.rs` - create menu model, attach to cards and rows - `src/ui/app_card.rs` - gesture attachment on FlowBoxChild --- ## 6. Files Modified Summary | File | Changes | |------|---------| | `src/ui/app_card.rs` | 72px icon, .title-3 name, single badge, .card class, gesture for context menu | | `src/ui/library_view.rs` | FlowBox max 4 cols, .rich-list on ListBox, list row restructure, context menu creation and attachment | | `src/ui/detail_view.rs` | 96px icon, ViewStack/ViewSwitcher tabs, redistribute rows into 4 tab pages, banner gradient | | `src/window.rs` | Parameterized actions for context menu (launch, update, scan, integrate, open-folder, copy-path) | | `data/resources/style.css` | Remove .app-card rules, add .icon-rounded, update .detail-banner with gradient, keep all WCAG styles | | `src/ui/widgets.rs` | Minor - ensure icon helper supports .icon-dropshadow | ## Verification After implementation: 1. `cargo build` - zero errors, zero warnings 2. `cargo test` - all 128+ tests pass 3. Visual verification of all three views in light + dark mode 4. Right-click context menu works on cards and list rows 5. Detail view tabs switch correctly, content is correctly distributed 6. Keyboard navigation: Tab through cards, Enter to open, Escape to go back 7. All WCAG AAA compliance preserved