Mycelium

II · Relationship

What Happens to Where I Was?

Modal, side panel, or a new page

The URL tells you where you are. The next question is what happens to that place when something opens on top of it.

Some things open over the page. Some open beside it. Some replace it. I call all three top layers, the route change included, because from where the person stands it's the same moment: they clicked something, and something else now has the screen.

They aren't the same thing, though, and the difference isn't style.


Three different answers

A modal stops the page. The page is still there, dimmed behind it, but the person can't touch it until the modal is answered or dismissed. It says: wait. This first.

A side panel (a drawer, a sheet) opens next to the page. The page is still there and, usually, still usable. Close the panel and nothing has moved. It says: you're still here. Here's a bit more.

A route change replaces the page. The person is somewhere else now, with its own address, and the back button knows the way home. It says: you've gone somewhere. You can come back.

<figure style="margin:1.6rem 0;text-align:center"><svg width="400" height="204" viewBox="0 0 400 204" role="img" aria-label="one customer record opened three ways: as a modal over the dimmed list, as a panel beside the list, and as its own page with its own address"><rect x="8" y="8" width="122" height="160" rx="6" fill="none" stroke="#d8d2c8" stroke-width="1"/><rect x="16" y="16" width="40" height="6" rx="3.0" fill="#c9c2b6"/><rect x="16" y="30" width="106" height="16" rx="3" fill="#fff" stroke="#d8d2c8" stroke-width="1"/><circle cx="24" cy="38" r="4" fill="#e0dad0"/><rect x="32" y="36" width="47.7" height="4" rx="2.0" fill="#e0dad0"/><rect x="16" y="50" width="106" height="16" rx="3" fill="#fff" stroke="#d8d2c8" stroke-width="1"/><circle cx="24" cy="58" r="4" fill="#e0dad0"/><rect x="32" y="56" width="47.7" height="4" rx="2.0" fill="#e0dad0"/><rect x="16" y="70" width="106" height="16" rx="3" fill="#fff" stroke="#d8d2c8" stroke-width="1"/><circle cx="24" cy="78" r="4" fill="#e0dad0"/><rect x="32" y="76" width="47.7" height="4" rx="2.0" fill="#e0dad0"/><rect x="16" y="90" width="106" height="16" rx="3" fill="#fff" stroke="#d8d2c8" stroke-width="1"/><circle cx="24" cy="98" r="4" fill="#e0dad0"/><rect x="32" y="96" width="47.7" height="4" rx="2.0" fill="#e0dad0"/><rect x="16" y="110" width="106" height="16" rx="3" fill="#fff" stroke="#d8d2c8" stroke-width="1"/><circle cx="24" cy="118" r="4" fill="#e0dad0"/><rect x="32" y="116" width="47.7" height="4" rx="2.0" fill="#e0dad0"/><rect x="16" y="130" width="106" height="16" rx="3" fill="#fff" stroke="#d8d2c8" stroke-width="1"/><circle cx="24" cy="138" r="4" fill="#e0dad0"/><rect x="32" y="136" width="47.7" height="4" rx="2.0" fill="#e0dad0"/><rect x="9" y="9" width="120" height="158" rx="6" fill="#3a3631" fill-opacity="0.28"/><rect x="22" y="40" width="94" height="96" rx="6" fill="#fff" stroke="#7a1f1f" stroke-width="1.2"/><circle cx="38" cy="58" r="9" fill="#e0dad0"/><rect x="52" y="52" width="42.300000000000004" height="6" rx="3.0" fill="#c9c2b6"/><rect x="52" y="62" width="28.2" height="4" rx="2.0" fill="#e0dad0"/><rect x="32" y="82" width="66.60000000000001" height="4" rx="2.0" fill="#eeeae3"/><rect x="32" y="93" width="51.8" height="4" rx="2.0" fill="#eeeae3"/><rect x="32" y="104" width="59.2" height="4" rx="2.0" fill="#eeeae3"/><rect x="32" y="115" width="37.0" height="4" rx="2.0" fill="#eeeae3"/><text x="108" y="52" font-family="Inter, system-ui, sans-serif" font-size="10" font-weight="400" fill="#8f887d" text-anchor="middle">×</text><rect x="139" y="8" width="122" height="160" rx="6" fill="none" stroke="#d8d2c8" stroke-width="1"/><rect x="147" y="16" width="40" height="6" rx="3.0" fill="#c9c2b6"/><rect x="147" y="30" width="46" height="16" rx="3" fill="#fff" stroke="#d8d2c8" stroke-width="1"/><circle cx="155" cy="38" r="4" fill="#e0dad0"/><rect x="163" y="36" width="20.7" height="4" rx="2.0" fill="#e0dad0"/><rect x="147" y="50" width="46" height="16" rx="3" fill="#fff" stroke="#d8d2c8" stroke-width="1"/><circle cx="155" cy="58" r="4" fill="#e0dad0"/><rect x="163" y="56" width="20.7" height="4" rx="2.0" fill="#e0dad0"/><rect x="147" y="70" width="46" height="16" rx="3" fill="#fff" stroke="#d8d2c8" stroke-width="1"/><circle cx="155" cy="78" r="4" fill="#e0dad0"/><rect x="163" y="76" width="20.7" height="4" rx="2.0" fill="#e0dad0"/><rect x="147" y="90" width="46" height="16" rx="3" fill="#fff" stroke="#d8d2c8" stroke-width="1"/><circle cx="155" cy="98" r="4" fill="#e0dad0"/><rect x="163" y="96" width="20.7" height="4" rx="2.0" fill="#e0dad0"/><rect x="147" y="110" width="46" height="16" rx="3" fill="#fff" stroke="#d8d2c8" stroke-width="1"/><circle cx="155" cy="118" r="4" fill="#e0dad0"/><rect x="163" y="116" width="20.7" height="4" rx="2.0" fill="#e0dad0"/><rect x="147" y="130" width="46" height="16" rx="3" fill="#fff" stroke="#d8d2c8" stroke-width="1"/><circle cx="155" cy="138" r="4" fill="#e0dad0"/><rect x="163" y="136" width="20.7" height="4" rx="2.0" fill="#e0dad0"/><rect x="148" y="50" width="44" height="16" rx="3" fill="#f2e4e1" stroke="#7a1f1f" stroke-width="1"/><rect x="197" y="9" width="63" height="158" rx="0" fill="#fff" stroke="#7a1f1f" stroke-width="1.2"/><circle cx="211" cy="42" r="9" fill="#e0dad0"/><rect x="225" y="36" width="28.8" height="6" rx="3.0" fill="#c9c2b6"/><rect x="225" y="46" width="19.2" height="4" rx="2.0" fill="#e0dad0"/><rect x="205" y="66" width="39.6" height="4" rx="2.0" fill="#eeeae3"/><rect x="205" y="77" width="30.799999999999997" height="4" rx="2.0" fill="#eeeae3"/><rect x="205" y="88" width="35.2" height="4" rx="2.0" fill="#eeeae3"/><rect x="205" y="99" width="22.0" height="4" rx="2.0" fill="#eeeae3"/><rect x="270" y="8" width="122" height="160" rx="6" fill="none" stroke="#d8d2c8" stroke-width="1"/><rect x="278" y="14" width="106" height="12" rx="6" fill="#eeeae3"/><text x="284" y="23" font-family="'JetBrains Mono', ui-monospace, monospace" font-size="6.5" font-weight="400" fill="#3a3631" text-anchor="start">← /customers/7f2a</text><rect x="278" y="34" width="106" height="126" rx="4" fill="#fff" stroke="#7a1f1f" stroke-width="1.2"/><circle cx="294" cy="58" r="9" fill="#e0dad0"/><rect x="308" y="52" width="47.7" height="6" rx="3.0" fill="#c9c2b6"/><rect x="308" y="62" width="31.799999999999997" height="4" rx="2.0" fill="#e0dad0"/><rect x="288" y="82" width="77.4" height="4" rx="2.0" fill="#eeeae3"/><rect x="288" y="93" width="60.199999999999996" height="4" rx="2.0" fill="#eeeae3"/><rect x="288" y="104" width="68.8" height="4" rx="2.0" fill="#eeeae3"/><rect x="288" y="115" width="43.0" height="4" rx="2.0" fill="#eeeae3"/><text x="69.0" y="184" font-family="Inter, system-ui, sans-serif" font-size="9" font-weight="500" fill="#3a3631" text-anchor="middle">modal</text><text x="69.0" y="196" font-family="Inter, system-ui, sans-serif" font-size="8" font-weight="400" fill="#8f887d" text-anchor="middle" font-style="italic">wait, this first</text><text x="200.0" y="184" font-family="Inter, system-ui, sans-serif" font-size="9" font-weight="500" fill="#3a3631" text-anchor="middle">side panel</text><text x="200.0" y="196" font-family="Inter, system-ui, sans-serif" font-size="8" font-weight="400" fill="#8f887d" text-anchor="middle" font-style="italic">you&#x27;re still here</text><text x="331.0" y="184" font-family="Inter, system-ui, sans-serif" font-size="9" font-weight="500" fill="#3a3631" text-anchor="middle">route change</text><text x="331.0" y="196" font-family="Inter, system-ui, sans-serif" font-size="8" font-weight="400" fill="#8f887d" text-anchor="middle" font-style="italic">you&#x27;ve gone somewhere</text></svg><figcaption style="font-size:.8rem;color:#a8a298;font-style:italic;margin-top:.4rem">One record, three claims about what it is: an interruption, a detail of the list, a place.</figcaption></figure>

Each one tells the person something about the place they were standing, before anything inside it is read. And that's also a statement about what the thing that opened is. Open a customer in a modal and you've said a customer is an interruption. In a panel, a detail of the list. On a page, a place. Same record, three claims about its nature.


The contracts, and the rules

Some of what the three promise isn't mine to decide, or yours. The person learned it from every other product they've used, the same way they learned that a raised rectangle presses. These are the base contracts, and they hold whatever the product:

A modal owes the person the page as they left it, changed only by what they did in the modal. When it closes, nothing else behind it has moved, scrolled or changed. It owes them a way out that isn't the answer, unless the decision truly can't be skipped. And it isn't a place: pressing back shouldn't throw them out of a page they never left. A modal that opens a modal has made them two interruptions deep, and most people lose the thread of where they started somewhere around there.

A side panel owes the person the page beside it, still there and still theirs. It's about something on that page, and closing it changes nothing behind. If the person can act on the page while the panel is open, the panel has to keep up with what they do.

A route change owes the person an address. The new place can be arrived at cold, from a link, a bookmark, a refresh. And it owes them the way back: back returns them along the path they actually took.

On top of the contracts sit the rules, and the rules are yours. Which things in your product open in a modal, which in a panel, which get a page of their own. Whether a panel gets an address. Whether a modal can ever be the size of a form. I have rules for this, made for the products I know, and I don't think they're the point. The point is that the rules get decided once, on purpose, by whoever owns the system, instead of screen by screen by whoever happens to be building that screen.

When nobody decides, it shows. The same kind of thing opens in a modal here, a panel there, a page somewhere else. Each choice made sense where it was made. Together they say the product hasn't made up its mind what that thing is, and the person, who reads the top layer as part of the answer, can't make up theirs either.


Where this bends

Phones test the side panel's contract. If its job is to sit beside the page, a phone has no room for it; keep that rule, and on a phone you give the panel up. Bend it, and it's worth knowing what you're bending toward, because the real line between a panel and a modal was never the shape. It's whether the thing is part of the person's journey or interrupts it. Is this something they work on alongside the page, or something that stops them until it's done? Does it belong to where they are, or does it ask them to be somewhere else for a moment? However you answer, the answer goes into the contracts once, and then it holds on every screen. That's what lets the person stop checking.