{"slug":"badge-soup","meta":{"title":"Badge Soup","slug":"badge-soup","kind":"anti-pattern","summary":"Every attribute rendered as its own coloured pill, so the row is a wall of chips and colour has stopped separating anything.","problem":"A row carries six badges in five hues at the same saturation, and two of the hues mean two different things each. Under a squint test the table is confetti; the badge that means \"a human must act\" looks exactly like the one that means \"annual plan\".","family":["scan"],"principles":["progressive-disclosure","consistency"],"status":"stable","visibility":"public","related":[{"title":"Color, Icons, and Contrast","url":"/cookbook/color-icons-and-contrast","summary":"The authority on the colour budget this violates, with the contrast floors."},{"title":"Lifecycle Status","url":"/patterns/lifecycle-status","summary":"The usual fix — one named state instead of six independent chips."}]},"body":"## How you get here\n\nA badge is the cheapest way to put a fact on a row, and it looks deliberate. So\nevery attribute that someone wants visible becomes a badge, and every badge\nwants its own colour so it can be told apart from the others.\n\nThe tipping point is unremarkable. Three badges is a row. Six is soup, and it\nhappens one reasonable request at a time.\n\n## How to recognise it\n\n- More than about three chips on one row or card.\n- Two badges that mean different kinds of thing — a lifecycle state and a\n  billing plan — rendered identically.\n- The same hue used for two meanings anywhere in the product. Purple for\n  \"draft\" in one place and \"re-opened\" in another is the documented example\n  from our own ticket page.\n- Every badge at the same saturation, so nothing is louder than anything else.\n- Squinting turns the list into confetti rather than showing you where to look.\n\n## Why it fails\n\nColour is **preattentive**: the eye spends it before you read a word. That makes\nit powerful and strictly limited. The budget is roughly three semantic colours\nplus neutrals, each with exactly one meaning.\n\nSix hues do not give six channels of information. They give **zero**, because\nthe reader cannot hold the mapping, so they stop trying and read the text\ninstead — at which point every badge is a slower version of a word.\n\nThere is a second failure underneath. Most of what becomes a badge is not a\nstatus at all. \"Annual plan\" and \"EU region\" are attributes. Rendering an\nattribute with the same visual weight as \"needs a human\" asserts they are the\nsame kind of fact, and they are not.\n\n## The way out\n\n1. **Decide what the row is for**, and keep the one or two facts that change\n   what someone does. The rest belong on the record.\n2. **Neutral by default.** Grey chips for everything informational. That alone\n   fixes most of it.\n3. **Spend colour on exceptions only**, at most three meanings — amber for\n   needs-a-human, rose for broken, emerald for a positive delta — and never let\n   a hue carry two meanings.\n4. **Encode roles with structure, not hue.** Position, indentation and grouping\n   show what things are; colour shows what needs attention.\n5. **Back every colour with a word or an icon**, so the row still reads in\n   greyscale.\n\n## The test\n\nBlur your eyes, or shrink the browser to 25%. A good list shows a few points of\ncolour where attention is needed and grey everywhere else. Badge soup looks\nlike a bag of sweets, and in that state the urgent row is genuinely no easier to\nfind than the routine one — which is the whole cost.\n"}