Separator
One board, one fill, one pixel. The smallest component in the kit, and the one whose whole behaviour lives in the space around it.
One board, one fill, one pixel. There is no stroke, no radius and no padding, because a rule that carried any of those would stop being a rule. Everything that makes a separator work - how much air sits on either side of it - belongs to whatever is doing the separating.
A 339 × 1 and a 1 × 20 are not the same shape rotated; they resize along different axes and you place them in different kinds of layout. Recording that as a property rather than expecting a designer to rotate the horizontal one keeps the two from drifting apart.
The source's other prop decides whether assistive technology announces the rule or skips it. It changes no pixel, so there is nothing for a variant to show. Set it in code: decorative when the line is scenery, and leave it off when the line is the thing dividing two sections.
Three jobs for one pixel
535 by 578, holding the shadcn demo and one arrangement of its own. A horizontal rule under a heading, vertical rules between inline links, and taller vertical rules between figures. Same component all five times; only the length and the space around it change.
A separator is a claim about grouping
Every rule you draw says these things belong together and those do not. That is a strong claim for one pixel to make, and it is why the last example here is the one with no separators in it at all.
Three groups, two rules. Without them the eight buttons read as one undifferentiated row and you have to know the tool to know where undo stops and formatting starts.
One thing the file cannot record: a vertical separator needs a parent that gives it a height. In the kit it is drawn at 20 and at 40 because those are the two rows it sits in, but in code it is a stretched child of a flex row, and dropping one into a container with no height makes it vanish. That is the single most common way this component fails to appear.
One component, two variants
Read straight out of the Penpot file. The axes below are the property names you will see in the variant dropdown.
Using the Separator
Because the two resize along different axes. A horizontal rule stretches to the width of what it divides and stays 1 tall; a vertical one stretches to the height of its row and stays 1 wide. Drawing one and turning it ninety degrees would leave every instance carrying a rotation you have to undo before you can size it.
It is in the source and it is not in the file, because it changes nothing you can see. It decides whether a screen reader announces the rule or passes over it. Set it in code: decorative when the line is scenery inside a group that is already labelled, and leave it off when the line is genuinely what separates two sections.
Because nothing gave it a height. It is 1 wide and stretches to fill its parent, so in a flex row with no height it renders as a one-pixel square you will never spot. The kit draws it at 20 next to a line of text and at 40 next to a two-line figure, which are the two heights it actually turns up at.
Above the first row or below the last one. A list that opens and closes with a line has been put in a box without anyone drawing the box, and it will not line up with whatever surface is actually around it. Rules go between things, never around them.
No, and this is the one real design decision the component carries. Spacing groups things without drawing anything and is almost always the better first attempt; cards group them loudly and start to suggest each row is independently actionable. Reach for the rule when vertical space is tight, not because a list looks unfinished. The last example on this page puts all three side by side.