Visual system

Every chart and diagram on this site is inline SVG generated from the same data as the tables beside it, styled from the same tokens as the surrounding page, and animated under one motion policy. This page is the catalogue: for each layout, the decision that selects it, a text blueprint, and the rendered component.

Principles

Four rules that decide what a figure is allowed to do. They are the reason no chart here carries a heat map, a gradient, or a rounded corner.

Colour classifies

A mark's colour repeats the classification axis it belongs to — static, dynamic, collected, manual, ownership. It never encodes magnitude, and it never ranks. A bar and a status tag describing the same value always agree.

Every number is written

A bar carries its value as text, a point carries its name, an axis carries its ticks. Removing all colour from the page loses a grouping, never a fact.

Figures are data, not decoration

A figure appears only where it says something the adjacent table cannot. There are no hero images and no illustrative graphics; a figure that repeats its caption is deleted.

Motion is state, not entrance

Animation shows a value arriving or a state changing. Nothing loops except where the loop is the subject, and every rule is inside a reduced-motion guard.

Back to top

Motion system

Three durations and two easings. A transition that cannot be assigned one of them is not added.

linear — reserved for continuous motion that must not appear to decelerate: streaming pipeline dashes, the flywheel.
--ease, cubic-bezier(.2,.6,.2,1) — the default for state change: hover, focus, colour.
--ease-out, cubic-bezier(0,.7,.3,1) — arrivals: bars growing, lines drawing, a figure entering the viewport.

Specimen tracks replaying the three timing functions. With prefers-reduced-motion: reduce set, the pucks hold still and every rule below is inert.

TokenValueRoleApplied to
--dur-fast120 msPointer feedbackTag and cell hover, value labels appearing on a chart mark
--dur-base220 msState changeCard hover lift, navigation colour, focus ring
--dur-slow480 msArrivalBars growing from the axis, boxes fading in, the permalink flag
--dur-draw1100 msPath drawingLine series drawn along stroke-dashoffset
Stagger .d1.d860 ms eachSequencingA series reads left to right instead of arriving at once
animation-timeline: view()Scroll-linkedTriggerWhere supported, a figure animates as it enters; elsewhere it animates on load

The complete motion vocabulary. Durations are declared once as custom properties; no component defines its own timing.

Reduced motion is the floor, not a downgrade. Every animated rule on this site sits inside @media (prefers-reduced-motion: no-preference), so the reduced state is the plain stylesheet rather than a stripped variant of an animated one. Bars are drawn at full width, lines at full length, and no information is carried by the animation itself.

Back to top

Quantitative charts

Seven layouts covering comparison, trend, distribution, composition, and schedule. Each is drawn from the atlas dataset rather than from sample numbers, so the figure on this page is the same figure that appears in context.

Bar chart

Use when: one categorical dimension is compared on one measure, and the category labels are too long to fit under columns.

Cat A: [========]      80
Cat B: [=====]         50
Cat C: [==========]   100
       0 ------------ max
Dynamic scripting — 9. 9 of 38 indexed entriesDynamic scripting9C family — 8. 8 of 38 indexed entriesC family8ML and functional — 5. 5 of 38 indexed entriesML and functional5Systems and ownership — 4. 4 of 38 indexed entriesSystems and ownership4Managed runtimes — 4. 4 of 38 indexed entriesManaged runtimes4Array and statistical — 4. 4 of 38 indexed entriesArray and statistical4Lisp family — 2. 2 of 38 indexed entriesLisp family2Logic and declarative — 2. 2 of 38 indexed entriesLogic and declarative209
Indexed entries per family. Bars grow from the axis on entry; hovering or tabbing to a row raises it and shows the full note. Source: this atlas's index.

Column chart

Use when: the categorical dimension is itself ordered — decades, versions, releases — so position along the axis carries meaning.

 9 |           #
 6 |        #  #
 3 |  #  #  #  #  #  #
 0 +--------------------
   50s 60s 70s 80s 90s 00s
024791950s: 331950s1960s: 441960s1970s: 441970s1980s: 661980s1990s: 991990s2000s: 552000s2010s: 772010s2020s: 002020sentries
First appearances per decade. The empty 2020s column is the finding, not a gap: the decade's activity is in language revisions rather than new general-purpose languages.

Line chart

Use when: a measure is continuous over an ordered axis and the shape of the change matters more than any single value.

Val ^            _.-*
    |        _.-*
    |    _.-*
    +------------------> Time
0101928381950s1960s1970s1980s1990s2000s2010s2020sCumulative · 1950s: 33Cumulative · 1960s: 77Cumulative · 1970s: 1111Cumulative · 1980s: 1717Cumulative · 1990s: 2626Cumulative · 2000s: 3131Cumulative · 2010s: 3838Cumulative · 2020s: 3838CumulativePer decade · 1950s: 33Per decade · 1960s: 44Per decade · 1970s: 44Per decade · 1980s: 66Per decade · 1990s: 99Per decade · 2000s: 55Per decade · 2010s: 77Per decade · 2020s: 00Per decadeentries
Cumulative index size against new entries per decade. The line draws itself along its own path length; each point exposes its value on hover or focus.

Quadrant / 2×2

Use when: two independent axes place items relative to each other, and the interesting content is which quadrant something falls in, not its exact coordinate.

        Checked early
   (Static + GC) | (Static + manual)
 GC ------------+------------ Manual
   (Dynamic+GC) | (Dynamic+manual)
        Checked late
Managed and checkedManual and checkedManaged and late-boundManual and late-boundCollectedMixedManualDynamicStaticCCAdaAdaC++C++HaskellHaskellPythonPythonJavaJavaJavaScriptJavaScriptGoGoRustRustTypeScriptTypeScriptSwiftSwiftZigZigMemory control given to the programmerType checking done before running
Twelve languages on two classification axes. Positions are ordinal, not measured — the chart shows grouping, and deliberately carries no numeric scale to be over-read.

Radar / spider

Use when: three or more comparable subjects are scored on the same small set of axes and the shape of the profile is the point.

              [Safety]
                 |
     [Speed]---\ | /---[Interop]
               \|/
       [Tooling]-+-[Simplicity]
Compile-time safetyInteroperabilityTooling in the boxRuntime predictabilitySmall-language simplicitySwiftRustGo
Editorial scores on five axes, stated as such. A radar is the one layout here whose values are a judgement; it is used for shape comparison only and never totalled into a score.

Gantt

Use when: several items occupy spans on one shared axis and the overlap between them is the question.

Task 1: [====]
Task 2:     [======]
Task 3:           [===]
        W1  W2  W3  W4  W5
20142017202020232026Swift 4 mode — 2017Swift 4 mode2017Swift 4.2 mode — 2018Swift 4.2 mode2018Swift 5 mode — 2019 to todaySwift 5 mode2019 to todaySwift 6 mode — 2024 to todaySwift 6 mode2024 to todayABI stability — from 5.0ABI stabilityfrom 5.0
Language mode lifetimes. Swift's modes are cumulative rather than successive — every mode a compiler has ever shipped stays selectable per module, which is what the overlapping bars show.

Stacked bar

Use when: each category splits into parts of a whole and both the total and the split matter.

Family A |####----|  8
Family B |######  |  6
         collected  manual
Dynamic scriptingDynamic scripting · Collected: 999C familyC family · Collected: 33C family · Manual: 558ML and functionalML and functional · Collected: 555Systems and ownershipSystems and ownership · Manual: 22Systems and ownership · Ownership: 224Managed runtimesManaged runtimes · Collected: 444Array and statisticalArray and statistical · Collected: 33Array and statistical · Manual: 114Lisp familyLisp family · Collected: 222Logic and declarativeLogic and declarative · Collected: 11Logic and declarative · Engine: 112CollectedManualOwnershipEngine
Memory model composition per family. The segment colours are the same ones the memory pages and the status tags use, so the chart needs no legend of its own to be read against them.

Pyramid / funnel

Use when: levels are ranked and each one rests on the one below, or a population narrows at each step.

        /  \
       / L1 \    (strategic)
      /------\
     /   L2   \  (tactical)
    /----------\
   /     L3     \ (foundational)
Application codewhat the user runsStandard librarycollections, strings, concurrencyLanguage runtimereference counting, metadata, dispatchOperating system and hardwarethreads, allocator, memory model
The strata a language sits on. Width encodes breadth of responsibility, not quantity; the layout is chosen when the resting-on relationship is the message.

Layers

Use when: the same stacking is better read as equal tiers, because each one has a name and a note rather than a size.

+-----------------------------+
| Layer 3: Presentation       |
+-----------------------------+
| Layer 2: Domain services    |
+-----------------------------+
| Layer 1: Infrastructure     |
+-----------------------------+
Sourcewhat the author writes; one language mode per moduleSILSwift-level optimisation: ARC, generics, exclusivityLLVM IRtarget-independent optimisation and code generationObject codelinked against the runtime and standard library
The swiftc lowering stack. Layers is the right layout when tiers are equal in importance and the reader needs the note beside each one; a pyramid would falsely imply the base is the largest.

Venn

Use when: two sets overlap and naming the intersection is the whole point.

     /-----\      /-----\
    /   A   \    /   B   \
   (    ( A and B )       )
    \       /    \       /
     \-----/      \-----/
Statically typed21 of 38 entriesGarbage collected27 of 38 entriesBoth10 entries
Static typing and tracing collection are independent choices: ten indexed languages take both, which is why this atlas treats type discipline and memory model as separate axes rather than one spectrum.

Back to top

Structural diagrams

Six layouts for things that have parts. The distinction that decides between them is whether the relationship is containment, descent, connection, or reference.

Architecture

Use when: components, tiers and the connections between them, where the reader needs to know what talks to what.

[Client] --> [API Gateway] --> [Service]
                  |              |
                  v              v
              [(Queue)]     [(Database)]
swift buildSwiftPM manifestswiftc driverone job per fileModule.swiftmoduleSIL optimiserSwift-level passesLLVM IRtarget codegenMacro pluginseparate processObject file.o, then linkedexpansion
The Swift build pipeline as components. The dashed animated edge marks the one connection that leaves the compiler process: macro expansion runs in a separate sandboxed plugin.

Nested / box-in-box

Use when: the relationship is containment — every inner thing is inside exactly one outer thing.

+---------------- Module ------------+
| +---------- File ----------------+ |
| | [Type A]      [Type B]         | |
| +--------------------------------+ |
+------------------------------------+
PackageModuleFileprivatefileprivate
Swift's access levels are defined by containment, which is why they are drawn this way: internal stops at the module boundary, package at the package boundary, and private at the enclosing declaration.

Tree

Use when: a single root descends into children and no node has two parents.

          [ Root ]
         /   |    \
      [B1]  [B2]  [B3]
      /  \    |
   [L1] [L2] [L3]
AnyValue typesReference typesAbstractionsstructenumclassactorprotocolsome P / any P
Swift's type kinds. A tree is correct here because the division is exhaustive and disjoint; where a thing can have several parents, the nested or architecture layouts are used instead.

Org chart

Use when: the tree encodes ownership and routing — who decides, who is asked, where a change goes.

          [ Core team ]
        /              \
   [ Workgroup ]    [ Workgroup ]
    /       \         /      \
 [SG]      [SG]    [SG]     [SG]
Swift Core TeamLanguage Steering GroupPlatform Steering GroupEcosystem Steering GroupEvolution reviewLanguage modesLinux, WindowsAndroid, EmbeddedSwiftPM, DocCTesting, Format
Swift project governance. An org chart differs from a tree only in what the edge means — here it is “delegates authority to”, which tells a contributor where a proposal is decided.

ER / data model

Use when: entities have identity, fields and keys, and the cardinality between them is load-bearing.

+-------------+      +--------------+
| PACKAGE     |1    *| TARGET       |
+-------------+------+--------------+
| PK name     |      | PK name      |
|    products |      | FK package   |
+-------------+      +--------------+
PackagePK nameproductsdependenciesswiftLanguageModes1*TargetPK nameFK packagetypeswiftSettings1*Source filePK pathFK targetlanguage mode
A package manifest as a data model. The cardinality labels are the content: the language mode is a property of the target, not the package, which is what makes incremental Swift 6 migration possible.

Timeline

Use when: events sit at points on one axis and the reader needs their order and their spacing.

--(2014)---[ 1.0 ]---------------->
--(2019)---[ ABI stable ]--------->
--(2024)---[ Swift 6 ]------------>
20141.0 announced2015Open sourced2019ABI stability2021async / await2024Swift 6 mode20266.3 series
Six milestones on one axis. Cards alternate above and below the line so labels never collide; the axis is ordinal, and unequal real intervals are not implied to be equal.

Loop / flywheel

Use when: the process has no end state — its output is its own next input.

        --> [Build] --
       /              \
  [Monitor]        [Deploy]
       \              /
        <-- [Test] <--
PitchProposalReviewDecisionImplementation
The Swift Evolution cycle. The ring rotates continuously because the loop itself is the subject; this is the only figure on the site that animates indefinitely.

Back to top

Flow and process

Five layouts for things that happen in an order. The choice between them is whether the axis is logic, time, actor, or data.

Flowchart

Use when: a decision branches the path and the reader has to follow one branch to an outcome.

   [Start] --> < Decision? >
                  | Yes  | No
                  v      v
            [Action A] [Action B]
StartCompiles inSwift 6 mode?Adopt the modeset swiftLanguageMode(.v6)Stay on 5fix diagnostics firstyesno
The per-module migration decision. A flowchart earns its space only when there is a real branch; a straight run of steps is a process flow instead.

Process flow

Use when: the steps are sequential with no branch, and naming the handoffs is what the reader needs.

[Intake] -> [Validate] -> [Execute] -> [Log]
ParseSwiftSyntaxASTType-checkconstraint solvertyped ASTLower to SILARC, genericsSILEmitLLVM IR, object
The four stages of swiftc, with the artefact that crosses each boundary named on the edge. Moving dashes indicate direction without an animated legend.

Data flow

Use when: the diagram is about what moves between stages, and the transport or schema is as important as the stage.

[Producer] ==(Kafka)==> [Spark] ==(S3)==> [DW]
Declaration@freestanding / @attachedsyntax treePlugin processSwiftSyntax, sandboxednew syntaxExpansionsyntax insertedexpanded sourceType-checkexpansion checked too
Macro expansion as a data flow. The same layout as a process flow, with the payload rather than the step carrying the label — here it matters that the plugin receives and returns syntax, never types.

Sequence

Use when: several participants exchange messages and the ordering between them over time is the subject.

Actor     Service      DB
  |          |          |
  |--req---->|          |
  |          |--query-->|
  |          |<--rows---|
  |<--res----|          |
CallerActor StoreDiskawait store.value(k)read (suspends; actor released)bytesvalue — state may have changed
Actor reentrancy, which is hard to state in prose and obvious on a time axis: the suspension in the middle releases the actor, so any state read before the await may be stale after it.

State machine

Use when: a thing occupies exactly one of a fixed set of states and named events move it between them.

(Draft) --[Submit]--> (Review) --[Approve]--> (Live)
   ^                     |
   +-------[Reject]------+
SuspendedRunningCancelledresumecancel()cooperative check, then unwinds
A Swift task's lifecycle. The back edge is the point: cancellation sets a flag rather than stopping the task, so the transition out of Cancelled happens only when the task next checks.

Swimlane

Use when: the same process crosses several actors and the handoff between them is where the cost or the risk is.

Lanes  | Step 1    Step 2    Step 3
User   | [Req] ------+
Ops    |             v
       |          [Proc] ---> [Done]
AuthorWrite moduleCompilerCheck isolationReviewerRead diagnosticsAuthorAnnotate, rebuildLaneStep 1Step 2Step 3Step 4
Migration as a cross-functional process. The lane change is the content: the compiler, not the reviewer, is the participant that finds data races, which is what changes the review's job.

Back to top

Futures

What this design system is not doing yet, and why. Recorded as decisions rather than a backlog, so a later reader can tell a deliberate omission from an oversight.

Platform capabilityAvailabilityWhat it would buyDecision here
animation-timeline: view()Shipping in Chromium and SafariFigures animate as they enter the viewport, with no scroll listenerIn use behind @supports; elsewhere figures animate once on load
@view-transitionShipping for same-document; cross-document rolling outCross-page navigation could keep the header and nav fixed while the article changesNot adopted: the site is nine static pages and the transition would be decoration
Container queriesInteroperableA chart could choose its own label density from its own width instead of the viewport'sUsed for the motion specimens; charts still key off the viewport
text-wrap: balance / prettyInteroperableHeadings and captions break without a one-word last lineCandidate; needs checking against the dense table captions first
Dark colour schemeAvailable nowA second token block under prefers-color-schemeDeliberately not shipped: the palette is tuned for contrast on paper-white and would need re-deriving, not inverting
@scopeShipping in Chromium and SafariComponent styles could be bounded without class prefixesNot needed at this size; the whole stylesheet is under 20 KB
Scroll-driven progress indicatorAvailable nowA reading-progress rule on long reference pagesCandidate for the Swift article, which is the only page long enough to want one

Availability describes browser support at the time of writing, August 2026. Every row marked as in use is behind an @supports query or a media query, so no page depends on it.

The constraint that holds

No runtime framework and no JavaScript. Every interaction on this site — scroll-triggered figures, hover values, keyboard-scrollable tables, focus rings — is CSS and SVG. Anything that cannot be built that way is not built.

What would change that

Sorting and filtering the comparison matrices are the only features worth script, and only if the tables outgrow reading. Until then, ordering is editorial and stated in each caption.

How a figure gets added

A generator in viz.py, called with real data from atlas.py. A figure whose numbers are typed in by hand rather than derived is a diagram, and is labelled as one.

Back to top