Files
yellowjacket/.planning/quick/12-add-favorite-icon-to-album-grid-track-li/12-PLAN.md
T

5.9 KiB

phase, plan, type, wave, depends_on, files_modified, autonomous, requirements
phase plan type wave depends_on files_modified autonomous requirements
quick-12 12 execute 1
frontend/src/components/cover-grid/album-dropdown.ts
true
Add a favorite (heart/star) icon to each track row in the album grid dropdown (``), matching the existing pattern from ``.

Purpose: Users can see at a glance which tracks are favorited and toggle favorites directly from the album dropdown, consistent with the track list view. Output: Updated album-dropdown.ts with per-track favorite icon.

<execution_context> @/home/caleb/.config/opencode/get-shit-done/workflows/execute-plan.md @/home/caleb/.config/opencode/get-shit-done/templates/summary.md </execution_context>

@.planning/STATE.md @frontend/src/components/cover-grid/album-dropdown.ts @frontend/src/store/controllers/favorites-controller.ts

From frontend/src/store/controllers/favorites-controller.ts:

export class FavoritesController implements ReactiveController {
    constructor(host: ReactiveControllerHost);
    isFavorited(filePath: string): boolean;
    get iconName(): string;  // returns 'heart' or 'star'
    toggleFavorite(filePath: string): Promise<void>;
}

Existing favorite icon pattern from track-list.ts:

// In the component class:
private favCtrl = new FavoritesController(this);

// In renderTrackRow():
const isFav = this.favCtrl.isFavorited(track.FilePath);
const favVariant = isFav ? 'solid' : 'regular';

// In the template, as the FIRST element in the track row:
<div
  class=${classMap({ 'fav-icon': true, favorited: isFav })}
  @click=${(e: MouseEvent) => {
      e.stopPropagation();
      void this.favCtrl.toggleFavorite(track.FilePath);
  }}
>
  <wa-icon
    name=${this.favCtrl.iconName}
    variant=${favVariant}
  ></wa-icon>
</div>

CSS for favorite icon (from track-list.ts):

.fav-icon {
  display: flex; align-items: center; justify-content: center;
  width: 24px; flex-shrink: 0; cursor: pointer;
  color: var(--yj-text-tertiary, #666);
  font-size: var(--yj-text-sm);
  transition: color 0.1s ease;
}
.fav-icon:hover { color: var(--yj-text-primary, #fff); }
.fav-icon.favorited { color: var(--yj-accent, #ffd43b); }
.fav-icon.favorited:hover { color: var(--yj-accent, #ffd43b); opacity: 0.8; }
Task 1: Add favorite icon to album dropdown track rows frontend/src/components/cover-grid/album-dropdown.ts Modify `album-dropdown.ts` to add a per-track favorite icon, following the exact pattern from `track-list.ts`:
  1. Add imports:

    • Import FavoritesController from @store/controllers/favorites-controller
    • Import classMap from lit/directives/class-map.js
  2. Add controller instance to the class body (next to the existing player controller):

    private favCtrl = new FavoritesController(this);
    
  3. Add CSS for .fav-icon inside the existing static override styles = css\...`block, after the.track-durationrule. Use a compact sizing appropriate for the 12px font dropdown (usewidth: 18pxinstead of track-list's24px, and font-size: 11px` to be proportional to the 12px track rows):

    .fav-icon {
        display: flex;
        align-items: center;
        justify-content: center;
        width: 18px;
        flex-shrink: 0;
        cursor: pointer;
        color: var(--yj-text-tertiary, #666);
        font-size: 11px;
        transition: color 0.1s ease;
    }
    .fav-icon:hover {
        color: var(--yj-text-primary, #fff);
    }
    .fav-icon.favorited {
        color: var(--yj-accent, #ffd43b);
    }
    .fav-icon.favorited:hover {
        color: var(--yj-accent, #ffd43b);
        opacity: 0.8;
    }
    
  4. Update renderTrackRow() to add the favorite icon BETWEEN the track number and the track title. Compute isFav and favVariant at the top of the method, then insert the icon element:

    const isFav = this.favCtrl.isFavorited(track.FilePath);
    const favVariant = isFav ? 'solid' : 'regular';
    

    Insert after <span class="track-number"> and before <span class="track-title">:

    <div
        class=${classMap({ 'fav-icon': true, favorited: isFav })}
        @click=${(e: MouseEvent) => {
            e.stopPropagation();
            void this.favCtrl.toggleFavorite(track.FilePath);
        }}
    >
        <wa-icon
            name=${this.favCtrl.iconName}
            variant=${favVariant}
        ></wa-icon>
    </div>
    

Important: The click handler MUST call e.stopPropagation() to prevent the track-row click handler from also firing when toggling favorites. Run: cd frontend && npx tsc --noEmit Verify: TypeScript compilation passes with no errors in album-dropdown.ts.

  • Album dropdown track rows display a heart/star icon (matching user's configured icon style) between the track number and title
  • Favorited tracks show the icon in accent color (solid variant)
  • Non-favorited tracks show a subtle tertiary-colored icon (regular variant)
  • Clicking the icon toggles the favorite state without triggering track selection
  • Icon reactively updates when favorite state changes (via FavoritesController subscription)
`cd frontend && npx tsc --noEmit` — full TypeScript check passes

<success_criteria>

  • Favorite icon visible in album dropdown track rows
  • Icon matches configured style (heart or star)
  • Favorited state reflected visually (solid + accent color vs regular + tertiary)
  • Click toggles favorite without selecting/playing track
  • No TypeScript errors </success_criteria>
After completion, create `.planning/quick/12-add-favorite-icon-to-album-grid-track-li/12-SUMMARY.md`