Skip to content

feat: place icons — picker UI and rendering #2

@MarkCesium

Description

@MarkCesium

Context

Replace the current colored-initial placeholder (PlaceAvatar) with real user-selectable icons. Backend support tracked in PlaceBrain/contracts#1, PlaceBrain/places#1, PlaceBrain/gateway#2. This issue is the frontend half.

Design decisions (from earlier discussion)

  • Curated Lucide icon preset (~24 keys): `home`, `building`, `warehouse`, `factory`, `tent`, `tree-pine`, `wrench`, `server`, `store`, `school`, `church`, `hotel`, `hospital`, `landmark`, `mountain`, `ship`, `plane`, `train`, `trees`, `sun`, `moon`, `flame`, `snowflake`, `leaf`. Kept in `src/entities/place/model/icons.ts`.
  • Palette of ~8 color keys matching the existing `--color-avatar-N-bg` / `--color-avatar-N-fg` variables in `src/app/styles/variables.css`. Stored as palette key, not hex — see contracts#1 rationale.
  • Fallback to the existing `PlaceAvatar` (colored initial) when `icon` is null on the place.

Changes

  • Extend `src/entities/place/model/types.ts` with optional `icon: string | null` and `icon_color: string | null`.
  • Update `useCreatePlace` / `useUpdatePlace` payloads in `src/entities/place/api/place.api.ts`.
  • New `src/entities/place/ui/PlaceIcon.vue` — renders the Lucide icon if set; otherwise falls back to ``. Props: `place`, `size` (sm | md | lg, matching `PlaceAvatar`).
  • Replace `` usages in the sidebar (`src/widgets/sidebar/ui/SidebarPlacesList.vue`) and wherever the avatar is shown — keep `PlaceAvatar` as the fallback internal to `PlaceIcon`.
  • New `src/features/place-icon-picker/PlaceIconPicker.vue`: grid of icons (+ a 'no icon' option) + palette swatches + preview via ``.
  • Embed the picker in `CreatePlaceModal` and `EditPlaceModal`.
  • All icons in the picker and in rendered rows must have `shrink-0` so flex layout does not squish them in narrow containers (see `frontend/CLAUDE.md`).

Acceptance

  • User can pick, change, or clear an icon on a place.
  • Sidebar, place detail header, and `PlaceCardGrid` all show the chosen icon.
  • Light and dark themes render icon colors through CSS variables, no hardcoded Tailwind palette classes.
  • `npx vue-tsc -b`, lint, format clean.

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions