It’s interesting, teaches you new things, clearly talks about and shows its inspirations, and is free of the sort of bloviating, pretentious, nutrition-free language that often accompanies typeface reveals.
At first, I thought I was going to get creative with the positions and angles of the stencil “bridges” that traverse the letterforms. I tried fun diagonal bridges like the ones pictured below, but I found that the fancier I got, the more distracting the gaps became. And it was important to me that the design didn’t feel too clever or self-aware.
So after much experimentation, I ended up sticking with vertical bridges for the vast majority of shapes. (A handful of diagonal bridges are stashed in an OpenType Stylistic Set.)
While Nickel Stencil shifts them to the left or right to reduce the clutter of horizontal branches, Slight Chance’s bridges mostly run right down the center, leaving branches on both sides…it’s more clutter, but it’s also more corners to make soft and worn.
I happily made exceptions when this approach left a distractingly short fragment. Sometimes I shifted the bridge to one side or another (see crossbars like B and a), sometimes I used a diagonal bridge (see K and A), and sometimes I used a horizontal bridge (see T and t).
Plus, the typeface and its origins are really cool.
One way to read this is “phew, whatever I’m working on is nowhere near this bad, so I can sleep soundly.”
But I also think there’s another way to see it: as a cautionary tale. If you don’t care, if you don’t teach, if you don’t create the right processes and culture and incentives, if you don’t prevent certain doors from being opened, if you don’t push and empower others to push against the entropy and the laziness – this might be how your stuff ends up, too.
I recently rewatched two reviews of AI companion devices from Marques Brownlee (a.k.a. MKBHD), which both came out in April 2024 – the Humane AI Pin and the Rabbit R1:
Brownlee is a charismatic reviewer, and I won’t lie – there’s a certain amount of delicious schadenfreude seeing two products announced with so much unnecessary hubris faceplant so solidly.
But past all that, what stood out to me was the storytelling, and this is why I wanted to post these videos; the work feels good here, and deserves studying in how to talk about these things.
Brownlee manages to cut through the bullshit and candidly talk (but also show) what these devices should be all about. There are some nice editing choices; casually pulling up the phone and getting an answer while the AI Pin is still thinking is a pretty powerful moment. The reviews also come with higher-level reflections, and what stuck with me since the original watch years ago were the segments about how more and more often, devices like these – but not just these devices – come out of the gate profoundly unfinished.
The Pin and the Rabbit are also interesting to compare. They are both underbaked in some similar ways: the quality of the AI output, overfocusing on hardware at the expense of software, and the interaction systems that throw good money after bad and come out of the gate with strange complexity – AI Pin had the tricky-to-use laser projector menus, and Rabbit R1 managed to overgimmick a simple thing that is a rotary controller. On the other hand, one of the devices felt a lot more ambitious than the other. Also, both had fascinating differences in the packaging and their whole approach – it almost feels like there was a generational difference between the two endeavors.
(Humane Inc. has folded since. You can still buy the R1, which was since updated with a new UI, but it seems the company is pivoting to more generic-feeling software.)
On the morning of December 28, 1998, the day before the game Myth II: Soulblighter was supposed to hit the store shelves, the publisher received a phone call:
[…] one of Bungie’s overseas publishers called to say that a woman had played the game and then tried to uninstall it. The game software had uninstalled Myth II as it was supposed to--but it had also erased some of the other files on her hard drive.
The first reaction was panic […] [Bungie cofounder Jason] Jones and another programmer tried to replicate the problem. They quickly found it and figured out how to correct the faulty lines of code. Fixing the problem would be easy—except for the 200,000 copies that were already packaged or on the road.
Seropian, Jones, Zartman, Donohue, and sales and marketing director David Joost met to decide what to do. They had two options. The first was to say nothing. The argument in favor of this alternative was that the problem occurred only when the program was uninstalled and then only when someone had installed the game in an unconventional way to begin with. Since the chances were slim that anyone would install the game in this weird fashion and uninstall it right away, the risk to the company’s reputation was minuscule, particularly since they could post an announcement on their Web site along with a free patch that could be downloaded to correct the problem.
The second option was to recall the game. That would force them to trace every copy that had already gone out, scrap every finished copy, and start all over again.
I was curious about the cause of the bug, and found this answer from someone who worked on the original Myth I:
So I wrote the Myth TFL installer (not this one). The reason this happened is because you could install other maps and whatnot, and to make the uninstall clean, we had to recursively delete your data folder.
In the sequel, somehow that code […] was used to delete the applications directory, instead of just the data directory in the applications directory. So if you installed it on C:\, it would delete everything recursively from there.
Nowadays, uninstall usually leaves any user installed files (like saves or downloaded content) but at the time, as the article suggests, hard drive space was more precious. Also, I wasn’t there for this issue, so I don’t know the above for sure, but having written the previous installer, I’m pretty confident that’s what happened.
The installer tries to erase a previous version of iTunes using (with root privileges) the rm -rf command. However it doesn’t take into account that volume names can contain spaces. […]
When the diskname (partition name) starts with a space the following happens: rm -rf /Volumes/ harddiskname/iTunes.app 2> /dev/null
So rm removes /Volumes (all mount points!) and a nonexistent path harddiskname/iTunes.app, but no errors are displayed because they are /dev/nulled.
And a very similar thing a decade later, from Steam’s Linux installer:
I launched Steam. It did not launch, it offered to let me browse, and still could not find it when I pointed to the new location. Steam crashed. I restarted it.
It re-installed itself and everything looked great. Until I looked and saw that steam had apparently deleted everything owned by my user recursively from the root directory. Including my 3TB external drive I back everything up to that was mounted under /media.
The culprit was identified by another user a few messages down:
rm -rf "$STEAMROOT/"* could be evaluated as rm -rf "/"* if $STEAMROOT is empty
These are the sort of classic user-generated content meets string concatenation/interpolation bugs that haunt engineers’s dreams.
The solution: If a user gives you a string, you have to wrap it as safely as possible so that it could never break apart into pieces in transit.
So you wrap the path with quotation marks. (I believe you can actually do this everywhere in Linux – cd "/usr/local" will work as well as cd /usr/local – except no one ever does so as it’s quite annoying.) But then, a string with quotation marks would escape containment, so you have to escape those by changing " to \". And then, naturally, you also have to escape any freefloating backslashes to \\.
Of course, there are usually functions that take care of all of the above; you just have to remember to use them, as well as think about the edge cases like a variable being empty to begin with.
Here, the wrapping isn’t for security reasons, but to help people understand where the command ends and the string begins. But this introduces a new challenge, as any type of visual wrapping – quotation marks, bolding, italicization – can draw undue attention to the string itself. So, sometimes you just leave it be and hope for the best:
But let’s go back to the installation issues. I bet there are were tons more string interpolation and escaping bugs that we simply never learned about. Yet, as users of a project called Bumblebee learned in 2011, nothing beats the destructive power of a simple typo.
The best way to start here is with the summary of the fix to the bug, because that is the best encapsulation of the story:
An extra space at line 351: rm -rf /usr /lib/nvidia-current/xorg/xorg
causes the install.sh script to do an rm -rf on the /usr directory for people installing in ubuntu.
Totally uncool dude!!! The script deletes everything under /usr. I just had to reinstall linux on my pc to recover.
Removing the space will fix this. Probably should do it quickly!!!
I started GUIdebook in 2003, and last updated it exactly twenty years ago.
It’s an interesting time capsule itself now, incompatible with mobile reading and sporting an aged design. I have kept it up because it’s apparently used as a reference in various user interface courses, and if you haven’t seen it, it could be a fun browse.
I walked away from it by accident, distracted by a new job, but I always wanted to evolve it into something better as my storytelling skills and my interactive skills grew.
But the direct preview of what I dreamt GUIdebook of becoming was in my last year’s interactive piece Frame of preference. It’s a history of the first twenty years of Mac interfaces told through its settings, it has a proper narrative (I never got to it with GUIdebook), and instead of screenshots, it uses Infinite Mac’s technology to tell the stories via emulation. I’m pretty proud of how it turned out, and you might enjoy it if you haven’t seen it yet.
I would love to try a few more things like it.
But, back to GUIdebook. Keeping it alive for 20 years required multiple updates as PHP evolved, and a more recent rewrite that ditched easily-hackable PHP altogether. (Don’t ask me how I know it’s easily hackable.) None of these were particularly noticeable on the surface, but I recently added one tiny user-visible change – the screenshots are now properly pixellated:
It was fun – and slightly eerie – to update the site’s history page two decades after I touched it last.
There is this lesson every programmer learns when building or debugging something, and it’s “reduce your blast radius.”
Let’s say I want to draw some stylized text showing current time in some code I haven’t touched in a while. Instead of doing all that in one fell swoop, I should:
use a non-changing test string, instead of the current time (so I reduce the surface area of things that could fail),
start with unstyled text, instead of immediately stylizing it (same as above),
or, even, begin by modifying the text or color of something that’s already drawn, to make sure I’m touching the right file, that the compilation succeeds, that auto-refresh works, etc. (perhaps using the venerable border: 10px solid hotpink, as mentioned recently by Roel Nieskens).
Coders intuitively develop a sense of how big of a leap to take in what situation. You can theoretically noscope a complex regular expression in one go and it will feel fantastic, but if you fail, you might end up going slower than someone who attacks the problem piece by piece.
There’s a version of this outside of programming, and I sometimes call these peace-of-mind functions.
Perhaps the most common one is a menu command called Check for Updates, found in many apps. At least when it comes to kind software, “newer” means “better,” so if something seems to not be going well, making sure you’re on the latest version can save some headache.
Here’s a pretty standard example in Glyphs:
Figma goes extra, explaining its slightly more complicated situation:
Another common peace-of-mind dialog is necessary permissions. Here’s a nice example from Audio Hijack:
One more category is cloud syncing. Here, Bear provides additional information about why a sync might be in trouble:
These three peace-of-mind functions seem pretty common these days, but here are a few more specific examples.
The SF Symbols app has a Check Installed Fonts… command to make sure the fonts are in order (SF Symbols don’t exist as a separate font, but piggyback on other fonts like SF Pro).
In Figma, we added a line at the bottom that plainly says “knowing all we know, your screen should be able to display the extra colors necessary for Display P3”:
Right inside notification settings, Slack allows you to click “Show an example” to summon a fake notification:
And even though none of these peace-of-mind functions above are very in-your-face, sometimes they get hidden even further. Here, the Detect Displays button only appears when you hold ⌥, allowing you to hasten auto detection:
And, in the previous Audio Hijack example, you could hold ⇧ to “flush the pipes”:
These might all feel somewhat disappointing. Shouldn’t those things just happen automagically? Why would I need to jump through hoops only to arrive at a window saying “everything is fine”?
The way I understand and appreciate it is that the creators of these know that there are limitations to magic: that some things cannot be guaranteed, or that users might have battle scars from other apps. Cloud syncing works like magic most of the time, but when I’m on a plane, I would love to have a written confirmation that everything has been synced. Sometimes I click Skip This Version on an update, and forget I did that. Permissions just go haywire once in a while.
These functions reduce the blast radius. If Figma tells me “your display supports P3” but I still don’t see the rich-gamut colors, I can turn my attention to the file itself, instead of wasting time debugging the part of the chain that isn’t actually broken. If I click “Show an example of a notification” in Slack and nothing comes out, I know the problem is somewhere ahead of Slack, likely in System Settings.
There is, of course, a risk that some of these anti-magical interfaces might end up like some loading states do – a self-fulfilling prophecy that makes the owners care less about things just working quietly and robustly in the background, without the user every worrying. But all of these above feel okay to me, giving me peace of mind that at least here, in this neck of the woods, everything is working well.
Previously, we also talked about Raycast’s confetti that could serve a similar purpose.
This is how interaction systems slowly fall apart. […] It is likely that Safari’s exception will now be treated as “blessed,” and start spreading further. Given enough time, more and more pills will go in whatever direction they want when dragged – and people will learn not to trust any of them.
I didn’t quite get this right, as it seems this hasalready happened. It might have been Safari that used a “blessed” interaction from elsewhere. Conversations with a few readers helped me piece together a larger story of how we got here. I fired off some of my old iPhones and emulators to verify them, and so let’s go back in time all the way to 2007.
Step 1: These rotary controls for timers have been here since the first iPhone. Note how you drag the background, not the selection, but that works because the background is styled as a physical object, you see the options extending in both directions, and the selection remains fixed in place.
Step 2: In iOS 7 in 2013, the camera app adopts a similar treatment, but on a horizontal plane. This is roughly as above, flattened, but with the background still extending in both directions, showing adjacent options. This also made some skeuomorphic sense because this control is very “mechanical” – you could imagine such a wheel on a real-life camera.
Step 3: In 2023, Safari follows in those footsteps for its tab groups (which originally was a more traditional menu). It might have felt like the right thing to reuse, but the control doesn’t feel as refined as the Camera’s. It also introduces the problems where tapping no longer scrolls to the initial position (mentioned in part 1) and the too-eager tab group creation overflow (mentioned in part 2).
Step 4: This is where the trouble begins. Camera gets redesigned for iOS 26 and liquid glass. The team decides to rearrange and simplify the control visually, but at a price of making the interactions feel more complex: there are now only two items visible by default (the background doesn’t extend to hint at other options in its resting state), the current selection no longer stays in place, and the control generally suggests tab-like interactions but doesn’t provide them.
Step 5: At some point in the beta process, the Camera team perhaps realizes the same thing I found challenging in part 2 – these now look like pills, and elsewhere the system taught us finger drag moves pills rather than the background. In iOS 26 beta 4, the direction is reversed compared to all previous versions of the app.
Step 6: Seemingly almost immediately, people complain, since many years of motor memory are now compromised. So, in beta 5, Apple adds a setting called “classic mode switching” – similar to natural scrolling years before, on macOS side.
Step 7: However, not long after that, in beta 6, Apple removes the setting and reverts to the original direction from steps 3–4.
Things that come to my mind:
Inverting the control to go the other way in step 5 was where the consequences of previous steps reared their ugly head. I imagine perhaps the strength of complaints surprised Apple, which found itself without a backup plan, between the rock and a hard place: earning either the immediate ire of power users (whose motor memory was disrespected) or the future ire of other users (who will experience no consistency between pilled controls going forward).
Adding a setting would be kicking the can down the road, but so is – as I hoped to establish in part 2 – leaving things as they are: There’s still a systemic problem where controls in Camera and Safari are now at odds with other pilled controls.
What makes a control a control is not paper principles, but a collection of details working together. Removing the extended background, restyling the control, and making the selection no longer stay in place might feel like small changes in isolation, but at some point Theseus would like a word. I see this sometimes in other surfaces, where individual UX changes compound over time, become basically dead reckoning, and result in a boiled frog.
I wonder if Apple succumbed somewhat to the “dumb consistency” problem: often it’s better to be inconsistent in a smart way than consistent in a dumb way. It might feel good for all the tabs and the pills and the toggles to look the same visually, but that feels like dumb consistency if they behave differently. It might seem good for Safari to reuse Camera’s toggle, but the Camera is generally a one-of-a-kind, bespoke app, so it has some leeway here. Safari doesn’t really get to play by those rules.
I am curious why the Camera team didn’t invert the direction and the ordering of things. In this case, two wrongs would make a right, and this would keep the motor memory intact. (I imagine the reason is that this would trip up people who remembered things cerebrally, rather than “in their fingers.”)
I feel the team wasn’t given or didn’t give itself enough time, which jibes with how unpolished the entire liquid glass effort was in its first year. In a perfect world, the camera control would probably have been redesigned again before launch to avoid tricking the motor memory – or perhaps the whole original iOS 26 change reverted.
That’s Camera. Where’s Safari in all that? Just where it started: Safari’s control today again seems just like a cheaper, more hurried, less thoughtful version of what Camera does. The Camera toggle doesn’t have the jarring “swipe to the left to create a new space” flow, doesn’t need to support tap to top, shows you the background affordance more readily, uses haptics, feels less buggy, and even only allows you to swipe one notch at a time, so the control feels precise and never runs away from you.
In the just-released iOS 27, the Camera is even slightly improved – it again shows more of its surroundings even before any swipes.
I haven’t noticed any updates to the Safari control.
The story of this entire system now appears to be this:
The Camera team made mistakes that could have been avoided; changes to deep motor memory do take years and have to be planned and approached with patience.
The Safari tabs have been drafting behind the Camera tabs, but still introducing smaller mistakes of their own: continuing to prioritize strange interactions in lieu of intuitive ones, and forgoing some of the nuance.
Both look like pills and, when dragged, go in the opposite direction as other pills in the system.
In all these screengrabs, I’m dragging my finger to the right:
I don’t, of course, know all the details, and I realize I am harsh in my assessment. I sympathize with the depth of the challenge not just for the team – motor memory can be brutal, and established interaction systems are really hard to evolve – but also in coordinating with other teams in a closed-off culture like Apple’s.
Then again, these are iPhone’s top-tier surfaces so I think it’s fair to expect excellence, and this is also not the first time Safari team has made some puzzling design choices. Perhaps most importantly, Apple is also the platform owner and they set the tone for other apps, which we’ve seen recently in their indirect influence over CleanShot’s settings.
I hope you found some interesting things in this long post. As a reminder why it all matters, and why protecting systems of interactions like tap to top (part 1), or slide on an object to move it in a predictable way (part 2) is important, this is a quote from one of the readers:
It’s actually worse [in Camera], because often you are in a bit of a hurry to take a picture and it behaving unexpectedly is the last thing you need. I had this once or twice: suddenly it was in video mode and by the time I had it back in regular photo mode, the train I was trying to photograph was long gone.
I’ll be curious if we see more evolution of these spaces, and hopeful Apple resolves the problems. But now, I’m ready to stop talking about Safari’s tabs for a while.
Thank you to Nikita Prokopov, Daniel Dickison, Jeremy Kanter, and Martin Hoffman.
A fun little video by Bofner talking about how two Castlevania games on the original Nintendo Game Boy achieved a certain visual effect that wasn’t technically possible:
What I really liked was this sequence of events:
Game Boy introduces a special immovable layer to accommodate HUD/GUI elements within games (such as score displays or life meters),
Castlevania programmers come up with a creative hack to use the HUD layer draw a movable spike wall instead,
then, they use another hack to draw the HUD anyway, outside of the HUD layer.
Here’s what happens when you try to update your Android phone if it’s low on battery (even if it’s connected to a charger):
It’s a pretty cheap error UI, a misaligned string thrown carelessly in between existing interface pieces. It doesn’t even bother explaining what “too low” means.
Compare this to what the Playdate does in the same situation:
If the device battery is depleted, the software simply charges if first to the necessary minimum (spelled out on screen), before automatically proceeding to the actual update – all without any user intervention.
We previously talked about fire-and-forget states, or interfaces which give you confidence that once the process starts, it will finish on its own. (If you don’t like military references, we could call these tap-and-walk-away.)
This is a really good example. There is even a nice corresponding version for when your Playdate needs to be plugged in first:
Once you do, the process again continues by itself right until the end.
Over the years, I learned about many gotchas and strange differences between keyboard handling on Mac and Windows – pertinent especially to web apps, which use the same codebase to cater to both. I thought it might be helpful to someone if I compile them all in one place.
This post is meant to be a reference, and there aren’t any cute or riveting stories hiding inside – if this seems boring to you, feel free to skip to the next one!
Different names for keys
What Windows calls Backspace, Mac calls Delete. What Windows calls Delete, Macs call Forward Delete. (This means saying “Delete” without specifying the platform might actually be confusing.)
What Windows calls ⏎ Enter, Mac calls ⏎ Return. However, Macs also have an ⌤ Enter, although only on a numeric keypad (previously, it was even there on laptops!). On keyboards without the physical Enter key, you can simulate it via Fn+Return.
In most Mac software, Enter and Return do the same thing. There are a few exceptions – for example, Photoshop adds a new line on Return but commits on Enter, and some classic pro apps like Cubase or Pro Tools do different things, too – but it seems to be a dying tradition. (If you are curious about the history of Return and Enter, I wrote about it once.)
Windows customarily calls the secondary key Numpad Enter. I don’t believe Fn+Enter works to simulate it.
Generally, third-party keyboards use Windows verbiage – so, Backspace and Enter. If a keyboard offers Mac conventions at all, they usually only extend to modifier keys.
Modifier keys
⌃ Control on Windows is the equivalent to ⌘ Command on a Mac. (Paste, for example, is ⌃V on Windows and ⌘V on a Mac.) But, confusingly, Apple devices still have a Control key, too. This was originally meant for terminal applications, but these days many GUI apps use it as an extra modifier key of much lesser significance than Control on Windows.
This means that for apps, Windows devices offer Ctrl, Alt, and Shift – and Macs offer ⌘ Command, ⌥ Option, ⌃ Control, and ⇧ Shift. That’s one more modifier key, and thus more space to breathe. (We’re not counting the Windows key or the 🌐 Globe/Fn key since those are technically reserved by the operating system.)
Some keyboards offer extra key caps you can swap to match the platform, for example:
Others cover all the bases on fixed key caps, in an awkward way:
Many stick with Windows-only legends.
(Just swapping the key caps is not enough. The keyboard also has to swap the scan codes it sends, since the code for Alt is the same as the code for ⌥, and the code for ⌘ is the same as the code for ⊞.)
Words vs. symbols
Apple devices rely more on symbols on their keys and in their menus, although they don’t do so consistently. Here are all of them:
⇧ Shift
⌃ Control
⌥ Option
⌘ Command
⏎ Return
⌤ Enter
🌐 Globe/Fn
⇥ Tab
⎋ Esc (not printed on keyboards, for some reason)
⌫ Delete
⌦ Forward Delete
⌧ Clear
≣ Contextual Menu (only on full-size keyboards)
⇞ Page Up (only on full-size keyboards)
⇟ Page Down (only on full-size keyboards)
↖ Home (only on full-size keyboards)
↘ End (only on full-size keyboards)
Actually, I lied about the last four. On modern Apple keyboards, they are:
↑ Page Up
↓ Page Down
⤒ Home
⤓ End
Reusing the regular arrows for Page Up and Down is one of a few perplexing decisions from Apple’s keyboard designers. The arrow key symbols look like this – ◀▶▲▼ – but only on Apple keyboards. Here is an older and a newer Apple keyboard showing what happened:
(Luckily, the confusing dual arrow key situation only happens on less popular, full-size keyboards.)
Historically, Apple keyboards used symbols more on non-US keyboards, but starting with the 2026 models, they unified when they show symbols and when they show symbols and legends, across all keyboards. (The only key with just a text legend is Esc, making the appearance of ⎋ in menus extra puzzling.)
Windows keyboards typically use words – this is why in tight quarters you sometimes see shortenings like Ctrl, Bkspc, PrtSc, Del, PgUp, Win, and so on. (I don’t think Apple ever abbreviates their legends with the exception of Esc for Escape.) In some countries, the legends are translated – as an example, in Germany, Ctrl sometimes appears as Strg.
The symbols that crossed over to Windows side are:
⇧ for Shift
⇪ or 🔒 or a similar symbol for Caps Lock (on non-US keyboards)
⏎ for Enter – note the same arrow as Mac’s ⏎ Return
← for Backspace – note a different arrow than Mac’s ⌫ Delete
⇥ for Tab (you can also sometimes see ⭾, which is a symbol representing Tab and Reverse Tab together; Reverse Tab used to be a separate key on some 1970s terminals)
⊞ for Windows key – the style of the logo will be different depending on the age of the keyboard, roughly matching the Windows logo at the time; some keyboards also use a more abstract shape, or call the key Start or System instead of Windows
≣ for contextual menu key (a.k.a. Application Key) – just as Apple added that key on its large keyboards, Microsoft started removing it in favor of emoji key, Office key, and then Copilot key
⌃ for Control (especially in nerdy contexts)
I have not seen any other popular symbols on the Windows side of the aisle, and I am not even sure if the above would be widely understood. But here’s an example:
Here is the same Chrome menu on Windows and on macOS:
(In other words, you’d never say “⌃V is Paste on Windows” like I did above.)
Function keys
Both Windows and Macs have function keys.
On Windows, traditionally those were claimed by the operating system or the apps as shortcuts. Here are some examples of well-known function key assignments:
Alt+F4 – close the app
F1 – help
F11 – maximize window
F12 – dev tools in browsers
On Macs, traditionally the apps didn’t reach for function keys, as those were reserved solely for the users to do stuff with. (However, some combination of ⌃ and function keys are used by the operating system for accessibility options, and I occasionally see apps use function keys these days.)
Windows keyboards top off at F12, but some Mac keyboards reuse the three special PC keys, and even take over the unnecessary Num Lock/Caps Lock/Scroll Lock island, and end up going up to F19:
Access to extra characters
In text fields, Apple has a system where pressing ⌥ with printing keys outputs more characters, for example ⌥Q outputs œ, and ⌥7 outputs a ¶ pilcrow. Additionally, ⇧ works in this context, so for example ⌥⇧Q outputs Œ, and ⌥⇧7 outputs a ‡ double dagger.
Note that not only letters, but basically all printing keys have secret ⌥ and ⌥⇧ assignments. (Also note some of these are dead keys.)
Also, ⌥ assignments vary per location! The above was U.S. English, here’s Polish with a lot of differences:
This means it’s best to avoid ⌥-based shortcuts in text fields, since they might conflict with some important character.
By the way, while the above two are just mock-ups, on some physical keyboards (here: British English), some of the important ⌥ invocations are actually printed on keys:
Windows doesn’t have the above feature. However, Windows has an alternative feature where typing Alt+numpad keys allows to enter any character by its code. (For example, Alt+0128 outputs €. Num Lock has to be enabled. I don’t think it’s possible to do it without a numeric keypad present.)
Mac has a version of this feature, but it requires adding Unicode Hex Input keyboard and switching to it beforehand. Then, pressing ⌥20AC outputs €.
Right Alt key on Windows
While Mac modifier keys are completely symmetrical, Windows makes an exception for Alt. On many non-US keyboards, right Alt is also known as AltGr, and does something similar to ⌥ on a Mac: it outputs letters when pressed in combination with printing keys.
For example, on Polish keyboards AltGr+A = ą, AltGr+C = ć, AltGr+Shift+A = Ą, and so on with 15 more combinations. Many other keyboards do similar things.
The way it differs from ⌥ on a Mac is that these are usually reserved for core letters and punctuation necessary for each language, rather than the typographical smorgasbord that Apple provides.
For legacy reasons, and also for keyboards that do not have a physical AltGr key, you can also invoke all these using Ctrl+Alt combinations instead (so, Ctrl+Alt+A = ą). This means that just as you have to be careful about ⌥-based shortcuts in text fields on a Mac, so you should be of Ctrl+Alt-based shortcuts on Windows.
Just like on Macs, on some keyboards, selected AltGr options will be printed in the corners or fronts of keys:
Text fields
Text fields in Mac OS apps and web browsers/websites use some of the standard Unix/Linux shortcuts based on the ⌃ Control key:
⌃A – move to the beginning of the line
⌃E – move to the end of the line
⌃F – move to the right, or forwards (hold ⌥ to jump through words)
⌃B – move to the left, or backwards (hold ⌥ to jump through words)
⌃N – move down or to the next command
⌃P – move up or to the previous command
⌃L – scroll the window so that the text cursor is in the vertical middle
⌃H – delete (backspace)
⌃D – forward delete
⌃K – delete (kill) to the end of the line
⌃T – swap (transpose) the adjacent characters
⌃O – insert new line, but (contrary to Return) do not move the cursor there
You can combine many of the above with holding ⇧ to extend the selection.
A small group of vocal users love these.
Windows still supports Shift+Delete for cut, Ctrl+Insert for copy, and Shift+Insert for paste. I am not sure how many people use these.
On a Mac, in simple input fields, ↑ and ↓ jumps to the beginning and end (same as ⌘←→). This often conflicts with command line history, autocomplete pop-ups, and so on.
Windows doesn’t have this convention, and Home and End serve this purpose instead.
Macs support the iPhone-inspired convention of holding a key to show related accented characters, instead of triggering auto-repeat. Windows doesn’t have this feature.
Differing shortcut conventions worth knowing about
On a Mac, redo is typically ⌘⇧Z. On Windows, it’s typically Ctrl+Y.
On a Mac, refresh (in browsers, etc.) is typically ⌘R. On Windows, it’s typically F5, although browsers support Ctrl+R, too, and seem to be shifting to that being the default.
Reserved keys
Windows’s eponymous ⊞ Windows key is reserved solely for the use of the operating system, and so is Mac’s 🌐 Fn/Globe key. (Although I am not 100% sure of that as I found one place you can create 🌐 shortcuts as a user – I’m just not certain if it’s intentional.)
However, each platform also has a lot of shortcut combinations that are effectively unavailable, for example ⌘⇥ and ⌘M on a Mac, or Alt+Tab and Ctrl+Shift+Escape on Windows.
If you’re a web app, you will compete for shortcuts with the operating system (like any app would), but also with the browser itself. You can typically take over shortcuts like ⌘S or ⌘P, but depending on the browser or the platform, some might be sacred and unavailable. No Mac browser will allow a website to claim ⌘Q, ⌘W, or ⌘T. Safari won’t allow a web app to override ⌘R. Arc browser won’t allow to override ⌘⇧C. (This is not a complete list.)
Jumping around
Tabbing and Shift tabbing is customarily used to jump between UI elements, but it behaves slightly differently in native apps.
On Windows, tabbing jumps through all interactive elements:
On Mac, Tab jumps only to those interactive elements that require keyboard to operate (such as input fields). You can toggle a System Settings preference and ask macOS to mimic Windows behaviour – see the last toggle below – but it’s not supported well everywhere.
PgUp and PgDn work differently:
On Windows, they move the text cursor a screen up or down.
On a Mac, they scroll the view up and down, but they do not move the text cursor if it’s present (so, they are more an equivalent of clicking on the scrollbar chute).
Similarly, Home and End work differently:
On Windows, they scroll the contents (and move the cursor if present) to the top or the bottom of a view, or move the cursor to the beginning or the end of an input field.
On a Mac, in views they scroll to the beginning or end without moving the cursor. In input fields, Home/End do nothing, but you can use ⌘←→ to accomplish the same.
On both platforms, Fn+↑↓ does PgUp/PgDn, and Fn+←→ does Home/End. (Do you see how confusing it is to say that given that ↑↓ already mean PgUp/Dn on a Mac?)
Windows has a tradition of enabling access to menus and visible controls by pressing Alt and letter keys. This has evolved over time and is not as consistent as it used to be, but it might be worth knowing about.
Less popular keys
On a 100-plus-key keyboard, Windows might have:
Insert – still used in some contexts for overtyping
In a strange twist of fate, it’s not only third-party keyboards that favor Windows legends. Some of Apple’s keyboards in between 1980s and 2000s showed PC legends, too! (This was to court PC compatibility of then-beleaguered Macs.) Here’s the classic Apple Extended Keyboard, showing legends for Insert, Delete (naming it Del to avoid confusion with its own), Print Screen, Scroll Lock, Pause, Num Lock, and Alt:
Did I miss anything or make a mistake? Let me know!