Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,11 @@ shadows, three easings.
your bundler fingerprints them out of `node_modules`. You do not need a copy in
`static/fonts`.

**Marks** — `EngineWordmark` and `EngineIcon`, vector, in the two sanctioned
colourways (`variant="primary"` white, `variant="secondary"` Off Black). Size
by height alone. The wordmark is artwork, not type — with the vector in the
package there is no reason to typeset "engine" in Proxima Nova again.

**Primitives** — Alert, Badge, Button, Card, Checkbox, Dialog, Input, Label,
Popover, Progress, RadioGroup, Select, Separator, Skeleton, Switch, Table, Tabs,
Textarea, Tooltip.
Expand Down
6 changes: 5 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@engineio/ui",
"version": "0.0.0-development",
"description": "The Engine design system tokens, fonts and Svelte primitives.",
"description": "The Engine design system \u2014 tokens, fonts and Svelte primitives.",
"license": "UNLICENSED",
"private": false,
"type": "module",
Expand Down Expand Up @@ -38,6 +38,10 @@
"./components/ui/*": {
"types": "./dist/components/ui/*/index.d.ts",
"svelte": "./dist/components/ui/*/index.js"
},
"./components/brand": {
"types": "./dist/components/brand/index.d.ts",
"svelte": "./dist/components/brand/index.js"
}
},
"scripts": {
Expand Down
1 change: 1 addition & 0 deletions src/app.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="color-scheme" content="dark" />
<title>Engine Design System</title>
<link rel="icon" href="data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%22-95%200%201000%201000%22%3E%3Cpath%20fill%3D%22%23fff%22%20fill-rule%3D%22evenodd%22%20clip-rule%3D%22evenodd%22%20d%3D%22M809.525%20207.792H755.007C786.985%20265.518%20805.192%20331.931%20805.192%20402.597C805.192%20521.09%20754%20627.625%20672.527%20701.297C745.977%20767.713%20794.816%20860.839%20803.724%20965.356C805.349%20984.429%20789.676%201000%20770.534%201000H632.061C612.919%201000%20597.724%20984.35%20594.357%20965.507C578.074%20874.372%20498.414%20805.195%20402.597%20805.195C306.78%20805.195%20227.121%20874.372%20210.837%20965.507C207.47%20984.35%20192.275%201000%20173.134%201000H34.6592C15.5177%201000%20-0.154779%20984.429%201.4707%20965.356C10.3784%20860.84%2059.2162%20767.714%20132.665%20701.298C51.192%20627.626%203.5177e-05%20521.09%200%20402.597C0%20180.249%20180.249%200%20402.597%200H809.525V207.792ZM402.597%20207.793C295.009%20207.793%20207.792%20295.01%20207.792%20402.598C207.792%20510.185%20295.009%20597.402%20402.597%20597.402C510.184%20597.402%20597.401%20510.185%20597.401%20402.598C597.401%20295.01%20510.184%20207.793%20402.597%20207.793Z%22%2F%3E%3C%2Fsvg%3E" />
%sveltekit.head%
</head>
<body data-sveltekit-preload-data="hover">
Expand Down
75 changes: 75 additions & 0 deletions src/lib/components/brand/engine-icon.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
<script lang="ts" module>
/**
* The two sanctioned colourways, and the only two.
*
* primary — Pure White, for the dark surfaces the brand actually uses
* secondary — Off Black, for print, letterhead and inverted brand panels
*
* These are named after the source artwork (Engine_Primary_Icon.svg /
* Engine_Secondary_Icon.svg) rather than after the colour, so the files and
* the code agree.
*/
export type EngineMarkVariant = "primary" | "secondary"
</script>

<script lang="ts">
import { cn } from "$lib/utils.js"
import type { SVGAttributes } from "svelte/elements"

// The Engine figure mark. Vector, from the brand team's own artwork — which
// closes the gap the earlier marks had: every previous badge and lockup in
// this system was a raster extraction from deck page images at roughly 29px,
// and went soft above 24px. This scales.
//
// THE MARK IS ARTWORK, NOT AN ICON. The brand allows it in white or Off
// Black and nothing else — never outlined, stretched, skewed, or recoloured.
// That is why colour is a two-value `variant` rather than `currentColor`:
// with currentColor any ancestor's text colour silently becomes brand
// colour, and a magenta wordmark is one careless `text-primary` away. The
// variant makes the sanctioned choice the only reachable one.
//
// Sizing is by class, and height-only: `class="h-8"` with width following
// from the viewBox. Never set both — the brand forbids distortion, and the
// 810x1000 ratio is not one anybody reproduces by hand.

let {
ref = $bindable(null),
variant = "primary",
class: className,
title,
...restProps
}: SVGAttributes<SVGSVGElement> & {
ref?: SVGSVGElement | null
variant?: EngineMarkVariant
/**
* Accessible name. Omit when the mark sits beside the word "Engine" or
* other naming text — then it is decorative and gets aria-hidden, so a
* screen reader does not announce the brand twice.
*/
title?: string
} = $props()
</script>

<svg
bind:this={ref}
viewBox="0 0 810 1000"
xmlns="http://www.w3.org/2000/svg"
class={cn(
"h-8 w-auto shrink-0",
variant === "primary" ? "text-foreground" : "text-background",
className,
)}
role={title ? "img" : undefined}
aria-hidden={title ? undefined : "true"}
{...restProps}
>
{#if title}
<title>{title}</title>
{/if}
<path
fill="currentColor"
fill-rule="evenodd"
clip-rule="evenodd"
d="M809.525 207.792H755.007C786.985 265.518 805.192 331.931 805.192 402.597C805.192 521.09 754 627.625 672.527 701.297C745.977 767.713 794.816 860.839 803.724 965.356C805.349 984.429 789.676 1000 770.534 1000H632.061C612.919 1000 597.724 984.35 594.357 965.507C578.074 874.372 498.414 805.195 402.597 805.195C306.78 805.195 227.121 874.372 210.837 965.507C207.47 984.35 192.275 1000 173.134 1000H34.6592C15.5177 1000 -0.154779 984.429 1.4707 965.356C10.3784 860.84 59.2162 767.714 132.665 701.298C51.192 627.626 3.5177e-05 521.09 0 402.597C0 180.249 180.249 0 402.597 0H809.525V207.792ZM402.597 207.793C295.009 207.793 207.792 295.01 207.792 402.598C207.792 510.185 295.009 597.402 402.597 597.402C510.184 597.402 597.401 510.185 597.401 402.598C597.401 295.01 510.184 207.793 402.597 207.793Z"
/>
</svg>
86 changes: 86 additions & 0 deletions src/lib/components/brand/engine-wordmark.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
<script lang="ts">
import { cn } from "$lib/utils.js"
import type { SVGAttributes } from "svelte/elements"
import type { EngineMarkVariant } from "./engine-icon.svelte"

// The Engine wordmark. Vector, from the brand team's artwork.
//
// "The engine wordmark is a custom soft-rounded face, not Proxima Nova. It is
// artwork. Never set the wordmark in type, never approximate it in a
// lookalike, never outline, stretch, skew or recolour it beyond white / Off
// Black." That rule is the reason this component exists at all — with the
// vector in the package there is no longer any excuse to typeset "engine" in
// Proxima Nova and hope.
//
// Colour is the same two-value variant as EngineIcon, for the same reason:
// `currentColor` would let any ancestor's text colour become brand colour.
//
// Sizing is height-only by class. The mark is 2000x449, so `class="h-6"`
// gives a ~107px-wide wordmark — check the small end, because the counters in
// the two "e"s and the "g" close up before the shape stops being legible.
// Master-brand surfaces carry this; a sub-brand surface carries a lockup
// (wordmark plus the sub-brand name), which this package does not ship
// because the badge artwork is still raster.

let {
ref = $bindable(null),
variant = "primary",
class: className,
title = "Engine",
...restProps
}: SVGAttributes<SVGSVGElement> & {
ref?: SVGSVGElement | null
variant?: EngineMarkVariant
/**
* Accessible name, defaulting to "Engine" — unlike the icon, a wordmark
* carries the company name as its content, so it is almost never
* decorative. Pass `title={undefined}` to hide it from screen readers when
* it sits next to naming text.
*/
title?: string | undefined
} = $props()
</script>

<svg
bind:this={ref}
viewBox="0 0 2000 449"
xmlns="http://www.w3.org/2000/svg"
class={cn(
"h-6 w-auto shrink-0",
variant === "primary" ? "text-foreground" : "text-background",
className,
)}
role={title ? "img" : undefined}
aria-hidden={title ? undefined : "true"}
{...restProps}
>
{#if title}
<title>{title}</title>
{/if}
<g fill="currentColor">
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M1124.28 93.2987H1099.82C1114.16 119.218 1122.33 149.036 1122.33 180.765C1122.33 233.968 1099.36 281.802 1062.82 314.881C1095.77 344.704 1117.68 386.522 1121.67 433.456C1122.4 442.013 1115.38 448.999 1106.8 449H1044.66C1036.08 449 1029.27 441.978 1027.76 433.524C1020.46 392.599 984.73 361.532 941.748 361.532C898.765 361.532 863.032 392.599 855.733 433.524C854.225 441.978 847.414 449 838.835 449H776.699C768.119 449 761.096 442.013 761.823 433.456C765.816 386.523 787.723 344.704 820.671 314.881C784.127 281.802 761.163 233.968 761.163 180.765C761.164 80.9315 842.013 0.000368566 941.745 0H1124.28V93.2987ZM941.748 93.2987C893.491 93.2994 854.371 132.459 854.37 180.765C854.37 229.071 893.49 268.232 941.748 268.233C990.005 268.233 1029.13 229.071 1029.13 180.765C1029.13 132.459 990.005 93.2987 941.748 93.2987Z"
/>
<path
d="M557.281 3.88776C656.366 3.88775 736.812 83.771 737.853 182.71H737.865V345.983C737.865 354.57 730.909 361.532 722.33 361.532H660.194C651.615 361.531 644.661 354.57 644.661 345.983V184.652L644.631 182.395C643.435 135.132 604.785 97.1865 557.281 97.1865C509.777 97.1869 471.127 135.132 469.931 182.395L469.903 184.652V345.983C469.903 354.57 462.949 361.531 454.371 361.532H392.234C383.656 361.532 376.7 354.57 376.699 345.983V182.71H376.711C377.753 83.7712 458.196 3.88812 557.281 3.88776Z"
/>
<path
d="M1225.24 0C1233.82 0.00063118 1240.78 6.9616 1240.78 15.5485V345.981C1240.78 354.568 1233.82 361.531 1225.24 361.532H1163.11C1154.53 361.531 1147.57 354.567 1147.57 345.978V15.551C1147.57 6.96271 1154.53 0.00051524 1163.11 0H1225.24Z"
/>
<path
d="M1444.66 3.88776C1543.75 3.88775 1624.19 83.7707 1625.23 182.71H1625.24V345.983C1625.24 354.57 1618.29 361.532 1609.71 361.532H1547.58C1539 361.532 1532.04 354.57 1532.04 345.983V184.652L1532.01 182.395C1530.81 135.132 1492.16 97.1865 1444.66 97.1865C1397.16 97.1869 1358.51 135.132 1357.31 182.395L1357.28 184.652V345.983C1357.28 354.57 1350.33 361.531 1341.75 361.532H1279.61C1271.03 361.532 1264.08 354.57 1264.08 345.983V182.71H1264.09C1265.13 83.7709 1345.57 3.88812 1444.66 3.88776Z"
/>
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M180.582 3.88776C279.667 3.88775 360.113 83.771 361.154 182.71H361.166V198.258C361.166 206.846 354.212 213.809 345.633 213.809H100.481C113.966 244.699 144.753 266.288 180.582 266.288C201.923 266.288 221.478 258.63 236.652 245.909C242.288 241.184 250.272 239.768 256.639 243.448L312.403 275.674C320.364 280.275 322.649 290.798 316.601 297.727C283.498 335.638 234.834 359.587 180.582 359.587C82.7983 359.586 3.17237 281.787 0.097158 184.652H0C3.50508e-06 183.679 0.00958911 182.707 0.0249123 181.737C0.00958911 180.767 3.50462e-06 179.796 0 178.822H0.097158C3.17237 81.687 82.7983 3.88812 180.582 3.88776ZM180.582 97.1865C147.053 97.1867 117.94 116.093 103.289 143.835H257.875C243.224 116.093 214.111 97.1865 180.582 97.1865Z"
/>
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M1819.42 3.88776C1918.5 3.88775 1998.95 83.771 1999.99 182.71H2000V198.258C2000 206.846 1993.05 213.809 1984.47 213.809H1739.32C1752.8 244.699 1783.59 266.288 1819.42 266.288C1840.76 266.288 1860.31 258.63 1875.49 245.909C1881.12 241.184 1889.11 239.768 1895.47 243.448L1951.24 275.674C1959.2 280.275 1961.48 290.798 1955.43 297.727C1922.33 335.638 1873.67 359.587 1819.42 359.587C1721.63 359.586 1642.01 281.787 1638.93 184.652H1638.83C1638.83 183.679 1638.84 182.707 1638.86 181.737C1638.84 180.767 1638.83 179.796 1638.83 178.822H1638.93C1642.01 81.687 1721.63 3.88812 1819.42 3.88776ZM1819.42 97.1865C1785.89 97.1867 1756.77 116.093 1742.12 143.835H1896.71C1882.06 116.093 1852.94 97.1865 1819.42 97.1865Z"
/>
</g>
</svg>
4 changes: 4 additions & 0 deletions src/lib/components/brand/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import EngineIcon, { type EngineMarkVariant } from "./engine-icon.svelte"
import EngineWordmark from "./engine-wordmark.svelte"

export { EngineIcon, EngineWordmark, type EngineMarkVariant }
6 changes: 6 additions & 0 deletions src/lib/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,12 @@ export type {
WithoutChildrenOrChild,
} from "./utils.js"

export {
EngineIcon,
EngineWordmark,
type EngineMarkVariant,
} from "./components/brand/index.js"

export {
Alert,
AlertDescription,
Expand Down
52 changes: 47 additions & 5 deletions src/routes/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
DialogHeader,
DialogTitle,
DialogTrigger,
EngineIcon,
EngineWordmark,
Input,
Label,
Popover,
Expand Down Expand Up @@ -111,11 +113,15 @@
<TooltipProvider>
<div class="mx-auto max-w-[1480px] px-10 py-16">
<header class="pb-14">
<p
class="mb-4 font-mono text-[11px] font-semibold tracking-[0.08em] text-grey-400 uppercase"
>
Engine · Design System · {__DS_VERSION__}
</p>
<div class="mb-6 flex items-center gap-4">
<EngineWordmark class="h-7" />
<span class="h-6 w-px bg-grey-700"></span>
<p
class="font-mono text-[11px] font-semibold tracking-[0.08em] text-grey-400 uppercase"
>
Design System · {__DS_VERSION__}
</p>
</div>
<h1 class="max-w-[920px] text-[72px] leading-[0.94] font-bold tracking-[-0.02em]">
One system. Every surface.
</h1>
Expand All @@ -127,6 +133,42 @@
</p>
</header>

<Section
eyebrow="Section 00"
title="Marks."
note="Vector artwork from the brand team, in the only two colourways the brand sanctions — Pure White for dark surfaces, Off Black for print and inverted panels. The wordmark is a custom soft-rounded face, not Proxima Nova: it is artwork, never set in type and never approximated."
>
<Row label="Wordmark — master brand surfaces">
<EngineWordmark class="h-8" />
</Row>
<Row label="Figure mark">
<EngineIcon class="h-14" title="Engine" />
</Row>
<Row label="Secondary, on an inverted panel">
<div class="flex items-center gap-8 rounded-card bg-foreground px-8 py-6">
<EngineWordmark variant="secondary" class="h-8" />
<EngineIcon variant="secondary" class="h-10" />
</div>
</Row>
<Row label="Scale — height-only, never both dimensions">
<div class="flex items-end gap-8">
<EngineIcon class="h-6" />
<EngineIcon class="h-8" />
<EngineIcon class="h-12" />
<EngineIcon class="h-16" />
</div>
</Row>
<p class="max-w-[920px] text-[15px] leading-[1.45] text-grey-300">
Colour is a two-value <span class="font-mono text-[13px]">variant</span>
rather than <span class="font-mono text-[13px]">currentColor</span> on
purpose: with currentColor any ancestor's text colour silently becomes
brand colour, and a magenta wordmark is one careless
<span class="font-mono text-[13px]">text-primary</span> away. Size by
height alone — the brand forbids distortion, and neither the 810:1000
nor the 2000:449 ratio is one anybody reproduces by hand.
</p>
</Section>

<Section
eyebrow="Section 01"
title="Colour."
Expand Down