Skip to content

feat: add color_name field to Filament — human-readable color name with nearest-neighbor RGB lookup#905

Open
hannut wants to merge 7 commits intoDonkie:masterfrom
hannut:feature/color-name
Open

feat: add color_name field to Filament — human-readable color name with nearest-neighbor RGB lookup#905
hannut wants to merge 7 commits intoDonkie:masterfrom
hannut:feature/color-name

Conversation

@hannut
Copy link
Copy Markdown

@hannut hannut commented Apr 5, 2026

This is a personal fork I run for my own use. Sharing it in case any of it is useful to merge upstream — feel free to take what you want or ignore the whole thing.

What's here

feature/color-name branch — 7 commits from master:

Backend

  • spoolman/color_names.py — a table of ~75 named colors (CSS + common filament shades) with nearest-neighbor Euclidean RGB lookup. Three functions: hex_to_color_name, color_name_to_hex, list_color_names.
  • Filament response now includes color_name — computed from color_hex via nearest-neighbor match, read-only.
  • FilamentParameters accepts color_name as input — resolved to color_hex on write. Validation error if unknown.
  • New endpoints: GET /filament/color-names, GET /filament/used-colors, GET /filament/color-map
  • color_name filter and sort on GET /filament and GET /spool — handled in Python after the SQL query since it's a computed field with no DB column.

Frontend

  • Color column in filament and spool lists: color swatch + name, filterable by colors present in the database, sortable.
  • Color name autocomplete in filament edit/create forms, populated from /filament/color-map. Selecting a name sets the color picker; changing the color picker updates the name field to the nearest match.
  • Color swatch moved from the Name column to a dedicated Color column.

Docker

  • Added a node-builder stage so the frontend is compiled from source instead of copied from the upstream image. Required for any fork that changes the frontend.

CI (fork-specific, not relevant upstream)

  • Gitea Actions workflow that builds and pushes to my self-hosted registry.

Notes

  • The color table is intentionally small and hand-curated. It's meant to give useful names to typical filament colors, not to be exhaustive.
  • color_name sorting and filtering is Python-side because SQLAlchemy can't sort on computed fields — the pattern is documented in the commit message.
  • All ideas are mine; implementation was done with heavy use of Claude Code.

hannut added 7 commits April 5, 2026 18:13
Adds spoolman/color_names.py — a self-contained color table of ~75 named
colors (CSS + common filament shades) with three helpers:

  hex_to_color_name(hex)  → nearest named color via Euclidean RGB distance
  color_name_to_hex(name) → exact hex for a given name (case-insensitive)
  list_color_names()      → sorted list of all accepted names
  color_map()             → {name: hex} dict for UI autocomplete
…terable

Response (read):
  Filament.color_name is populated by hex_to_color_name(color_hex) in
  Filament.from_db(). It is a derived field, not stored in the database.

Input (write):
  FilamentParameters accepts color_name; a @model_validator resolves it
  to color_hex via color_name_to_hex() before saving. Validation error if
  the name is unknown.

New endpoints:
  GET /filament/color-names   — list of all accepted color names
  GET /filament/used-colors   — distinct color names+hex in the database
  GET /filament/color-map     — {name: hex} dict for UI autocomplete

Filtering/sorting:
  GET /filament?color_name=   — comma-separated filter
  GET /spool?filament.color_name=  — same for spool list
  color_name is a computed field, so filtering and sorting are done in
  Python after the SQL query (all matching rows are fetched, sorted,
  then paginated in Python).
…ol lists

Filament list:
  - New Color column shows a 16×16 swatch next to the color name
  - Column is sortable (Python-side sort) and filterable via a dropdown
    that lists only colors actually present in the database, each with a swatch
  - Color swatch removed from the Name column (was cluttering it)

Spool list:
  - Same Color column added; filament.color_name is collapsed into the
    ISpoolCollapsed interface and the filter uses the same used-colors endpoint

Support:
  - TextColumn helper added to column.tsx (unsortable variant of SortedColumn)
  - useSpoolmanUsedColorNames and useSpoolmanColorNames hooks added to
    otherModels.tsx (fetch from /filament/used-colors and /filament/color-names)
  - IFilament interface extended with color_name?: string
  - Filament detail view shows color_name below the hex swatch
Both edit.tsx and create.tsx get:
  - A color_name AutoComplete field below the color picker, populated from
    GET /filament/color-map (loads once on mount)
  - Each option shows a 16×16 swatch next to the name
  - Selecting a name sets color_hex on the form (name → hex)
  - Changing the color picker updates color_name to the nearest match (hex → name)
    using the same Euclidean RGB distance calculation done server-side
…ream image

Upstream copies client/dist from ghcr.io/donkie/spoolman:latest, which means
forks cannot include frontend changes without a custom build step.

This adds a node-builder stage (Node 20) that:
  1. Copies package.json, package-lock.json, and .npmrc (needed for legacy-peer-deps)
  2. Runs npm ci
  3. Writes VITE_APIURL=/api/v1 to .env.production
  4. Runs npm run build

The python-runner stage then copies /build/dist from node-builder instead of
from a pre-built image.
Fork-specific: builds and pushes to a self-hosted Gitea registry on push
to the hannu branch. Derives the registry hostname from GITHUB_SERVER_URL
(strips https://) — no server-specific values hardcoded. Uses
REGISTRY_TOKEN secret and github.repository_owner for login.

Not intended for upstream — included for completeness of the fork history.
Adds a notice at the top of the README explaining:
  - Why this fork exists (human-readable color names feature)
  - What was changed (color_name API field + UI, Docker build from source)
  - That all ideas are the author's own but implementation used Claude Code
    (Anthropic's AI assistant) extensively
  - That the feature/color-name branch has clean, cherry-pickable commits
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant