# Why our notes hide at the screen edge

> **TL;DR** Stickies by Coduo keeps an unpinned sticky at the right screen edge as a 12 by 84 pt colour sliver, and hovering it for 100 ms peeks a 264 by 176 pt card. The numbers are design Board 02's, pinned in code on 6 September 2026 after a native SwiftUI motion study with 18 tunable values was built the day before: reveal spring 0.32 s response at 0.82 damping, retract 0.28 s at 0.90, a 20 pt hot zone, a 200 ms leave grace. The study's fling-to-stash never reached the app, because the sticky window's drag belongs to AppKit and reports no release velocity.

Stickies by Coduo, our sticky notes app for the Mac, gives every sticky two places to live. Pinned, it floats on the desktop as its own window. Unpinned, it goes to the right edge of the screen and shows only a thin strip of its colour. This post is how that edge got its numbers: which ones we tuned, which ones a design board fixed, and one behaviour we built, liked and did not ship. The app is not released yet; everything below is from the code on `main`.

## Why put sticky notes at the screen edge at all?

Because the two placements are the whole model. The project's vocabulary file defines a sticky as existing "in exactly one of two placements, pinned or stashed", and a stashed sticky as one that "rests at the right screen edge, showing only its sliver". The sliver is meant to carry enough colour to tell one note from another and no content at all.

So a note you are not using costs you 12 points of screen width, not a window. Hover a sliver and that one card peeks out far enough to read its title and first lines while its neighbours stay slivers. Click it and it opens. Move away and it goes back.

## What did the first sketch get wrong?

The first sketch got most of the numbers right and could not vouch for the motion. It was a single HTML file, committed at 22:13 on 5 September 2026 as `docs/prototypes/stash-motion.html`, with the right layout and most of the right numbers: 264 pt wide notes, a 12 pt visible sliver, 84 pt sliver height, 4 pt gaps, a 30 pt reveal threshold, a 100 ms hover dwell and a 200 ms leave grace.

What it could not tell us was how the stash would feel on a Mac. It ran its own spring: a hand-written integrator that steps position and velocity in 6 ms slices from an angular frequency of 2π divided by the response. The panel under the sliders says so in as many words: the browser study translates the board's spring into a physical one and "does not run SwiftUI". A spring that looks right in a browser tab is a claim about the browser.

Nine minutes later, at 22:22, the same study landed as native SwiftUI (`App/PrototypeModel.swift`, `App/PrototypeInspector.swift`, `App/PrototypeView.swift`). The browser sketch was retired as a design tool. It came back nineteen days later in a different role, which is further down.

## What does a native motion study let you tune that a design board can't?

A native study lets you tune motion while it is moving, under your own hand. A board can annotate "spring(0.32, 0.82)" beside a dashed line, but it cannot let you grab a note halfway through that spring and feel whether the handoff is smooth. The native study's inspector opens with the instruction "Try grabbing a moving note", and every note's position is two spring axes, each holding a value and a velocity. A drag starts from wherever the spring had got to, and a retarget continues with the velocity the note already had.

The study exposes 18 values in `PrototypeTuning`:

| Group | Value | Default | Slider range |
| --- | --- | --- | --- |
| Spring | Response | 0.32 s | 0.18 to 0.8 |
| Spring | Damping | 0.82 | 0.5 to 1.2 |
| Spring | Playback speed | 1.0× | 0.2 to 1.5 |
| Edge stash | Note width | 264 pt | 200 to 340 |
| Edge stash | Note height | 300 pt | 180 to 360 |
| Edge stash | Visible sliver | 12 pt | 6 to 36 |
| Edge stash | Sliver height | 84 pt | 42 to 100 |
| Edge stash | Stack gap | 4 pt | 2 to 24 |
| Edge stash | Magnetic reach | 140 pt | 40 to 260 |
| Edge stash | Attraction | 10 pt | 0 to 28 |
| Edge stash | Reveal threshold | 30 pt | 12 to 90 |
| Edge stash | Hover intent | 0.1 s | 0 to 0.3 |
| Edge stash | Leave grace | 0.2 s | 0 to 0.4 |
| Window fan | Item spacing | 10 pt | 2 to 26 |
| Window fan | Hover scale | 1.045× | 1 to 1.12 |
| Window fan | Neighbour displacement | 9 pt | 0 to 22 |
| Window fan | Fan spread | 18 pt | 0 to 36 |
| Window fan | Stagger | 0.035 s | 0 to 0.07 |

Four spring presets sit above the sliders: Board default (0.32, 0.82), Calm (0.38, 1.0), Playful (0.38, 0.65) and "Spring.swift original" (0.7, 0.7), the house values from Meng To's Spring library. Playback speed scales the simulation clock, so you can run a reveal at 0.2× and watch where it overshoots.

Two of the values are about intent, not motion. Magnetic reach and attraction make a resting sliver lean up to 10 pt toward the pointer once it comes within 140 pt of the edge, scaled by how close the pointer is horizontally and vertically. Hover intent and leave grace stop a peek from firing when the pointer only passes through the edge, and stop it from vanishing when the pointer overshoots the card by a few points.

One detail we liked: the study never stores a separate retract spring. It derives it from the reveal, with 0.875 times the response and damping raised by 0.08, capped at 1.2. At the board default of 0.32 and 0.82 that gives 0.28 and 0.90, exactly the retract spring the board specifies.

## Which numbers shipped, and why those?

The board's numbers shipped. On 6 September at 09:04, a commit titled "pin board-defined motion tokens" replaced the provisional values in `Sources/StickiesKit/Motion.swift`, the one file every animation in the app has to go through. The provisional values had been read off the Spring library the evening before, marked as placeholders until the boards' motion specs landed:

| Token | Provisional, 5 Sept | Pinned, 6 Sept | Where the pinned value comes from |
| --- | --- | --- | --- |
| Peek reveal | 0.35 s, 0.70 | 0.32 s, 0.82 | Board 02 |
| Peek retract | 0.28 s, 1.00 | 0.28 s, 0.90 | Board 02 |
| Pin pop | 0.40 s, 0.55 | 0.45 s, 0.88 | Board 03 |
| Standard | 0.50 s, 0.70 | 0.70 s, 0.70 | Spring library house values |

The reason for each value is the board. Nothing in the repo records why the designer picked 0.82 over 0.8, and we are not going to invent one. What the repo does record is how the values stay put: tests in `MotionTests.swift` assert the reveal, retract and pin-pop values, and the commit's evidence shows the check failing when the reveal response was changed from 0.32 to 0.33, before being restored.

The edge geometry shipped as the board drew it too, in `DeckGeometry.swift`: a 12 by 84 pt sliver (42 pt when the body is empty), 4 pt gaps, a 264 by 176 pt peek card, a hot zone 20 pt deep with 4 pt of vertical slop, a 100 ms enter debounce and a 200 ms retract delay. Past 7 stashed stickies [the stash scrolls](https://www.coduo.co/stickies/features/stash-to-screen-edge). Every one of those matches a value annotated on Board 01 or Board 02.

Where the study and the board differ, the shipped value is the board's. The study wakes a sliver within 30 pt of the edge and reveals the whole 300 pt note; the shipped hot zone is the board's 20 pt, and the peek is the board's 264 by 176 pt card. On 7 September the project wrote the split down as a ruling: the boards govern geometry, tints, stacking, ordering, copy and window level, and the native study "supersedes the boards for all animation and physics".

## What didn't ship, and why?

Three things. The first is still planned; the second is undecided; the third is out of the product.

**The physics.** The shipped deck does not yet move the way the study does. In the build on `main`, the peek card appears in place: its offset is fixed at the screen's right edge minus 264 pt, the panel under it resizes without animation, and the reveal spring drives the card's opacity. Board 02 asks for 252 pt of travel with the height growing from 84 to 176 pt; the card does not travel yet. The per-frame spring advance that gives the study its interruptible feel has one caller today, the study itself. Porting it into the live deck, along with the magnetic lean, is an open task. The owner's word for the gap in the task file is "bland and brittle".

**Fling-to-stash.** In the study you can throw a note at the right edge and it stashes itself. On release, `endDrag` clamps the drag velocity to ±1,600 pt/s and projects where the note would coast using a 0.99 decay: current position plus velocity per millisecond times 0.99 / (1 − 0.99), which is 99 times the per-millisecond velocity. At the clamp that is 158.4 pt of coast. If the projected note would end with more than 45% of its width past the screen edge, it stashes; otherwise it settles 0.05 s of velocity further along.

None of that can run on a real sticky. The [pinned sticky](https://www.coduo.co/stickies/features/pinned-floating-stickies) window sets `isMovableByWindowBackground = true`, so AppKit owns the drag and the app never sees a release velocity. A review on 8 September put it plainly: the setting "makes the prototype's tuned release momentum … unreachable", and the choice between owning the drag and dropping the momentum was being "decided by accident". It is still open. Today a pinned sticky drags like any other Mac window, and you stash it with its pin control.

**The window fan.** The study's fan, a staggered list of every note with a hover scale and neighbour displacement, has no counterpart in the app. Five of the 18 values tune something that does not exist in the product.

The fling did find a home. On 24 September the browser sketch was ported into the landing page's hero, where you can write on a sticky, drag it by its title bar and throw it at the right edge to stash it, with the same ±1,600 pt/s clamp and the same 0.99 projection. The website can have the throw because its playground keeps its own pointer history and computes the release velocity from it. The Mac app hands the sticky window's drag to AppKit and gets no velocity back.

## Whose work did we build on?

Two open-source projects, both MIT-licensed and vendored into `docs/reference/code/` with their licences.

The stash itself is adapted from [Noty](https://github.com/aimen08/noty) by aimen08. Its deck of notes resting at a screen edge, waking on pointer approach and opening on click is the interaction we started from. Its rest state became our stashed slivers, its per-note reveal became our peek, and its floating note became our pinned sticky. It also documented the traps we would otherwise have found the slow way: a non-activating panel that will not take typing until it is made key, a first click swallowed by an inactive app, full-screen Spaces needing the right window level, and multi-display decks that have to rebuild around display IDs rather than indices.

The spring vocabulary came from [Spring](https://github.com/MengTo/Spring) by Meng To. We took only its numbers: it is UIKit-era code that does not build on macOS, and the rule in the repo is "Numbers cross; code does not." Its 0.7 and 0.7 house values are still in Motion.swift as the fallback for anything no board annotates.

## Frequently asked questions

### Where do stashed notes go in Stickies by Coduo?

To the right edge of the screen. A stashed sticky shows only a 12 pt wide, 84 pt tall colour sliver, stacked with 4 pt gaps and centred vertically. Stickies by Coduo stashes on the right edge only.

### How long do you have to hover before a stashed sticky peeks?

100 ms inside a hot zone 20 pt deep from the screen edge, the sliver's height plus 4 pt of slop above and below. The peek retracts 200 ms after the pointer leaves both the hot zone and the peek card.

### What spring does Stickies by Coduo use for the peek?

The reveal uses a SwiftUI spring with a 0.32 s response and a 0.82 damping fraction, and the retract uses 0.28 s at 0.90. Both values come from the design board for hover peek and are pinned by tests in the app's Motion.swift.

### Can you throw a note at the screen edge to stash it in Stickies by Coduo?

Not in the Mac app. The motion study had fling-to-stash, but a pinned sticky's window is dragged by AppKit, which reports no release velocity, so the momentum projection has nothing to read. The throw does work in the playground at the top of the website.

### Is Stickies by Coduo available yet?

No. Stickies by Coduo is not released yet. The values in this post are from the code on the main branch as of 25 September 2026.
