<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" xmlns:googleplay="http://www.google.com/schemas/play-podcasts/1.0"><channel><title><![CDATA[UI Engineering Excellence: Deeps]]></title><description><![CDATA[Hard builds and deep dives, from showstoppers to work worth bookmarking. Expect clear trade-offs and measured results.]]></description><link>https://blog.robhameetman.com/s/deeps</link><image><url>https://substackcdn.com/image/fetch/$s_!deTI!,w_256,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdc5e8141-3a0f-4181-8804-acdbb61e8707_359x359.png</url><title>UI Engineering Excellence: Deeps</title><link>https://blog.robhameetman.com/s/deeps</link></image><generator>Substack</generator><lastBuildDate>Wed, 15 Apr 2026 16:53:44 GMT</lastBuildDate><atom:link href="https://blog.robhameetman.com/feed" rel="self" type="application/rss+xml"/><copyright><![CDATA[Robert Henry Hameetman]]></copyright><language><![CDATA[en]]></language><webMaster><![CDATA[robhameetman@substack.com]]></webMaster><itunes:owner><itunes:email><![CDATA[robhameetman@substack.com]]></itunes:email><itunes:name><![CDATA[Rob Hameetman]]></itunes:name></itunes:owner><itunes:author><![CDATA[Rob Hameetman]]></itunes:author><googleplay:owner><![CDATA[robhameetman@substack.com]]></googleplay:owner><googleplay:email><![CDATA[robhameetman@substack.com]]></googleplay:email><googleplay:author><![CDATA[Rob Hameetman]]></googleplay:author><itunes:block><![CDATA[Yes]]></itunes:block><item><title><![CDATA[Architecting Design Systems for Human Perception]]></title><description><![CDATA[From art theory to code: cognitive framing that boosts discoverability, consistency, and delivery velocity.]]></description><link>https://blog.robhameetman.com/p/design-systems-for-human-perception</link><guid isPermaLink="false">https://blog.robhameetman.com/p/design-systems-for-human-perception</guid><dc:creator><![CDATA[Rob Hameetman]]></dc:creator><pubDate>Mon, 25 Aug 2025 22:53:00 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/dec40623-1506-4735-bb21-e324828114e3_2464x1856.webp" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><em>Hi, I&#8217;m Rob. This is a free issue of UI Engineering Excellence. I write for Frontend Engineers and Product Developers on how to be the best at building apps that win in the market. Subscribe if this is useful. Paid readers get early looks and occasional behind&#8209;the&#8209;scenes notes:</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://blog.robhameetman.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://blog.robhameetman.com/subscribe?"><span>Subscribe now</span></a></p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!mIVN!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff7b56674-e107-4a7b-b36b-525890194457_2464x1856.webp" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!mIVN!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff7b56674-e107-4a7b-b36b-525890194457_2464x1856.webp 424w, https://substackcdn.com/image/fetch/$s_!mIVN!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff7b56674-e107-4a7b-b36b-525890194457_2464x1856.webp 848w, https://substackcdn.com/image/fetch/$s_!mIVN!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff7b56674-e107-4a7b-b36b-525890194457_2464x1856.webp 1272w, https://substackcdn.com/image/fetch/$s_!mIVN!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff7b56674-e107-4a7b-b36b-525890194457_2464x1856.webp 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!mIVN!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff7b56674-e107-4a7b-b36b-525890194457_2464x1856.webp" width="1456" height="1097" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/f7b56674-e107-4a7b-b36b-525890194457_2464x1856.webp&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1097,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:2345606,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/webp&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://blog.robhameetman.com/i/168566184?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff7b56674-e107-4a7b-b36b-525890194457_2464x1856.webp&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!mIVN!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff7b56674-e107-4a7b-b36b-525890194457_2464x1856.webp 424w, https://substackcdn.com/image/fetch/$s_!mIVN!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff7b56674-e107-4a7b-b36b-525890194457_2464x1856.webp 848w, https://substackcdn.com/image/fetch/$s_!mIVN!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff7b56674-e107-4a7b-b36b-525890194457_2464x1856.webp 1272w, https://substackcdn.com/image/fetch/$s_!mIVN!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff7b56674-e107-4a7b-b36b-525890194457_2464x1856.webp 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Back in 1993, Donald Norman coined &#8216;user experience&#8217; to remind us that emotions, behavior, and satisfaction should steer product decisions.</p><p>Design tokens- simple name&#8209;value pairs for colors, type, spacing, and more- let us compose those experiences in code.</p><p>A clear token hierarchy allows for flexible theming and gives design and engineering a ubiquitous visual language.</p><p>One common approach bundles lower&#8209;level <em>options</em> into higher&#8209;level <em>decisions</em>. Many teams split tokens into three or four layers to keep things organized.</p><blockquote><p><em>&#8220;How to convey the idea that, when designing a product, we&#8217;re not just assembling blocks&#8230; But we also want our user to feel something.&#8221;<br>&#8212; </em>Audrey Hacq, <a href="https://uxdesign.cc/atomic-design-creativity-28ef74d71bc6">Atomic Design &amp; creativity</a></p></blockquote><p><strong>The Problem: </strong>Design systems treat tokens as subatomic design particles, ignoring human perception.</p><p>That misses the point by a mile.</p><p>Since we preach user experience, you'd expect these models to mirror how our minds work. Yet no framework nudges you to consider the user at every layer.</p><p>In this post, I&#8217;ll introduce a slight paradigm shift by mapping tokens with how our brains perceive digital interfaces.</p><p>The result isn&#8217;t an entirely novel token architecture but an evolution of existing 3-tier and 4-tier models into an experience&#8209;first framework.</p><p>The model has four main layers of abstraction for tokens, each serving a distinct purpose:</p><p><strong>Signals</strong>: <em>Simple tokens</em> that transmit discrete design information.<br><strong>Qualia</strong>: <em>Composite tokens</em> representing instances of subjective consciousness.<br><strong>Noemata</strong>: <em>Component tokens</em> as repeatable attributes of an experience.<br><strong>Strata</strong>: <em>Theme tokens</em> for the manifold horizon in which experiences occur.</p><p>Each layer corresponds to a stage in the chain from raw design stimulus to experienced interface all within the framework of the user&#8217;s perspective, mirroring the progression from observation to sensation to realization.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!PtGp!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa0b2c19a-e482-409c-bae9-593836495c4b_1917x600.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!PtGp!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa0b2c19a-e482-409c-bae9-593836495c4b_1917x600.png 424w, https://substackcdn.com/image/fetch/$s_!PtGp!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa0b2c19a-e482-409c-bae9-593836495c4b_1917x600.png 848w, https://substackcdn.com/image/fetch/$s_!PtGp!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa0b2c19a-e482-409c-bae9-593836495c4b_1917x600.png 1272w, https://substackcdn.com/image/fetch/$s_!PtGp!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa0b2c19a-e482-409c-bae9-593836495c4b_1917x600.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!PtGp!,w_2400,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa0b2c19a-e482-409c-bae9-593836495c4b_1917x600.png" width="1100" height="344.5054945054945" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/a0b2c19a-e482-409c-bae9-593836495c4b_1917x600.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:false,&quot;imageSize&quot;:&quot;large&quot;,&quot;height&quot;:456,&quot;width&quot;:1456,&quot;resizeWidth&quot;:1100,&quot;bytes&quot;:60537,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.robhameetman.com/i/168566184?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa0b2c19a-e482-409c-bae9-593836495c4b_1917x600.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:&quot;center&quot;,&quot;offset&quot;:false}" class="sizing-large" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!PtGp!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa0b2c19a-e482-409c-bae9-593836495c4b_1917x600.png 424w, https://substackcdn.com/image/fetch/$s_!PtGp!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa0b2c19a-e482-409c-bae9-593836495c4b_1917x600.png 848w, https://substackcdn.com/image/fetch/$s_!PtGp!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa0b2c19a-e482-409c-bae9-593836495c4b_1917x600.png 1272w, https://substackcdn.com/image/fetch/$s_!PtGp!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa0b2c19a-e482-409c-bae9-593836495c4b_1917x600.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>We&#8217;ll go over these layers in more detail further down, describing their role and how they relate to both implementation and perception, with examples of what tokens in that layer look like.</p><p>To get the most out of it, we first need to understand how design tokens and the methods we use to create them are built on prior explorations of human perception as forms of art.</p><h2>Why Perception Matters</h2><p>It&#8217;s already there, implicitly.</p><p>Design is as much about psychology as it is aesthetics. A <code>$primary-color</code> draws user attention, a <code>$spacing-L</code> suggests a comfortable margin, and so on.</p><p>When we tune color scales using harmonious intervals or scale typography with musical precision, we&#8217;re guiding the user&#8217;s eye in a way that reduces cognitive friction and builds trust.</p><p>We&#8217;re also ensuring some valuable consistency on our end. If you&#8217;ve ever wasted time trying to figure out why <code>--grey-150</code> exists when every other interval in every hue increments by 100, you know what I mean.</p><p>Colors, shapes, typography, and layout all work in concert to form a user's impression within milliseconds.</p><h3>From Art To Interface</h3><p>I studied a bit of art history in college for my Graphic Design major and can&#8217;t get enough of art movements and the philosophies behind them.</p><p>Soon after graduation I discovered Synchromism, a little-known short-lived early 20th-century movement that explored the relationship between color and music.</p><blockquote><p><em>&#8220;Before investigating the analogy of colour intervals it is necessary to emphasise the fact that the psychological equivalent of the simultaneous perception of two or more sounds, is the simultaneous perception of two or more juxtaposed colours. Consequently the analogue of harmony in sound must be sought in juxtaposed colours. Melody in colour will therefore result from the </em>espacement<em> of colours, their isolation by intervening neutral tint, and also from the order in which colours lie on the field of vision.&#8221;</em></p><p><em>&#8212; </em>Percival Tudor-Hart, &#8220;The Analogy of Sound and Color&#8221;, <em>Cambridge Magazine</em> 7, no. 21 (2 March 1918): 485</p></blockquote><h3>Synchromism In 30 Seconds</h3><p>Synchromism was an art movement founded by Stanton Macdonald-Wright and Morgan Russell.</p><p>From a desire to create form from color alone, they used musical scales as a framework to build paintings from pure hue relationships (called <em>synchromies</em>), defining &#8220;color scales&#8221; to orchestrate visual harmony just as a symphony arranges sound.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!NlOA!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F44f1faad-84be-4743-95f3-c7550b5a8012_570x546.webp" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!NlOA!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F44f1faad-84be-4743-95f3-c7550b5a8012_570x546.webp 424w, https://substackcdn.com/image/fetch/$s_!NlOA!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F44f1faad-84be-4743-95f3-c7550b5a8012_570x546.webp 848w, https://substackcdn.com/image/fetch/$s_!NlOA!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F44f1faad-84be-4743-95f3-c7550b5a8012_570x546.webp 1272w, https://substackcdn.com/image/fetch/$s_!NlOA!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F44f1faad-84be-4743-95f3-c7550b5a8012_570x546.webp 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!NlOA!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F44f1faad-84be-4743-95f3-c7550b5a8012_570x546.webp" width="500" height="478.94736842105266" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/44f1faad-84be-4743-95f3-c7550b5a8012_570x546.webp&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:546,&quot;width&quot;:570,&quot;resizeWidth&quot;:500,&quot;bytes&quot;:57468,&quot;alt&quot;:&quot;Stanton Macdonald-Wright, NATURE SYNCHROMY, 1924, oil on canvas, Metropolitan Museum of Art, New York&quot;,&quot;title&quot;:&quot;&quot;,&quot;type&quot;:&quot;image/webp&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.robhameetman.com/i/168566184?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F44f1faad-84be-4743-95f3-c7550b5a8012_570x546.webp&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Stanton Macdonald-Wright, NATURE SYNCHROMY, 1924, oil on canvas, Metropolitan Museum of Art, New York" title="Stanton Macdonald-Wright, NATURE SYNCHROMY, 1924, oil on canvas, Metropolitan Museum of Art, New York" srcset="https://substackcdn.com/image/fetch/$s_!NlOA!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F44f1faad-84be-4743-95f3-c7550b5a8012_570x546.webp 424w, https://substackcdn.com/image/fetch/$s_!NlOA!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F44f1faad-84be-4743-95f3-c7550b5a8012_570x546.webp 848w, https://substackcdn.com/image/fetch/$s_!NlOA!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F44f1faad-84be-4743-95f3-c7550b5a8012_570x546.webp 1272w, https://substackcdn.com/image/fetch/$s_!NlOA!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F44f1faad-84be-4743-95f3-c7550b5a8012_570x546.webp 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Pick one hue as your central &#8220;note&#8221;. Add the third and fifth tones from the color spectrum like a musical chord, placing them in nearby shapes.</p><p>Synchromies show waves of colors moving in and out, often converging into a vortex that bursts outward in complex harmonies.</p><p>Like a light show without lasers.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!tOBQ!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F01f76e08-591f-4b9c-b325-c46dea18c6e7_1337x1384.webp" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!tOBQ!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F01f76e08-591f-4b9c-b325-c46dea18c6e7_1337x1384.webp 424w, https://substackcdn.com/image/fetch/$s_!tOBQ!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F01f76e08-591f-4b9c-b325-c46dea18c6e7_1337x1384.webp 848w, https://substackcdn.com/image/fetch/$s_!tOBQ!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F01f76e08-591f-4b9c-b325-c46dea18c6e7_1337x1384.webp 1272w, https://substackcdn.com/image/fetch/$s_!tOBQ!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F01f76e08-591f-4b9c-b325-c46dea18c6e7_1337x1384.webp 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!tOBQ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F01f76e08-591f-4b9c-b325-c46dea18c6e7_1337x1384.webp" width="499" height="516.5415108451758" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/01f76e08-591f-4b9c-b325-c46dea18c6e7_1337x1384.webp&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1384,&quot;width&quot;:1337,&quot;resizeWidth&quot;:499,&quot;bytes&quot;:2091816,&quot;alt&quot;:&quot;Stanton Macdonald-Wright, Synchromy No.&#8239;3, 1917, oil on canvas, Brooklyn Museum, New York&quot;,&quot;title&quot;:null,&quot;type&quot;:&quot;image/webp&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.robhameetman.com/i/168566184?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F01f76e08-591f-4b9c-b325-c46dea18c6e7_1337x1384.webp&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Stanton Macdonald-Wright, Synchromy No.&#8239;3, 1917, oil on canvas, Brooklyn Museum, New York" title="Stanton Macdonald-Wright, Synchromy No.&#8239;3, 1917, oil on canvas, Brooklyn Museum, New York" srcset="https://substackcdn.com/image/fetch/$s_!tOBQ!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F01f76e08-591f-4b9c-b325-c46dea18c6e7_1337x1384.webp 424w, https://substackcdn.com/image/fetch/$s_!tOBQ!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F01f76e08-591f-4b9c-b325-c46dea18c6e7_1337x1384.webp 848w, https://substackcdn.com/image/fetch/$s_!tOBQ!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F01f76e08-591f-4b9c-b325-c46dea18c6e7_1337x1384.webp 1272w, https://substackcdn.com/image/fetch/$s_!tOBQ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F01f76e08-591f-4b9c-b325-c46dea18c6e7_1337x1384.webp 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Imagine throwing ass to this&#8230;</figcaption></figure></div><p>Underpinning this methodology is a deep engagement with contemporary color science and music theory.</p><p>This rational basis aimed to deliver color that could be &#8220;heard&#8221; as well as seen.</p><h3>Influence in Design Systems</h3><p>Synchromism&#8217;s core insight (that harmonious aesthetic relationships can be composed like music) laid a conceptual foundation that guides modern design systems.</p><p>Though most prominent in color ramps and type scales, it can just as easily apply to spacing units, motion durations, and more.</p><h4>Color Scales</h4><p>Design systems often use what&#8217;s called a <em>nonatonic</em> (9-step) color scale from 100 to 900, with each interval 10% darker. An 18-step version denominated by 50 (5% darker) is <em>octodecatonic</em>.</p><p>These darkness intervals act like octaves, keeping each shade in harmony. HSL lightness shifts by a constant geometric ratio, like moving up scale degrees.</p><p>The terms <em>nonatonic</em> and <em>octodecatonic</em> come from musical scales and reference a stable central hue or &#8220;tonic&#8221; that usually sits at 500 or 450 (i.e. the median of the range).</p><p>Thankfully we don&#8217;t have to do all this by hand anymore, we can do it in CSS directly with <code>color-mix()</code>:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!d4F2!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F06a3770a-1c18-4e88-bf78-dc8d163c88da_2704x1492.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!d4F2!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F06a3770a-1c18-4e88-bf78-dc8d163c88da_2704x1492.png 424w, https://substackcdn.com/image/fetch/$s_!d4F2!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F06a3770a-1c18-4e88-bf78-dc8d163c88da_2704x1492.png 848w, https://substackcdn.com/image/fetch/$s_!d4F2!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F06a3770a-1c18-4e88-bf78-dc8d163c88da_2704x1492.png 1272w, https://substackcdn.com/image/fetch/$s_!d4F2!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F06a3770a-1c18-4e88-bf78-dc8d163c88da_2704x1492.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!d4F2!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F06a3770a-1c18-4e88-bf78-dc8d163c88da_2704x1492.png" width="1456" height="803" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/06a3770a-1c18-4e88-bf78-dc8d163c88da_2704x1492.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:803,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:398014,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.robhameetman.com/i/168566184?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F06a3770a-1c18-4e88-bf78-dc8d163c88da_2704x1492.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!d4F2!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F06a3770a-1c18-4e88-bf78-dc8d163c88da_2704x1492.png 424w, https://substackcdn.com/image/fetch/$s_!d4F2!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F06a3770a-1c18-4e88-bf78-dc8d163c88da_2704x1492.png 848w, https://substackcdn.com/image/fetch/$s_!d4F2!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F06a3770a-1c18-4e88-bf78-dc8d163c88da_2704x1492.png 1272w, https://substackcdn.com/image/fetch/$s_!d4F2!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F06a3770a-1c18-4e88-bf78-dc8d163c88da_2704x1492.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Natural tinting and shading isn&#8217;t as simple as the current color mixed with white and black respectively; it often blends in complementary colors and other colors of light around it.</p><p>A better approach is to choose a more dynamic range implemented like so:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!RucO!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcd0c19d1-d20d-42ec-aca0-c4df82e1fca3_2704x1564.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!RucO!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcd0c19d1-d20d-42ec-aca0-c4df82e1fca3_2704x1564.png 424w, https://substackcdn.com/image/fetch/$s_!RucO!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcd0c19d1-d20d-42ec-aca0-c4df82e1fca3_2704x1564.png 848w, https://substackcdn.com/image/fetch/$s_!RucO!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcd0c19d1-d20d-42ec-aca0-c4df82e1fca3_2704x1564.png 1272w, https://substackcdn.com/image/fetch/$s_!RucO!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcd0c19d1-d20d-42ec-aca0-c4df82e1fca3_2704x1564.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!RucO!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcd0c19d1-d20d-42ec-aca0-c4df82e1fca3_2704x1564.png" width="1456" height="842" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/cd0c19d1-d20d-42ec-aca0-c4df82e1fca3_2704x1564.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:842,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:422324,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.robhameetman.com/i/168566184?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcd0c19d1-d20d-42ec-aca0-c4df82e1fca3_2704x1564.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!RucO!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcd0c19d1-d20d-42ec-aca0-c4df82e1fca3_2704x1564.png 424w, https://substackcdn.com/image/fetch/$s_!RucO!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcd0c19d1-d20d-42ec-aca0-c4df82e1fca3_2704x1564.png 848w, https://substackcdn.com/image/fetch/$s_!RucO!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcd0c19d1-d20d-42ec-aca0-c4df82e1fca3_2704x1564.png 1272w, https://substackcdn.com/image/fetch/$s_!RucO!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcd0c19d1-d20d-42ec-aca0-c4df82e1fca3_2704x1564.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>That said, we usually want to keep the tonic for fades:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!1YBM!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff060c86d-2867-4c50-b21e-3b43d606a13a_2704x2360.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!1YBM!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff060c86d-2867-4c50-b21e-3b43d606a13a_2704x2360.png 424w, https://substackcdn.com/image/fetch/$s_!1YBM!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff060c86d-2867-4c50-b21e-3b43d606a13a_2704x2360.png 848w, https://substackcdn.com/image/fetch/$s_!1YBM!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff060c86d-2867-4c50-b21e-3b43d606a13a_2704x2360.png 1272w, https://substackcdn.com/image/fetch/$s_!1YBM!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff060c86d-2867-4c50-b21e-3b43d606a13a_2704x2360.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!1YBM!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff060c86d-2867-4c50-b21e-3b43d606a13a_2704x2360.png" width="1456" height="1271" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/f060c86d-2867-4c50-b21e-3b43d606a13a_2704x2360.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1271,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:781499,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.robhameetman.com/i/168566184?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff060c86d-2867-4c50-b21e-3b43d606a13a_2704x2360.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!1YBM!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff060c86d-2867-4c50-b21e-3b43d606a13a_2704x2360.png 424w, https://substackcdn.com/image/fetch/$s_!1YBM!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff060c86d-2867-4c50-b21e-3b43d606a13a_2704x2360.png 848w, https://substackcdn.com/image/fetch/$s_!1YBM!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff060c86d-2867-4c50-b21e-3b43d606a13a_2704x2360.png 1272w, https://substackcdn.com/image/fetch/$s_!1YBM!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff060c86d-2867-4c50-b21e-3b43d606a13a_2704x2360.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>For JavaScript/TypeScript tokens, we can reproduce <code>color-mix()</code> with <a href="https://www.npmjs.com/package/chroma-js">Chroma.js</a>:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!MuK8!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff3a920f4-0994-4a53-8508-721032c6e8da_2704x2856.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!MuK8!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff3a920f4-0994-4a53-8508-721032c6e8da_2704x2856.png 424w, https://substackcdn.com/image/fetch/$s_!MuK8!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff3a920f4-0994-4a53-8508-721032c6e8da_2704x2856.png 848w, https://substackcdn.com/image/fetch/$s_!MuK8!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff3a920f4-0994-4a53-8508-721032c6e8da_2704x2856.png 1272w, https://substackcdn.com/image/fetch/$s_!MuK8!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff3a920f4-0994-4a53-8508-721032c6e8da_2704x2856.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!MuK8!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff3a920f4-0994-4a53-8508-721032c6e8da_2704x2856.png" width="1456" height="1538" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/f3a920f4-0994-4a53-8508-721032c6e8da_2704x2856.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1538,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:790943,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.robhameetman.com/i/168566184?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff3a920f4-0994-4a53-8508-721032c6e8da_2704x2856.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!MuK8!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff3a920f4-0994-4a53-8508-721032c6e8da_2704x2856.png 424w, https://substackcdn.com/image/fetch/$s_!MuK8!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff3a920f4-0994-4a53-8508-721032c6e8da_2704x2856.png 848w, https://substackcdn.com/image/fetch/$s_!MuK8!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff3a920f4-0994-4a53-8508-721032c6e8da_2704x2856.png 1272w, https://substackcdn.com/image/fetch/$s_!MuK8!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff3a920f4-0994-4a53-8508-721032c6e8da_2704x2856.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><h4>Typographic Scales</h4><p>If you aren&#8217;t already familiar with <a href="https://spencermortensen.com/articles/typographic-scale/">Spencer Mortensen&#8217;s breakdown of typographic scales</a>, give it a read. It&#8217;s a classic!</p><p>In short, he lays out the following formula for creating harmonious typographic scales:</p><div class="latex-rendered" data-attrs="{&quot;persistentExpression&quot;:&quot;f_i = f_0 r^{\\frac{i}{n}}&quot;,&quot;id&quot;:&quot;ZLQNLCUFRG&quot;}" data-component-name="LatexBlockToDOM"></div><p>His rationale is as straightforward as it gets so it&#8217;s worth repeat here:</p><blockquote><p><em>&#8220;A typographer chooses sizes from a typographic scale in the same way that a musician chooses notes from a musical scale.</em></p><p><em>Like a musical scale, a typographic scale is a </em>scale<em>, so it must obey the scaling property: if </em>f<em> is a size in the scale, then </em>rf<em> must also be a size in the scale, where </em>r<em> is the ratio of the scale.&#8221;</em></p></blockquote><p>Guess what? We can do this directly in CSS too!</p><p>The following gives us a <em>dodecatonic golden typographic scale</em> (12-step scale where the ratio is the golden ratio):</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!-P2s!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9a647c8-4232-476b-b13c-c6576257411e_2704x3288.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!-P2s!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9a647c8-4232-476b-b13c-c6576257411e_2704x3288.png 424w, https://substackcdn.com/image/fetch/$s_!-P2s!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9a647c8-4232-476b-b13c-c6576257411e_2704x3288.png 848w, https://substackcdn.com/image/fetch/$s_!-P2s!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9a647c8-4232-476b-b13c-c6576257411e_2704x3288.png 1272w, https://substackcdn.com/image/fetch/$s_!-P2s!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9a647c8-4232-476b-b13c-c6576257411e_2704x3288.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!-P2s!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9a647c8-4232-476b-b13c-c6576257411e_2704x3288.png" width="1456" height="1770" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/d9a647c8-4232-476b-b13c-c6576257411e_2704x3288.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1770,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:1052010,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.robhameetman.com/i/168566184?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9a647c8-4232-476b-b13c-c6576257411e_2704x3288.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!-P2s!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9a647c8-4232-476b-b13c-c6576257411e_2704x3288.png 424w, https://substackcdn.com/image/fetch/$s_!-P2s!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9a647c8-4232-476b-b13c-c6576257411e_2704x3288.png 848w, https://substackcdn.com/image/fetch/$s_!-P2s!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9a647c8-4232-476b-b13c-c6576257411e_2704x3288.png 1272w, https://substackcdn.com/image/fetch/$s_!-P2s!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9a647c8-4232-476b-b13c-c6576257411e_2704x3288.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>The tonic (<code>f&#8320;</code>) isn&#8217;t quite the median here but the scale works the same way.</p><p>We can tell by rendering each interval and visualizing an imaginary line at the edge or spaces in between. Notice how the line is curved for User Agent styling:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!1PcA!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0517de0e-3175-47eb-ae45-cf0f9ff1b3bc_1900x864.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!1PcA!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0517de0e-3175-47eb-ae45-cf0f9ff1b3bc_1900x864.png 424w, https://substackcdn.com/image/fetch/$s_!1PcA!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0517de0e-3175-47eb-ae45-cf0f9ff1b3bc_1900x864.png 848w, https://substackcdn.com/image/fetch/$s_!1PcA!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0517de0e-3175-47eb-ae45-cf0f9ff1b3bc_1900x864.png 1272w, https://substackcdn.com/image/fetch/$s_!1PcA!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0517de0e-3175-47eb-ae45-cf0f9ff1b3bc_1900x864.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!1PcA!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0517de0e-3175-47eb-ae45-cf0f9ff1b3bc_1900x864.png" width="1456" height="662" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/0517de0e-3175-47eb-ae45-cf0f9ff1b3bc_1900x864.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:662,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:192607,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.robhameetman.com/i/168566184?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0517de0e-3175-47eb-ae45-cf0f9ff1b3bc_1900x864.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!1PcA!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0517de0e-3175-47eb-ae45-cf0f9ff1b3bc_1900x864.png 424w, https://substackcdn.com/image/fetch/$s_!1PcA!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0517de0e-3175-47eb-ae45-cf0f9ff1b3bc_1900x864.png 848w, https://substackcdn.com/image/fetch/$s_!1PcA!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0517de0e-3175-47eb-ae45-cf0f9ff1b3bc_1900x864.png 1272w, https://substackcdn.com/image/fetch/$s_!1PcA!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0517de0e-3175-47eb-ae45-cf0f9ff1b3bc_1900x864.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>When typography is scalar, the line is straight:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!CflI!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbc7d1cb3-3a30-4124-82f1-a1f748aa4c5d_1900x944.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!CflI!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbc7d1cb3-3a30-4124-82f1-a1f748aa4c5d_1900x944.png 424w, https://substackcdn.com/image/fetch/$s_!CflI!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbc7d1cb3-3a30-4124-82f1-a1f748aa4c5d_1900x944.png 848w, https://substackcdn.com/image/fetch/$s_!CflI!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbc7d1cb3-3a30-4124-82f1-a1f748aa4c5d_1900x944.png 1272w, https://substackcdn.com/image/fetch/$s_!CflI!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbc7d1cb3-3a30-4124-82f1-a1f748aa4c5d_1900x944.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!CflI!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbc7d1cb3-3a30-4124-82f1-a1f748aa4c5d_1900x944.png" width="1456" height="723" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/bc7d1cb3-3a30-4124-82f1-a1f748aa4c5d_1900x944.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:723,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:263430,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.robhameetman.com/i/168566184?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbc7d1cb3-3a30-4124-82f1-a1f748aa4c5d_1900x944.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!CflI!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbc7d1cb3-3a30-4124-82f1-a1f748aa4c5d_1900x944.png 424w, https://substackcdn.com/image/fetch/$s_!CflI!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbc7d1cb3-3a30-4124-82f1-a1f748aa4c5d_1900x944.png 848w, https://substackcdn.com/image/fetch/$s_!CflI!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbc7d1cb3-3a30-4124-82f1-a1f748aa4c5d_1900x944.png 1272w, https://substackcdn.com/image/fetch/$s_!CflI!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbc7d1cb3-3a30-4124-82f1-a1f748aa4c5d_1900x944.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><h2>Compositional Tokens</h2><p>Humans understand the world not by isolating individual elements, but by weaving them together into a coherent context.</p><p>In fact, the very word "context" comes from the Latin <em>contextus</em>, meaning "to weave together," highlighting that context is something actively constructed rather than a static backdrop.</p><p>Cognitive scientists note that context creation is an active, two-sided process; we continuously integrate cues from the environment and in turn our understanding of the context influences how we perceive those cues.</p><p>In other words, context and content shape each other in tandem, much like threads woven into a single fabric. At the neural level, the brain literally binds together features of an environment or experience to create a unique context representation.</p><p>Research in memory formation shows that the hippocampus quickly constructs a &#8220;conjunctive&#8221; representation of the various features of a place or situation.</p><p>This bound representation means that even a small subset of those features can later trigger recall of the whole context through pattern completion.</p><p>In cognitive terms, what we see or hear is heavily influenced by surrounding cues and our expectations.</p><p>The same visual or UI element can feel completely different in a different setting or theme. This underscores why designing for perception means designing for context: the human brain will always interpret interface signals through whatever contextual frame is in place.</p><h3>Signals</h3><p>Generally speaking, a signal is a transmission of information from one part of a system to another. In design systems, they provide a finite palette of options from which more complex experiences emerge.</p><p>By thinking about them in terms of constraints, we enforce a baseline harmony and limit the design space to a controlled and ubiquitous vocabulary.</p><h4>Wait- Aren&#8217;t Qualia Irreducible?</h4><p>Philosophically, <em>qualia</em> refer to the subjective, irreducible experience of consciousness.</p><p>Whether or not irreducibility is true depends on if subjective consciousness fully emerges from the objective processes of the brain.</p><p>Regardless, it&#8217;s undoubtedly true that sensory experience involves signals transmitted through the nervous system. Our brains receive and process these signals to construct our perception of the world around us.</p><p>Given this, we can make an argument either way such that this paradigm becomes flexible enough for both 3-tier and 4-tier token architectures. In a 3-tier token architecture, signals simply become the most granular qualia.</p><h4>Constraints</h4><ul><li><p>Signal tokens are either discrete raw values or use other signals to compute a new signal.</p></li><li><p>1 token = 1 value</p></li></ul><h4>Examples</h4><p>Signals should be used whenever you need a concrete value.</p><p>If you plan on computing scalar values for color and typography like we do above, it&#8217;s a good idea to have a set of core signals that include some of the terms and ratios mentioned earlier:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!m5XO!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdda1f23f-b0c5-43cb-aa2c-47c1bba89773_2704x1928.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!m5XO!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdda1f23f-b0c5-43cb-aa2c-47c1bba89773_2704x1928.png 424w, https://substackcdn.com/image/fetch/$s_!m5XO!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdda1f23f-b0c5-43cb-aa2c-47c1bba89773_2704x1928.png 848w, https://substackcdn.com/image/fetch/$s_!m5XO!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdda1f23f-b0c5-43cb-aa2c-47c1bba89773_2704x1928.png 1272w, https://substackcdn.com/image/fetch/$s_!m5XO!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdda1f23f-b0c5-43cb-aa2c-47c1bba89773_2704x1928.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!m5XO!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdda1f23f-b0c5-43cb-aa2c-47c1bba89773_2704x1928.png" width="1456" height="1038" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/dda1f23f-b0c5-43cb-aa2c-47c1bba89773_2704x1928.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1038,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:306009,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.robhameetman.com/i/168566184?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdda1f23f-b0c5-43cb-aa2c-47c1bba89773_2704x1928.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!m5XO!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdda1f23f-b0c5-43cb-aa2c-47c1bba89773_2704x1928.png 424w, https://substackcdn.com/image/fetch/$s_!m5XO!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdda1f23f-b0c5-43cb-aa2c-47c1bba89773_2704x1928.png 848w, https://substackcdn.com/image/fetch/$s_!m5XO!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdda1f23f-b0c5-43cb-aa2c-47c1bba89773_2704x1928.png 1272w, https://substackcdn.com/image/fetch/$s_!m5XO!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdda1f23f-b0c5-43cb-aa2c-47c1bba89773_2704x1928.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Signals can also be values for other things like breakpoints, spacing, border radii, shadows, and so on:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!WKLK!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5f7e587b-24bd-4305-b626-b0bc1007161b_2704x1288.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!WKLK!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5f7e587b-24bd-4305-b626-b0bc1007161b_2704x1288.png 424w, https://substackcdn.com/image/fetch/$s_!WKLK!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5f7e587b-24bd-4305-b626-b0bc1007161b_2704x1288.png 848w, https://substackcdn.com/image/fetch/$s_!WKLK!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5f7e587b-24bd-4305-b626-b0bc1007161b_2704x1288.png 1272w, https://substackcdn.com/image/fetch/$s_!WKLK!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5f7e587b-24bd-4305-b626-b0bc1007161b_2704x1288.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!WKLK!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5f7e587b-24bd-4305-b626-b0bc1007161b_2704x1288.png" width="1456" height="694" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/5f7e587b-24bd-4305-b626-b0bc1007161b_2704x1288.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:694,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:222932,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.robhameetman.com/i/168566184?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5f7e587b-24bd-4305-b626-b0bc1007161b_2704x1288.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!WKLK!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5f7e587b-24bd-4305-b626-b0bc1007161b_2704x1288.png 424w, https://substackcdn.com/image/fetch/$s_!WKLK!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5f7e587b-24bd-4305-b626-b0bc1007161b_2704x1288.png 848w, https://substackcdn.com/image/fetch/$s_!WKLK!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5f7e587b-24bd-4305-b626-b0bc1007161b_2704x1288.png 1272w, https://substackcdn.com/image/fetch/$s_!WKLK!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5f7e587b-24bd-4305-b626-b0bc1007161b_2704x1288.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><h4>Naming</h4><p>Since signals are often part of a scale or compound value, they&#8217;re usually named relative to similar signals (e.g. <code>$red-400</code> vs <code>$red-500</code> or <code>$dark-red</code> vs <code>$light-red</code>) within the same group. Numbers should provide consistency across intervals:</p><blockquote><p>&#9989; <strong>GOOD</strong>: <code>$red-fade-90</code>, <code>$red-fade-80<br></code>&#10060; <strong>BAD</strong>: <code>$faded-red</code>, <code>$more-faded-red</code></p></blockquote><div><hr></div><h3>Qualia</h3><p>The term <em>qualia</em> (singular: <em>quale</em>, pronounced &#8220;kwol-ay&#8221;) comes from <a href="https://iep.utm.edu/sense-da/">sense-data theory</a>, referring to the subjective quality of conscious experience as properties of sense-data themselves.</p><p>When we see a button on a screen, properties like &#8220;red color, 10pt font, 4px radius&#8221; <a href="https://en.wikipedia.org/wiki/Feature_integration_theory?utm_source=blog.robhameetman.com">are parsed pre-attentively and then combined</a>, almost like a form of sensory data compression.</p><p>What we actually experience is the overall look and feel as a prominent call to action.</p><h4>Make It Make Sense</h4><p>Imagine trying to describe what it feels like to see the color red to someone born totally blind.</p><p>Qualia are these immediate sensations. They capture &#8220;what it&#8217;s like&#8221; to experience a signal with meaningful context.</p><p>In reality, we don&#8217;t just run into the color red. Rather, we experience the &#8220;redness&#8221; of something like an apple or a can of Coca-Cola or a button on a screen.</p><p>As qualia, the redness of an apple isn&#8217;t equivalent to the redness of a can of Coca-Cola even if the two hues are exactly the same.</p><p>If signals are ingredients, qualia are flavors. They encourage us to start thinking in terms of low-level sensations rather than objective values.</p><h4>Constraints</h4><ul><li><p>Qualia may use raw values, signals, and other qualia.</p></li><li><p>They should never use noemata or strata.</p></li></ul><h4>Examples</h4><p>Qualia typically use signals either directly or in composite values to create new tokens with specialized meaning.</p><p>For example, a color scale might have signals for blue like <code>$blue-100</code> used by qualia like <code>$primary-color</code> or <code>$info-color</code>.</p><p>Consider our typographic scale from earlier.</p><p>The scalar tokens <code>&#8212;-f12</code>, <code>&#8212;-f11</code>, <code>&#8212;-f10</code>, etc. are signals, while the heading tokens <code>&#8212;-h1</code>, <code>&#8212;-h2</code>, <code>&#8212;-h3</code>, etc. are qualia. Both types are used for font sizes, but the latter have specialized meaning as heading sizes.</p><p>These tokens can then compose more complex qualia for the headings as CSS <code>font</code> shorthands:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!X-BL!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F15a598b0-e125-425d-8829-4881ae05cb4f_3420x992.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!X-BL!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F15a598b0-e125-425d-8829-4881ae05cb4f_3420x992.png 424w, https://substackcdn.com/image/fetch/$s_!X-BL!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F15a598b0-e125-425d-8829-4881ae05cb4f_3420x992.png 848w, https://substackcdn.com/image/fetch/$s_!X-BL!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F15a598b0-e125-425d-8829-4881ae05cb4f_3420x992.png 1272w, https://substackcdn.com/image/fetch/$s_!X-BL!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F15a598b0-e125-425d-8829-4881ae05cb4f_3420x992.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!X-BL!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F15a598b0-e125-425d-8829-4881ae05cb4f_3420x992.png" width="1456" height="422" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/15a598b0-e125-425d-8829-4881ae05cb4f_3420x992.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:422,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:181676,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.robhameetman.com/i/168566184?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F15a598b0-e125-425d-8829-4881ae05cb4f_3420x992.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!X-BL!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F15a598b0-e125-425d-8829-4881ae05cb4f_3420x992.png 424w, https://substackcdn.com/image/fetch/$s_!X-BL!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F15a598b0-e125-425d-8829-4881ae05cb4f_3420x992.png 848w, https://substackcdn.com/image/fetch/$s_!X-BL!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F15a598b0-e125-425d-8829-4881ae05cb4f_3420x992.png 1272w, https://substackcdn.com/image/fetch/$s_!X-BL!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F15a598b0-e125-425d-8829-4881ae05cb4f_3420x992.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>By packaging decisions in this way, qualia also help reduce errors. Use theme wherever you want to encapsulate a design decision with a purpose.</p><p>As a rule of thumb, if a style decision would appear in CSS as a shorthand or a group of properties, it&#8217;s a good candidate for a quale token.</p><h4>Naming</h4><p>Quale token names should capture meaning or usage. A good practice is to think, <em>&#8220;How would I describe this token&#8217;s role to a colleague or stakeholder?&#8221;</em></p><p>For example, when naming and grouping color qualia, consider the underlying meaning. Words like &#8220;primary&#8221;, &#8220;secondary&#8221;, &#8220;tertiary&#8221; are about <em>priority</em>; system colors indicate <em>intent</em>:</p><blockquote><p>&#10060; <strong>BAD</strong>: <code>$red</code>, <code>$grey</code><br>&#9989; <strong>GOOD</strong>: <code>$primary-color</code>, <code>$secondary-color</code><br>&#9989; <strong>GOOD</strong>: <code>$error-color</code>, <code>$disabled-color</code></p></blockquote><div><hr></div><h3>Noemata</h3><p>In phenomenological terms, noemata (singular: noema) refer to the content of thought; essentially, something as it is experienced or intended in the mind.</p><p>This ensures that each component&#8217;s design supports its function.</p><h4>Noematic Nuance</h4><p>Conceptually, noemata overlap with the Platonic idea of <em>eidos, </em>the essence of a thing&#8212;it&#8217;s &#8220;thingness&#8221;, if you will.</p><p>In programming terms, eidos is like an <code>interface</code> implemented by a <code>class</code>. It&#8217;s the <em>mental contract</em> that determines how language shapes reality.</p><p>Building on our red apple example from earlier, let&#8217;s break down the requirements for some eidetic analysis:</p><ul><li><p>it must be an apple</p></li><li><p>it must be red (mostly)</p></li></ul><p>The word &#8220;mostly&#8221; here is the key to understanding the nuance between eidos and noemata.</p><p>Say we have two red apples. One has a small spot of discoloration; the other has no perceivable discoloration. Both are red enough to be red apples but you probably think of one as fresher than the other.</p><p>In order to account for freshness at the eidos level, we have to increase language specificity from &#8220;red apple&#8221; to something like &#8220;fresh red apple&#8221; or &#8220;entirely red apple&#8221;, which narrows the noematic scope.</p><p>If we have two fresh (entirely) red apples, we can still perceive one as fresher than the other but now we need more sensory information like texture, firmness, maybe even aroma or taste.</p><p>Both eidos and noemata represent ideal forms. The nuance is that eidos defines what makes a thing that thing while noemata are the repeatable attributes of an experience of that thing.</p><h4>Constraints</h4><ul><li><p>Noemata may use any tokens from any other layer.</p></li><li><p>In some cases they may also be another noema token.</p></li><li><p>In rare cases they may be one-off values.</p></li></ul><h4>Examples</h4><p>Use noemata tokens to organize design decisions by component. This way, if a particular component needs to be reskinned or adjusted, you can tweak its tokens without affecting others.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!AJcP!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F39762360-1d76-413f-b684-76d54d098240_2940x780.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!AJcP!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F39762360-1d76-413f-b684-76d54d098240_2940x780.png 424w, https://substackcdn.com/image/fetch/$s_!AJcP!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F39762360-1d76-413f-b684-76d54d098240_2940x780.png 848w, https://substackcdn.com/image/fetch/$s_!AJcP!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F39762360-1d76-413f-b684-76d54d098240_2940x780.png 1272w, https://substackcdn.com/image/fetch/$s_!AJcP!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F39762360-1d76-413f-b684-76d54d098240_2940x780.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!AJcP!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F39762360-1d76-413f-b684-76d54d098240_2940x780.png" width="1456" height="386" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/39762360-1d76-413f-b684-76d54d098240_2940x780.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:386,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:116333,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.robhameetman.com/i/168566184?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F39762360-1d76-413f-b684-76d54d098240_2940x780.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!AJcP!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F39762360-1d76-413f-b684-76d54d098240_2940x780.png 424w, https://substackcdn.com/image/fetch/$s_!AJcP!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F39762360-1d76-413f-b684-76d54d098240_2940x780.png 848w, https://substackcdn.com/image/fetch/$s_!AJcP!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F39762360-1d76-413f-b684-76d54d098240_2940x780.png 1272w, https://substackcdn.com/image/fetch/$s_!AJcP!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F39762360-1d76-413f-b684-76d54d098240_2940x780.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Noemata sometimes reference other noemata when it makes sense, though this usually happens intramodularly:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!GhaB!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F81afd497-3d32-4060-837f-4e195902e276_2940x920.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!GhaB!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F81afd497-3d32-4060-837f-4e195902e276_2940x920.png 424w, https://substackcdn.com/image/fetch/$s_!GhaB!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F81afd497-3d32-4060-837f-4e195902e276_2940x920.png 848w, https://substackcdn.com/image/fetch/$s_!GhaB!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F81afd497-3d32-4060-837f-4e195902e276_2940x920.png 1272w, https://substackcdn.com/image/fetch/$s_!GhaB!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F81afd497-3d32-4060-837f-4e195902e276_2940x920.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!GhaB!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F81afd497-3d32-4060-837f-4e195902e276_2940x920.png" width="1456" height="456" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/81afd497-3d32-4060-837f-4e195902e276_2940x920.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:456,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:145453,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.robhameetman.com/i/168566184?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F81afd497-3d32-4060-837f-4e195902e276_2940x920.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!GhaB!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F81afd497-3d32-4060-837f-4e195902e276_2940x920.png 424w, https://substackcdn.com/image/fetch/$s_!GhaB!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F81afd497-3d32-4060-837f-4e195902e276_2940x920.png 848w, https://substackcdn.com/image/fetch/$s_!GhaB!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F81afd497-3d32-4060-837f-4e195902e276_2940x920.png 1272w, https://substackcdn.com/image/fetch/$s_!GhaB!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F81afd497-3d32-4060-837f-4e195902e276_2940x920.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>From time to time, it may be appropriate to reference noemata from other components:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!JcGV!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8475a33c-d82f-4a36-9b29-294a8e0e8058_2940x848.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!JcGV!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8475a33c-d82f-4a36-9b29-294a8e0e8058_2940x848.png 424w, https://substackcdn.com/image/fetch/$s_!JcGV!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8475a33c-d82f-4a36-9b29-294a8e0e8058_2940x848.png 848w, https://substackcdn.com/image/fetch/$s_!JcGV!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8475a33c-d82f-4a36-9b29-294a8e0e8058_2940x848.png 1272w, https://substackcdn.com/image/fetch/$s_!JcGV!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8475a33c-d82f-4a36-9b29-294a8e0e8058_2940x848.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!JcGV!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8475a33c-d82f-4a36-9b29-294a8e0e8058_2940x848.png" width="1456" height="420" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/8475a33c-d82f-4a36-9b29-294a8e0e8058_2940x848.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:420,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:128184,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.robhameetman.com/i/168566184?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8475a33c-d82f-4a36-9b29-294a8e0e8058_2940x848.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!JcGV!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8475a33c-d82f-4a36-9b29-294a8e0e8058_2940x848.png 424w, https://substackcdn.com/image/fetch/$s_!JcGV!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8475a33c-d82f-4a36-9b29-294a8e0e8058_2940x848.png 848w, https://substackcdn.com/image/fetch/$s_!JcGV!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8475a33c-d82f-4a36-9b29-294a8e0e8058_2940x848.png 1272w, https://substackcdn.com/image/fetch/$s_!JcGV!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8475a33c-d82f-4a36-9b29-294a8e0e8058_2940x848.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><h4>Naming</h4><p>Noema token names usually prefix the component or pattern name to group them:</p><blockquote><p>&#10060; <strong>BAD</strong>: <code>$color-background-dropdown</code><br>&#9989; <strong>GOOD</strong>: <code>$dropdown-color</code></p></blockquote><p>This way, anyone looking at the token name knows which component it belongs to and what aspect it controls.</p><p>It&#8217;s also helpful to mirror the component&#8217;s parts/states in the token names. When it comes to buttons and links specifically, we recommend the term &#8220;engaged&#8221; when pressed and hover states overlap instead of words like &#8220;active&#8221;. <code>:active</code> is a CSS pseudo-class and misusing this term can cause confusion.</p><p>By naming noemata tokens clearly, we capture the nuance of each component&#8217;s design in a way that is immediately understandable.</p><div><hr></div><h3>Strata</h3><p>The contextual background or frame in which the user&#8217;s experience occurs is called their <em>horizon</em>.</p><p>A horizon links past experiences together and, in those connections, guides which new ones join the series. Those links then shape our overarching sense of reality.</p><p>The user&#8217;s horizon includes not just what is explicitly present in the viewport, but also the implied possibilities and potential experiences. The interstitial links of these experiences are the theme.</p><p>A theme is essentially a configuration.</p><p>Strata (singular: stratum), therefore, are the layers that configure the user&#8217;s horizon of experience.</p><h4>Constraints</h4><ul><li><p>Strata may use qualia and signal tokens.</p></li><li><p>They may also reference another stratum token.</p></li><li><p>They should never use noemata.</p></li><li><p>In rare cases they may be one-off values.</p></li></ul><h4>Examples</h4><p>Use strata to enable theming at scale.</p><p>While strata could be limited to specific pages or views, a good rule of thumb is to keep these tokens relevant to design elements used anywhere in the app:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!7dcn!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8f863890-a17a-42a0-8237-f0c6469588c6_2940x1208.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!7dcn!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8f863890-a17a-42a0-8237-f0c6469588c6_2940x1208.png 424w, https://substackcdn.com/image/fetch/$s_!7dcn!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8f863890-a17a-42a0-8237-f0c6469588c6_2940x1208.png 848w, https://substackcdn.com/image/fetch/$s_!7dcn!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8f863890-a17a-42a0-8237-f0c6469588c6_2940x1208.png 1272w, https://substackcdn.com/image/fetch/$s_!7dcn!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8f863890-a17a-42a0-8237-f0c6469588c6_2940x1208.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!7dcn!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8f863890-a17a-42a0-8237-f0c6469588c6_2940x1208.png" width="1456" height="598" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/8f863890-a17a-42a0-8237-f0c6469588c6_2940x1208.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:598,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:235297,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.robhameetman.com/i/168566184?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8f863890-a17a-42a0-8237-f0c6469588c6_2940x1208.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!7dcn!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8f863890-a17a-42a0-8237-f0c6469588c6_2940x1208.png 424w, https://substackcdn.com/image/fetch/$s_!7dcn!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8f863890-a17a-42a0-8237-f0c6469588c6_2940x1208.png 848w, https://substackcdn.com/image/fetch/$s_!7dcn!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8f863890-a17a-42a0-8237-f0c6469588c6_2940x1208.png 1272w, https://substackcdn.com/image/fetch/$s_!7dcn!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8f863890-a17a-42a0-8237-f0c6469588c6_2940x1208.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>They can also encapsulate categories of components:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!AZBO!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1d687da7-75e4-4c9b-b59b-8a6aea37b000_2940x1276.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!AZBO!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1d687da7-75e4-4c9b-b59b-8a6aea37b000_2940x1276.png 424w, https://substackcdn.com/image/fetch/$s_!AZBO!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1d687da7-75e4-4c9b-b59b-8a6aea37b000_2940x1276.png 848w, https://substackcdn.com/image/fetch/$s_!AZBO!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1d687da7-75e4-4c9b-b59b-8a6aea37b000_2940x1276.png 1272w, https://substackcdn.com/image/fetch/$s_!AZBO!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1d687da7-75e4-4c9b-b59b-8a6aea37b000_2940x1276.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!AZBO!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1d687da7-75e4-4c9b-b59b-8a6aea37b000_2940x1276.png" width="1456" height="632" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/1d687da7-75e4-4c9b-b59b-8a6aea37b000_2940x1276.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:632,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:252222,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.robhameetman.com/i/168566184?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1d687da7-75e4-4c9b-b59b-8a6aea37b000_2940x1276.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!AZBO!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1d687da7-75e4-4c9b-b59b-8a6aea37b000_2940x1276.png 424w, https://substackcdn.com/image/fetch/$s_!AZBO!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1d687da7-75e4-4c9b-b59b-8a6aea37b000_2940x1276.png 848w, https://substackcdn.com/image/fetch/$s_!AZBO!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1d687da7-75e4-4c9b-b59b-8a6aea37b000_2940x1276.png 1272w, https://substackcdn.com/image/fetch/$s_!AZBO!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1d687da7-75e4-4c9b-b59b-8a6aea37b000_2940x1276.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>As strata these tokens tell us that the system doesn&#8217;t have <code>&lt;Form&gt;</code> component; if it does, they become noemata.</p><h4>Naming</h4><p>Strata shouldn&#8217;t &#8220;know&#8221; the theme they&#8217;re in, meaning names should be theme-agnostic.</p><blockquote><p>&#10060; <strong>BAD</strong>: <code>$theme-brand-text-color</code><br>&#9989; <strong>GOOD</strong>: <code>$text-color</code></p></blockquote><div><hr></div><h2>Component Categorization</h2><p>Beyond token architecture, a way to further align design systems with human understanding is to categorize UI components by their executive function.</p><p>For consistency, I&#8217;m sticking with words that end in &#8220;ation&#8221; but the taxonomy of executive function itself isn't a strict science. Teams should feel free to modify these categories and use different terms if it better suits their context.</p><p>Many UI components can serve multiple purposes, but this approach provides a useful lens for thinking about design intent.</p><p>For instance:</p><ul><li><p><strong>Actuation/Activation</strong> - Components that cause something to become active or effective, or simply to "turn on":</p><ul><li><p><code>&lt;Button&gt;</code>/<code>&lt;Button.Group&gt;</code></p></li><li><p><code>&lt;Checkbox&gt;</code>/<code>&lt;Checkbox.Group&gt;</code></p></li><li><p><code>&lt;Radio&gt;</code>/<code>&lt;Radio.Group&gt;</code></p></li><li><p><code>&lt;Toggle&gt;</code></p></li></ul></li><li><p><strong>Adaptation</strong> - Components that allow the user experience to change or be changed in accordance with various edge cases:</p><ul><li><p><code>&lt;Autocomplete&gt;</code></p></li><li><p><code>&lt;CatchError&gt;</code>/<code>&lt;ErrorBoundary&gt;</code></p></li><li><p><code>&lt;ErrorPage&gt;</code></p></li><li><p><code>&lt;Loading&gt;</code></p></li><li><p><code>&lt;LanguageSelector&gt;</code></p></li><li><p><code>&lt;Image&gt;</code></p></li><li><p><code>&lt;NoResults&gt;</code></p></li><li><p><code>&lt;ThemeSwitcher&gt;</code></p></li><li><p><code>&lt;Skeleton&gt;</code></p></li><li><p><code>&lt;Video&gt;</code></p></li></ul></li><li><p><strong>Classification</strong> - Components that label, categorize, or filter content:</p><ul><li><p><code>&lt;Avatar&gt;</code>/<code>&lt;Avatar.Group&gt;</code></p></li><li><p><code>&lt;Chip&gt;</code> or <code>&lt;Pill&gt;</code></p></li><li><p><code>&lt;Label&gt;</code></p></li><li><p><code>&lt;Search&gt;</code></p></li><li><p><code>&lt;Tag&gt;</code></p></li></ul></li><li><p><strong>Explication</strong> - Components that explain or assist user understanding of the interface or content:</p><ul><li><p><code>&lt;BarChart&gt;</code></p></li><li><p><code>&lt;GeoChart&gt;</code></p></li><li><p><code>&lt;Histogram&gt;</code></p></li><li><p><code>&lt;Popover&gt;</code></p></li><li><p><code>&lt;Tooltip&gt;</code></p></li><li><p><code>&lt;TreeMap&gt;</code></p></li></ul></li><li><p><strong>Narration</strong> - Components that present content or guide through a temporal flow:</p><ul><li><p><code>&lt;Fade&gt;</code></p></li><li><p><code>&lt;ProgressBar&gt;</code></p></li><li><p><code>&lt;SlideIn&gt;</code>/<code>&lt;SlideOut&gt;</code></p></li><li><p><code>&lt;Stepper&gt;</code></p></li><li><p><code>&lt;Timeline&gt;</code></p></li></ul></li><li><p><strong>Organization</strong> - Components that bring content together to help users identify information and/or maintain consistency:</p><ul><li><p><code>&lt;Article&gt;</code></p></li><li><p><code>&lt;Carousel&gt;</code></p></li><li><p><code>&lt;Dashboard&gt;</code></p></li><li><p><code>&lt;Grid&gt;</code></p></li><li><p><code>&lt;Menu&gt;</code></p></li><li><p><code>&lt;Pagination&gt;</code></p></li><li><p><code>&lt;Select&gt;</code> or <code>&lt;Dropdown&gt;</code></p></li><li><p><code>&lt;Tabs&gt;</code></p></li><li><p><code>&lt;Table&gt;/&lt;DataGrid&gt;</code></p></li></ul></li><li><p><strong>Orientation</strong> - Components that help users navigate across pages and views:</p><ul><li><p><code>&lt;Breadcrumbs&gt;</code></p></li><li><p><code>&lt;Footer&gt;</code></p></li><li><p><code>&lt;Header&gt;</code></p></li><li><p><code>&lt;NavBar&gt;</code></p></li><li><p><code>&lt;Sidebar&gt;</code></p></li><li><p><code>&lt;Sitemap&gt;</code></p></li></ul></li><li><p><strong>Prioritization</strong> - Components that highlight or emphasize important information to grab attention:</p><ul><li><p><code>&lt;Alert&gt;</code></p></li><li><p><code>&lt;Badge&gt;</code></p></li><li><p><code>&lt;Banner&gt;</code></p></li><li><p><code>&lt;Callout&gt;</code></p></li><li><p><code>&lt;Drawer&gt;</code></p></li><li><p><code>&lt;Hero&gt;</code></p></li><li><p><code>&lt;Modal&gt;</code></p></li><li><p><code>&lt;Notification&gt;</code>/<code>&lt;Toast&gt;</code></p></li><li><p><code>&lt;Snackbar&gt;</code></p></li></ul></li><li><p><strong>Segmentation</strong> - Components that break or structure content into digestible sections:</p><ul><li><p><code>&lt;Accordion&gt;</code></p></li><li><p><code>&lt;Box&gt;</code></p></li><li><p><code>&lt;Card&gt;</code></p></li><li><p><code>&lt;Divider&gt;</code></p></li><li><p><code>&lt;List&gt;</code></p></li><li><p><code>&lt;Item&gt;</code></p></li><li><p><code>&lt;Page&gt;</code></p></li><li><p><code>&lt;Section&gt;</code></p></li></ul></li></ul><p>On the surface, this approach might not appear to offer much more than traditional affordance-based component classifications. The main advantage of naming groups by the job they do is that conversations align to outcomes instead of surface form (&#8220;is this a button or a link?&#8221;).</p><p>You can plan to &#8220;improve actuation clarity across checkout&#8221; or &#8220;harden adaptation in low-connectivity scenarios,&#8221; then ship coordinated changes across multiple components with shared tokens and guidelines.</p><p>Specs can state, &#8220;This screen uses actuation and prioritization patterns,&#8221; which immediately maps to known tokens, behaviors, and even accessibility rules. Designers choose which function; engineers apply the corresponding patterns.</p><p>Instrumentation can also roll up by function: activation rate, time-to-orient, attention capture vs. dismissal, etc. Product decisions become &#8220;our prioritization patterns underperform on mobile,&#8221; not &#8220;this one toast is weird.&#8221;</p><p>Further, components like <code>&lt;ErrorBoundary&gt;</code>, <code>&lt;Image&gt;</code>, <code>&lt;Video&gt;</code>, <code>&lt;Skeleton&gt;</code>, etc. tend to be disregarded by Product as "utilities"; grouping them under <em>Adaptation</em> clarifies their actual value.</p><p>Likewise, <code>&lt;Menu&gt;</code> and <code>&lt;List&gt;</code> are both typically considered structural components in most design systems, and Product Developers often don&#8217;t understand the difference. This approach clarifies that a <code>&lt;List&gt;</code> is a method of segmentation while a <code>&lt;Menu&gt;</code> is more about organization.</p><p>The goal is to encourage thinking about why a component exists and to organize your library in a way that reflects those purposes. This can help ensure coverage and guide designers on what component to use for a given problem.</p><h2>Final Thoughts</h2><p>Embracing the construction of human perception as a guiding concept leads to a token architecture that is flexible, scalable, and truly user-centric.</p><p>By mirroring how humans construct and perceive contexts through meaningful combinations and nuanced variations, we create scalable design systems that feel naturally adaptive.</p><p>The user&#8217;s experience will be distinct where it matters, yet comfortably familiar underneath, because we&#8217;ve engineered our tokens the way the mind itself works: composing new experiences out of well-understood pieces, artfully woven together.</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!LRLx!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17b509d7-f748-4f7e-92db-a8ed3d1f3352_792x428.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!LRLx!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17b509d7-f748-4f7e-92db-a8ed3d1f3352_792x428.png 424w, https://substackcdn.com/image/fetch/$s_!LRLx!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17b509d7-f748-4f7e-92db-a8ed3d1f3352_792x428.png 848w, https://substackcdn.com/image/fetch/$s_!LRLx!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17b509d7-f748-4f7e-92db-a8ed3d1f3352_792x428.png 1272w, https://substackcdn.com/image/fetch/$s_!LRLx!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17b509d7-f748-4f7e-92db-a8ed3d1f3352_792x428.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!LRLx!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17b509d7-f748-4f7e-92db-a8ed3d1f3352_792x428.png" width="300" height="162.12121212121212" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/17b509d7-f748-4f7e-92db-a8ed3d1f3352_792x428.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:428,&quot;width&quot;:792,&quot;resizeWidth&quot;:300,&quot;bytes&quot;:37166,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:&quot;&quot;,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.robhameetman.com/i/154924704?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17b509d7-f748-4f7e-92db-a8ed3d1f3352_792x428.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!LRLx!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17b509d7-f748-4f7e-92db-a8ed3d1f3352_792x428.png 424w, https://substackcdn.com/image/fetch/$s_!LRLx!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17b509d7-f748-4f7e-92db-a8ed3d1f3352_792x428.png 848w, https://substackcdn.com/image/fetch/$s_!LRLx!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17b509d7-f748-4f7e-92db-a8ed3d1f3352_792x428.png 1272w, https://substackcdn.com/image/fetch/$s_!LRLx!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17b509d7-f748-4f7e-92db-a8ed3d1f3352_792x428.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><div><hr></div><h2>Up Next</h2><div class="digest-post-embed" data-attrs="{&quot;nodeId&quot;:&quot;fb650cd6-0685-41f9-9e1c-9a59f0211c2f&quot;,&quot;caption&quot;:&quot;Icons are everywhere, yet they&#8217;re probably the easiest thing in your design system to screw up. I&#8217;ve seen so many <Icon> components that overcomplicate the DOM while doing nothing to make accessibility easier to achieve.&quot;,&quot;cta&quot;:&quot;Read full story&quot;,&quot;showBylines&quot;:true,&quot;size&quot;:&quot;sm&quot;,&quot;isEditorNode&quot;:true,&quot;title&quot;:&quot;[WIP] Accessible SVG Icons The Right Way&quot;,&quot;publishedBylines&quot;:[{&quot;id&quot;:179249864,&quot;name&quot;:&quot;Rob Hameetman&quot;,&quot;bio&quot;:&quot;I build Design Systems and Micro-frontends in TypeScript and React with a focus on developer experience / Staff Frontend Engineer / TED curator / Ex-Apple (HIG) / 1.2M+ subs&quot;,&quot;photo_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/fd162dbf-8c1b-48bc-b6e7-0969af7da7ca_475x475.jpeg&quot;,&quot;is_guest&quot;:false,&quot;bestseller_tier&quot;:null}],&quot;post_date&quot;:&quot;2025-08-24T22:17:59.979Z&quot;,&quot;cover_image&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/c54b3810-d9fa-4986-9775-77008fb03c90_2464x1856.webp&quot;,&quot;cover_image_alt&quot;:null,&quot;canonical_url&quot;:&quot;https://blog.robhameetman.com/p/accessible-svg-icons&quot;,&quot;section_name&quot;:&quot;Resources&quot;,&quot;video_upload_id&quot;:null,&quot;id&quot;:166355744,&quot;type&quot;:&quot;newsletter&quot;,&quot;reaction_count&quot;:1,&quot;comment_count&quot;:0,&quot;publication_id&quot;:null,&quot;publication_name&quot;:&quot;UI Engineering Excellence&quot;,&quot;publication_logo_url&quot;:&quot;https://substackcdn.com/image/fetch/$s_!deTI!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdc5e8141-3a0f-4181-8804-acdbb61e8707_359x359.png&quot;,&quot;belowTheFold&quot;:true,&quot;youtube_url&quot;:null,&quot;show_links&quot;:null,&quot;feed_url&quot;:null}"></div><div class="digest-post-embed" data-attrs="{&quot;nodeId&quot;:&quot;90ce0459-c10b-4761-a73d-237628d0b045&quot;,&quot;caption&quot;:&quot;Feature teams move slower than they should. What takes a week could take a day. Simple changes somehow break unrelated things. New hires need months to become useful.&quot;,&quot;cta&quot;:&quot;Read full story&quot;,&quot;showBylines&quot;:true,&quot;size&quot;:&quot;sm&quot;,&quot;isEditorNode&quot;:true,&quot;title&quot;:&quot;[WIP] Building a Pit of Success with Inductive Reasoning&quot;,&quot;publishedBylines&quot;:[{&quot;id&quot;:179249864,&quot;name&quot;:&quot;Rob Hameetman&quot;,&quot;bio&quot;:&quot;I&#8217;m a Staff Design Engineer who builds sexy, scalable enterprise-strength design systems.&quot;,&quot;photo_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/fd162dbf-8c1b-48bc-b6e7-0969af7da7ca_475x475.jpeg&quot;,&quot;is_guest&quot;:false,&quot;bestseller_tier&quot;:null}],&quot;post_date&quot;:&quot;2025-08-24T22:01:39.994Z&quot;,&quot;cover_image&quot;:&quot;https://substackcdn.com/image/fetch/$s_!v3zD!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F818fc660-922d-4795-992a-dfaeefa0d752_2464x1856.webp&quot;,&quot;cover_image_alt&quot;:null,&quot;canonical_url&quot;:&quot;https://blog.robhameetman.com/p/building-a-pit-of-success&quot;,&quot;section_name&quot;:&quot;Deeps&quot;,&quot;video_upload_id&quot;:null,&quot;id&quot;:166478385,&quot;type&quot;:&quot;newsletter&quot;,&quot;reaction_count&quot;:1,&quot;comment_count&quot;:0,&quot;publication_id&quot;:null,&quot;publication_name&quot;:&quot;UI Engineering Excellence&quot;,&quot;publication_logo_url&quot;:&quot;https://substackcdn.com/image/fetch/$s_!deTI!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdc5e8141-3a0f-4181-8804-acdbb61e8707_359x359.png&quot;,&quot;belowTheFold&quot;:true,&quot;youtube_url&quot;:null,&quot;show_links&quot;:null,&quot;feed_url&quot;:null}"></div><div class="digest-post-embed" data-attrs="{&quot;nodeId&quot;:&quot;5bd8eae0-5271-4e31-9303-0c7392e3f0e3&quot;,&quot;caption&quot;:&quot;&quot;,&quot;cta&quot;:&quot;Read full story&quot;,&quot;showBylines&quot;:true,&quot;size&quot;:&quot;sm&quot;,&quot;isEditorNode&quot;:true,&quot;title&quot;:&quot;[WIP] Mode-Aware Tokens with OKLCH&quot;,&quot;publishedBylines&quot;:[{&quot;id&quot;:179249864,&quot;name&quot;:&quot;Rob Hameetman&quot;,&quot;bio&quot;:&quot;I build Design Systems and Micro-frontends in TypeScript and React with a focus on developer experience / Staff Frontend Engineer / TED curator / Ex-Apple (HIG) / 1.2M+ subs&quot;,&quot;photo_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/fd162dbf-8c1b-48bc-b6e7-0969af7da7ca_475x475.jpeg&quot;,&quot;is_guest&quot;:false,&quot;bestseller_tier&quot;:null}],&quot;post_date&quot;:&quot;2025-08-24T22:30:37.254Z&quot;,&quot;cover_image&quot;:&quot;https://substackcdn.com/image/fetch/$s_!NYv-!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F55ac3ddc-ddc7-4527-843b-20f73583d2a2_2464x1856.webp&quot;,&quot;cover_image_alt&quot;:null,&quot;canonical_url&quot;:&quot;https://blog.robhameetman.com/p/wip-mode-aware-tokens-with-oklch&quot;,&quot;section_name&quot;:&quot;Resources&quot;,&quot;video_upload_id&quot;:null,&quot;id&quot;:171579490,&quot;type&quot;:&quot;newsletter&quot;,&quot;reaction_count&quot;:0,&quot;comment_count&quot;:0,&quot;publication_id&quot;:null,&quot;publication_name&quot;:&quot;UI Engineering Excellence&quot;,&quot;publication_logo_url&quot;:&quot;https://substackcdn.com/image/fetch/$s_!deTI!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdc5e8141-3a0f-4181-8804-acdbb61e8707_359x359.png&quot;,&quot;belowTheFold&quot;:true,&quot;youtube_url&quot;:null,&quot;show_links&quot;:null,&quot;feed_url&quot;:null}"></div><p>Any thoughts on what else you&#8217;d like to see? Leave a comment or hop into chat and let me know!</p><div><hr></div><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://blog.robhameetman.com/p/design-systems-for-human-perception?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://blog.robhameetman.com/p/design-systems-for-human-perception?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://blog.robhameetman.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption"><em>If you enjoyed this post, please subscribe, hit the &#10084;&#65039; button, and share/restack &#128257; it with others who might find it helpful!</em></p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item><item><title><![CDATA[[WIP] Building a Pit of Success with Inductive Reasoning]]></title><description><![CDATA[Feature teams move slower than they should.]]></description><link>https://blog.robhameetman.com/p/building-a-pit-of-success</link><guid isPermaLink="false">https://blog.robhameetman.com/p/building-a-pit-of-success</guid><dc:creator><![CDATA[Rob Hameetman]]></dc:creator><pubDate>Sun, 24 Aug 2025 22:01:39 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!v3zD!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F818fc660-922d-4795-992a-dfaeefa0d752_2464x1856.webp" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!v3zD!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F818fc660-922d-4795-992a-dfaeefa0d752_2464x1856.webp" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!v3zD!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F818fc660-922d-4795-992a-dfaeefa0d752_2464x1856.webp 424w, https://substackcdn.com/image/fetch/$s_!v3zD!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F818fc660-922d-4795-992a-dfaeefa0d752_2464x1856.webp 848w, https://substackcdn.com/image/fetch/$s_!v3zD!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F818fc660-922d-4795-992a-dfaeefa0d752_2464x1856.webp 1272w, https://substackcdn.com/image/fetch/$s_!v3zD!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F818fc660-922d-4795-992a-dfaeefa0d752_2464x1856.webp 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!v3zD!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F818fc660-922d-4795-992a-dfaeefa0d752_2464x1856.webp" width="1456" height="1097" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/818fc660-922d-4795-992a-dfaeefa0d752_2464x1856.webp&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1097,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:1467192,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/webp&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://blog.robhameetman.com/i/166478385?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F818fc660-922d-4795-992a-dfaeefa0d752_2464x1856.webp&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!v3zD!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F818fc660-922d-4795-992a-dfaeefa0d752_2464x1856.webp 424w, https://substackcdn.com/image/fetch/$s_!v3zD!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F818fc660-922d-4795-992a-dfaeefa0d752_2464x1856.webp 848w, https://substackcdn.com/image/fetch/$s_!v3zD!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F818fc660-922d-4795-992a-dfaeefa0d752_2464x1856.webp 1272w, https://substackcdn.com/image/fetch/$s_!v3zD!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F818fc660-922d-4795-992a-dfaeefa0d752_2464x1856.webp 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Feature teams move slower than they should. What takes a week could take a day. Simple changes somehow break unrelated things. New hires need months to become useful.</p><p>This isn't a people problem. It's a systems problem.</p><p>The root cause is excessive cognitive load. It's the mental weight developers carry to understand your code, your patterns, and your unique way of doing things. This load is the silent killer of velocity and quality.</p><p>Most advice on this focuses on cleaning up code. That's only a third of the battle. You can't just fix the symptoms. You need a strategy to fix the environment.</p><p>This article gives you that strategy. First, we'll unpack the complete cognitive load framework. Then, we'll reveal the most powerful tool to reduce it: engineering for inductive reasoning.</p><p>Your goal is to build a system where the right way to do things is the easiest way to discover. This is how you turn a team of good engineers into a high-performance engine.</p><h2><strong>Understanding Cognitive Load (Completely)</strong></h2><p>If you&#8217;ve read <a href="https://github.com/zakirullin/cognitive-load">Cognitive Load Is What Matters</a> on Github, then you&#8217;re already ahead of the curve. This is a great primer but only covers two types of mental overhead.</p><p>In software, we deal with three specific types of load. You must understand all three to fix the problem.</p><p>Here&#8217;s a more complete overview of how mental overhead is categorized according to <em>cognitive load theory</em>:</p><ul><li><p><strong>Intrinsic</strong><br>Overhead associated directly with a topic- i.e. the code, the problem, the business logic, and so on. Essentially, this is what comes to mind when we think of complexity. Spaghetti code overloads working memory, making it more difficult to do our work.</p></li><li><p><strong>Germane</strong><br>Overhead required to create a permanent store of knowledge or &#8220;schema&#8221;. In cognitive psychology, a <em>schema</em> is a mental model of how everything fits together. Thus, germane overhead is the effort required to build up recognition- which works faster than recall.</p></li><li><p><strong>Extraneous</strong><br>Overhead added by how information is presented. It comes from how we write and document code, not what the code does. It's the mental energy spent deciphering a bad variable name or untangling a nested conditional.</p></li></ul><p>Germane overhead is about building recognition but it&#8217;s rooted in the perceiver&#8217;s level of effort, whereas intrinsic overhead is about information itself and extraneous overhead is about its source.</p><p>These three types of mental overhead are not separate. They work together.</p><p>A complex task (high intrinsic load) becomes impossible when buried in messy code (high extraneous load). Both are made worse if the system itself becomes a niche skill that new hires must master (high germane load).</p><p>Your job is to manage the entire system. Ignoring one type just shifts the burden elsewhere. You need a tool that addresses all three at once.</p>
      <p>
          <a href="https://blog.robhameetman.com/p/building-a-pit-of-success">
              Read more
          </a>
      </p>
   ]]></content:encoded></item><item><title><![CDATA[The Cost of Outrage: How Hot Takes Fuel The Enshitification Of Software Engineering]]></title><description><![CDATA[Spreading Technical Disinformation Has Never Been Easier]]></description><link>https://blog.robhameetman.com/p/the-cost-of-outrage-how-hot-takes</link><guid isPermaLink="false">https://blog.robhameetman.com/p/the-cost-of-outrage-how-hot-takes</guid><dc:creator><![CDATA[Rob Hameetman]]></dc:creator><pubDate>Mon, 02 Jun 2025 11:02:36 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/9e776b17-3ea6-4e22-aa83-df144ad5a4e7_2464x1856.webp" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><em>Hi, I&#8217;m Rob. This is a free issue of UI Engineering Excellence. I write for Frontend Engineers and Product Developers on how to be the best at building apps that win in the market. Subscribe if this is useful. Paid readers get early looks and occasional behind&#8209;the&#8209;scenes notes:</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://blog.robhameetman.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://blog.robhameetman.com/subscribe?"><span>Subscribe now</span></a></p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!fKKV!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F11fd352e-7ff5-41da-8164-ff1647b55f3c_2464x1856.webp" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!fKKV!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F11fd352e-7ff5-41da-8164-ff1647b55f3c_2464x1856.webp 424w, https://substackcdn.com/image/fetch/$s_!fKKV!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F11fd352e-7ff5-41da-8164-ff1647b55f3c_2464x1856.webp 848w, https://substackcdn.com/image/fetch/$s_!fKKV!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F11fd352e-7ff5-41da-8164-ff1647b55f3c_2464x1856.webp 1272w, https://substackcdn.com/image/fetch/$s_!fKKV!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F11fd352e-7ff5-41da-8164-ff1647b55f3c_2464x1856.webp 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!fKKV!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F11fd352e-7ff5-41da-8164-ff1647b55f3c_2464x1856.webp" width="1456" height="1097" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/11fd352e-7ff5-41da-8164-ff1647b55f3c_2464x1856.webp&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1097,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:1991758,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/webp&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://blog.robhameetman.com/i/164096986?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F11fd352e-7ff5-41da-8164-ff1647b55f3c_2464x1856.webp&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!fKKV!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F11fd352e-7ff5-41da-8164-ff1647b55f3c_2464x1856.webp 424w, https://substackcdn.com/image/fetch/$s_!fKKV!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F11fd352e-7ff5-41da-8164-ff1647b55f3c_2464x1856.webp 848w, https://substackcdn.com/image/fetch/$s_!fKKV!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F11fd352e-7ff5-41da-8164-ff1647b55f3c_2464x1856.webp 1272w, https://substackcdn.com/image/fetch/$s_!fKKV!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F11fd352e-7ff5-41da-8164-ff1647b55f3c_2464x1856.webp 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>This morning, LinkedIn suggested this post in my feed:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!1GbP!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1f004035-1cd7-4d8b-a31f-48a4e1deb056_1100x1714.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!1GbP!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1f004035-1cd7-4d8b-a31f-48a4e1deb056_1100x1714.png 424w, https://substackcdn.com/image/fetch/$s_!1GbP!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1f004035-1cd7-4d8b-a31f-48a4e1deb056_1100x1714.png 848w, https://substackcdn.com/image/fetch/$s_!1GbP!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1f004035-1cd7-4d8b-a31f-48a4e1deb056_1100x1714.png 1272w, https://substackcdn.com/image/fetch/$s_!1GbP!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1f004035-1cd7-4d8b-a31f-48a4e1deb056_1100x1714.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!1GbP!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1f004035-1cd7-4d8b-a31f-48a4e1deb056_1100x1714.png" width="341" height="531.34" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/1f004035-1cd7-4d8b-a31f-48a4e1deb056_1100x1714.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1714,&quot;width&quot;:1100,&quot;resizeWidth&quot;:341,&quot;bytes&quot;:570752,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.robhameetman.com/i/164096986?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1f004035-1cd7-4d8b-a31f-48a4e1deb056_1100x1714.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!1GbP!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1f004035-1cd7-4d8b-a31f-48a4e1deb056_1100x1714.png 424w, https://substackcdn.com/image/fetch/$s_!1GbP!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1f004035-1cd7-4d8b-a31f-48a4e1deb056_1100x1714.png 848w, https://substackcdn.com/image/fetch/$s_!1GbP!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1f004035-1cd7-4d8b-a31f-48a4e1deb056_1100x1714.png 1272w, https://substackcdn.com/image/fetch/$s_!1GbP!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1f004035-1cd7-4d8b-a31f-48a4e1deb056_1100x1714.png 1456w" sizes="100vw"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><blockquote><p>I will never, ever use reduce in Javascript.<br>.<br>.<br>&#8221;Reduce is more elegant.&#8221;<br>&#8221;Real devs use functional methods&#8221;<br>&#8221;Loops are old-school.&#8221;<br>&#8221;It&#8217;s just one line, bro.&#8221;<br><br>These are not principles.<br>They&#8217;re just disguised best practices.</p><p>But here&#8217;s the truth:<br>You&#8217;re not writing code for applause.<br>You&#8217;re writing it to be understood.</p><p>&#128078; .reduce() hides logic in syntax<br>&#128078; It often obscures the intent.<br>&#128078; It sacrifices readability for cleverness</p><p>You know what doesn&#8217;t do that?<br>&#9989; A simple for loop.</p><p>Because when the code breaks at 2AM,<br>It won&#8217;t be the code that saves you.</p><p>It&#8217;ll be the line you can actually read quickly.</p></blockquote><p>The first line makes it clear right off the bat that this is rage bait. And particularly low-effort AI rage bait at that. It&#8217;s an opinion designed to be so outrageous and <s>unconventional</s> absurd that more seasoned engineers can&#8217;t help but comment, which in turn maximizes the author&#8217;s reach.</p><p>Content like this goes beyond basic ignorance or lack of experience/expertise into a level of technical disinformation that we as an industry need to get better at identifying and discouraging.</p><p>The key piece of context that pushes this into disinformation territory comes with a deeper understanding of the declarative paradigm itself, which focuses on making code more readable by building up small, compositional abstractions that can result in an almost DSL<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-1" href="#footnote-1" target="_self">1</a>-like experience at scale.</p><h3>A Quick Primer On Declarative Programming</h3><p>Most examples of declarative programming in JS/TS focus on built-in array methods, so if you look it up or ask AI you&#8217;re likely to get an example like this one, where let&#8217;s say a new array is created from an existing array by removing <code>null</code> values and converting the remaining numeric values to strings:</p><pre><code>const arr = [1, 2, 3, 4, null, 6, 7, null, 9, null];
const newArr = [] as Array&lt;string&gt;;

/* Imperative Approach */
for (let i = 0; i &lt; arr.length; i++) {
  if (arr[i] !== null) {
    newArr.push(String(arr[i]));
  }
}

/* Declarative Approach */
const newArr = arr.filter((value) =&gt; value !== null).map(String);</code></pre><p>While built-in <code>Array</code> methods like <code>.filter()</code>, <code>.map()</code>, and <code>.reduce()</code> are declarative, examples like these don&#8217;t fully illustrate why declarative code is advantageous beyond just eliminating a few lines of code here and there.</p><p>The paradigm itself is more about increasing readability by writing code in a way where the thing you want to do happens by simply calling a method <code>.doTheThing()</code> rather than describing <em>how</em> the thing is done. Declarative methods can use loops and other imperative control flows under the hood, so a slightly better example would be rewriting an implementation that starts out like this:</p><blockquote><p>&#128466;&#65039; <strong>Note<br></strong>You probably won&#8217;t actually have this kind of business logic in a real app, but it gets the idea across so hear me out.</p></blockquote><pre><code>interface Person {
  readonly name: string;
  position: energy;
  position: number;
}

const alice: Person = {
  name: 'Alice',
  energy: 100,
  position: 0,
};

const move = (
  person: Person,
  speed: number,
  distance = 1,
  effort = speed,
) =&gt; {
  if (person.energy) {
    for (let i = distance; i &gt; 0; i -= speed) {
      person.position += speed;
      person.energy -= effort;
    }
  }
};

const walk = (person: Person, distance = 1) =&gt;
  move(person, 0.5, distance);

const run = (person: Person, distance = 1) =&gt;
  move(person, 2, distance);

const jump = (person: Person, distance = 1) =&gt;
  move(person, 1, distance, 1.5);

walk(alice, 10);
run(alice, 5);
jump(alice, 4);
walk(alice, 8);</code></pre><p>While we do have our logic broken up into specialized functions, this code is not declarative because each function has to be told which <code>Person</code> is moving as a parameter, so we have to pass <code>alice</code> in as an argument every time. In a more functional approach, you could curry the <code>move()</code> function to get around this like so:</p><pre><code>const move = (person: Person) =&gt;
  (speed: number, distance = 1, effort = speed) =&gt; {
    if (person.energy) {
      for (let i = distance; i &gt; 0; i -= speed) {
        person.position += speed;
        person.energy -= effort;
      }
    }
  };

const aliceMoves = move(alice);
const aliceWalks = (distance = 1) =&gt; aliceMoves(0.5, distance);
const aliceRuns = (distance = 1) =&gt; aliceMoves(2, distance);
const aliceJumps = (distance = 1) =&gt; aliceMoves(1, distance, 1.5);

aliceWalks(10);
aliceRuns(5);
aliceJumps(4);
aliceWalks(8);</code></pre><p>This is a lot better in terms of readability but not so much scalability because we still need discrete functions for each person we want to move. In order to make this code declarative, we need to go beyond simply updating Alice&#8217;s position and return an updated copy of <code>alice</code>:</p><pre><code>interface Person {
  position: number;
  readonly name: string;
  readonly move(speed: number, distance: number, effort: number) =&gt; this;
  readonly walk(distance: number) =&gt; this;
  readonly run(distance: number) =&gt; this;
  readonly jump(distance: number) =&gt; this;
}

const alice: Person = {
  name: 'Alice',
  energy: 100,
  position: 0,
  move(speed: number, distance = 1, effort = speed) {
    if (this.energy) {
      for (let i = distance; i &gt; 0; i -= speed) {
        this.position += speed;
        this.energy -= effort;
      }
    }

    return this;
  },
  walk(distance = 1) {
    return this.move(0.5, distance);
  },
  run(distance = 1) {
    return this.move(2, distance);
  },
  jump(distance = 1) {
    return this.move(1, distance, 1.5);
  },
};</code></pre><p>Writing our code this way allows us to move Alice like this:</p><pre><code>alice.walk(10).run(5).jump(4).walk(8);</code></pre><p>Like I said, you probably won&#8217;t actually shift a <code>Person</code> object&#8217;s position in a real app, but the same principles apply whenever you need a series of heterogeneous transformations (e.g., applying user profile updates, composing query filters, or processing form data.)</p><blockquote><p>&#9757;&#65039; <strong>If this section was helpful let me know!</strong><br>I&#8217;m considering writing up a more in-depth post that dives into this with more relevant examples; I might also do it as a 2-part series that builds on this and shows how I&#8217;ve used RxJS with React in the past to build web apps with declarative streams that have insane performance.</p></blockquote><div><hr></div><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://blog.robhameetman.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption"><em>Like what you&#8217;re seeing so far?</em></p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><div><hr></div><h3>Technical Disinformation</h3><p>Now that we understand what declarative methods like <code>.reduce()</code> are all about, we can start to get a better sense of why this kind of content isn&#8217;t eligible for the same benefits of the doubt we would typically afford the author of the rage bait from earlier, who has just under 3 years of experience at this point.</p><p>Given the examples above, we can see how the &#128078; points being labelled as such is misleading. Except for the last one, the points themselves are fine but should be &#128077; instead. Hiding logic in syntax is a feature of declarative code not a bug. It is, in fact, the point.</p><p>The only time I&#8217;ve seen <code>.reduce()</code> kinda sacrifice readability for cleverness is when it&#8217;s used to pipe async functions sequentially, like this:</p><pre><code>asyncFunctions.reduce(
  (resolved, next) =&gt;
    resolved
      .then((result) =&gt; next(result))
      .catch(console.error),
  Promise.resolve(),
);</code></pre><p>In most cases though, it&#8217;s used to build objects from arrays in situations where <code>Object.fromEntries()</code> isn&#8217;t an option.</p><p>The final two sentences would normally get a pass as well (albeit with a raised eyebrow) but given how sus his whole post is already, I&#8217;m not inclined to start now. Anyone who&#8217;s actually had to respond to a production incident at 2am can tell you it&#8217;s not simple code that saves you, it&#8217;s your recognition- which is faster than recall- leveraging the mental shortcuts you&#8217;ve built up.</p><h3>Newbz These Days!</h3><p>In the beginning (of people teaching themselves to code,) we had books. Fat. Ass. Books. My dad had a book somewhere on one of his bookshelves on C++ that&#8217;s 30 years old now and girthier than my whole fist. Expert software engineers were the people who literally wrote the canonical book or manual on the technical subject of their expertise, or they made a name for themselves as the creator of that subject. Plenty did both.</p><p>Even in the 2010s, posting something like this on your Medium blog <em>intentionally</em> as an aspiring professional would be akin to shouting &#8220;I&#8217;m just an imposter, don&#8217;t hire me!&#8221;</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!M5CH!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0394df66-3860-450f-8744-81b0954ee572_760x910.webp" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!M5CH!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0394df66-3860-450f-8744-81b0954ee572_760x910.webp 424w, https://substackcdn.com/image/fetch/$s_!M5CH!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0394df66-3860-450f-8744-81b0954ee572_760x910.webp 848w, https://substackcdn.com/image/fetch/$s_!M5CH!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0394df66-3860-450f-8744-81b0954ee572_760x910.webp 1272w, https://substackcdn.com/image/fetch/$s_!M5CH!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0394df66-3860-450f-8744-81b0954ee572_760x910.webp 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!M5CH!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0394df66-3860-450f-8744-81b0954ee572_760x910.webp" width="292" height="349.63157894736844" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/0394df66-3860-450f-8744-81b0954ee572_760x910.webp&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:910,&quot;width&quot;:760,&quot;resizeWidth&quot;:292,&quot;bytes&quot;:null,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!M5CH!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0394df66-3860-450f-8744-81b0954ee572_760x910.webp 424w, https://substackcdn.com/image/fetch/$s_!M5CH!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0394df66-3860-450f-8744-81b0954ee572_760x910.webp 848w, https://substackcdn.com/image/fetch/$s_!M5CH!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0394df66-3860-450f-8744-81b0954ee572_760x910.webp 1272w, https://substackcdn.com/image/fetch/$s_!M5CH!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0394df66-3860-450f-8744-81b0954ee572_760x910.webp 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>The tradition of sharing knowledge in this way meant that people positioning themselves as rising stars still had to demonstrate a solid understanding of more sophisticated technique, or at least an eagerness to learn.</p><p>Aimee Knight and Lydia Hallie come to mind as engineers who stood out to me around this time as particularly admirable for their ability to bring others along with them as they entered the field and grew. As Juniors they had no problem talking shop with seasoned experts. If you take a look at <a href="https://www.aimeemarieknight.com/">Aimee's blog</a> today, it&#8217;s as technical as one would expect from an expert software engineer. Lydia&#8217;s technical expertise and her desire to share it continues to speak for itself.</p><h3>Juniors Cannot Be Junior Anymore</h3><p>Bootcamps have flooded the industry with new Engineers, especially on the frontend. While the idea that this number doubles every 5 years is more of a myth these days, <a href="https://survey.stackoverflow.co/2024/developer-profile#3-years-of-professional-coding-experience-by-developer-type">data from the most recent Stack Overflow Annual Developer Survey</a> does show that the average Frontend Engineer has less than 8 years of experience.</p><p>I&#8217;ve definitely noticed the impact of this especially over the past few years; at least the last two organizations I've been at have had ICs under Staff that were a standard deviation below what I&#8217;d typically expect in terms of technical expertise <em>at every level</em>. And it&#8217;s not just me who&#8217;s noticed! In one of these roles this was a widely acknowledged fact amongst the Staff+ group.</p><p>At first I chalked it up to that organization having scaled too rapidly, but seeing this pattern across multiple organizations consecutively has made the talent gap in the industry crystal clear.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!eieD!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb9f77d02-446c-4143-8afb-205c945d1db6_650x500.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!eieD!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb9f77d02-446c-4143-8afb-205c945d1db6_650x500.png 424w, https://substackcdn.com/image/fetch/$s_!eieD!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb9f77d02-446c-4143-8afb-205c945d1db6_650x500.png 848w, https://substackcdn.com/image/fetch/$s_!eieD!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb9f77d02-446c-4143-8afb-205c945d1db6_650x500.png 1272w, https://substackcdn.com/image/fetch/$s_!eieD!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb9f77d02-446c-4143-8afb-205c945d1db6_650x500.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!eieD!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb9f77d02-446c-4143-8afb-205c945d1db6_650x500.png" width="498" height="383.0769230769231" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/b9f77d02-446c-4143-8afb-205c945d1db6_650x500.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:500,&quot;width&quot;:650,&quot;resizeWidth&quot;:498,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!eieD!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb9f77d02-446c-4143-8afb-205c945d1db6_650x500.png 424w, https://substackcdn.com/image/fetch/$s_!eieD!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb9f77d02-446c-4143-8afb-205c945d1db6_650x500.png 848w, https://substackcdn.com/image/fetch/$s_!eieD!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb9f77d02-446c-4143-8afb-205c945d1db6_650x500.png 1272w, https://substackcdn.com/image/fetch/$s_!eieD!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb9f77d02-446c-4143-8afb-205c945d1db6_650x500.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">&#128279; link: https://medium.com/@jankammerath/the-junior-developer-role-has-become-great-again-85e47b7bcbde</figcaption></figure></div><p>With the advent of AI upon us, Juniors by today&#8217;s standards have been all but replaced, along with some contractors who do team augmentation as an extra pair of hands. We don&#8217;t need new people who write code without having any idea how it works because we have AI for that now! And AI is at least much, much faster.</p><p>But companies aren&#8217;t just going to stop hiring Juniors. ICs get old after a while, and expensive, and become consultants or go into management or leadership or retire early. We still need new folks to start somewhere, so the job description needs a revamp. The problem for recent grads is that the job market, already oversaturated as it is, is insanely bottom-heavy.</p><p>The intensity of this competition effectively raises the bar and, I believe, will eventually close the talent gap. The demand for experts is decreasing<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-2" href="#footnote-2" target="_self">2</a>, but the value of expertise itself is actually increasing. What I would never tell a candidate I&#8217;m passing on is that you can have an Ivy League CS degree and 5 FAANG/MAMAA internships but there&#8217;s a line of folks out the door who are just as eager to learn and capable of doing so just as quickly, so if you&#8217;re only as technical as your AI then you aren&#8217;t going to yield the best return on investment.</p><blockquote><p>&#128173; <strong>BTW</strong><br>If you do actually have an Ivy League CS degree and 5 FAANG/MAMAA internships you&#8217;re gonna be fine. Eventually.</p></blockquote><h3>Wrapping This Up</h3><p>Back to the LinkedIn post at the top, it should go without saying at this point that dishing out a blatantly bad technical opinion is probably a bad idea. It&#8217;s not that it won&#8217;t work- it unfortunately does work to a certain degree or else this guy wouldn&#8217;t be doing it.</p><p>Not sure how many followers he added but his comments were riddled with Seniors calling him out as a bad engineer (&#8220;sounds like a skill issue&#8221;). And that was unfortunately the whole idea. So I threw him on my blocklist, and I&#8217;m sure I wasn&#8217;t the only one.</p><p>But if I&#8217;m looking at the trade-offs, in the long-run, building an audience at the cost of connecting with more technical peers who strive to make a name for themselves by actually knowing what they&#8217;re talking about doesn&#8217;t seem worth it. These folks will someday surpass you both in talent and pay, if they aren&#8217;t already ahead. And this will lock you in as Yet Another Engineer Who Only Writes About Soft Skills, because the audience that you do have are going to be chalk full of vibe coders<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-3" href="#footnote-3" target="_self">3</a> and Product/Growth Developers.</p><p>Look, I&#8217;m not even saying don&#8217;t ever use rage bait. We all do it sometimes; I have opinions in my Notes that, while genuine, definitely come across as rage bait-ey. What matters is that these are opinions I&#8217;ve formed as a result of a decade of industry experience; I&#8217;m not contriving them just to increase my numbers.</p><p>If you <em>must</em> resort to technical hot takes on LinkedIn, at least use <strong>The &#8220;Prove Me Wrong&#8221;</strong> variant so you don&#8217;t make yourself look like an asshole who is unable or unwilling to take feedback in code review.</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!LRLx!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17b509d7-f748-4f7e-92db-a8ed3d1f3352_792x428.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!LRLx!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17b509d7-f748-4f7e-92db-a8ed3d1f3352_792x428.png 424w, https://substackcdn.com/image/fetch/$s_!LRLx!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17b509d7-f748-4f7e-92db-a8ed3d1f3352_792x428.png 848w, https://substackcdn.com/image/fetch/$s_!LRLx!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17b509d7-f748-4f7e-92db-a8ed3d1f3352_792x428.png 1272w, https://substackcdn.com/image/fetch/$s_!LRLx!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17b509d7-f748-4f7e-92db-a8ed3d1f3352_792x428.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!LRLx!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17b509d7-f748-4f7e-92db-a8ed3d1f3352_792x428.png" width="300" height="162.12121212121212" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/17b509d7-f748-4f7e-92db-a8ed3d1f3352_792x428.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:428,&quot;width&quot;:792,&quot;resizeWidth&quot;:300,&quot;bytes&quot;:37166,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:&quot;&quot;,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.robhameetman.com/i/154924704?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17b509d7-f748-4f7e-92db-a8ed3d1f3352_792x428.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!LRLx!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17b509d7-f748-4f7e-92db-a8ed3d1f3352_792x428.png 424w, https://substackcdn.com/image/fetch/$s_!LRLx!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17b509d7-f748-4f7e-92db-a8ed3d1f3352_792x428.png 848w, https://substackcdn.com/image/fetch/$s_!LRLx!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17b509d7-f748-4f7e-92db-a8ed3d1f3352_792x428.png 1272w, https://substackcdn.com/image/fetch/$s_!LRLx!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17b509d7-f748-4f7e-92db-a8ed3d1f3352_792x428.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><div><hr></div><blockquote><p>&#128591; BTW my subscribers are <strong>the best</strong>, my previous post on <em><strong><a href="https://blog.robhameetman.com/p/aligning-components-with-custom-html?r=2ypy2w">Aligning Components with Custom HTML Attributes</a></strong></em> achieved an 80% open rate and I can&#8217;t thank each of you enough for taking the time to read it!</p></blockquote><h2>Up Next</h2><div class="digest-post-embed" data-attrs="{&quot;nodeId&quot;:&quot;64b5c768-58cf-4d76-91bc-a4066f5f4653&quot;,&quot;caption&quot;:&quot;Feature teams move slower than they should. What takes a week could take a day. Simple changes somehow break unrelated things. New hires need months to become useful.&quot;,&quot;cta&quot;:&quot;Read full story&quot;,&quot;showBylines&quot;:true,&quot;size&quot;:&quot;sm&quot;,&quot;isEditorNode&quot;:true,&quot;title&quot;:&quot;[WIP] Building a Pit of Success with Inductive Reasoning&quot;,&quot;publishedBylines&quot;:[{&quot;id&quot;:179249864,&quot;name&quot;:&quot;Rob Hameetman&quot;,&quot;bio&quot;:&quot;I&#8217;m a Staff Design Engineer who builds sexy, scalable enterprise-strength design systems.&quot;,&quot;photo_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/fd162dbf-8c1b-48bc-b6e7-0969af7da7ca_475x475.jpeg&quot;,&quot;is_guest&quot;:false,&quot;bestseller_tier&quot;:null}],&quot;post_date&quot;:&quot;2025-08-24T22:01:39.994Z&quot;,&quot;cover_image&quot;:&quot;https://substackcdn.com/image/fetch/$s_!v3zD!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F818fc660-922d-4795-992a-dfaeefa0d752_2464x1856.webp&quot;,&quot;cover_image_alt&quot;:null,&quot;canonical_url&quot;:&quot;https://blog.robhameetman.com/p/building-a-pit-of-success&quot;,&quot;section_name&quot;:&quot;Deeps&quot;,&quot;video_upload_id&quot;:null,&quot;id&quot;:166478385,&quot;type&quot;:&quot;newsletter&quot;,&quot;reaction_count&quot;:1,&quot;comment_count&quot;:0,&quot;publication_id&quot;:2076716,&quot;publication_name&quot;:&quot;UI Engineering Excellence&quot;,&quot;publication_logo_url&quot;:&quot;https://substackcdn.com/image/fetch/$s_!deTI!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdc5e8141-3a0f-4181-8804-acdbb61e8707_359x359.png&quot;,&quot;belowTheFold&quot;:true,&quot;youtube_url&quot;:null,&quot;show_links&quot;:null,&quot;feed_url&quot;:null}"></div><div class="digest-post-embed" data-attrs="{&quot;nodeId&quot;:&quot;2168e223-8f1b-4760-8fee-fc2ed39543b7&quot;,&quot;caption&quot;:&quot;Icons are everywhere, yet they&#8217;re probably the easiest thing in your design system to screw up. I&#8217;ve seen so many <Icon> components that overcomplicate the DOM while doing nothing to make accessibility easier to achieve.&quot;,&quot;cta&quot;:&quot;Read full story&quot;,&quot;showBylines&quot;:true,&quot;size&quot;:&quot;sm&quot;,&quot;isEditorNode&quot;:true,&quot;title&quot;:&quot;[WIP] Accessible SVG Icons The Right Way&quot;,&quot;publishedBylines&quot;:[{&quot;id&quot;:179249864,&quot;name&quot;:&quot;Rob Hameetman&quot;,&quot;bio&quot;:&quot;I&#8217;m a Staff Design Engineer who builds sexy, scalable enterprise-strength design systems.&quot;,&quot;photo_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/fd162dbf-8c1b-48bc-b6e7-0969af7da7ca_475x475.jpeg&quot;,&quot;is_guest&quot;:false,&quot;bestseller_tier&quot;:null}],&quot;post_date&quot;:&quot;2025-08-24T22:17:59.979Z&quot;,&quot;cover_image&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/c54b3810-d9fa-4986-9775-77008fb03c90_2464x1856.webp&quot;,&quot;cover_image_alt&quot;:null,&quot;canonical_url&quot;:&quot;https://blog.robhameetman.com/p/accessible-svg-icons&quot;,&quot;section_name&quot;:&quot;Resources&quot;,&quot;video_upload_id&quot;:null,&quot;id&quot;:166355744,&quot;type&quot;:&quot;newsletter&quot;,&quot;reaction_count&quot;:1,&quot;comment_count&quot;:0,&quot;publication_id&quot;:2076716,&quot;publication_name&quot;:&quot;UI Engineering Excellence&quot;,&quot;publication_logo_url&quot;:&quot;https://substackcdn.com/image/fetch/$s_!deTI!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdc5e8141-3a0f-4181-8804-acdbb61e8707_359x359.png&quot;,&quot;belowTheFold&quot;:true,&quot;youtube_url&quot;:null,&quot;show_links&quot;:null,&quot;feed_url&quot;:null}"></div><div class="digest-post-embed" data-attrs="{&quot;nodeId&quot;:&quot;14412bb5-e6bd-4dc1-bc53-718fc3a028f5&quot;,&quot;caption&quot;:&quot;Hi, I&#8217;m Rob. This is a free issue of UI Engineering Excellence. I write for Frontend Engineers and Product Developers on how to be the best at building apps that win in the market. Subscribe if this is useful. Paid readers get early looks and occasional behind&#8209;the&#8209;scenes notes:&quot;,&quot;cta&quot;:&quot;Read full story&quot;,&quot;showBylines&quot;:true,&quot;size&quot;:&quot;sm&quot;,&quot;isEditorNode&quot;:true,&quot;title&quot;:&quot;Architecting Design Systems for Human Perception&quot;,&quot;publishedBylines&quot;:[{&quot;id&quot;:179249864,&quot;name&quot;:&quot;Rob Hameetman&quot;,&quot;bio&quot;:&quot;I&#8217;m a Staff Design Engineer who builds sexy, scalable enterprise-strength design systems.&quot;,&quot;photo_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/fd162dbf-8c1b-48bc-b6e7-0969af7da7ca_475x475.jpeg&quot;,&quot;is_guest&quot;:false,&quot;bestseller_tier&quot;:null}],&quot;post_date&quot;:&quot;2025-08-25T22:53:00.000Z&quot;,&quot;cover_image&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/dec40623-1506-4735-bb21-e324828114e3_2464x1856.webp&quot;,&quot;cover_image_alt&quot;:null,&quot;canonical_url&quot;:&quot;https://blog.robhameetman.com/p/design-systems-for-human-perception&quot;,&quot;section_name&quot;:&quot;Deeps&quot;,&quot;video_upload_id&quot;:null,&quot;id&quot;:168566184,&quot;type&quot;:&quot;newsletter&quot;,&quot;reaction_count&quot;:4,&quot;comment_count&quot;:0,&quot;publication_id&quot;:2076716,&quot;publication_name&quot;:&quot;UI Engineering Excellence&quot;,&quot;publication_logo_url&quot;:&quot;https://substackcdn.com/image/fetch/$s_!deTI!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdc5e8141-3a0f-4181-8804-acdbb61e8707_359x359.png&quot;,&quot;belowTheFold&quot;:true,&quot;youtube_url&quot;:null,&quot;show_links&quot;:null,&quot;feed_url&quot;:null}"></div><p>Any thoughts on what else you&#8217;d like to see? Leave a comment or hop into chat and let me know! I&#8217;ll be on vacation most of this month but have plenty to dive into as soon as I&#8217;m back.</p><div><hr></div><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://blog.robhameetman.com/p/the-cost-of-outrage-how-hot-takes?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://blog.robhameetman.com/p/the-cost-of-outrage-how-hot-takes?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://blog.robhameetman.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption"><em>If you enjoyed this post, please subscribe, hit the &#10084;&#65039; button, and share/restack &#128257; it with others who might find it helpful!</em></p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-1" href="#footnote-anchor-1" class="footnote-number" contenteditable="false" target="_self">1</a><div class="footnote-content"><p>Domain-Specific Language- a specialized language used for certain contexts, e.g. <a href="https://cucumber.io/docs/gherkin/reference">Gherkin</a> for BDD-style testing.</p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-2" href="#footnote-anchor-2" class="footnote-number" contenteditable="false" target="_self">2</a><div class="footnote-content"><p>Demand for experts has been decreasing since entrepreneurs started shifting away from scalability toward acquirability.</p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-3" href="#footnote-anchor-3" class="footnote-number" contenteditable="false" target="_self">3</a><div class="footnote-content"><p>By &#8220;vibe coders&#8221; I mean people who don&#8217;t review or correct AI-written code, not people who use AI-integrated tooling in general.</p></div></div>]]></content:encoded></item><item><title><![CDATA[The Newest Version of Claude Created a UI Pattern I’ve Never Seen Before]]></title><description><![CDATA[What happens when AI challenges conventional design system patterns?]]></description><link>https://blog.robhameetman.com/p/the-newest-version-of-claude-created-a-ui-pattern-ive-never-seen-before</link><guid isPermaLink="false">https://blog.robhameetman.com/p/the-newest-version-of-claude-created-a-ui-pattern-ive-never-seen-before</guid><dc:creator><![CDATA[Rob Hameetman]]></dc:creator><pubDate>Tue, 25 Feb 2025 11:15:25 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/1dd244ee-7afc-452e-825f-7d31e2c97e35_2464x1856.webp" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><em>Hi, I&#8217;m Rob. This is a free issue of UI Engineering Excellence. I write for Frontend Engineers and Product Developers on how to be the best at building apps that win in the market. Subscribe if this is useful. Paid readers get early looks and occasional behind&#8209;the&#8209;scenes notes:</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://blog.robhameetman.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://blog.robhameetman.com/subscribe?"><span>Subscribe now</span></a></p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Kur5!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcbeb0ce2-1df7-4db3-b746-909b9a19fd3d_2464x1856.webp" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Kur5!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcbeb0ce2-1df7-4db3-b746-909b9a19fd3d_2464x1856.webp 424w, https://substackcdn.com/image/fetch/$s_!Kur5!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcbeb0ce2-1df7-4db3-b746-909b9a19fd3d_2464x1856.webp 848w, https://substackcdn.com/image/fetch/$s_!Kur5!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcbeb0ce2-1df7-4db3-b746-909b9a19fd3d_2464x1856.webp 1272w, https://substackcdn.com/image/fetch/$s_!Kur5!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcbeb0ce2-1df7-4db3-b746-909b9a19fd3d_2464x1856.webp 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Kur5!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcbeb0ce2-1df7-4db3-b746-909b9a19fd3d_2464x1856.webp" width="1456" height="1097" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/cbeb0ce2-1df7-4db3-b746-909b9a19fd3d_2464x1856.webp&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1097,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:1940612,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/webp&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://blog.robhameetman.com/i/157864768?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcbeb0ce2-1df7-4db3-b746-909b9a19fd3d_2464x1856.webp&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!Kur5!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcbeb0ce2-1df7-4db3-b746-909b9a19fd3d_2464x1856.webp 424w, https://substackcdn.com/image/fetch/$s_!Kur5!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcbeb0ce2-1df7-4db3-b746-909b9a19fd3d_2464x1856.webp 848w, https://substackcdn.com/image/fetch/$s_!Kur5!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcbeb0ce2-1df7-4db3-b746-909b9a19fd3d_2464x1856.webp 1272w, https://substackcdn.com/image/fetch/$s_!Kur5!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcbeb0ce2-1df7-4db3-b746-909b9a19fd3d_2464x1856.webp 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Over the past month, I've been exploring how AI can accelerate the code mockup process for design system components. We started with a structured methodology, then moved into comparing leading AI models like <strong>ChatGPT o3, Claude 3.5 Sonnet, and DeepSeek R1.</strong></p><p>Today, Anthropic released Claude Code and <strong>Claude 3.7 Sonnet</strong>, a new model with an extended reasoning mode to mirror the complex chain-of-thought that precedes output by <strong>ChatGPT o3-mini-high</strong> and <strong>DeepSeek R1</strong>.</p><p>DeepSeek shattered my expectations by demonstrating that AI doesn&#8217;t necessarily always get worse as complexity increases, though Claude 3.5 Sonnet proved an impressively close runner-up. Can Claude 3.7 Sonnet&#8217;s reasoning one-up DeepSeek&#8217;s?</p><p>Let&#8217;s find out!</p><div><hr></div><h2>Testing The Same Components</h2><p>To maintain consistency with my previous tests, I evaluated <strong>Claude 3.7 Sonnet</strong> against the same three components:</p><ul><li><p><strong>&lt;Kbd /&gt;</strong> - Our atomic component representing keyboard keys</p></li><li><p><strong>&lt;Breadcrumbs /&gt;</strong> - Our molecular component for navigational breadcrumbs</p></li><li><p><strong>&lt;Table /&gt;</strong> - Our complex organism component for data display</p></li></ul><p>Let's dive in and see how Claude 3.7 Sonnet performed in each case.</p><div><hr></div><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://blog.robhameetman.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">&#10084;&#65039; Like what you&#8217;re seeing so far?</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><div><hr></div><p><code>&lt;Kbd /&gt;</code><br>&#9989; <strong>Passable Rough Draft</strong></p><ul><li><p><strong>Pattern: </strong>Standalone Component</p></li><li><p><strong>Approach #1: Individual Key Components</strong></p></li></ul><pre><code>// Single key
&lt;Kbd&gt;A&lt;/Kbd&gt;

// Key combination (manual arrangement)
&lt;span&gt;
  &lt;Kbd&gt;Ctrl&lt;/Kbd&gt;
  &lt;span&gt;+&lt;/span&gt;
  &lt;Kbd&gt;C&lt;/Kbd&gt;
&lt;/span&gt;

// With styling variants
&lt;Kbd size="small" variant="outline"&gt;Tab&lt;/Kbd&gt;

// Using special key constants
&lt;Kbd&gt;{KEY_SYMBOLS.COMMAND}&lt;/Kbd&gt;</code></pre><ul><li><p><strong>Approach #2: Combination Support Built-in</strong></p></li></ul><pre><code>// Single key
&lt;Kbd&gt;A&lt;/Kbd&gt;

// Key combination as array
&lt;Kbd keys={["Ctrl", "C"]} /&gt;

// Custom separator
&lt;Kbd keys={["Cmd", "Option", "Esc"]} separator="+" /&gt;

// With styling variants
&lt;Kbd keys={["Shift", "Tab"]} size="small" variant="outline" /&gt;

// Using key binding object
&lt;Kbd keyBinding={{ 
  modifier: ["Ctrl", "Alt"],
  key: "Delete"
}} /&gt;</code></pre><ul><li><p><strong>Discrete Props</strong>:</p><ul><li><p><strong>Kbd</strong>: <code>keys</code>, <code>keyBinding</code>, <code>separator</code>, <code>size</code>, <code>variant</code></p></li></ul></li><li><p><strong>Ancillary Resources:</strong></p><ul><li><p><strong>Functions:</strong> <code>normalizeKeyNames()</code>, <code>formatKeyBinding()</code></p></li><li><p><strong>Types: </strong><code>KeyBinding</code>, <code>KbdProps</code>, <code>KbdSize</code>, <code>KbdVariant</code></p></li><li><p><strong>Constants:</strong> <code>KBD_SIZE</code>, <code>KBD_VARIANT</code>,<code> KEY_SYMBOLS</code>, PLATFORM_KEYS</p></li></ul></li></ul><h4>Review</h4><p>The last test for this component was the first time Claude really <strong>"wow!"&#8217;d</strong> me. Unlike <strong>ChatGPT o3-mini-high</strong> and <strong>DeepSeek R1</strong>, which <strong>considered but rejected</strong> a compound component approach, Claude&#8217;s lack of explicit reasoning actually led to a <strong>more exploratory result</strong>&#8212;one that felt closer to something that might actually be submitted to VSDS at VividSeats.</p><p>That said, <strong>Claude 3.7 also skipped the compound component approach</strong>, allowing some logical flaws to slip through.</p><ul><li><p><strong>Approach #1</strong> is simple and straightforward, but the way spans are used makes it unclear what the <strong>actual implementation</strong> would accomplish without variants.</p></li><li><p><strong>Approach #2</strong> is cleaner, and while I initially questioned whether it was distinct enough, the switch from text child to a<strong> </strong><code>keys</code><strong> </strong>prop makes it a valid alternative.</p></li><li><p>However, the difference between<strong> </strong><code>key</code><strong> </strong>and<strong> </strong><code>keyBinding</code> is unclear beyond passing <code>keyBinding</code> to <code>formatKeyBinding()</code>. The extra structure for <strong>labelling modifiers</strong> also feels unnecessary.</p></li></ul><p>Even if modifiers are needed labels, I&#8217;d <strong>avoid passing objects through props</strong> when possible&#8212;key/value pairs usually should just be <strong>explicit props</strong> instead:</p><pre><code>&lt;Kbd modifier={['Ctrl', 'Alt']} key="Delete" /&gt;</code></pre><p>The best parts of this result are:<br>&#9989; <strong>Cross-platform considerations</strong><br>&#9989; <strong>Well-aligned ancillary resources</strong><br>&#9989; <strong>Better code quality</strong> (const assertions!?)</p><p>It would be even better if <code>KbdSize</code><strong> and </strong><code>KbdVariant</code> were inferred from the <code>KBD_SIZE</code> and <code>KBD_VARIANT</code> constants via <code>typeof</code>, but that&#8217;s something for review.</p><p>Overall, some details in the usage snippets are a bit dubious, but the output is <strong>solid enough</strong> to present. Now, let&#8217;s see what happens when we give Claude 3.7 more to work with!</p><div><hr></div><p><code>&lt;Breadcrumbs /&gt;</code><br>&#9888;&#65039; <strong>Questionable</strong></p><ul><li><p><strong>Pattern:</strong> Compound component</p></li><li><p><strong>Approach #1: Compound Component with Explicit Items</strong></p><ul><li><p><strong>Subcomponents:</strong> <code>Breadcrumbs.Item</code></p></li></ul></li></ul><pre><code>&lt;Breadcrumbs testId="site-breadcrumbs"&gt;
  &lt;Breadcrumbs.Item href="/"&gt;Home&lt;/Breadcrumbs.Item&gt;
  &lt;Breadcrumbs.Item href="/products"&gt;Products&lt;/Breadcrumbs.Item&gt;
  &lt;Breadcrumbs.Item href="/products/electronics"&gt;Electronics&lt;/Breadcrumbs.Item&gt;
  &lt;Breadcrumbs.Item active&gt;Smartphones&lt;/Breadcrumbs.Item&gt;
&lt;/Breadcrumbs&gt;</code></pre><ul><li><p><strong>Approach #2: Compound Component with Custom Separator</strong></p><ul><li><p><strong>Subcomponents:</strong> <code>Breadcrumbs.Item</code>, <code>Breadcrumbs.Separator</code></p></li></ul></li></ul><pre><code>&lt;Breadcrumbs 
  testId="custom-breadcrumbs"
  separator={&lt;Breadcrumbs.Separator&gt;/&lt;/Breadcrumbs.Separator&gt;}
&gt;
  &lt;Breadcrumbs.Item href="/"&gt;Home&lt;/Breadcrumbs.Item&gt;
  &lt;Breadcrumbs.Item href="/products"&gt;Products&lt;/Breadcrumbs.Item&gt;
  &lt;Breadcrumbs.Item active&gt;Categories&lt;/Breadcrumbs.Item&gt;
&lt;/Breadcrumbs&gt;</code></pre><ul><li><p><strong>Approach #3: Combination Support Built-in</strong></p></li></ul><pre><code><code>const items: BreadcrumbItem[] = [
  { label: 'Home', href: '/' },
  { label: 'Products', href: '/products' },
  { label: 'Electronics', href: '/products/electronics' },
  { label: 'Smartphones', active: true }
];

&lt;Breadcrumbs 
  testId="data-driven-breadcrumbs"
  items={items} 
/&gt;</code></code></pre><ul><li><p><strong>Discrete Props</strong>:</p><ul><li><p><strong>Breadcrumbs</strong>: <code>maxDisplayed</code>, <code>items</code> (Approach #3), <code>separator</code>, <code>truncate</code>, <code>onCollapse()</code>, <code>onExpand()</code></p></li><li><p><strong>Breadcrumbs.Item</strong>: <code>active</code>, <code>href</code>, <code>icon</code>, <code>onPress()</code></p></li></ul></li><li><p><strong>Ancillary Resources:</strong></p><ul><li><p><strong>Hooks:</strong> <code>useBreadcrumbsContext()</code>, <code>useCollapsedItems()</code></p></li><li><p><strong>Functions:</strong> <code>formatBreadcrumbs()</code></p></li><li><p><strong>Types:</strong> <code>BreadcrumbItem</code>, <code>BreadcrumbsContextValue</code></p></li><li><p><strong>Enums:</strong> <code>BreadcrumbDisplayMode</code></p></li><li><p><strong>Constants: </strong><code>DEFAULT_SEPARATOR</code>, DEFAULT_MAX_DISPLAYED</p></li></ul></li></ul><h4>Review</h4><p><strong>Approach #1</strong> and <strong>Approach #3</strong> are both passable, <strong>Approach #2</strong> is not since it&#8217;s really just the same as <strong>Approach #1</strong> but with an extra subcomponent. Unfortunately, this is enough of a loss of credibility to keep this result in the <strong>Questionable</strong> category, though it&#8217;s presentable if we just <strong>remove Approach #2</strong>.</p><p>Again, the code snippets are much better than Claude 3.5. The hooks make more sense and they align with other resources (e.g. <code>useBreadcrumbsContext()</code> and <code>BreadcrumbsContextValue</code>.) Interestingly, Claude 3.7 also described the return type of <code>useCollapsedItems()</code>, which is an object that includes some state and a method <code>toggleCollapse()</code>.</p><p>For anyone curious about what <code>BreadcrumbDisplayMode</code> is, here you go!</p><pre><code>enum BreadcrumbDisplayMode {
  All = "all",
  Collapsed = "collapsed",
  FirstLast = "firstLast"
}</code></pre><div><hr></div><p><code>&lt;Table /&gt;</code> <br>&#9989; <strong>Passable Rough Draft</strong></p><ul><li><p><strong>Pattern:</strong> Compound component</p></li><li><p><strong>Variants:</strong></p></li><li><p><strong>Subcomponents:</strong></p></li><li><p><strong>Approach #1: Full Compound Structure with Context</strong></p></li></ul><pre><code>// Usage example
const BasicTable = () =&gt; (
  &lt;Table testId="user-data-table"&gt;
    &lt;Table.Caption&gt;List of active users&lt;/Table.Caption&gt;
    &lt;Table.Header&gt;
      &lt;Table.Row&gt;
        &lt;Table.HeaderCell&gt;Name&lt;/Table.HeaderCell&gt;
        &lt;Table.HeaderCell&gt;Email&lt;/Table.HeaderCell&gt;
        &lt;Table.HeaderCell&gt;Role&lt;/Table.HeaderCell&gt;
      &lt;/Table.Row&gt;
    &lt;/Table.Header&gt;
    &lt;Table.Body&gt;
      {users.map((user) =&gt; (
        &lt;Table.Row key={user.id}&gt;
          &lt;Table.Cell&gt;{user.name}&lt;/Table.Cell&gt;
          &lt;Table.Cell&gt;{user.email}&lt;/Table.Cell&gt;
          &lt;Table.Cell&gt;{user.role}&lt;/Table.Cell&gt;
        &lt;/Table.Row&gt;
      ))}
    &lt;/Table.Body&gt;
    &lt;Table.Footer&gt;
      &lt;Table.Row&gt;
        &lt;Table.Cell colSpan={3}&gt;Total Users: {users.length}&lt;/Table.Cell&gt;
      &lt;/Table.Row&gt;
    &lt;/Table.Footer&gt;
  &lt;/Table&gt;
);

// Sortable example
const SortableTable = () =&gt; {
  const [sortConfig, setSortConfig] = useState&lt;SortConfig&gt;({ key: 'name', direction: 'ascending' });
  
  const handleSort = (key: string) =&gt; {
    // Sort logic here
  };
  
  return (
    &lt;Table testId="sortable-user-table"&gt;
      &lt;Table.Header&gt;
        &lt;Table.Row&gt;
          &lt;Table.HeaderCell sortable onSort={() =&gt; handleSort('name')} sortDirection={sortConfig.key === 'name' ? sortConfig.direction : undefined}&gt;
            Name
          &lt;/Table.HeaderCell&gt;
          &lt;Table.HeaderCell sortable onSort={() =&gt; handleSort('email')} sortDirection={sortConfig.key === 'email' ? sortConfig.direction : undefined}&gt;
            Email
          &lt;/Table.HeaderCell&gt;
          &lt;Table.HeaderCell&gt;Role&lt;/Table.HeaderCell&gt;
        &lt;/Table.Row&gt;
      &lt;/Table.Header&gt;
      &lt;Table.Body&gt;
        {/* Sorted users */}
      &lt;/Table.Body&gt;
    &lt;/Table&gt;
  );
};</code></pre><ul><li><p><strong>Approach #2: Compositional with Column Definition</strong></p></li></ul><pre><code>// Usage example
const ColumnDefinedTable = () =&gt; {
  const columns: Array&lt;ColumnDefinition&gt; = [
    { key: 'name', header: 'Name', sortable: true },
    { key: 'email', header: 'Email', sortable: true },
    { key: 'role', header: 'Role' }
  ];
  
  return (
    &lt;Table 
      testId="user-table-defined" 
      columns={columns}
      data={users}
      caption="List of active users"
      onSort={(key, direction) =&gt; { /* Handle sort */ }}
    &gt;
      &lt;Table.Pagination 
        totalItems={users.length} 
        itemsPerPage={10} 
        onPageChange={(page) =&gt; { /* Handle page change */ }} 
      /&gt;
    &lt;/Table&gt;
  );
};

// With custom cell rendering
const CustomCellTable = () =&gt; {
  const columns: Array&lt;ColumnDefinition&gt; = [
    { 
      key: 'name', 
      header: 'Name', 
      render: (user) =&gt; &lt;strong&gt;{user.name}&lt;/strong&gt; 
    },
    { 
      key: 'status', 
      header: 'Status', 
      render: (user) =&gt; (
        &lt;Table.StatusCell status={user.status} /&gt;
      )
    },
    { 
      key: 'actions', 
      header: 'Actions', 
      render: (user) =&gt; (
        &lt;Table.ActionCell&gt;
          &lt;Button onPress={() =&gt; editUser(user)}&gt;Edit&lt;/Button&gt;
          &lt;Button onPress={() =&gt; deleteUser(user)}&gt;Delete&lt;/Button&gt;
        &lt;/Table.ActionCell&gt;
      )
    }
  ];
  
  return (
    &lt;Table 
      testId="custom-cell-table" 
      columns={columns}
      data={users}
    /&gt;
  );
};</code></pre><ul><li><p><strong>Discrete Props</strong>:</p><ul><li><p><strong>Table</strong>: <code>columns</code>, <code>data</code> (Approach #2), <code>striped</code>, <code>bordered</code>, <code>compact</code>, <code>hoverable</code>, <code>sortConfig</code>,  <code>onSort()</code></p></li><li><p><strong>Table.Row</strong>: <code>selected</code>, <code>onPress()</code></p></li><li><p><strong>Table.Cell</strong>: <code>colSpan</code>, <code>rowSpan</code>, <code>align</code>, <code>truncate</code></p></li><li><p><strong>Table.HeaderCell</strong>: <code>colSpan</code>, <code>rowSpan</code>, <code>align</code>, <code>sortable</code>, <code>sortDirection</code>, <code>onSort()</code></p></li><li><p><strong>Table.Pagination</strong>: <code>currentPage</code>, <code>totalItems</code>, <code>itemsPerPage</code>, <code>onPageChange()</code></p></li></ul></li><li><p><strong>Ancillary Resources:</strong></p><ul><li><p><strong>Hooks:</strong> <code>useSortableTable()</code>, <code>useSelectableTable()</code>, <code>usePaginatedTable()</code>, <code>useTable()</code></p></li><li><p><strong>Functions:</strong> <code>sortTableData()</code>, <code>filterTableData()</code>, <code>paginateTableData()</code></p></li><li><p><strong>Types:</strong> <code>ColumnDefinition</code>, <code>SortConfig</code>, <code>SortableTableResult</code>, <code>SelectableTableOptions</code>, <code>SelectableTableResult</code>, <code>PaginationOptions</code>, <code>PaginatedTableResult</code>, <code>TableContext</code></p></li><li><p><strong>Enums:</strong> <code>SortDirection</code>, <code>TableCellAlignment</code></p></li><li><p><strong>Constants: </strong><code>DEFAULT_ITEMS_PER_PAGE</code>, <code>DEFAULT_PAGE_SIZES</code>, <code>DEFAULT_SORT_DIRECTION</code></p></li></ul></li></ul><h4><strong>Review</strong></h4><p>At first glance, both approaches feel <strong>over-engineered</strong>, and I wasn&#8217;t sure Approach #2 was distinct enough to be a true alternative. But looking closer, I noticed something I hadn&#8217;t seen before.</p><p>Compound components are <strong>only mutually exclusive to standalone components</strong>&#8212;they&#8217;re often used as <strong>base components</strong> both inside and outside the design system. When this happens <strong>within</strong> the design system, we call it a <strong>Compound-as-Base Hybrid</strong>.</p><p>Typically, compound components take subcomponents as children, but some cases <strong>invert this relationship</strong>, allowing a subcomponent (often a <code>Group</code>) to take the parent as children instead.</p><h4><strong>A New Pattern Emerges</strong></h4><p>Approach #2 does something interesting with <code>Table.ActionCell</code> and <code>Table.StatusCell</code>. Instead of using <code>Table.Cell</code> as just another subcomponent, <strong>Claude 3.7 treats it as a base subcomponent</strong>&#8212;essentially creating a base pattern within a compound component.</p><p>I&#8217;ve seen entire compound components used as base components, but I&#8217;ve never come across <strong>a compound component with a base subcomponent </strong>like this.</p><h4><strong>Potential Controversy</strong></h4><p>Is this a novel pattern or just so rare that I haven't encountered it before? Hard to say. Typically, <strong>base component variants</strong> are more <strong>generic</strong>&#8212;for example, atomic components like <code>Button</code> use system colors (<code>error</code>, <code>info</code>, <code>success</code>, <code>warning</code>, etc.) to compose specialized variants like <code>InfoButton</code>, <code>SuccessButton</code>, etc.</p><p>For <strong>more complex components</strong>, specialized variants are usually built <strong>outside</strong> the design system, composing agnostic design system components into <strong>business-specific</strong> variants&#8212;think a <code>Card</code> component spawning <code>NewsCard</code>, <code>BlogCard</code>, and <code>OfferCard</code>.</p><p>The biggest <strong>mistake</strong> teams make when building design systems is overfitting components to their specific business problems. And while it&#8217;s okay to tailor implementation details to company needs, a design system&#8217;s core purpose is to solve <strong>common, business-agnostic UI challenges</strong>.</p><p>A <strong>good design system</strong> should be flexible enough that if your org <strong>pivoted to a new industry</strong>, you could rebuild your platform using the <strong>same components</strong>. If your design system is <strong>entangled with business logic</strong>, you&#8217;re doing it wrong.</p><h4><strong>Applying This Pattern</strong></h4><p>This is where this <strong>new pattern</strong> could be controversial. For atomic components, specialization typically aligns with <strong>business-agnostic concerns</strong> like intent and system colors. But are<strong> </strong><code>Table.ActionCell</code><strong> </strong>and<strong> </strong><code>Table.StatusCell</code><strong> </strong>really business-agnostic enough to live in the design system?</p><p>Some might argue this makes the pattern an <strong>anti-pattern</strong>, but I see potential use cases&#8212;particularly in something like a <code>Form</code> component, where <code>Form.Input</code> could act as a base for specialized variants like <code>Form.NumericalInput</code>, <code>Form.ColorInput</code>, <code>Form.PhoneInput</code>, <code>Form.EmailInput</code>, etc.</p><p>Bringing this to the VSDS team would spark quite a debate&#8212;a roundtable discussion, if you will. And honestly? We love a good roundtable!</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!LRLx!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17b509d7-f748-4f7e-92db-a8ed3d1f3352_792x428.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!LRLx!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17b509d7-f748-4f7e-92db-a8ed3d1f3352_792x428.png 424w, https://substackcdn.com/image/fetch/$s_!LRLx!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17b509d7-f748-4f7e-92db-a8ed3d1f3352_792x428.png 848w, https://substackcdn.com/image/fetch/$s_!LRLx!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17b509d7-f748-4f7e-92db-a8ed3d1f3352_792x428.png 1272w, https://substackcdn.com/image/fetch/$s_!LRLx!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17b509d7-f748-4f7e-92db-a8ed3d1f3352_792x428.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!LRLx!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17b509d7-f748-4f7e-92db-a8ed3d1f3352_792x428.png" width="300" height="162.12121212121212" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/17b509d7-f748-4f7e-92db-a8ed3d1f3352_792x428.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:428,&quot;width&quot;:792,&quot;resizeWidth&quot;:300,&quot;bytes&quot;:37166,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:&quot;&quot;,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.robhameetman.com/i/154924704?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17b509d7-f748-4f7e-92db-a8ed3d1f3352_792x428.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!LRLx!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17b509d7-f748-4f7e-92db-a8ed3d1f3352_792x428.png 424w, https://substackcdn.com/image/fetch/$s_!LRLx!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17b509d7-f748-4f7e-92db-a8ed3d1f3352_792x428.png 848w, https://substackcdn.com/image/fetch/$s_!LRLx!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17b509d7-f748-4f7e-92db-a8ed3d1f3352_792x428.png 1272w, https://substackcdn.com/image/fetch/$s_!LRLx!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17b509d7-f748-4f7e-92db-a8ed3d1f3352_792x428.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><div><hr></div><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://blog.robhameetman.com/p/the-newest-version-of-claude-created-a-ui-pattern-ive-never-seen-before?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://blog.robhameetman.com/p/the-newest-version-of-claude-created-a-ui-pattern-ive-never-seen-before?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://blog.robhameetman.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">If you enjoyed this post, please subscribe, hit the &#10084;&#65039; button, and share/restack &#128257; it with others who might find it helpful!</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><div><hr></div><p></p>]]></content:encoded></item><item><title><![CDATA[The AI Playbook for Design Systems: What Works, What Fails, and Why]]></title><description><![CDATA[How do ChatGPT o3, Claude 3.5 Sonnet, and DeepSeek R1 compare when planning enterprise-strength design system components? The results shocked me!]]></description><link>https://blog.robhameetman.com/p/ai-driven-code-mockups</link><guid isPermaLink="false">https://blog.robhameetman.com/p/ai-driven-code-mockups</guid><dc:creator><![CDATA[Rob Hameetman]]></dc:creator><pubDate>Tue, 04 Feb 2025 10:46:24 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/6638f075-6915-406a-85a6-c13fc5ad3bfe_2464x1856.webp" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><em>Hi, I&#8217;m Rob. This is a free issue of UI Engineering Excellence. I write for Frontend Engineers and Product Developers on how to be the best at building apps that win in the market. Subscribe if this is useful. Paid readers get early looks and occasional behind&#8209;the&#8209;scenes notes:</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://blog.robhameetman.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://blog.robhameetman.com/subscribe?"><span>Subscribe now</span></a></p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!esCa!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff8752c7a-c861-4b22-86e5-c5b6bb12677a_2464x1856.webp" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!esCa!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff8752c7a-c861-4b22-86e5-c5b6bb12677a_2464x1856.webp 424w, https://substackcdn.com/image/fetch/$s_!esCa!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff8752c7a-c861-4b22-86e5-c5b6bb12677a_2464x1856.webp 848w, https://substackcdn.com/image/fetch/$s_!esCa!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff8752c7a-c861-4b22-86e5-c5b6bb12677a_2464x1856.webp 1272w, https://substackcdn.com/image/fetch/$s_!esCa!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff8752c7a-c861-4b22-86e5-c5b6bb12677a_2464x1856.webp 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!esCa!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff8752c7a-c861-4b22-86e5-c5b6bb12677a_2464x1856.webp" width="1456" height="1097" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/f8752c7a-c861-4b22-86e5-c5b6bb12677a_2464x1856.webp&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1097,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:817200,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/webp&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://blog.robhameetman.com/i/154956189?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff8752c7a-c861-4b22-86e5-c5b6bb12677a_2464x1856.webp&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!esCa!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff8752c7a-c861-4b22-86e5-c5b6bb12677a_2464x1856.webp 424w, https://substackcdn.com/image/fetch/$s_!esCa!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff8752c7a-c861-4b22-86e5-c5b6bb12677a_2464x1856.webp 848w, https://substackcdn.com/image/fetch/$s_!esCa!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff8752c7a-c861-4b22-86e5-c5b6bb12677a_2464x1856.webp 1272w, https://substackcdn.com/image/fetch/$s_!esCa!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff8752c7a-c861-4b22-86e5-c5b6bb12677a_2464x1856.webp 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><h2>A Refresher On Code Mockups</h2><p>Last week, I introduced <strong><a href="https://blog.robhameetman.com/p/how-to-write-a-code-mockup?r=2ypy2w">code mockups</a></strong>&#8212;a structured approach to designing UI components before they&#8217;re built. This method improves <strong>scalability and maintainability</strong>, but it&#8217;s time-consuming, requiring deep exploration, iteration, and validation.</p><p>AI has the potential to change that. By <strong>automating pattern exploration, generating usage examples, and enforcing best practices</strong>, Engineers can iterate on <strong>AI-assisted scaffolding</strong>&#8212;focusing on <strong>high-impact decisions instead of repetitive setup</strong>.</p><p>In this article, I&#8217;ll explore how AI enhanced the <strong><a href="https://blog.robhameetman.com/p/how-to-write-a-code-mockup?r=2ypy2w">code mockup workflow</a></strong>, making it faster, more efficient, and accessible. Plus, I&#8217;ll share how we&#8217;re applying it at <strong>Vivid Seats</strong> to streamline design system development.</p><p>Let&#8217;s dive in.</p><div><hr></div><h2>What Are We Working With?</h2><div><hr></div><h3>1. The Workflow</h3><p>Copy everything from <em><a href="https://blog.robhameetman.com/i/154924704/code-mockups-for-enterprise-strength-design-system-components">Code Mockups For Enterprise-Strength Design System Components</a></em> to the end and paste it in <strong>The Prompt</strong>, replacing <code>{{WORKFLOW}}</code>. Remember to strip out any promotional sections.</p><div class="digest-post-embed" data-attrs="{&quot;nodeId&quot;:&quot;dc35e2c5-51d0-426a-b6df-cd4f5cf1fcfd&quot;,&quot;caption&quot;:&quot;Hi, I&#8217;m Rob. This is a free issue of UI Engineering Excellence. I write for Frontend Engineers and Product Developers on how to be the best at building apps that win in the market. Subscribe if this is useful. Paid readers get early looks and occasional behind&#8209;the&#8209;scenes notes:&quot;,&quot;cta&quot;:&quot;Read full story&quot;,&quot;showBylines&quot;:true,&quot;size&quot;:&quot;sm&quot;,&quot;isEditorNode&quot;:true,&quot;title&quot;:&quot;How To Write A Code Mockup&quot;,&quot;publishedBylines&quot;:[{&quot;id&quot;:179249864,&quot;name&quot;:&quot;Rob Hameetman&quot;,&quot;bio&quot;:&quot;I build Design Systems and Micro-frontends in TypeScript and React with a focus on developer experience / Staff Frontend Engineer / TED curator / Ex-Apple (HIG) / 1.2M+ subs&quot;,&quot;photo_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/fd162dbf-8c1b-48bc-b6e7-0969af7da7ca_475x475.jpeg&quot;,&quot;is_guest&quot;:false,&quot;bestseller_tier&quot;:null}],&quot;post_date&quot;:&quot;2025-01-23T11:33:32.814Z&quot;,&quot;cover_image&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/e525a0d0-6699-4e01-9dad-7c3a58d94570_2048x2048.webp&quot;,&quot;cover_image_alt&quot;:null,&quot;canonical_url&quot;:&quot;https://blog.robhameetman.com/p/how-to-write-a-code-mockup&quot;,&quot;section_name&quot;:&quot;Resources&quot;,&quot;video_upload_id&quot;:null,&quot;id&quot;:154924704,&quot;type&quot;:&quot;newsletter&quot;,&quot;reaction_count&quot;:1,&quot;comment_count&quot;:0,&quot;publication_id&quot;:null,&quot;publication_name&quot;:&quot;UI Engineering Excellence&quot;,&quot;publication_logo_url&quot;:&quot;https://substackcdn.com/image/fetch/$s_!deTI!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdc5e8141-3a0f-4181-8804-acdbb61e8707_359x359.png&quot;,&quot;belowTheFold&quot;:true,&quot;youtube_url&quot;:null,&quot;show_links&quot;:null,&quot;feed_url&quot;:null}"></div><div><hr></div><h3>2. The Template</h3><p>Copy everything in the code block below and paste it in <strong>The Prompt</strong>, replacing <code>{{TEMPLATE}}</code>:</p><pre><code><code># Code Mockup: &lt;Component /&gt; [Template]

**Category:**

**Pattern:**

Choose One:

- Standalone Component
- Compound Component
- Base Component
- Compound-as-Base-Hybrid

**Key Stakeholders:**

- Recommend: _Your Name_
- Sponsor: _Design System Maintainer Name_
- Implement: _The Engineer doing the work if known_

&gt; **High-level Details**
&gt; _The code below is meant to give an idea of what the implementation in
&gt; Next might look like from a birds-eye view. It is not meant to (and
&gt; will not) be 100% correct; actual implementation details may vary._

## Pattern Notes

&gt; **DELETE BEFORE REVIEW**
&gt; _Add any details to this section that explain alterations of the
&gt; pattern or ways we might expect the pattern to evolve or change as
&gt; this component scales in complexity. Remove the entire section if you
&gt; have no notes prior to review._

## Variants

&gt; **DELETE BEFORE REVIEW**
&gt; _Delete this entire section if this is not a **Compound Component** or
&gt; **Compound-as-Base-Hybrid**. Otherwise, rename the below keeping the
&gt; naming convention for **Base Components** using the name of the base
&gt; as the suffix in variant names (e.g. variants of a base component
&gt; `Button` should be named `ThisButton`, `ThatButton`, etc.)_

Component will be used as a base in the following shared components:

- `VariantComponent`
- `VariantComponent`
- `VariantComponent`
- `VariantComponent`

## Composition Strategy

&gt; **DELETE BEFORE REVIEW**
&gt; _Add mocked up component usage code snippets in this section._

### Approach #1:

### Approach #2:

## Props

### Component

&gt; **DELETE BEFORE REVIEW**
&gt; _Add to the following set of minimum required props. Check our prop
&gt; standards to ensure consistency in our component contracts.
&gt; Review guidelines to ensure props avoid becoming interdependent.
&gt; Leave comments or footnotes exploring alternative approaches for
&gt; specific prop(s) as needed._

| PROP      | TYPE                                        | USAGE    |
| --------- | ------------------------------------------- | -------- |
| as        | `keyof JSX.IntrinsicElements | ElementType` | OPTIONAL |
| className | `string`                                    | OPTIONAL |
| error     | `Error  | null`                             | OPTIONAL |
| loading   | `boolean`                                   | OPTIONAL |
| testId    | `string`                                    | OPTIONAL |

### Component.SubComponent

&gt; **DELETE BEFORE REVIEW**
&gt; _Add to the following set of minimum required props. Check our prop
&gt; standards to ensure consistency in our component contracts.
&gt; Review guidelines to ensure props avoid becoming interdependent.
&gt; Leave comments or footnotes exploring alternative approaches for
&gt; specific prop(s) as needed._

| PROP      | TYPE                                        | USAGE    |
| --------- | ------------------------------------------- | -------- |
| as        | `keyof JSX.IntrinsicElements | ElementType` | OPTIONAL |
| className | `string`                                    | OPTIONAL |
| error     | `Error  | null`                             | OPTIONAL |
| loading   | `boolean`                                   | OPTIONAL |
| testId    | `string`                                    | OPTIONAL |

&gt; **DELETE BEFORE REVIEW**
&gt; _Add one of these sections for each subcomponent if the component is a
&gt; **Compound Component** or **Compound-As-Base-Hybrid**. Remove this
&gt; entire section if the component is a **Standard Component** or **Base
&gt; Component**._

&gt; **DELETE BEFORE REVIEW**
&gt; _The following section(s) are optional but recommended so that we
&gt; don&#8217;t keep reinventing wheels._

## Utils

### Hooks

### Functions

### Types &amp; Interfaces

### Enums &amp; Constants</code></code></pre><div><hr></div><h3>3. The Prompt</h3><ul><li><p><code>[text surrounded by brackets]</code> is optional.</p></li><li><p><code>{{TEXT}}</code> using handlebars syntax indicates where specific content should be injected.</p></li><li><p><code>(pick one: foo|bar|baz)</code> indicates where you should pick one of the provided options.</p></li></ul><pre><code><code>Write a Code Mockup for a new &lt;Component /&gt; component[ implemented as a (pick: standard|compound|base) component].

Here's the workflow for writing a Code Mockup:

"{{WORKFLOW}}"

Here is the list of all Standardized Props for context:

| PROP            | TYPE                                         | USAGE    |
| --------------- | -------------------------------------------- | -------- |
| as              | `keyof JSX.IntrinsicElements \| ElementType` | OPTIONAL |
| animated        | `boolean`                                    | OPTIONAL |
| className       | `string`                                     | OPTIONAL |
| children        | ReactNode                                    | OPTIONAL |
| disabled        | `boolean`                                    | OPTIONAL |
| error           | `Error  \| null`                             | OPTIONAL |
| fullWidth       | `boolean`                                    | OPTIONAL |
| loading         | `boolean`                                    | OPTIONAL |
| testId          | `string`                                     | REQUIRED |
| onPress()       | `PressEventHandler`                          | OPTIONAL |
| onPressEnter()  | `EnterEventHandler`                          | OPTIONAL |
| onPressEscape() | `EscapeEventHandler`                         | OPTIONAL |
| onPressSpace()  | `SpaceEventHandler`                          | OPTIONAL |
| onPressTab()    | `TabEventHandler`                            | OPTIONAL |
| onTabBack()     | `TabBackEventHandler`                        | OPTIONAL |


Use this template for the Code Mockup:

```Markdown
{{TEMPLATE}}
```

[Optionally, add a short description of the differing approaches you're looking into in your mockups. Design Responsibility? Splitting up components? Any other details that are relevant?]

The response may be output as regular text; markdown from the template may be applied instead of preserved. Do not complete the Key Stakeholders section, as it will be filled out later. Remember that code mockups for design system components are about abstracting the underlying mechanics, so do not generate any code which includes implementation details of this component or its potential ancillary dependencies. Utility functions, hooks, enums, constants, etc should be described in juxtaposition to each other with regard to potential approaches. Prop and ancillary types and interfaces are an exception to this rule, since they are separate from implementation. Remember when naming types and interfaces that they should not know they are types and interfaces respectively, so do not prefix names with `T` or `I`, nor include any other such redundancy like ending the name with `Type`, or `Data` for types/interfaces that represent data. Generics and type parameters should use capitalized single letter names from the letter `T`, incrementing one letter of the alphabet for each additional generic or type parameter. Arrays should use generic syntax (i.e. `Array&lt;T&gt;` instead of `T[]`.) Do not use object literal types unless writing a mapped type, since index mapping and key remapping are not allowed in interfaces. Properties in interfaces should be `readonly` except in cases where they are intentionally mutable; likewise, arrays should be typed as `ReadonlyArray`s unless they are intentionally mutated in place. Destructure type and value imports from React rather than using the `React` namespace with a default import named React. Do not use "style" props like `marginTop` or `border` unless they are already included on the list of Standardized Props. Keep usage snippets as focused as possible, and do not include surrounding boilerplate unless absolutely necessary.</code></code></pre><div><hr></div><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://blog.robhameetman.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption"><em>&#10084;&#65039; Like what you&#8217;re seeing so far?</em></p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><div><hr></div><h2>The Results</h2><p>I trialed and refined this process with multiple models to see which provides the best jumping-off point, and the results were <strong>not</strong> what I was expecting.</p><p>I wanted to see how AI would handle heterogenous levels of complexity, so I experimented with the following components:</p><ul><li><p><code>&lt;Kbd /&gt;</code><br>An atomic component so simple one might wonder why it exists at all when one could just use the <code>&lt;kbd&gt;</code> HTML element directly.</p></li><li><p><code>&lt;Breadcrumbs /&gt;</code><br>A molecule component just complex enough that it can be implemented with any of the three main patterns described in <strong>The Workflow</strong>.</p></li><li><p><code>&lt;Table /&gt;</code><br>An organism component too complex to be anything other than a compound component.</p></li></ul><p>The only prompt which specified the pattern was the prompt for the Table component. Other than this, I was hands off and did not add any context or details about how the component could or should be built.</p><div><hr></div><h3>ChatGPT o3</h3><div><hr></div><p><code>&lt;Kbd /&gt;</code>  -  &#9888;&#65039; <strong>Questionable<br></strong><em>ChatGPT o3</em></p><ul><li><p><strong>Pattern:</strong> Standalone component</p></li><li><p><strong>Approach #1:</strong> <strong>Basic Usage</strong></p></li></ul><pre><code>&lt;Kbd testId="kbd-basic"&gt;Enter&lt;/Kbd&gt;</code></pre><ul><li><p><strong>Approach #2: Composite Key Sequence</strong></p></li></ul><pre><code>&lt;Kbd className="custom-kbd" testId="kbd-sequence"&gt;
  &lt;span&gt;Ctrl&lt;/span&gt; + &lt;span&gt;Shift&lt;/span&gt; + &lt;span&gt;Esc&lt;/span&gt;
&lt;/Kbd&gt;</code></pre><ul><li><p><strong>No discrete props</strong></p></li><li><p><strong>No ancillary resources</strong></p></li></ul><h4>Review</h4><p><strong>Approach #1</strong> closely follows the behavior of the <code>&lt;kbd&gt;</code> HTML element, making it a familiar and intuitive choice.</p><p><strong>Approach #2</strong> is interesting because it supports multiple keys, though the usage snippet demonstrates bad technique by wrapping keys in spans. </p><p>It also looks like the AI misunderstood the <strong>testId</strong> prop being marked as <strong>REQUIRED</strong> in the Standardized Props table. This designation simply means the component must <strong>support</strong> <code>testId</code>, not that every instance <strong>must</strong> include it. In general, props&#8212;especially standardized ones&#8212;should rarely be <strong>mandatory</strong> unless there's a compelling reason to enforce their usage.</p><div><hr></div><p><code>&lt;Breadcrumbs /&gt;</code>  -  &#10060; <strong>Not Passable<br></strong><em>ChatGPT o3</em></p><ul><li><p><strong>Pattern:</strong> Compound component</p></li><li><p><strong>Subcomponents:</strong> <code>Breadcrumbs.Item</code></p></li><li><p><strong>Approach #1: </strong><em>(the AI did not name either approach)</em></p></li></ul><pre><code>&lt;Breadcrumbs testId="breadcrumbs"&gt;
  &lt;Breadcrumbs.Item as="a" href="/" testId="breadcrumb-home"&gt;
    Home
  &lt;/Breadcrumbs.Item&gt;
  &lt;Breadcrumbs.Item as="a" href="/products" testId="breadcrumb-products"&gt;
    Products
  &lt;/Breadcrumbs.Item&gt;
  &lt;Breadcrumbs.Item testId="breadcrumb-current"&gt;
    Current Page
  &lt;/Breadcrumbs.Item&gt;
&lt;/Breadcrumbs&gt;</code></pre><ul><li><p><strong>Approach #2:</strong></p></li></ul><pre><code>const breadcrumbItems = [
  { label: 'Home', href: '/', testId: 'breadcrumb-home' },
  { label: 'Products', href: '/products', testId: 'breadcrumb-products' },
  { label: 'Current Page', testId: 'breadcrumb-current' },
];

&lt;Breadcrumbs testId="breadcrumbs" className="custom-breadcrumbs"&gt;
  {breadcrumbItems.map((item, index) =&gt; (
    &lt;Breadcrumbs.Item 
      key={index}
      as={item.href ? 'a' : 'span'}
      href={item.href}
      testId={item.testId}
      disabled={item.disabled}
    &gt;
      {item.label}
    &lt;/Breadcrumbs.Item&gt;
  ))}
&lt;/Breadcrumbs&gt;</code></pre><ul><li><p><strong>No discrete props</strong></p></li><li><p><strong>Ancillary Resources:</strong></p><ul><li><p><strong>Hooks:</strong> <code>useBreadcrumbsContext()</code> and an optional <code>useResponsiveBreadcrumbs()</code> hook to handle dynamic layout adjustments</p></li><li><p><strong>Functions:</strong> <code>formatBreadcrumbs()</code></p></li><li><p><strong>Types:</strong> <code>BreadcrumbsProps</code>, <code>BreadcrumbItemProps</code></p></li><li><p><strong>Constants: </strong><code>BREADCRUMBS_SEPARATOR</code></p></li></ul></li></ul><h4>Review</h4><p>This fails because it&#8217;s essentially the <strong>same approach</strong> served two different ways. </p><p>The <strong>subcomponent naming</strong> is lacking in refinement&#8212;<code>Breadcrumbs.Item</code> feels okay but a bit generic and uninspired. A more <strong>semantic</strong> choice like <code>Breadcrumbs.Crumb</code> or a more <strong>streamlined</strong> option like <code>Breadcrumbs.Link</code> would improve clarity and usability.</p><p>Then there&#8217;s <code>formatBreadcrumbs()</code>&#8212;which, as far as I can tell, isn&#8217;t even being used. The output describes it as a function that converts data into an array of <code>Breadcrumbs.Item</code> subcomponents, but the usage snippets either handle this conversion manually or skip it altogether by passing subcomponents as children. Even if it <strong>were</strong> used, it should probably be a <strong>custom hook</strong> since it&#8217;s returning <strong>presentation logic</strong>, not just transformed data.</p><div><hr></div><p><code>&lt;Table /&gt;</code>  -  &#10060; <strong>Not Passable<br></strong><em>ChatGPT o3</em></p><ul><li><p><strong>Pattern:</strong> Compound component (the output implies more of a <em>Compound-as-Base Hybrid</em> by including specialized variants)</p></li><li><p><strong>Variants:</strong> <code>DataTable</code>, <code>SortableTable</code>, <code>PaginatedTable</code>, <code>ResponsiveTable</code></p></li><li><p><strong>Subcomponents:</strong> <code>Table.Header</code>, <code>Table.Row</code>, <code>Table.Cell</code>, <code>Table.Body</code>, <code>Table.Footer</code>, <code>Table.Caption</code></p></li><li><p><strong>Approach #1: Basic Table Structure</strong></p></li></ul><pre><code>&lt;Table testId="basic-table" className="custom-table"&gt;
  &lt;Table.Header&gt;
    &lt;Table.Row&gt;
      &lt;Table.Cell as="th"&gt;Name&lt;/Table.Cell&gt;
      &lt;Table.Cell as="th"&gt;Age&lt;/Table.Cell&gt;
      &lt;Table.Cell as="th"&gt;Location&lt;/Table.Cell&gt;
    &lt;/Table.Row&gt;
  &lt;/Table.Header&gt;
  &lt;Table.Body&gt;
    &lt;Table.Row&gt;
      &lt;Table.Cell&gt;Jane Doe&lt;/Table.Cell&gt;
      &lt;Table.Cell&gt;29&lt;/Table.Cell&gt;
      &lt;Table.Cell&gt;New York&lt;/Table.Cell&gt;
    &lt;/Table.Row&gt;
    &lt;Table.Row&gt;
      &lt;Table.Cell&gt;John Smith&lt;/Table.Cell&gt;
      &lt;Table.Cell&gt;34&lt;/Table.Cell&gt;
      &lt;Table.Cell&gt;San Francisco&lt;/Table.Cell&gt;
    &lt;/Table.Row&gt;
  &lt;/Table.Body&gt;
&lt;/Table&gt;</code></pre><ul><li><p><strong>Approach #2:</strong> <strong>Table with Footer and Optional Caption</strong></p><p>I decided to omit the code snippet for this to save space since its the same as the above but with:</p></li></ul><pre><code>&lt;Table.Caption&gt;Employee Directory&lt;/Table.Caption&gt;</code></pre><ul><li><p><strong>No discrete props</strong></p></li><li><p><strong>Ancillary Resources:</strong></p><ul><li><p><strong>Hooks:</strong> <code>useTableSort()</code> and an optional <code>useTablePagination()</code> hook</p></li><li><p><strong>Functions:</strong> <code>calculateColumnWidths()</code>, <code>mergeCellStyles()</code></p></li><li><p><strong>Types:</strong> Prop types for each subcomponent</p></li><li><p><strong>Enums:</strong> <code>TableSortDirection</code> (e.g. <code>ASC</code> and <code>DESC</code>)</p></li><li><p><strong>Constants: </strong><code>DEFAULT_CELL_PADDING</code></p></li></ul></li></ul><h4>Review</h4><p>This fails pretty much right off the bat because the usage snippets show <code>Table.Header</code> and <code>Table.Footer</code> in both approaches but the title of <strong>Approach #2</strong> implies that basic table structure should not include a header and footer.</p><p>Also, only standardized props? No discrete props? Not even a <code>sortOrder</code> prop that uses a <code>TableSortDirection</code>?</p><div><hr></div><h3>Claude 3.5 Sonnet</h3><div><hr></div><p><code>&lt;Kbd /&gt;</code>  -  &#9989; <strong>Passable Rough Draft<br></strong><em>Claude 3.5 Sonnet</em></p><ul><li><p><strong>Pattern: </strong>Standalone or Compound Component</p></li><li><p><strong>Approach #1: Single Component with Key Combinations</strong></p></li></ul><pre><code>// Individual key
&lt;Kbd&gt;&#8984;&lt;/Kbd&gt;

// Key combination
&lt;Kbd&gt;&#8984; + K&lt;/Kbd&gt;

// Sequential combination
&lt;Kbd&gt;g g&lt;/Kbd&gt;

// With custom separator
&lt;Kbd separator="+"&gt;&#8984; K&lt;/Kbd&gt;

// Nested in text
Press &lt;Kbd&gt;&#8984;&lt;/Kbd&gt; + &lt;Kbd&gt;K&lt;/Kbd&gt; to open the command palette</code></pre><ul><li><p><strong>Approach #2: Compound Component with Specialized Parts</strong></p><ul><li><p><strong>Subcomponents:</strong> <code>Kbd.Key</code>, <code>Kbd.Group</code>, <code>Kbd.Separator</code></p></li></ul></li></ul><pre><code>// Individual key
&lt;Kbd.Key&gt;&#8984;&lt;/Kbd.Key&gt;

// Key combination
&lt;Kbd.Group&gt;
  &lt;Kbd.Key&gt;&#8984;&lt;/Kbd.Key&gt;
  &lt;Kbd.Separator&gt;+&lt;/Kbd.Separator&gt;
  &lt;Kbd.Key&gt;K&lt;/Kbd.Key&gt;
&lt;/Kbd.Group&gt;

// Sequential combination
&lt;Kbd.Group sequential&gt;
  &lt;Kbd.Key&gt;g&lt;/Kbd.Key&gt;
  &lt;Kbd.Key&gt;g&lt;/Kbd.Key&gt;
&lt;/Kbd.Group&gt;</code></pre><ul><li><p><strong>Discrete Props</strong>:</p><ul><li><p><strong>Kbd</strong>: <code>separator</code>, <code>size</code>, <code>variant</code></p></li><li><p><strong>Kbd.Group</strong>: <code>sequential</code></p></li></ul></li><li><p><strong>Ancillary Resources:</strong></p><ul><li><p><strong>Types: </strong>Prop types for the component in <strong>Approach #1</strong> and for each subcomponent in <strong>Approach #2</strong> except for <code>Kbd.Separator</code></p></li><li><p><strong>Enums:</strong> <code>KbdSize</code>, <code>KbdVariant</code></p></li><li><p><strong>Constants:</strong> <code>DEFAULT_KBD_SEPARATOR</code></p></li></ul></li></ul><h4>Review</h4><p>The difference in quality between this and ChatGPT o3 is Grand Canyon huge. This is mind-blowingly better. Multiple patterns, discrete props, utils, the works! On a component this simple, output this good can be used with only minor refinement.</p><p>If an Engineer at Vivid Seats brought this forward for review with the VSDS team, my main feedback would be that <code>Kbd.Key</code> should just be the parent <code>Kbd</code> so we <strong>don&#8217;t bloat complexity</strong> with redundant subcomponents. While compound components typically take multiple subcomponents as children, in some cases they can use an <strong>inverted form</strong> which allows for a subcomponent (typically <code>Group</code>) to take the parent as children instead.</p><p>I would also dig in a bit to understand why including variants is necessary to meet requirements for this component. It&#8217;s not out of the realm of possibility, but without a mockup backing it up it <strong>feels over-Engineered</strong>. If we actually have a business case for <code>KbdVariants</code>, then naturally a question of whether we should consider a <strong>Base Component pattern</strong> for these variants would follow.</p><p>Also, the Kbd.<code>Separator</code> subcomponent is unnecessary. Given the way keyboard commands <strong>chain together</strong>, we have no reason not to assume that &#8220;+&#8221; should be the operator until or unless business requirements make it clear otherwise. That said, if we kept this subcomponent, it should use a <strong>string-only semantic </strong><code>as</code><strong> prop</strong> instead of accepting a text child each time so that we can rely on <code>DEFAULT_KBD_SEPARATOR</code> unless we need to override it.</p><pre><code>&lt;Kbd.Separator as="+" /&gt;</code></pre><p>Lastly, <code>size</code> should be <code>fontSize</code>, if we include a specialized prop for this at all. As an inline element, <strong>it&#8217;s size should scale conformally</strong> with the size of the text it contains, so there&#8217;s no need for an enum like <code>KbdSize</code>.</p><p>I&#8217;d probably still lean towards <strong>Approach #1</strong>, but this at least gave us an idea of what another possibility might look like, even if just to confirm it&#8217;s too much. All in all, a very impressive jumping-off point.</p><div><hr></div><p><code>&lt;Breadcrumbs /&gt;</code>  -  &#9989; <strong>Passable Rough Draft<br></strong><em>Claude 3.5 Sonnet</em></p><ul><li><p><strong>Pattern: </strong>Standalone or Compound Component</p></li><li><p><strong>Approach #1: Data-Driven Composition</strong></p></li></ul><pre><code>&lt;Breadcrumbs
  items={[
    { label: "Dashboard", href: "/dashboard" },
    { label: "Projects", href: "/dashboard/projects" },
    { label: "Project Details" }
  ]}
/&gt;</code></pre><ul><li><p><strong>Approach #2: Explicit Composition</strong></p><ul><li><p><strong>Subcomponents:</strong> <code>Breadcrumbs.Item</code>, <code>Breadcrumbs.Separator</code></p></li></ul></li></ul><pre><code>&lt;Breadcrumbs&gt;
  &lt;Breadcrumbs.Item&gt;
    &lt;Link href="/dashboard"&gt;Dashboard&lt;/Link&gt;
  &lt;/Breadcrumbs.Item&gt;
  &lt;Breadcrumbs.Separator&gt;/&lt;/Breadcrumbs.Separator&gt;
  &lt;Breadcrumbs.Item&gt;
    &lt;Link href="/dashboard/projects"&gt;Projects&lt;/Link&gt;
  &lt;/Breadcrumbs.Item&gt;
  &lt;Breadcrumbs.Separator&gt;/&lt;/Breadcrumbs.Separator&gt;
  &lt;Breadcrumbs.Item aria-current="page"&gt;
    Project Details
  &lt;/Breadcrumbs.Item&gt;
&lt;/Breadcrumbs&gt;</code></pre><ul><li><p><strong>Discrete Props</strong>:</p><ul><li><p><strong>Breadcrumbs</strong>: <code>separator</code></p></li><li><p><strong>Breadcrumbs.Item</strong>: <code>current</code></p></li></ul></li><li><p><strong>Ancillary Resources:</strong></p><ul><li><p><strong>Hooks:</strong> <code>useBreadcrumbs()</code> vs <code>useRouteAsBreadcrumbs(</code>)</p></li><li><p><strong>Functions:</strong> <code>createBreadcrumbsFromPath()</code> vs <code>createBreadcrumbsFromRoutes()</code></p></li><li><p><strong>Types:</strong> <code>BreadcrumbItem</code>, <code>BreadcrumbContext</code></p></li></ul></li></ul><h4>Review</h4><p>Some criticism from the <code>Kbd</code> component carry over, like <code>Breadcrumbs.Separator</code> using children instead of a prop as needed. But the output is, again, miles better than ChatGPT o3.</p><p>The best thing about this output is that it includes <code>Link</code>, showing how we can use other components compositionally. It also clearly juxtaposes two approaches for hooks and reflects the potential downstream impact of these approaches in subsequent utility functions.</p><p>Claude 3.5 Sonnet also used the <em>Pattern Notes</em> section to outline four ways we might want to change or improve the component in the future.</p><p>I would lean towards <strong>Approach #2</strong> and give it a semantic <code>as</code> prop so that we can streamline the usage like this:</p><pre><code>&lt;Breadcrumbs&gt;
  &lt;Breadcrumbs.Item as={Link} href="/dashboard"&gt;
    Dashboard
  &lt;/Breadcrumbs.Item&gt;
  &lt;Breadcrumbs.Separator /&gt;
  &lt;Breadcrumbs.Item as={Link} href="/dashboard/projects"&gt;
    Projects
  &lt;/Breadcrumbs.Item&gt;
  &lt;Breadcrumbs.Separator /&gt;
  &lt;Breadcrumbs.Item aria-current="page"&gt;
    Project Details
  &lt;/Breadcrumbs.Item&gt;
&lt;/Breadcrumbs&gt;</code></pre><div><hr></div><p><code>&lt;Table /&gt;</code>  -  &#9888;&#65039; <strong>Questionable<br></strong><em>Claude 3.5 Sonnet</em></p><ul><li><p><strong>Pattern:</strong> Compound Component</p></li><li><p><strong>Subcomponents:</strong> Table.Header, Table.Body, Table.Row, Table.Body, Table.Pagination</p></li><li><p><strong>Approach #1: Explicit Structure</strong></p></li></ul><pre><code>&lt;Table&gt;
  &lt;Table.Header&gt;
    &lt;Table.Row&gt;
      &lt;Table.HeaderCell sortable&gt;Name&lt;/Table.HeaderCell&gt;
      &lt;Table.HeaderCell&gt;Email&lt;/Table.HeaderCell&gt;
      &lt;Table.HeaderCell align="right"&gt;Status&lt;/Table.HeaderCell&gt;
    &lt;/Table.Row&gt;
  &lt;/Table.Header&gt;
  &lt;Table.Body&gt;
    &lt;Table.Row&gt;
      &lt;Table.Cell&gt;Jane Cooper&lt;/Table.Cell&gt;
      &lt;Table.Cell&gt;jane@example.com&lt;/Table.Cell&gt;
      &lt;Table.Cell align="right"&gt;Active&lt;/Table.Cell&gt;
    &lt;/Table.Row&gt;
  &lt;/Table.Body&gt;
  &lt;Table.Footer&gt;
    &lt;Table.Pagination /&gt;
  &lt;/Table.Footer&gt;
&lt;/Table&gt;</code></pre><ul><li><p><strong>Approach #2: Data-Driven</strong></p></li></ul><pre><code>&lt;Table 
  data={users}
  columns={[
    { key: 'name', header: 'Name', sortable: true },
    { key: 'email', header: 'Email' },
    { key: 'status', header: 'Status', align: 'right' }
  ]}
&gt;
  &lt;Table.Header /&gt;
  &lt;Table.Body&gt;
    {(row) =&gt; (
      &lt;Table.Row key={row.id}&gt;
        &lt;Table.Cell&gt;{row.name}&lt;/Table.Cell&gt;
        &lt;Table.Cell&gt;{row.email}&lt;/Table.Cell&gt;
        &lt;Table.Cell align="right"&gt;{row.status}&lt;/Table.Cell&gt;
      &lt;/Table.Row&gt;
    )}
  &lt;/Table.Body&gt;
  &lt;Table.Pagination /&gt;
&lt;/Table&gt;</code></pre><ul><li><p><strong>Discrete Props</strong>:</p><ul><li><p><strong>Table</strong>: <code>data</code>, <code>columns</code>, <code>sortable</code></p></li><li><p><strong>Table.Header</strong>: <code>sticky</code></p></li><li><p><strong>Table.HeaderCell</strong>: <code>align</code>, <code>sortable</code>, <code>sortDirection</code>, <code>onSort</code></p></li><li><p><strong>Table.Row</strong>: <code>selected</code></p></li><li><p><strong>Table.Pagination</strong>: <code>page</code>, <code>pageSize</code>, <code>onPageChange()</code></p></li></ul></li><li><p><strong>Ancillary Resources:</strong></p><ul><li><p><strong>Events:</strong> <code>SortEvent</code>, <code>SortEventHandler</code>, <code>PageChangeEvent</code>, <code>PageChangeEventHandler</code></p></li><li><p><strong>Hooks:</strong> useTableSort(), useTablePagination(), useTableSelection(), useTableFilters()</p></li><li><p><strong>Types:</strong> <code>Column</code>, <code>TableData</code>, <code>SortState</code>, <code>Alignment</code>, <code>SortDirection</code>, <code>RenderFunction&lt;T&gt;</code></p></li></ul></li></ul><h4>Review</h4><p>The output for this one reaches the limits I think for what AI will be able to do here on its own, at least for now.</p><p>These two approaches aren&#8217;t really mutually exclusive, you&#8217;ll probably end up doing both depending on how the component is used throughout the app. Better approaches would be to compare<strong> heterogeneous levels of design responsibility</strong>, or alternatively juxtaposing <strong>a basic compound component</strong> with no pagination, sorting, filtering, etc <strong>against a more complex version</strong> with this more advanced functionality to get a sense of how the component might scale or be built iteratively.</p><p>And this is why Tables are <em>hard</em>. At its core, the <code>Table</code> component operates as an <strong>ordered</strong> <strong>functional pipeline</strong>, where raw data flows through a series of <strong>pure transformations</strong> in a specific order before rendering. Each transformation is a function that takes the current dataset and returns a new, modified version:</p><pre><code>paginate(sort(filter(search(data))))</code></pre><p>We see a hook for filtering, but only sorting seems to be really thought out.</p><p>The best part of this output is that there are <strong>custom events</strong>! Custom events are also hard because they require special handling, don&#8217;t propagate predictably, and break framework optimizations. Instead of subclassing <code>Event</code> or using <code>CustomEvent</code>, extend native event types by <strong>defining subtypes in TypeScript</strong> for safer, more predictable behavior. Since we know that <code>SortEvent</code> and <code>PageChangeEvent</code> would be dispatched by pressing a button, we should type them like this:</p><pre><code>type SortEvent&lt;T&gt; = PointerEvent&lt;T&gt;
type SortEventHandler&lt;T&gt; = PointerEventHandler&lt;T&gt;

type PageChangeEvent&lt;T&gt; = PointerEvent&lt;T&gt;
type PageChangeEventHandler&lt;T&gt; = PointerEventHandler&lt;T&gt;</code></pre><p>In VSDS, we have a custom <code>PressEvent</code> to make it <strong>easier to share code</strong> between Mobile and Web, so we would create subtypes of that instead. The output, however, included only basic interfaces for these events.</p><pre><code>interface SortEvent {
  readonly column: string
  readonly direction: SortDirection
}

interface PageChangeEvent {
  readonly page: number
  readonly pageSize: number
}</code></pre><p>This might be a quirk we can iron out with more <strong>explicit direction</strong> in the prompt, but for now it&#8212; combined with the rudimentary approaches are enough to put this one in the <strong>Questionable</strong> category, but not at all a bad start!</p><div><hr></div><h3>DeepSeek R1</h3><div><hr></div><p><code>&lt;Kbd /&gt;</code>  -  &#9888;&#65039; <strong>Questionable<br></strong><em>DeepSeek R1</em></p><ul><li><p><strong>Pattern: </strong>Standalone Component</p></li><li><p><strong>Approach #1: Basic Semantic Usage</strong></p></li></ul><pre><code>// Single key
&lt;Kbd testId="enter-key"&gt;Enter&lt;/Kbd&gt;

// Disabled state
&lt;Kbd disabled testId="disabled-key"&gt;&#8984;&lt;/Kbd&gt;

// Custom element with animation
&lt;Kbd as="span" animated testId="animated-key"&gt;Tab&lt;/Kbd&gt;</code></pre><ul><li><p><strong>Approach #2: Keyboard Shortcut Grouping</strong></p></li></ul><pre><code>// Composition with other elements
&lt;div className="shortcut-group"&gt;
  &lt;Kbd testId="mod1"&gt;Ctrl&lt;/Kbd&gt; + 
  &lt;Kbd testId="mod2"&gt;Alt&lt;/Kbd&gt; + 
  &lt;Kbd testId="main-key"&gt;Del&lt;/Kbd&gt;
&lt;/div&gt;</code></pre><ul><li><p><strong>No Discrete Props</strong></p></li><li><p><strong>Ancillary Resources:</strong></p><ul><li><p><strong>Types: </strong><code>StandardKbdProps</code></p></li></ul></li></ul><h4>Review</h4><p>This output feels a lot closer to ChatGPT o3. It doesn&#8217;t actually give us two different approaches, just <strong>two different use-cases</strong>. Most interestingly though is that, according to DeepSeek&#8217;s <strong>exposed inner monologue</strong>, it briefly considered a compound component before deciding not to explore that pattern. This makes me think that with a bit of massaging, the prompt could be Engineered to yield more exploratory results.</p><p>We don&#8217;t really need more than one pattern here, so this output is <strong>Questionable</strong> at best.</p><div><hr></div><p><code>&lt;Breadcrumbs /&gt;</code>  -  &#9989; <strong>Passable Rough Draft<br></strong><em>DeepSeek R1</em></p><ul><li><p><strong>Pattern: </strong>Compound Component</p></li><li><p><strong>Approach #1: Explicit Composition</strong></p><ul><li><p><strong>Subcomponents:</strong> <code>Breadcrumbs.Item</code>, <code>Breadcrumbs.Separator</code></p></li></ul></li></ul><pre><code>&lt;Breadcrumbs testId="nav-trail"&gt;
  &lt;Breadcrumbs.Item href="/"&gt;Home&lt;/Breadcrumbs.Item&gt;
  &lt;Breadcrumbs.Separator /&gt;
  &lt;Breadcrumbs.Item href="/products"&gt;Products&lt;/Breadcrumbs.Item&gt;
  &lt;Breadcrumbs.Separator&gt;
    &lt;IconChevronRight size={12} /&gt;
  &lt;/Breadcrumbs.Separator&gt;
  &lt;Breadcrumbs.Item isCurrent&gt;Winter Collection&lt;/Breadcrumbs.Item&gt;
&lt;/Breadcrumbs&gt;</code></pre><ul><li><p><strong>Approach #2: Automated Separation</strong></p></li></ul><pre><code>&lt;Breadcrumbs 
  testId="auto-trail"
  separator={&lt;IconSlash size={10} /&gt;}
  items={[
    { href: '/', content: 'Home' },
    { href: '/settings', content: 'Settings' },
    { content: 'Profile' }
  ]}
/&gt;</code></pre><ul><li><p><strong>Discrete Props</strong>:</p><ul><li><p><strong>Breadcrumbs</strong>: <code>items</code>, <code>separator</code></p></li><li><p><strong>Breadcrumbs.Item</strong>: <code>isCurrent</code></p></li></ul></li><li><p><strong>Ancillary Resources:</strong></p><ul><li><p><strong>Hooks: </strong><code>useBreadcrumbItems()</code></p></li><li><p><strong>Types: </strong><code>BreadcrumbItem</code>, <code>BreadcrumbSeparatorProps</code></p></li><li><p><strong>Constants</strong>: <code>BREADCRUMB_ARIA_LABEL</code>, <code>CURRENT_PAGE_ARIA_LABEL</code></p></li></ul></li></ul><h4>Review</h4><p>This output is really interesting because it felt <strong>Questionable</strong> at first but, after thinking over it a bit, I&#8217;ve realized that this <strong>Passable</strong> and actually slightly outperformed Claude 3.5 Sonnet.</p><p><strong>Approach #2</strong> is a bit worse than its Claude counterpart. I mean really, an <code>IconSlash</code> component? But this does at least give a sense of how things could be handled compositionally, and its easy enough to revise this part to <code>separator=&#8221;/&#8221;</code>.</p><p><strong>Approach #1 </strong>is a bit better than its Claude counterpart because <code>Breadcrumbs.Separator</code> is used correctly as a self-closing childless element.</p><div><hr></div><p><code>&lt;Table /&gt;</code>  -  &#9989; <strong>Passable Rough Draft<br></strong><em>DeepSeek R1</em></p><ul><li><p><strong>Pattern:</strong> Compound Component</p></li><li><p><strong>Subcomponents:</strong> <code>Table.Header</code>, <code>Table.Head</code>, <code>Table.Body</code>, <code>Table.Row</code>, <code>Table.Cell</code></p></li><li><p><strong>Approach #1: Basic Composition</strong></p></li></ul><pre><code>&lt;Table testId="user-table" fullWidth&gt;
  &lt;Table.Header&gt;
    &lt;Table.Head&gt;Name&lt;/Table.Head&gt;
    &lt;Table.Head align="end"&gt;Age&lt;/Table.Head&gt;
  &lt;/Table.Header&gt;
  
  &lt;Table.Body&gt;
    &lt;Table.Row&gt;
      &lt;Table.Cell&gt;John Doe&lt;/Table.Cell&gt;
      &lt;Table.Cell align="end"&gt;30&lt;/Table.Cell&gt;
    &lt;/Table.Row&gt;
    
    &lt;Table.Row disabled&gt;
      &lt;Table.Cell&gt;Jane Smith&lt;/Table.Cell&gt;
      &lt;Table.Cell align="end" loading&gt;{/* Shows skeleton */}&lt;/Table.Cell&gt;
    &lt;/Table.Row&gt;
  &lt;/Table.Body&gt;
&lt;/Table&gt;</code></pre><ul><li><p><strong>Approach #2: Enhanced Features</strong></p></li></ul><pre><code>&lt;Table testId="sortable-table" error={fetchError}&gt;
  &lt;Table.Header&gt;
    &lt;Table.Head 
      sortable 
      sortDirection="asc"
      onSort={handleSort}
    &gt;
      Name
    &lt;/Table.Head&gt;
    
    &lt;Table.Head 
      align="end"
      sortable
      sortDirection="desc"
      onSort={handleAgeSort}
    &gt;
      Age
    &lt;/Table.Head&gt;
  &lt;/Table.Header&gt;

  {!fetchError &amp;&amp; (
    &lt;Table.Body loading={isLoading}&gt;
      {/* Skeleton rows when loading */}
      {data.map((item) =&gt; (
        &lt;Table.Row key={item.id}&gt;
          &lt;Table.Cell&gt;{item.name}&lt;/Table.Cell&gt;
          &lt;Table.Cell align="end"&gt;{item.age}&lt;/Table.Cell&gt;
        &lt;/Table.Row&gt;
      ))}
    &lt;/Table.Body&gt;
  )}
&lt;/Table&gt;</code></pre><ul><li><p><strong>Discrete Props</strong>:</p><ul><li><p><strong>Table.Head</strong>: <code>align</code>, <code>sortable</code>, <code>sortDirection</code>, <code>onSort</code></p></li><li><p><strong>Table.Cell</strong>: <code>align</code>, <code>colSpan</code></p></li></ul></li><li><p><strong>Ancillary Resources:</strong></p><ul><li><p><strong>Events:</strong> <code>SortEvent</code>, <code>SortEventHandler</code></p></li><li><p><strong>Types: </strong><code>Alignment</code>, <code>SortDirection</code></p></li><li><p><strong>Constants:</strong> ALIGN_CLASSES, SORT_ICON_DIRECTION</p></li></ul></li></ul><h4>Review</h4><p>This output is wild! DeepSeek R1&#8217;s MoE reasoning shines through here. Though <strong>not as sophisticated</strong> as a code mockup for a <code>Table</code> component realistically would be, which may also touch on <strong>heterogenous levels of design responsibility</strong>, this output at least considers how our Table might impact the wider codebase as more is added to it.</p><p>And the code just <strong>feels cleaner</strong> than what we got out of ChatGPT o3 or Claude 3.5 Sonnet. That said, though, this output does have the same issues with custom events as Claude 3.5 Sonnet, so I&#8217;m pretty sure we need to be more explicit about expectations for custom events in the prompt.</p><div><hr></div><h2>Key Takeaways</h2><div><hr></div><p>This experiment showed that <strong>AI can accelerate UI code mockups</strong>, but human oversight is still essential. More importantly, I assumed that AI would get worse as components got more complex, but this <strong>did not</strong> turn out to be the case. In fact:</p><p>&#128313; <strong>DeepSeek R1 is best for more complex components</strong> &#8211; Claude 3.5 Sonnet and ChatGPT o3 both struggled proportionally as components grew in complexity.</p><p>&#128313; <strong>Claude 3.5 Sonnet is best for everything else</strong> &#8211; ChatGPT o3 lagged behind in generating substantive approaches, but Claude handled atomic and molecule-level components with ease.</p><p>AI isn&#8217;t ready to take on everything from planning to execution, but it <strong>can speed up ideation and exploration</strong>. The future of <strong>AI-assisted UI development</strong> isn&#8217;t just about velocity&#8212;it&#8217;s about leveraging AI to achieve new professional levels of craftsmanship without hitting any speed bumps.</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!LRLx!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17b509d7-f748-4f7e-92db-a8ed3d1f3352_792x428.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!LRLx!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17b509d7-f748-4f7e-92db-a8ed3d1f3352_792x428.png 424w, https://substackcdn.com/image/fetch/$s_!LRLx!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17b509d7-f748-4f7e-92db-a8ed3d1f3352_792x428.png 848w, https://substackcdn.com/image/fetch/$s_!LRLx!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17b509d7-f748-4f7e-92db-a8ed3d1f3352_792x428.png 1272w, https://substackcdn.com/image/fetch/$s_!LRLx!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17b509d7-f748-4f7e-92db-a8ed3d1f3352_792x428.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!LRLx!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17b509d7-f748-4f7e-92db-a8ed3d1f3352_792x428.png" width="300" height="162.12121212121212" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/17b509d7-f748-4f7e-92db-a8ed3d1f3352_792x428.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:428,&quot;width&quot;:792,&quot;resizeWidth&quot;:300,&quot;bytes&quot;:37166,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:&quot;&quot;,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://blog.robhameetman.com/i/154924704?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17b509d7-f748-4f7e-92db-a8ed3d1f3352_792x428.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!LRLx!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17b509d7-f748-4f7e-92db-a8ed3d1f3352_792x428.png 424w, https://substackcdn.com/image/fetch/$s_!LRLx!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17b509d7-f748-4f7e-92db-a8ed3d1f3352_792x428.png 848w, https://substackcdn.com/image/fetch/$s_!LRLx!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17b509d7-f748-4f7e-92db-a8ed3d1f3352_792x428.png 1272w, https://substackcdn.com/image/fetch/$s_!LRLx!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17b509d7-f748-4f7e-92db-a8ed3d1f3352_792x428.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><div><hr></div><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://blog.robhameetman.com/p/ai-driven-code-mockups?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://blog.robhameetman.com/p/ai-driven-code-mockups?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://blog.robhameetman.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption"><em>If you enjoyed this post, please subscribe, hit the &#10084;&#65039; button, and share/restack &#128257; it with others who might find it helpful!</em></p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item></channel></rss>