Toggle Group
Three toggles as one control - joined behind a single border, spaced apart as separate ones, or stretched to fill the row.
The joined types put the edge on the container and leave the toggles bare, with a 1px rectangle between each pair. Butting three Outline toggles together instead doubles the border at every join and makes the strip a pixel taller than its parts.
With selectors a design file has no way to express: data-[spacing=0] strips the rounding, first: and last: put it back on the ends, and border-l-0 with first:border-l removes every left border but the first. The picture is the same; the mechanism has to differ.
Not visually - structurally. There is no container at all, and the toggles switch to the Outline variant so each one carries its own edge. It is the type to reach for when the group's members are unrelated enough to look separate.
The rule the file cannot draw
Every variant above shows one toggle on and two off, and that is all a still can say. What actually separates one group from another is the rule between its members: single lets one in at a time, multiple lets any number in. Same five drawings either way.
A group is a claim that these belong together
Joining three toggles into one control says they are the same kind of choice. Get that wrong and the strip reads as a single setting with three parts, which is exactly what a set of unrelated switches is not.
Exactly one alignment is true at a time, which is why this group is single.
Alignment is the clearest case there is: the three options are mutually exclusive by definition, one of them is always true, and joining them into one control says so before anyone clicks. Never leave a single-select group with nothing on unless no-alignment is a real state.
The order reverses, the corners follow
A joined group is the one place where mirroring costs something. The container's rounding is symmetrical so it needs no work, but in code the first and last members carry the rounded ends - and first and last swap sides under dir=rtl. Write them with logical properties and it happens on its own; write them as left and right and the strip comes apart.
They sit between siblings in a flex row, so reversing the row reverses them with it. That is the advantage of drawing a divider as a child rather than as a border on one side of each member - a left border would have to become a right one.
The source rounds the ends with first:rounded-l-md and last:rounded-r-md, which are physical - under rtl the first member is on the right and would get its rounding on the wrong side. rounded-s-md and rounded-e-md are the logical pair, and they need no dir-specific rule.
Align start, centre and end mirror with the text. Bold, italic and underline do not - they describe a shape rather than a side. It is the same per-icon decision the Toggle page makes, and a group does not change it.
One component, five variants
Read straight out of the Penpot file. The axes below are the property names you will see in the variant dropdown.
Using the Toggle Group
How the members are held together. Default butts them behind one base.input border with a 1px divider between each pair, so the strip reads as a single control. With Spacing drops the container entirely and switches the toggles to Outline, so each carries its own edge and they read as three separate controls - 8 between them in either orientation. Fill keeps the container but lets the members share the row equally instead of hugging their labels.
Because you get two borders at every join and a strip a pixel taller than its parts. The joined types put the edge on the container and leave the toggles bare, with a drawn 1px rectangle where the seam should be. That is one border, one radius, and one height.
With selectors a design file cannot express: data-[spacing=0] strips the rounding from every member, first: and last: put it back on the two ends, and border-l-0 with first:border-l removes every left border but the first. The picture is the same as the file's; only the mechanism differs, which matters when you rebuild it in code.
Not in the file - five of the six combinations are drawn. Filling along the vertical axis needs a parent with a height to fill, which is the part a component cannot carry. Take Default / Vertical and let the group stretch inside whatever gives it that height.
The rule between the members, and it is the one thing no drawing can show. Single lets one in at a time and is right when the options are mutually exclusive - alignment, a view switcher, a date range. Multiple lets any number in and is right for formatting marks. A reader cannot tell them apart by looking, so if the difference matters, the strip usually needs a label above it.
Only when no-choice is a real state. The source's single mode is collapsible: pressing the member that is already on turns it off. That is right for a filter you can clear and wrong for alignment, where text is always aligned somehow. Decide it deliberately rather than inheriting the default.
Yes, and that is the common case - the source's min-w-9 exists so a member can be square. It comes with the same requirement as a lone Toggle: an aria-label on every member and a tooltip on any glyph that is at all ambiguous. Three unlabelled icons in a row are three guesses.
The order and the dividers reverse on their own, because the dividers are children of a flex row rather than borders on one side of each member. Two things need care. The rounded ends in code are first:rounded-l-md and last:rounded-r-md, which are physical - swap them for rounded-s-md and rounded-e-md or the strip comes apart under rtl. And the icons follow the Toggle page's rule: alignment glyphs mirror, bold and italic do not.
No - this page in the file is the Components board and nothing else. The examples on this page are the kit's answer to that: single-select alignment, multi-select marks, a view switcher, a segmented filter on the Fill type, and the argument for choosing between joined and spaced.