v0.4.0 added forty-four drawings and redrew three hundred and fifteen. The changelog will tell you that much on its own, off the commit dates, without anyone having to write it down. What it cannot tell you is why any of it happened, and that turns out to be the more interesting half. So here it is: the families, and the faults.
Two things about that redraw count before anything else, because it is the number that looks wrong. The overwhelming majority of it is one change applied across the set: how a sharp stroke ends, which is its own story and not this one. What this post covers is the forty-four new drawings, and the handful of redraws that were faults rather than a treatment: seven bells, a database, a credit card and the duplicate below.
Four families, not forty-four decisions
Most of a batch this size is not forty-four separate calls. It is four or five, applied consistently. The parcel is the clearest example, and it is the one where the set answered the question for me.
Which modifiers a base is allowed to take is not a matter of taste here, it is something you can read off the drawings that already ship. Six bases carry the four arrows: calendar, clock, file, folder, image and smartphone. Every one of them holds content that moves in and out. A parcel is the thing that moves. Its absence from that list was a gap rather than a decision, so it got the arrows, plus the plus, minus, check, x and alert that every container base carries.
- package
- package-plus
- package-minus
- package-check
- package-x
- package-alert
- package-arrow-up
- package-arrow-down
- package-arrow-left
- package-arrow-right
The same test, applied the other way, is why the app tile did not get arrows. No base outside those six carries one, a tile is not a container of moving things, and its verbs are install, remove and approve, which plus, minus and check already say. It got the dot instead, which is what a notification looks like everywhere else in the set.
Search got ten, five on each glass. The construction came out of the existing search icon rather than being invented for the batch: the plate is the lens disc, the fill is that disc solid with the handle still stroked, and the sharp treatment pushes the handle a unit along its own diagonal.
One of the five would not cooperate. The signs are sized so that each one's furthest point lands on a path radius of 3, which is forced rather than chosen: the glass's inner ink edge is at 6, the gap the set keeps between elements takes 2, and the sign's own ink takes 1. The plus and the minus already sat exactly there. The list did not fit at any size that also cleared the 2-unit gap between its bars, so it is redrawn on a pitch of 4, which caps the bars at a radius of 2.236. Both glasses take the same signs, sized for the smaller of the two, because two sizes of check would read as two different checks.
- search-plus
- search-minus
- search-check
- search-x
- search-list
- search-2-plus
- search-2-minus
- search-2-check
- search-2-x
- search-2-list
The cloud took the same five signs on the same reasoning, and the umbrella turned into three drawings out of one: the canopy with its hem, the canopy with a slash across it, and a parasol, which is the umbrella with a pole where the hook should be. There was a fourth, the same canopy closed and stood upright, and I dropped it before the tag.
And then the ones that belong to nothing, which is the rest of it.
- briefcase
- bug
- crown
- flag
- flag-chequered
- traffic-light
- credit-card-2
- settings-dot
- replay
- move
- maximize-2
- circle-progress-play
git-merge was git-branch under a second name
This is the one worth reading if you maintain an icon set of your own.
While checking something unrelated, git-merge and git-branch turned out to be the same drawing. Not similar. The same. Byte-identical in fill, and in the other four variants identical but for the winding direction of the circles, which is a difference no renderer can show you on a stroke or on non-overlapping fills. Put side by side at any size, they were pixel-identical.
I drew both on 8 August and found the fault on 4 September, by which point it had gone out in every release the set has ever cut: v0.1.0 through v0.3.0, seven of them, on npm, in the Figma library and in the plugin. Nobody reported it, and I would not expect anyone to have. You reach for git-merge, you get a picture of some lines joining, and it looks like a merge because you were already thinking about merging.
A duplicate that renders identically is invisible to every check that looks at the picture. It is only visible to one that looks at the path.
Which of the two was wrong is answerable from the drawing itself. The shared picture has its junction at the top node, one arm carrying on down the trunk and the other running out to a leaf: one line becoming two, flowing down. That is a branch. So git-branch keeps it, and git-merge is the one that had been copied.
It is now that drawing mirrored about the horizontal centre line, so the trunk keeps its node at the bottom, the branch node moves to the top right, and both arms converge into the bottom node: two strands into one, going down. Closing the gap in git-pull-request was the other candidate and was rejected, because that gap is this family's spelling of a proposed rejoin, and a merge drawn four units of line away from it trades one collision for another.
Grey where there should be none
The duotone style paints a grey plate behind the black outline. The plate is supposed to be the outline's own offset, one unit inside the stroke, all the way around. On every bell in the set, it was not: each plate's flank had been sampled by hand rather than offset, and along about two thirds of its length it ran outside the ink.
I found it by recolouring the plate in Figma, which is the only way anyone was ever going to. The worst of it was 0.10 of a grid unit, on the plain bell in sharp. The grid is 24 units across and the icon is 24 pixels across, so that is a tenth of a pixel. Which is why it shipped, and why it kept shipping.
I rebuilt twenty-one such runs across fourteen files as real offsets: endpoints and end tangents held, handle lengths solved from the midpoint, each piece split until every sample sits at exactly one unit from the stroke. Worst error is now 0.0026, down from 0.10. Five of the runs are the rounded sign bells, which leave the notch at the point one unit above the stroke's cut and turn onto the offset along the cap's own circle; that turn was 0.0145 loose and is now the arc it was always meant to be.
- BeforeAfterbell
- BeforeAfterbell-dot
- BeforeAfterbell-check
- BeforeAfterbell-x
- BeforeAfterbell-plus
- BeforeAfterbell-minus
- BeforeAfterbell-off
A handful of the other redraws are the same shape of fault, found the same way: sharp caps standing outside the ink on the music notes, the map pins and the message dot; the clock rings sitting off their own circle; the database cylinder's plate offset the way the bells' now are. The remaining three hundred are the sharp end cut, one rule applied to every drawing at once, and they are a post of their own. What both have in common is the lesson: a treatment applied across three thousand files finds you every drawing that was only approximately right.
Getting it
All of it shipped in v0.4.0, in stroke, duotone and fill, rounded or sharp, free under the MIT licence.
Browse the set every drawing, filterable by style, corner treatment and category.
Install it the React package, the CLI, the shadcn registry and the plain SVGs.
Read the changelog the same events without the commentary, generated off the commits.