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
Open
feat: add color_name field to Filament — human-readable color name with nearest-neighbor RGB lookup#905hannut wants to merge 7 commits intoDonkie:masterfrom
hannut wants to merge 7 commits intoDonkie:masterfrom
Conversation
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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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-namebranch — 7 commits frommaster: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.Filamentresponse now includescolor_name— computed fromcolor_hexvia nearest-neighbor match, read-only.FilamentParametersacceptscolor_nameas input — resolved tocolor_hexon write. Validation error if unknown.GET /filament/color-names,GET /filament/used-colors,GET /filament/color-mapcolor_namefilter and sort onGET /filamentandGET /spool— handled in Python after the SQL query since it's a computed field with no DB column.Frontend
/filament/color-map. Selecting a name sets the color picker; changing the color picker updates the name field to the nearest match.Docker
node-builderstage 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)
Notes
color_namesorting and filtering is Python-side because SQLAlchemy can't sort on computed fields — the pattern is documented in the commit message.