Reference
How screens work
Designing an app screen is just this: a view (the things on screen) that reads some state (the facts the app remembers). A tap changes the state; the screen re-reads it. Once you can picture that, you can read a screen’s code and SEE the next screen before you tap. Here’s the model. Open the design lab →
- A screen is the view re-reading its state
The “view” is the list of things on the screen — a Text, a Toggle, a Button. The “state” is the little facts the app remembers — a number, a true/false, a word. The screen you SEE is just the view reading the state right now. Change the state and the same view shows a different screen.
- A tap runs an action
A Button (or a Toggle) carries an action: `stars += 1`, `vol = 0`, `soundOn.toggle()`. Tapping it runs that action, which changes ONE piece of state. Then the whole view re-reads the state and the screen updates.
- Text can read a value with \(…)
`Text("Stars: \(stars)")` prints the words “Stars: ” and then whatever `stars` is right now. When the number changes, the text changes with it — you don’t rewrite the Text, the state does the work.
- A Toggle is a true/false switch
`Toggle("Sound", soundOn)` shows the label and reads `soundOn` as On or Off. Tapping it flips true↔false — the simplest state there is.
- An if shows a line only when its test is true
`if soundOn { Text("🔊 On") }` puts that Text on screen ONLY when `soundOn` is true. Flip the state and the line appears or disappears. Two ifs — `if x` and `if x == false` — act like “this OR that”, exactly one showing.
- An action touches only its own variable
A button whose action is `score += 1` changes ONLY `score`. It does not touch the Hints toggle or anything else. If a screen part didn’t depend on `score`, it won’t move.
- One tap can cross a threshold
If a badge lives inside `if pts >= 10` and you have 8, one tap of “+2” reaches 10 — so the SAME tap that changes the number also makes the badge appear. Watch for the tests an action’s change might newly pass (or fail).
The dialect pieces
Text("Stars: \(stars)")Show text; \(var) reads a state value into it.Toggle("Sound", soundOn)A true/false switch bound to a state var; a tap flips it.Button("Add") { stars += 1 }A tappable control; the { … } is the action it runs on the state.if soundOn { … }Show the inside lines only while the test is true.stars += 1 · vol = 0 · soundOn.toggle()Actions: add/subtract, set to a value, or flip a switch.
Where this idea comes from
Buttons that say "press me"
The designer Don Norman wrote that a thing has an affordance (what it lets you do: a button can be pressed) and a signifier (what tells you so: it looks raised, it has a label). A screen goes wrong when the two disagree.
One thing to hold: ScreenForge’s own old screens. The picture screens you predict used to show buttons you could not press — a signifier with no affordance. Now a button in a picture is greyed and says "picture", and only the live screen has buttons and switches you can press.
Why it matters: In 2012 Evan Czaplicki’s Elm drew the whole screen as a value computed from inputs that change over time, and drew it again when they changed. Screen-building tools now put it as "the view is a function of the state", and ScreenForge works that way.
What we don’t know: Designers still argue about the word "affordance". Norman said people were using the word he brought into design wrongly, which is why he added "signifier" in 2008.
Dates:
- 1988 Norman writes about affordances in everyday things.
- 2008 Norman adds signifiers: what tells you what you can do.
- 2012 Elm draws a screen from its state, again on every change.
The trick to reading a screen is to find the ONE variable a tap changes, then re-read every line: a Text
re-reads it, a Toggle flips it, an if shows or hides its line. That’s the whole app.
Design a screen →