docs(quick-12): Add favorite icon to album grid track list dropdown
This commit is contained in:
@@ -0,0 +1,177 @@
|
||||
---
|
||||
phase: quick-12
|
||||
plan: 12
|
||||
type: execute
|
||||
wave: 1
|
||||
depends_on: []
|
||||
files_modified:
|
||||
- frontend/src/components/cover-grid/album-dropdown.ts
|
||||
autonomous: true
|
||||
requirements: []
|
||||
---
|
||||
|
||||
<objective>
|
||||
Add a favorite (heart/star) icon to each track row in the album grid dropdown (`<album-dropdown>`), matching the existing pattern from `<track-list>`.
|
||||
|
||||
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.
|
||||
</objective>
|
||||
|
||||
<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>
|
||||
|
||||
<context>
|
||||
@.planning/STATE.md
|
||||
@frontend/src/components/cover-grid/album-dropdown.ts
|
||||
@frontend/src/store/controllers/favorites-controller.ts
|
||||
|
||||
<interfaces>
|
||||
<!-- Existing pattern from track-list.ts to replicate -->
|
||||
|
||||
From frontend/src/store/controllers/favorites-controller.ts:
|
||||
```typescript
|
||||
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:
|
||||
```typescript
|
||||
// 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):
|
||||
```css
|
||||
.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; }
|
||||
```
|
||||
</interfaces>
|
||||
</context>
|
||||
|
||||
<tasks>
|
||||
|
||||
<task type="auto">
|
||||
<name>Task 1: Add favorite icon to album dropdown track rows</name>
|
||||
<files>frontend/src/components/cover-grid/album-dropdown.ts</files>
|
||||
<action>
|
||||
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):
|
||||
```typescript
|
||||
private favCtrl = new FavoritesController(this);
|
||||
```
|
||||
|
||||
3. **Add CSS** for `.fav-icon` inside the existing `static override styles = css\`...\`` block, after the `.track-duration` rule. Use a compact sizing appropriate for the 12px font dropdown (use `width: 18px` instead of track-list's `24px`, and `font-size: 11px` to be proportional to the 12px track rows):
|
||||
```css
|
||||
.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:
|
||||
```typescript
|
||||
const isFav = this.favCtrl.isFavorited(track.FilePath);
|
||||
const favVariant = isFav ? 'solid' : 'regular';
|
||||
```
|
||||
Insert after `<span class="track-number">` and before `<span class="track-title">`:
|
||||
```html
|
||||
<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.
|
||||
</action>
|
||||
<verify>
|
||||
Run: `cd frontend && npx tsc --noEmit`
|
||||
Verify: TypeScript compilation passes with no errors in album-dropdown.ts.
|
||||
</verify>
|
||||
<done>
|
||||
- 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)
|
||||
</done>
|
||||
</task>
|
||||
|
||||
</tasks>
|
||||
|
||||
<verification>
|
||||
`cd frontend && npx tsc --noEmit` — full TypeScript check passes
|
||||
</verification>
|
||||
|
||||
<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>
|
||||
|
||||
<output>
|
||||
After completion, create `.planning/quick/12-add-favorite-icon-to-album-grid-track-li/12-SUMMARY.md`
|
||||
</output>
|
||||
Reference in New Issue
Block a user