Chip / Tag
الشريحة<button> / role="option"
also calledtag، pill، filter chip، input chip، token، badge، شيب، تاج، وسم، شريحة تصفية، شريحة إدخال، كبسولة
A chip is a small capsule-shaped control carrying exactly one value: a keyword, a filter, a recipient. What makes it a chip is that it is interactive: pressing it changes state on the page, applying a filter, selecting itself, or dropping out of a list. If pressing it does nothing, it is not a chip, whatever shape it wears. A tag or label looks identical but is static metadata you read rather than press, so it belongs in a <span> and not a <button>; wrapping it in a button makes a screen reader announce clickable things that do nothing. A badge is not a standalone component at all: it is a count or a status glued onto another element (an icon, a tab, a button) that describes that element, and the user never interacts with it on its own. A pill is not a component in any sense either: the word names a shape, a radius equal to half the height, and a button, a tag, or a chip can all wear it. Shape does not decide the name; behaviour does.
If you called it…
Live specimen
Interact with the demo. Every part is real and numbered.
تصفية النتائج
الكلمات المفتاحية
Anatomy: every part, named
Hover a row to locate it in the demo above.
Build prompt
How it behaves right-to-left
This section is ours alone.
The icon and the × inside the chip
mirrorsThe order inside the chip is logical, not physical: the icon at the logical start and the × at the logical end, which puts the icon on the right and the × on the left in an Arabic page. A display: flex container with flex-direction: row does this on its own because the inline axis follows direction. Do not add row-reverse under [dir="rtl"]: it double-flips and drops the × back on the icon's side. What does need converting is asymmetric padding: padding: 4px 12px 4px 8px becomes padding-block: 4px plus padding-inline: 8px 12px, and margin-right on the icon becomes margin-inline-end.
How the row wraps and aligns
mirrorsThe wrapping itself mirrors on its own because it follows the inline axis, so the trap is not flex-wrap but alignment: justify-content: left and justify-content: right are physical values that ignore direction, while flex-start and start follow it, so swap left for flex-start or the chips pile up on the wrong side in Arabic while looking perfectly fine in English. The same rule applies to text-align: left inside the chip; the replacement is text-align: start. And if the row is an older inline-block layout held together by float: left, change the float to inline-start, because float is purely physical and knows nothing about page direction.
Arrow keys inside the group
mirrorsArrow keys are physical and the chips' DOM order is logical, so the mapping between them inverts: in an Arabic group ArrowRight must move focus to the previous chip and ArrowLeft to the next one, otherwise focus walks against the user's fingers. Read the direction off the element itself rather than from a global app setting: getComputedStyle(el).direction === "rtl" or el.matches(":dir(rtl)"). Then multiply the step by -1. Home, End, and Tab never invert, because they are logical already: Home is the first chip in the DOM wherever it lands on screen.
The scrollable chip rail
mirrorsIf the row is a horizontally scrolling rail instead of a wrapping one, the scroll maths breaks first: in RTL scrollLeft is 0 at the reading start (the right edge) and goes negative as the user moves toward the end, which is where modern browsers have settled, so any code assuming a 0-to-positive range scrolls the wrong way or does not move at all. Do not compute it by hand: use chip.scrollIntoView({ inline: "nearest", block: "nearest" }) to bring a selected chip into view, and scrollBy({ left: … }) with the sign flipped by direction for the scroll buttons. Add scroll-padding-inline-start so an auto-scrolled chip does not end up flush against the rail's edge.
A Latin value inside an Arabic chip
never mirrorsA chip carries a value that comes from the user or the API, and in an Arabic interface it is often Latin: "Framework: React 18" or "File: report-v2.pdf". Neutral characters (the dot, the hyphen, the parentheses, the colon, and the × itself) have no direction of their own and take the direction of their surroundings, so "(12)" lands on the wrong side of the Latin name or the hyphen glues itself to the next Arabic word. The fix is isolation, not forcing a direction: wrap the value in <bdi>, which is equivalent to <span dir="auto"> since the UA stylesheet gives it unicode-bidi: isolate and a default dir="auto", or apply unicode-bidi: isolate to the label span directly. Do not reach for <bdo> here: it overrides direction and reverses the character order itself.
In code
Each row is one framework's word for the same thing. Take the row your project speaks.
See also
Updated · 2026-08-19