Tooltip
A dark label that points back at what it names - 109 by 28, four sides, and an arrow that is half a rotated square.
Four variants, and the only thing that moves between them is the arrow. The box, the type and the padding are identical in all four, which is the right shape for a component whose job is to point somewhere - the side is about placement, not about appearance.
A 10 × 10 rectangle turned 45 degrees with its centre sitting exactly on the edge, so half shows and half is hidden behind the box. Only the corner that points is rounded, at 2 - the other three sit on or behind the edge, and softening those would notch the arrow where it meets the fill. It also means the arrow needs re-placing by hand after any resize.
Every variant carries a Kbd Group that is switched off, parked just past the label with the same 8 of gap the usage frame uses. Reveal it and the tooltip can name the keystroke it is describing, which is the one thing a tooltip is uniquely good at - then widen the box to fit it. The usage frame's last example shows it turned on.
The part a still cannot show
A tooltip is defined as much by its timing as by its drawing. Point at the button and wait - the delay is the whole difference between a helpful label and a page that flickers at you every time the pointer crosses it.
Two things the file cannot carry. The delay, which the source sets on a provider so every tooltip in an app agrees on it - and the animation, a fade and a 95% zoom that slides in from whichever side the tooltip is on. Both are behaviour rather than drawing, and both are worth deciding once rather than per tooltip.
Each side paired with its trigger
658 by 756, holding all four sides against a real Button, a two-line label, and one tooltip with the shortcut turned on. Every tooltip in it is an instance and every trigger is an Outline Button at sm - nothing in the frame is drawn twice.
A tooltip is a name, not an explanation
It appears on hover, it vanishes on leave, and a keyboard user meets it only on focus. That rules out anything a reader has to keep. Every example here is a label for something already on the screen.
Four glyphs with no labels, which is exactly the situation a tooltip is for. Note what it does not replace: every button still carries an aria-label, because a tooltip is a hover affordance and a screen reader needs the name whether or not anything is hovered.
Top and Bottom are safe, Left and Right are not
The Side axis names four physical sides, and two of them mean something different once the text runs the other way. A tooltip placed on the Right of its trigger is on the reading side in an English layout and on the trailing side in an Arabic one. The component cannot decide that for you; the code that places it has to.
Even padding, a symmetrical radius and a centred arrow, so the drawing is direction-blind. Only the copy inside it changes, and it changes on its own once dir is set on an ancestor.
The file names Left and Right because a design file has no reading direction. In code, ask for start and end and let the placement library mirror them - the source's own positioning does this, and it is the reason the Side axis is about the arrow rather than about intent.
Whatever side you ask for, a tooltip near an edge flips to the opposite one. That is a runtime decision no variant can hold, which is why all four sides exist in the file: you will need whichever one the viewport hands you.
One component, four sides
Read straight out of the Penpot file. The axes below are the property names you will see in the variant dropdown.
Using the Tooltip
Because it is the only thing that changes. The box, the type, the padding and the colours are identical in all four variants - what moves is the arrow, from one edge to another. That is the right shape for a component whose whole job is to point at something: the axis is about placement, not appearance.
As a 10 × 10 rectangle turned 45 degrees with its centre sitting exactly on the edge of the box, so half of it shows as a triangle and half hides behind the fill. Only the corner that points carries a radius, at 2 - the other three sit on or behind the edge of the box, and rounding those would notch the arrow where it joins the fill. Which corner that is follows the side: a square turned 45 degrees sends its top-left corner up, its top-right right, its bottom-right down and its bottom-left left. The consequence in Penpot is that the arrow is an absolute child: resize the tooltip and it has to be put back by hand.
Naming the keystroke the tooltip is describing. Every variant carries a two-key Kbd Group that is switched off, parked immediately past the label with the same 8 of gap the usage frame uses, so revealing it puts it in the right place and only the box has to grow; reveal it on an instance and the label reads Print document with Command and P beside it. The keys are real Kbd instances, so a change to Kbd reaches every tooltip that names a shortcut. It is the one job a tooltip does better than anything else in the kit.
base.primary for the box and base.primary-foreground for the type, which gives a near-black label with near-white text. Worth knowing that the source uses foreground and background instead. The picture is identical today; the difference shows up the moment you repoint primary to a brand colour, at which point every tooltip in the kit turns that colour.
One line, two at the outside - the file's wrapping example is 280 × 44, which is two lines at 12/16. Past that you have written a paragraph that disappears when the pointer moves, and a reader who needs a paragraph needs it to stay on the page. Put it in the layout instead.
The timing and the animation, both of which are behaviour rather than drawing. The source opens after a delay set once on a provider, then fades and zooms in from 95% with a slide from whichever side it is on. The delay is the difference between a helpful label and a page that flickers whenever the pointer crosses it, so decide it once for the whole app.
Not directly. A disabled button fires no pointer events, so the tooltip never opens, and it takes no focus either, so a keyboard user cannot reach it at all. Wrapping the button in the trigger fixes the hover case and not the keyboard one. If the reason a control is disabled matters, put it on the page as text - the tooltip may repeat it, but it must not be the only copy.
No. A tooltip is a hover and focus affordance; assistive technology needs the name whether or not anything is hovered. An icon button gets an aria-label and a tooltip, and the two usually say the same words. Dropping the label because the tooltip is there is the most common way an icon toolbar becomes unusable.
The box does - even padding, symmetrical radius, centred arrow, and copy that flips on its own with dir. The Side axis is the part that needs thought: Left and Right are physical, and a tooltip on the Right of its trigger is on the reading side in English and the trailing side in Arabic. Ask for start and end in code and let the positioning mirror them. Collision flipping overrides all of it anyway - a tooltip near an edge takes the opposite side, which is a runtime decision no variant can hold.