Give every tag a colour and an icon, drawn wherever the tag is #285
Labels
No labels
accessibility
authentication
breaking change
bug
documentation
enhancement
interface
internationalisation
observability
security
tier
1
tier
2
tier
3
tier/4
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
Postulo/postulo#285
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
What is wrong today
A tag has had a
colourfield since the beginning (core/models.py,Tag.colour, "A hint for the interface, such as “amber” or “sky”") and the tag form offers it, so a person types a colour, saves it, and nothing anywhere draws it: the detail page, the board card, the table row, the filters and the tags list all render every tag as the same grey pill (bg-ink-100 text-ink-600). The field is a promise the interface never kept, and free text besides, so "amber", "Amber", "orange-ish" and "#f59e0b" are all accepted and all mean nothing.A tag is the one thing in the application a person invents for themselves — the model says so, deliberately free-form — and on a board of forty cards it is the fastest way to tell "remote" from "relocation" from "referral". Forty identical grey pills do not do that job; a person reads each one.
What to do
Every tag gets a colour and an icon, chosen from fixed sets, and both are drawn wherever the tag is.
tag-grey,tag-blue,tag-amber,tag-violet,tag-teal,assets/css/app.cssaround line 376) plus a few more, each pair tuned to 3:1 against the card in both themes as those were. A migration maps what people typed to the nearest name where it is one, and to grey where it is not.greystays the default for a tag made from the API or from a bulk action, so an unstyled tag looks as it does today.home(remote),map-pin(relocation),users(referral),star,flag,clock,heart,briefcase,graduation-cap,banknote,globe,shield… — added toassets/icons.txtand synced like the rest. Blank means no icon, and blank stays the default.icon + wordin one colour, through one component (<c-tag>, since #263 made that the shape) so the six places that render a tag today render it once:application_detail.html,partials/application_card.html,partials/application_row.html(twice),tag_list.html, and the chips in the filters and the intake form. The word is always there, so colour and icon are second signals and never the only one — the rule #274 set for every cue in the interface, and the same rulepartials/plugin_tags.htmlalready states for the plugin pills. Forced colours (#277) keep the border and the icon and drop the fill, which is fine because the word is what carries the meaning.ApplicationDetailsIn.tags,ApplicationOut.tags), because that is what an extension or a script means by a tag; a tag made through the API is grey and iconless until somebody dresses it. Whether the tag list endpoint should carry colour and icon is a small separate question — probably yes, read-only, so a client can draw them the same way.What it is not
Not a colour picker. A free hex value would need a contrast check per tag per theme, would break under forced colours in a way a fixed palette does not, and would give a person a decision they did not ask for. Not emoji either: the record is printed on a CV's cover page nowhere, but the board is screen-read, and an emoji reads as its Unicode name where a lucide icon is
aria-hiddenbeside the word it decorates.Where it touches
core/models.py(Tag), a migration,applications/forms.py(TagForm),templates/cotton/tag.html(new) and the six templates above,assets/css/app.css(the tag palette),assets/icons.txt,core/export.pyandcore/importer.py, the tests around tags and the accessibility contrast test (tests/test_contrast.py) for the new pairs, plus the browser walk, which visits the tag form and list already.Classification
Enhancement, interface. Depends on nothing; #263 made the component the natural shape and #274/#277 set the rules it has to obey.