<?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:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Nathan Curtis on Medium]]></title>
        <description><![CDATA[Stories by Nathan Curtis on Medium]]></description>
        <link>https://medium.com/@nathanacurtis?source=rss-799c7c7840a------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/1*dHlxssasdBxNPbItO2d2Yw.jpeg</url>
            <title>Stories by Nathan Curtis on Medium</title>
            <link>https://medium.com/@nathanacurtis?source=rss-799c7c7840a------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Wed, 20 May 2026 13:34:31 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@nathanacurtis/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com" rel="hub"/>
        <item>
            <title><![CDATA[Implementing Slots in a Figma Library]]></title>
            <link>https://medium.com/@nathanacurtis/implementing-slots-in-a-figma-library-a9d6185318c2?source=rss-799c7c7840a------2</link>
            <guid isPermaLink="false">https://medium.com/p/a9d6185318c2</guid>
            <category><![CDATA[design-systems]]></category>
            <category><![CDATA[api]]></category>
            <category><![CDATA[slot]]></category>
            <category><![CDATA[ui-component]]></category>
            <dc:creator><![CDATA[Nathan Curtis]]></dc:creator>
            <pubDate>Mon, 02 Mar 2026 17:58:06 GMT</pubDate>
            <atom:updated>2026-03-02T17:58:06.211Z</atom:updated>
            <content:encoded><![CDATA[<h4>Go beyond “Swap swaps” to explore, decide on and implement slot patterns</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*y2Za8zicBkVtTpU3.png" /></figure><p>Figma’s native slots promise a more flexible and easily composable future for design libraries. System owners are eager to transform their components, often with the expectation of a simple, one-to-one swap of existing slot utility instances for the new slot layers.</p><p>“I can’t wait. Our components will be delightfully easier to use.” True</p><p>“Figma’s native slot layers are simple to set up.” Also true.</p><p>“Just swap slot utilities for slot layers!” Hold up a minute. That’s not quite right.</p><p>A transition to native slots should reach further than replacing your slot utility asset. Migrating to Figma’s slots should force system architects to critically look at how components are composed and customized.</p><p>This post describes the journey of implementing native slots in a Figma library, from discovery with exploration through deciding your patterns and implementing them across the catalog.</p><h3>Discovery</h3><p>Don’t expect to just open a Figma library branch, rapidly change a bunch of components and hit publish. Migrating a library to slots with deliberate care can be informed by discovery activities like a library audit, research, and synthesis to identify patterns.</p><h4>Audit</h4><p>Start by auditing your existing Figma assets. Begin with already-composable components that may include slot utility instances, but don’t stop there. My audit included any component or subcomponent asset, and I catalogued each component with:</p><ul><li><strong>Name</strong>, like Button or Pill / Start Visual.</li><li><strong>Role</strong> in the composition, such as Root / the “Main Component” versus its Header, Body, Footer, Actions, Start Element, End Element, or Other purpose</li><li><strong>Slot utility?</strong>, indicating if it has a slot utility bound to an instance swap prop.</li><li><strong>Slot utility as variant option?</strong>, if the slot utility is available in some variants but not others. For example, a Content prop with options for Icon, Mark, Avatar, and Slot option (that shows a slot utility).</li><li><strong>Composable nested instances?</strong>, if any nested instance had a slot utility in it. For example, a Button that has an End Visual with a slot utility option.</li><li><strong>Props</strong> (all types) to determine which variant, text, and boolean configurations will be kept, changed or removed.</li></ul><p>I found myself sorting component props that I expected to keep versus those to consider more deeply or expect to remove (at least some instance swap props, obviously!).</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*GisDCV7YBQqYXi-2.png" /><figcaption>Component slot audit, including component props</figcaption></figure><p>In hindsight, I would structure the data I collected (and the decisions to come) in the format of this <a href="https://docs.google.com/spreadsheets/d/1creGsbaqWyYbMa8jH6DFKv6DlbWlkQebUB7LPsH7kok/edit?usp=sharing">Slots Audit Google Sheet</a>. It boils down what can feel like myriad different cases and examples into the kinds of patterns and decisions to plan around.</p><h4>Comparative research</h4><p>The migration’s intended to balance incorporating legacy code patterns with adopting a modern, composable shape. While working through Figma assets, I also researched both:</p><ul><li>Compare against and align with <strong>existing code implementations</strong>, across platforms as needed and ideally via LLM prompts and agents</li><li>Gain inspiration from <strong>public libraries with strong compositional qualities</strong>, like Github Primer and MUI React.</li></ul><h4>Exploration</h4><p>Before making decisions, I dug in and experimented with many approaches within and across components. I varied many aspected of the architecture like where props were exposed, where elements were included, how content was available by default, and how to name each slot. This led to an array of working examples to workshop with the team.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*5LnhXVM4X511q9ks.png" /><figcaption>Explorations file format for slot patterns with examples and alternative approaches</figcaption></figure><p>I prepared a Figma file with sections per pattern, establishing dedicated zones for:</p><ul><li><strong>Examples</strong> established the pattern’s relevance. For example, the <a href="https://nathanacurtis.substack.com/p/figma-slots-for-repeating-items">Group and repeating items</a> pattern included Checkbox Group, Tabs, Radio Buttons, Breadcrumbs, Action List and Avatar Group. I annotated each likely slot area in magenta.</li><li><strong>Alternatives</strong> distinguished choices around component hierarchy, layer structure, props, slot layer depth, and slot default content.</li></ul><p>In the periphery, I tracked:</p><ul><li><strong>Open questions</strong> in the form of voting dots and rationale.</li><li><strong>Architecture</strong> decisions addressing conventions of slots, props and layout. If I felt strongly, I recommended a decision as a starting point.</li></ul><p>This enabled me to learn by building and thinking through how to communicate distinctions per slot model. As we worked through options and examples, we riffed and made decisions.</p><h3>Decisions</h3><p>It may <em>feel</em> like you are just working through components ( Checkbox Group, Card, Button), but the reality is that you are defining <strong>rules and standards</strong> to apply across your entire catalog as core patterns.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*Oj-CdAPKQdAUUE-c.png" /><figcaption>Sheet, shifted from audit to decisions focus</figcaption></figure><p>The spreadsheet started with the audit serves as a structured way to record and plan implementation of your slot approach, props, and layout as you refactor each and align them with code.</p><h4>Slot approach</h4><p>As decisions gave way to patterns, we ultimately decided on an <strong>approach</strong>. Each component or subcomponent was either EOL’ed (deleted) or kept with a slot architecture of:</p><ul><li>Slot, empty default</li><li>Slot, with default content</li><li>Configuration-first (props bound to layers, but no slot), “Custom” escape hatch (a slot with layers not bound to props)</li><li>Named slot, always visible</li><li>Named slot with visibility prop</li><li>Items slot</li><li>Subcomponent, no slot</li><li>Subcomponent with slot</li><li>No slot</li></ul><h4>Slot properties</h4><p>Slot property conventions are straightforward yet require agreement:</p><ul><li><strong>Name</strong> of both “default” slots (like children or items) and other named slots if needed</li><li><strong>Default content</strong>, whether none, uniform, or varying across variants</li><li><strong>Permissiveness</strong>, whether closed (to a strict set of anyOf children) or open (to set preferred values) as well as minItems and maxItems<strong> </strong>as relevant.</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*n1SZiHBsLD5v95v2.png" /><figcaption>Slot props per component, such as name and default content</figcaption></figure><h4>Slot layout</h4><p>I recommend avoiding setting visual styles of slots like color, corners, and strokes. However, it’s practical to set layout properties like direction, resizing and item spacing and work out with development how those do or don’t impact code implementation.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*7QAYv0hsehre4C7I.png" /><figcaption>Slot layout per component, such as item spacing and resizing</figcaption></figure><p><strong>Prohibit padding on the slot layer</strong>. A component should not control the inset of its slot. If internal padding is required, nest the slot within a containing frame and apply padding there.</p><p><strong>Empty slot sizing.</strong> In cases like Card and Modal, slots could be empty by default. Empty slots will retain a customized fixed height and width if needed. Discuss if and how to set the slot&#39;s default height or width, likely to a typical expected size.</p><h4>Refactored props and subcomponents</h4><p>The transition to composable native slots forces a look at every component, both for its own internals as well as its relationships with other components. This leads to refactoring, and I expect slots to result in a <a href="https://nathanacurtis.substack.com/p/configuration-collapse">configuration collapse</a> described in a recent, separate post. Composition, not configuration, becomes the preferred approach to solve many problems.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*QWEmhGsQIZOfm8oE.png" /><figcaption>Decisions to keep or remove existing Figma component props</figcaption></figure><h4>Relating design assets and code architecture</h4><p>In addition, consider a method to distinguish props that are “Figma helpers” that may not belong on a composable component’s code API.</p><p>For example, a Custom (false|true) prop that activates the slot for composability, and the bound label, description and visibility props presented to designers by default as the more common configurable case. This separates the bound label, description, and visibility props-presented for the common configurable case-from the asset&#39;s Custom appearances, which define its true, composable API.</p><p>In the spreadsheet, I distinguish these using the *. In our tooling, that’s transformed when converting Figma assets to specification data.</p><h3>Implementation</h3><p>Equipped with implementation patterns and confident decisions, it’s time to plan and convert a library, from low- to high-order components, one at a time.</p><p>Notable characteristics of my implementation plan included:</p><ul><li>One branch per component.</li><li>Convert components of the same pattern (such as <a href="https://docs.google.com/spreadsheets/d/1creGsbaqWyYbMa8jH6DFKv6DlbWlkQebUB7LPsH7kok/edit?usp=sharing">groups with repeating items</a>) simultaneously as a batch. That way, you can implement, review, and adjust across branches as decisions evolve.</li><li>Leave more deeply nested component structures for later, like Alert (with its e, Text and Actions) and Action List (with its Item, Start Visual, Text, and End Visual). This offers space to sit with the more complicated architecture for a bit as people adapt to the easier stuff.</li><li>Test slots using ready-made examples built beside the component assets. Early on, they are more test cases than published examples, even if they should represent acceptable cases by the time you publish.</li><li>Pilot and get feedback on many things before publishing all the things.</li></ul><p>Equipped with a plan, the conversion is a structured, component-by-component process of applying new conventions to a library that’s robust, tested, and ready for adoption.</p><p><em>Originally published at </em><a href="https://nathanacurtis.substack.com/p/implementing-slots-in-a-figma-library"><em>https://nathanacurtis.substack.com</em></a><em>.</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=a9d6185318c2" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Configuration Collapse]]></title>
            <link>https://medium.com/@nathanacurtis/configuration-collapse-5a1d68b4c672?source=rss-799c7c7840a------2</link>
            <guid isPermaLink="false">https://medium.com/p/5a1d68b4c672</guid>
            <category><![CDATA[api]]></category>
            <category><![CDATA[design-systems]]></category>
            <category><![CDATA[slot]]></category>
            <category><![CDATA[ui-component]]></category>
            <dc:creator><![CDATA[Nathan Curtis]]></dc:creator>
            <pubDate>Fri, 27 Feb 2026 18:00:02 GMT</pubDate>
            <atom:updated>2026-02-27T18:00:02.658Z</atom:updated>
            <content:encoded><![CDATA[<h4>As Figma Slots Push Composability, Be Ready to Drop Props</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*CjTVBLe5ZRrduWKI.png" /></figure><p>Glance at the Props panel of a mature Figma component, and you risk encountering a scrollbar of shame. Countless props fine tuning element visibility (like showIcon) and layout (horizontal or vertical direction). Each solves for a real yet specific case, added with the best of intentions.</p><p>Yet together, those “helpful” and enabling props sprawl into a paradox of configurable choice. When component variant counts explode or a simple change breaks an inherited style, it’s not because the design system is flawed-it’s because it’s using the wrong tool. The system further burdens itself to document, test, and maintain more features, locking it in a box of its own making.</p><p>A single, rigid component need not solve all things for all people.</p><p>Figma’s native slots are coming for your configurable props, and will tear many of them down. System power should come from not switches and variants, but by allowing for creative, unconstrained composition. This will demand a bold act: a configuration collapse to drop props that make components fragile.</p><p>This article explores this shift by moving our prop-first mindset to purer composability, with examples of the Pill, Alert and Card.</p><h3>A Leaner Component Core</h3><p>Shifting towards composability must leave the component’s identity untouched, retaining only behavioral and foundational visual props — such as state, appearance, and size—as the component’s essential, top-level API.</p><p>Yet many other props types and subcomponents are at risk, like:</p><ul><li><strong>Visibility</strong> props (Figma BOOLEAN props like showIcon, hideDescription, actionsVisible) declined severely in favor of controlling element presence and visibility via slot composition.</li><li><strong>Visual hack</strong> props declined, particularly those impacting single visual choices (e.g., color, corner radius, or border) of a nested layer.</li><li><strong>Subcomponents</strong> for varying layout and element structure were eliminated entirely (see the Alert &gt; Body &gt; Text example below).</li><li><strong>Configuration shifts</strong> removed complex props ( actionsVisible, actionsCount) in favor of a dedicated, simpler subcomponent that&#39;s slotted into the main component with potential constraints.</li></ul><p>Decoupled <strong>visual styling of composed children</strong> (e.g., the text color of a Button Label or a Card Title) is an undesirable but necessary trade-off. These relationships have efficient, effective controls in code, but become the composer&#39;s responsibility in Figma. Use strong, variant-specific defaults and rich examples to mitigate this challenge.</p><p>The immediate effect is <strong>leaner component APIs</strong>. In the long-term, teams and systems across the enterprise can better extend, build around, and build within core components without conflict and delay.</p><h3>Why Now? AI-Ready Components</h3><p>Design systems have been built for composability for some time. Systems have been putting the right props at the right levels of the right components. Putting things together feels right… in code. But not in design tools. And certainly not in design tools increasingly manipulated by AI.</p><p><strong>Because Figma can compose in components now</strong><br>So the easy answer is: because designers couldn’t do this before with Figma. Native slots — or more abstractly, composition within a component asset — was too difficult and clunky to replicate, so Figma’s architecture was different.</p><p>I think Figma prioritizing building slots in 2025 is neither because slot utility instance swapping sucks (it has for years) nor that slots just happened to be next on the roadmap. I speculate that slots are a priority because machines now compose interfaces and Figma needs customer’s assets ready for the challenge.</p><p><strong>Component composition is grammar</strong><br>In a prop-heavy system, element relationships are implicit and bound to prop combinations that are arbitrary and often quite uncommon. With composition, relationships become explicit: a Pill is composed of an Icon and text Label inside it, each with important yet contextual configurations of their own. This creates structure that AI can read, understand, and generate.</p><p><strong>Favor predictable patterns over hyper-configuration</strong><br>Also, a reduced configurable shape improves predictability. Figma boolean and layout variant props feel arbitrary and don’t cover all possible needs anyway. Instead, systems should supply AI with training data that records relationships in other ways, such as ready-made examples augmented with guidance. Models could perform better with fewer yet higher-confidence patterns rather than spinning on copious, hyper-specific configuration states.</p><p><strong>Layer semantics over flexible building blocks</strong><br>Figma’s slot composition also opens up opportunities to build purpose-driven components (like a ProductCard with opinionated structure and layouts) by wrapping a composable Card container starting point. This more effectively separates concerns, affords extensibility, and improves autonomy.</p><p>The takeaway shouldn’t be to “Drop all the props.” Instead, it’s about finding the right balance. It’s still essential to offer the right configurable choices at the right level without necessarily rigidly controlling what’s inside.</p><blockquote>Make the common configurable, make the uncommon composable</blockquote><p>Moreso, it’s about tearing away the structural noise from our configurable surface. Now’s the time to put compositional choices in the hands of the composer, scaffolded with starting points and guided by rich examples and context.</p><h3>Examples</h3><h3>Start and End Visuals</h3><p>Many more atomic components like Pill, Badge, Chip, Tab, Link, and Button have Start and/or End visuals on either side of a label. In the past, to control for a set of expected visual types (like an Icon, Mark, Image or Avatar), we’d use a component or subcomponent variant prop.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*bwEeD-_GOKGAO10I.png" /><figcaption>Pill layer structure before and after slot migration</figcaption></figure><p>With native slots, favor flexibility and ease over control. Nesting text and paired visuals (either hidden or visible by default) in a children slot.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*94KS38T3Z592sWRC.png" /><figcaption>Pill configuration before and after slot migration</figcaption></figure><p>This resulted in a near complete collapse of some component’s props, including:</p><ul><li>All visibility props (Start Visual Visible, End Visual Visible)</li><li>Type variant props</li><li>Padding variants that controlled spacing between a label and visual, omitted in favor of a composer implementing that choice.</li></ul><p>Icon is a predominant default visual. Certainly, adding it as a slot &quot;Preferred Value&quot; is a start. However, inserting it results in a likely Icon configuration mismatch. Alternatively, it could be included by slot, whether shown or hidden by default. That way, the Icon can be configured to match the parent state, such as Pillselected&#39;s impact on Icon&#39;s appearance.</p><p>The need to control was rare but did arise, such as Button / Start Visual. This strongly typed subcomponent reinforced expected use, even if it could be omitted and a different element included just in case.</p><h3>Body, Text and Actions Layout</h3><p>As component structure becomes more complicated, varying layouts and included elements become more common. For example, an Alert component may include a Title or Description or both as well as arrange those horizontally or vertically as well as their combination horizontally or vertically with Actions. Sometimes, the entire Alert&#39;s Body may need to be customized.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*dbZKOMg6vesbcoko.png" /><figcaption>Alert component with all elements arranged in varied layouts</figcaption></figure><p>This can be achieved with subcomponents, each with variants controlling layout directions (at multiple levels) and element visibility. “Most” layouts become configurable. Yet the overwhelmingly most common layout is all elements vertical, and three-level deep subcomponents always felt quite brittle.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*8qA-6nZUwO6n48c3.png" /><figcaption>Alert layer structure before and after slot migration</figcaption></figure><p>Alternatively the elements — both text elements like Title and Description as well as frame containers - could be included in a slot. This scaffolds a starting point with everything you need, enables rapid layout refactoring using the frames equipped with autolayout, removes the need for Body and Text subcomponents altogether. Anchoring on the predominant layout felt liberating.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*tj6keArEb-EJ4NSE.png" /><figcaption>Alert configuration before and after slot migration</figcaption></figure><p>As a result, subcomponents and their layout, text and visibility props vanished. Instead, the component asset was coupled with a few ready made examples of the alternative layouts. Designers have everything they need to achieve the outcome they want as quickly as before, yet with far more flexibility.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*-CLB4UKem-3z-VrU.png" /><figcaption>Alert component assets beside the ready-made examples</figcaption></figure><h3>Card</h3><p>Early Card experimentation focused on common structures – Visual, content layouts, Actions. Depending on the design system, that could result in useful, composable subcomponents that recombine in a few predictable ways.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*aW7QuBLV10o0xd-u.png" /></figure><p>Not this particular system. The system served divergent experiences spanning 50 brands. There simply was no predominant default, or even common limited collection. Instead, the system would likely require a deep collection of diverse ready-made examples. As a result, for the core library at least, it made sense to hollow out the Card to an unopinionated container.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*WcrwAS-kuLG3vNI0.png" /></figure><p>With a hollowed out container component, that meant the core library deliberately offered no configurable subparts. There’s justification for a composable Card / Visual , but the core team might rather focus on offering an Image component that you can overlay custom content instead. The Card / Actions subcomponent would echo the pattern established by Alert, but actions too were too diverse to normalize. Why bother? Just compose what you need.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*wUOGYXyFeIcJljca.png" /></figure><p>The core Card &#39;s unopinionated container is a strategic choice. Less is more. It acts as a maximally flexible foundation without imposing constraints, enabling other teams to build purpose-driven extensions.</p><p>A separate team has already begun. They’ve initiated a separate library, signaling a rich array of even more hyper-specific card content subcomponents and zones, layouts and visual expression. The design system will then weave those inspirations in among the broader collection of ready-made examples to guide everyone.</p><p>There’s no one shape that’s perfect for everyone. I’m making different judgments for different design systems as I go to get to the goodness-of-fit that works for each case. Onward!</p><p><em>Originally published at </em><a href="https://nathanacurtis.substack.com/p/configuration-collapse"><em>https://nathanacurtis.substack.com</em></a><em>.</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=5a1d68b4c672" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Figma Slots for Repeating Items]]></title>
            <link>https://medium.com/@nathanacurtis/figma-slots-for-repeating-items-64b28e35f56a?source=rss-799c7c7840a------2</link>
            <guid isPermaLink="false">https://medium.com/p/64b28e35f56a</guid>
            <category><![CDATA[api]]></category>
            <category><![CDATA[ui-component]]></category>
            <category><![CDATA[design-systems]]></category>
            <category><![CDATA[composition-api]]></category>
            <dc:creator><![CDATA[Nathan Curtis]]></dc:creator>
            <pubDate>Fri, 23 Jan 2026 18:41:54 GMT</pubDate>
            <atom:updated>2026-01-24T14:28:11.329Z</atom:updated>
            <content:encoded><![CDATA[<h4>How to convert one of your library’s most common patterns</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*uL38UDITbG19NjrJ.png" /></figure><p>As I talk with design system teams about Figma’s native slots rolling out for early evaluations, conversations invariably start with how a migration will replace Slot utility instances with native slots. I&#39;m pretty quick to point out that &quot;You may not even be using a slot utility for you most common kind of native slot. Have you thought about repeating items?&quot;</p><p>This post illustrates many examples of repeating items within a core component library and why it’s been difficult to date to compose them effectively. The solution is Figma’s new native slots, with a more careful architecture of naming, default content, and more granular specs.</p><h3>Background</h3><p>Many, many UI components serve as a container for repeating items. This is most common when a component’s purpose is as group containing items, like:</p><ul><li>checkbox in checkboxGroup</li><li>radioButton in radioButtonGroup</li><li>avatar in avatarGroup</li><li>button in buttonGroup</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*zaGy8rVv49PNY46E.png" /><figcaption>Checkbox and Radio button items in group component slots</figcaption></figure><p>Many components are groups implicitly even if not named that way:</p><ul><li>tab in tabs</li><li>breadcrumb in breadcrumbs</li><li>actionListItem in actionList</li><li>listItems in a list</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*Cdj1Wcmn17f_RmWO.png" /><figcaption>Tabs and Breadcrumbs as repeating items without being named a “group” or “list”</figcaption></figure><p>Repeating items also exist in a component area like actions in an alert, toolbar or dialog. Suffice it to say, a repeating item pattern is pervasive across a component library of any scale. As systems migrate Figma assets to native slots, don&#39;t be surprised when you find that repeating items are the most common composable pattern in a library.</p><h3>Anti-Patterns</h3><p>Unfortunately, that’s never been easy to enable in Figma component assets. This led to workarounds like instance swapping, hidden layers, and “count” props.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*sWnoFvEI38HCrZ4c.png" /><figcaption>Figma “slot utility” meant to be swapped out</figcaption></figure><p><strong>Instance Swapping: </strong>Some systems implement repeating items as an instance swap, even creating a row-based convention of instance swaps-within-instance swaps within which repeating items were placed. No thanks.</p><ul><li>Users find instance swapping ergonomically annoying</li><li>Users had to create a separate component asset to swap in an instance</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*2sscT70Cynqvl-93.png" /><figcaption>Figma instance with 3 — and ONLY 3 — hidden item instances</figcaption></figure><p><strong>Hidden Nested Instances: </strong>Systems also use hidden layers for extra items, with quantities based on implicit conventions (such as showing ‘x’ layers and hiding ‘y’ layers). Negative outcomes include:</p><ul><li>Users drill deep into component layers to find and manipulate items</li><li>Overridden instance layer visibility and other nested configurations, an antipattern</li><li>Items cannot be reordered</li><li>Additional items cannot be added</li><li>Degraded file performance due many hidden and often complicated layer hierarchies per instance</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*bfmjxXlrhmEVBnLf.png" /><figcaption>Figma component asset with a property to control item quantity</figcaption></figure><p><strong>Quantity Props:</strong> Systems add props like Count to control item quantity. For example, systems may implement an enum Count prop to display 1, 2 or 3 actions in an Alert.</p><p>This is composition, not configuration. Avoid it given negative outcomes of:</p><ul><li><strong>Variant explosion</strong> in component sets</li><li><strong>Handoff friction</strong> in handoff to ignore props not a part of the “official API”</li><li><strong>Item configuration</strong> conflation into props of a higher-order asset</li></ul><p>All of these approaches are hacks to make up for Figma’s historical lack of component asset composability.</p><h3>Solution</h3><p>Use Figma native slots to compose repeating items within a component asset and populate the slot’s default content with a reasonable and consistent number of items.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*gvBX1t5Ghi6iCBEk.png" /><figcaption>Figma Checkbox Group instance with an items slot</figcaption></figure><p>For example, include an items slot in a checkboxGroup with three checkbox instances by default. It&#39;s easy for the user to add, remove, reorder and even quick drag to create a longer list of items.</p><h4>Pros</h4><ul><li><strong>Improved Composability</strong>: Slots solve the primary problem: a clean container-child relationship to easily add, remove, and reorder items.</li><li><strong>Low Asset Complexity</strong>: This eliminates the need for workarounds like “hidden layers” and “count props,” which improves file performance and reduces implicit conventions.</li><li><strong>Clear API</strong>: An items slot is an explicit, native way to define the types and constraints of customizable children.</li></ul><h4>Cons</h4><ul><li><strong>Open, Uncontrolled Children</strong>: Figma slots are inherently open. They’ll take anything, no matter what you designate as “preferred.” Therefore, systems must trust users and implement methods to verify design and code.</li><li><strong>Risk of Empty Slots</strong>: The user can remove all default items, causing the slot to appear empty.</li><li><strong>More Complicated Definition</strong>: Systems must define a more granular slot architecture including naming, constraints and guidance.</li></ul><p>You could also assert it requires a learning curve. I wouldn’t agree. All the previous methods were both error prone and harder to use. The simplicity of starting with a composable area with items you need drastically saves time and is directly the interaction users prefer.</p><h3>Architecture</h3><p>When adding native slots to library components for repeating patterns, be mindful of details like naming the prop and layer, default content, minimum and maximum quantity, and permitted values.</p><h4>Naming</h4><p>In Figma, slots are both a property type (SLOT) and layer type (SlotNode). The names of each are revealed in the Props and Layers panels, respectively. Choosing a conventional name for both improves user understanding and expectations when composing repeating items across a library.</p><p><strong>Favor </strong>items<strong> (purposeful) over </strong>children<strong> generic)</strong>. During our refactor to native slots, we narrowed down to considering items versus children, where children had already been chosen generic component slots with no default content. We chose items to carry a narrower purpose that expects specific types of children.</p><p><strong>Distinguish </strong>items<strong> and </strong>children. In addition, components with items often have additional elements not included in the slot, such as an avatarGroup&#39;s end count or a checkboxGroup&#39;s header and error message. This, too, distinguishes the repeating items case from corresponding to &quot;all of a component&#39;s children.&quot;</p><pre>components:<br>  checkboxGroup:<br>    elements:<br>      items:<br>      header:<br>      description:<br>      validation:<br>    default:<br>      layout:<br>        - root<br>          - headerArea<br>            - header<br>            - description<br>          - items<br>          - error<br>            - errorIcon<br>            - errorMessage</pre><h4>Default Items</h4><p>Generally, three items seems the reasonable convention for most item sets, since three:</p><ul><li>Affords that it’s an indeterminate list more strongly than two or one</li><li>Enables distinguishing a selected item (often the first item) separately from other items in components like tabs and radioButtonGroup.</li></ul><p>Additionally, it’s important to not confuse default slot data with ready-made examples. Sure, a checkboxGroup can have many, many items, and you can depict that in your system&#39;s set of examples. However, that&#39;d prove a very hostile default relative to the far more frequent cases of a few items.</p><h4>Minimum and maximum item quantity</h4><p>Unlike generic slots which can be empty, slots for repeating items generally require one or more items. As a result, we’ll define such slots as minItems:1.</p><p>Occasionally, an items slot may govern a maximum number of items. For example, an Avatar group may include up to four Avatar components, after which a count to the right of the last item.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*Yd5AE1spRavNquAa.png" /><figcaption>avatarGroup instance with a slot</figcaption></figure><p>If a system chose to include this hard constraint, the avatarGroup would define an items slot as:</p><pre>components:<br>  avatarGroup:<br>    props:<br>      items:<br>        type: slot<br>        anyOf: avatar<br>        minItems: 1<br>        maxItems: 4</pre><h4>Permitted vs preferred values</h4><p>Figma’s slot preferred values match the experience for instance swapping. Undoubtedly, slot properties should associate the single item type (like checkbox within checkboxGroup) as preferred values.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*TDtEwn4jNH5bLOxu.png" /><figcaption>avatarGroup with avatar defined as a preferred value</figcaption></figure><p>Nevertheless, Figma’s slots are open to accept any child and cannot be formally governed. This relationship is stricter. In specification data, this is represented by a list anyOf items, like:</p><pre>components:<br>  checkboxGroup:<br>    props:<br>      items:<br>        type: slot<br>        anyOf: checkbox<br>        minItems: 1</pre><p>We’ll use <a href="https://nathanacurtis.substack.com/p/code-only-props-in-figma">code only props</a> to identify what items are permitted, minimums and maximums so as to handoff the intent via <a href="https://nathanacurtis.substack.com/p/components-as-data-2be178777f21">component data</a> downstream to collaborators and machines.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*kLSprwOO9O5SolVb.png" /><figcaption>checkboxGroup with additional “code only” props containing slot specification data</figcaption></figure><p>Figma’s native slots are the new primitive that shifts the burden of complexity from the designer’s canvas back to the system’s architecture. By providing an explicit, consistent API for repeating items, systems can move post brittle hacks and offer a cleaner canvas, a simpler property panel, and a more flexible library for everyone.</p><p><em>Originally published at </em><a href="https://substack.com/home/post/p-185557988"><em>https://nathanacurtis.substack.com</em></a><em>.</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=64b28e35f56a" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[“Code Only” Props in Figma]]></title>
            <link>https://medium.com/@nathanacurtis/code-only-props-in-figma-854ca0815e7d?source=rss-799c7c7840a------2</link>
            <guid isPermaLink="false">https://medium.com/p/854ca0815e7d</guid>
            <category><![CDATA[ui-components-library]]></category>
            <category><![CDATA[json]]></category>
            <category><![CDATA[design-systems]]></category>
            <category><![CDATA[api]]></category>
            <dc:creator><![CDATA[Nathan Curtis]]></dc:creator>
            <pubDate>Sun, 18 Jan 2026 20:53:34 GMT</pubDate>
            <atom:updated>2026-01-18T20:53:34.550Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*fFHZ-gUqmwWaKUt7.png" /></figure><p>I’m among those that steward cohesive component API. In designing systems, it’s our job to define and communicate accessibility, behavior and non-visual logic just as much as style and layout.</p><p>As we define components, we’ll face intricate questions that shape how components work. Figma hasn’t yet been the place to express all those answers. Yet, what if… we started shaping more of that via props to Figma assets?</p><p>This post details a technique for adding “code only props” to Figma components. It covers how these props better connect system designers with their users and system developer counterparts, how to build them into Figma, and ends with examples from simple to controversial to gloriously yet dizzyingly complicated.</p><h3>Challenges</h3><p>My work often focuses on a core component library that is built into Figma assets, transformed into <a href="https://nathanacurtis.substack.com/p/components-as-data-2be178777f21">spec data</a> and is implemented across iOS, Android, and the web.</p><p>Each component’s property shape can be complicated. Figma provides for many prop types: text (primarily for text characters), variant, boolean (for visibility), instance swap and soon slot too. Yet, Figma prop types are nowhere near comprehensive and bias heavily towards visual outcomes rather than broader concerns.</p><p>This challenges system designers, who want to:</p><ol><li>Specify non-visual accessibility and other configurations as a part of defining a system component</li><li>Maximize API they can shape and deliver into deterministic, automated processes</li><li>Expose non-visual props that product designers can use to express an intent</li><li>Clarify relationships of visual and non-visual props</li><li>Improve how Figma synchronizes with code libraries and other assets</li></ol><h3>Solution</h3><p>We began to add Figma TEXT and props and VARIANT props of nested instances that correspond to additional props, housed in a practically hidden “Code only props” layer.</p><h4>Step 1. Code-only props layer</h4><p>Add a Code only props layer as a child of the component’s root layer, positioned at (0,0) with width and height of 0.01 and clipping contents.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*2qppXr7ofQbWijFp.png" /><figcaption>Code only props layer with practically no size and clipping its contents</figcaption></figure><p>This virtually hidden layer contains semantically-relevant layers bound to component props that are nonetheless hidden from the visual experience.</p><h4>Step 2: Nest a layer per prop</h4><p>Add text and nested instance layers corresponding to each prop.</p><p>For example, interactive components like button, link, checkbox and breadcrumbs can include an Accessibility label prop. This property often maps to an internal label like aria-label or an associated &lt;label&gt; tag.</p><p>A system designer could bind an Accessibility label property to an Accessibility label text layer within the code only props frame.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*U8T3C8eqp3HD0Uiw.png" /><figcaption>A nested accessibility label text layer bound to text prop</figcaption></figure><p>A product designer will then see the prop in the Props panel.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*bMA932C803gvIelH.png" /><figcaption>An accessibility label prop visible in the props panel</figcaption></figure><p>In general, the text layer is left visible or hidden (thus suppressing the field from view) depending on whether it’s relevant to a product designer.</p><h4>Step 3: Integrate into handoff and automations</h4><p>Handoffs and tools (like <a href="https://nathanacurtis.substack.com/p/components-as-data-2be178777f21">generating specification data</a> from assets via tools like my <a href="https://nathanacurtis.substack.com/p/analysis-of-variants-9e440c30b93e">Anova plugin</a>) pick up the prop, adding accessibilityLabel to the versioned contract centrally leveraged to implement and maintain a component across platforms.</p><pre>components:<br>  {component name}:<br>    props:<br>      ...<br>      accessibilityLabel:<br>        type: string</pre><p>As Figma data is transformed, tools can:</p><ul><li>Infer types based on default values, such as a string (Label), number (0) or enumerated list (such as h1|h2|h3|h4|…), although be careful with that</li><li>Omit the Figma structure irrelevant to generated code, since the code only props layer and its children are metadata, not formal component layout</li><li>Add and bind these layers when generating Figma assets from spec data</li></ul><h4>Tradeoffs</h4><p>Sure, props like accessibilityLabel, headingRole, and maxRows are less important to designers exploring design concepts. Tradeoffs include:</p><ul><li>✅ Improves visibility of component props to product designers</li><li>✅ Enables system designers to shape more of the component API</li><li>❌ Complicates Figma assets</li><li>❌ Adds friction when defining component due to unclear boundaries on which props to include and how to name them (in my opinion, this is <em>productive</em> friction)</li></ul><h3>Additional Examples</h3><h3>Image src and altText</h3><p>If building for one platform or even a content management system, it may or may not be valuable for a product designer to specify an altText or src but it could still be relevant for a system designer to convey one or both expected props to a system developer or a pipeline.</p><p>To accomplish this, a system designer add both text layers, bind each to a component prop, and hide those irrelevant to product designer activities by hiding the text layer(s).</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*aq-EDq4Xvc0YJ75V.png" /><figcaption>Two text layers bound to component props, one layer hidden to suppress it’s display in the Props panel</figcaption></figure><p>The product designer would then only see the props they need to, such as only the altText prop.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*ld3nNiHt-IwcIqt0.png" /><figcaption>Props panel exposing only the altText prop</figcaption></figure><p>Spec data would predictably encode both props:</p><pre>components:<br>  image:<br>    props:<br>      ...<br>      src:<br>        type: string<br>      altText:<br>        type: string</pre><p>Now, there are reasons we’d avoid these props in many systems, such as (1) not needing to because they are default HTML attributes or (2) it’s platform specific, running counter to the broader goal of orchestration across platforms. Nevertheless, the example reflects the flexibility of exposing and hiding props.</p><h3>Heading Semantic Tag and Level</h3><p>For a prop used to set which HTML tag is rendered in the DOM, the Heading component Figma asset could include a nested instance of an as component with variants for h1|h2|h3|… and so on. While it feels odd to create such utility assets in Figma, it’s actually simple and quick.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*_QR50eubJ3_QA-ef.png" /><figcaption>Two props for As and Level, both hidden from the product designer</figcaption></figure><p>The instance with one variant prop then gets transformed into spec data alongside related props like level:</p><pre>components:<br>  heading:<br>    props:<br>      ...<br>      as:<br>        type: string<br>        enum:<br>          - h1<br>          - h2<br>          - h3<br>          - h4<br>        default: h1<br>        nullable: false<br>      level:<br>        enum:<br>          - 1<br>          - 2<br>          - 3<br>          - 4<br>          - 5<br>        default: 1<br>        nullable: false</pre><p>In code, this would be used as:</p><pre>&lt;Heading as=”h3” level=”2”&gt;My Title&lt;/Heading&gt;</pre><p>For teams working across platforms, they’d need to decide whether or not specification data captures platform-specific props like these and whether or not those sync with Figma assets. That said, decades of experience suggests that conversations of separating concerns of as (structure) and level (presentation) aren’t dead yet..</p><h3>Slot Properties</h3><p>As we migrate to native slots in Figma, we’re adding additional props to describe slot configurations like anyOf (permitted children), minItems and maxItems.</p><p>For the Checkbox Group, we’d expect at least one child and they’d only ever be a Checkbox. Therefore, we build our asset to include:</p><ul><li>The items slot prop</li><li>The items anyOf that includes a comma separated list of component names (in this case, set to simply Checkbox)</li><li>The items minItems prop, here set to 1</li></ul><p>Both props are hidden from view for the product designer.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*oaTWs-eVlX3ZeUJa.png" /><figcaption>Slot-specific configuration props</figcaption></figure><p>This corresponds to spec data of the shape:</p><pre>components:<br>  checkboxGroup:<br>    props:<br>      ...<br>      items:<br>        type: array<br>        anyOf: <br>          - checkbox<br>        minItems: 1</pre><p>We considered other options in Figma. The emerging slot prop type may include a description field. However, a description is a rich text, less stable and unstructured target for automated tools. If we were to leverage it, we’d use it for guidance, not specs. The already supported .preferredValues field is much closer in intent, but we chose to not overload it with what’s permitted values. More on that another time.</p><h3>Text Area</h3><p>In more complicated components, a system designer must consider what may become a dizzying array of logical relationships.</p><p>Textarea could include configurations like minimum value length, maximum value length, showing or hiding a max character count and whether that includes current character count. Not all these props reveal themselves visibly to the user.</p><p>For example, a minLength property could be enforced through a component behavior but not within a Figma asset. minLength could also be related to – but doesn’t trigger – a validation represented by Figma variant with an error message. As a result, minLength is a viable code only prop.</p><p>Textarea height might be bound by a minRows count (such as 2 by default) and a maxRows count (possibly undefined by default). In Figma, product designers simulate that by resizing and fixing asset height to fit their use case. Yet, system designers could imbue this intent via code only props.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*jtcCu4eZOlfN0ZHc.png" /><figcaption>Textarea props, including many code only props</figcaption></figure><p>These logical relationships result many text and boolean. All are built into the asset, enable logical relationships to show and hide relevant layers, and convey to spec data. Yeah, this one’s a doozy. Yet by the end of this modeling exercise, we’d learned much more about the component’s intricate behaviors.</p><p>Using “Code-Only Props” in Figma — it’s a bit of a technical trick using hidden layers to sneak data through — lets Figma be an origin of truth defining a component. It’s behind-the-scenes stuff, for sure. System designers should handle complicated requirements without making the product designer’s prop panel a mess.</p><p><em>Originally published at </em><a href="https://nathanacurtis.substack.com/p/code-only-props-in-figma"><em>https://nathanacurtis.substack.com</em></a><em>.</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=854ca0815e7d" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Slots in Design Systems]]></title>
            <link>https://medium.com/@nathanacurtis/slots-in-design-systems-f53698c2d745?source=rss-799c7c7840a------2</link>
            <guid isPermaLink="false">https://medium.com/p/f53698c2d745</guid>
            <category><![CDATA[design-systems]]></category>
            <category><![CDATA[front-end-development]]></category>
            <category><![CDATA[ui-design]]></category>
            <category><![CDATA[ui-component]]></category>
            <dc:creator><![CDATA[Nathan Curtis]]></dc:creator>
            <pubDate>Sat, 08 Nov 2025 03:26:28 GMT</pubDate>
            <atom:updated>2025-11-10T12:26:15.443Z</atom:updated>
            <content:encoded><![CDATA[<h4>Improving flexibility through custom composition inside components</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*ewBXTvypkTdo58Fu.png" /></figure><p>No system solves every problem we’ll ever face. Nor should we want it to. Instead, a well-architected system balances what’s fixed and what’s open, where you are constrained by guardrails and where you can — and should — innovate.</p><p>Insert slots.</p><p>Slots define the areas in a component to vary content and structure, adapt layout, and improvise new ideas. Adding flexible, customizable areas to components move systems away from rigid, frustrating boundaries designers and developers struggle with today. Emerging native support of slots in Figma should usher in a next generation of component libraries, enabling more customization we crave without sacrificing control and consistency systems promise.</p><p>This post introduces the concept of slots in UI components. First, we’ll define slots and demonstrate the many forms slots take across common, familiar components. From there, we’ll dive into considerations of slot types, properties, subcomponent parts, and ready-made examples we’ll curate. Ultimately, slots present an array of new architectural challenges we’ll face and resolve in the year(s) ahead.</p><h3>Getting Started</h3><p>A slot is a designated place inside a component where custom content can be inserted-an intentional opening in a component’s hierarchy to allow custom variation.</p><p>In Figma, a slot are presented as a layer bordered in pink that acts a frame inside a component instance. Inside that boundary, you compose whatever you want.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*fGtF0Q_hWqw3McdU.png" /></figure><p>In code, slots present as mechanisms like children (what’s included within the component’s tags) and tags and props like footer in the example below. Different platforms (like iOS and Android) and frameworks (like React, Web Components and Vue) use different syntax to accomplish the same goals.</p><pre>&lt;Card footer={&lt;Button variant=&quot;primary&quot;&gt;Buy now&lt;/Button&gt;}&gt;<br>  &lt;h2&gt;Product name&lt;/h2&gt;<br>  &lt;p&gt;Product description&lt;/p&gt;<br>&lt;/Card&gt;</pre><p>Slots make components composable and adaptable, providing a predictable way to customize content while preserving control of the component’s surrounding layout, styling, and behavior. Common needs can remain configurable, yet uncommon challenges can then be solved through composition.</p><p>Yet, slots blur component boundaries. Without slots, what’s inside a component is encapsulated, unyielding beyond what you configure using props. With slots, what’s inside can include a customized design. Teams become empowered to shape what they need, and systems continue to constrain what stays consistent.</p><p>Slots also improve alignment of design structure to how code works. Component hierarchies in React, Web Components, and native libraries are likely already quite composable. Adding component slots in design tools isn’t just a boon for creativity, it improves clarity and alignment during handoff and implementation, too.</p><h3>Usage</h3><p>Slots can impact more components across an ecosystem than one might expect. Sure, slots apply to moderately sized components that need customization. However, they can also apply to smaller “core” components as well as layout up through layers of composition including the page.</p><h4>General Slots</h4><p>Slots are most recognizable and expected in components like Modal and Card for which users already expect to compose content and structure inside. These are examples of general slots for the component’s main body, and typically corresponds the component code’s children.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*-S2-V4ICRI_YEVMk.png" /><figcaption>Modal and Card components with a slot for body content</figcaption></figure><h4>Named Slots</h4><p>Components name slots for multiple composable areas. For example, subtle shifts in content, styling, interactivity and layout abound in each area of a Row component seen stacked in feeds. Supporting each unique display as a configuration isn&#39;t just impractical, it&#39;s avoidable brittleness.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*10ID51rmBHVfHx-w.png" /><figcaption>Row component with significant, subtle variation across all areas</figcaption></figure><p>Instead, the Row warrants named slots. This three-part layout could enable customizing independent areas: the leading visual on the left, the text in the middle (possibly as the general slot), and the trailing actions on the right.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*mC68EH1rV5v11Yb2.png" /><figcaption>Row component with slots for leading visual, trailing actions and the default content between</figcaption></figure><h4>Slots for groups of repeating items</h4><p>Slots also improve our ability to encode nested yet flexible relationships. These are evident in group/item components like Checkbox Group, Tabs, Breadcrumbs and even Buttons. In each case, slots provide the space for an indeterminate quantity of a single, predictable type of children.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*FWEtwH8TIVuGBwpx.png" /></figure><h4>Nested slots</h4><p>Nested slot relationships can span more than two levels. An Action List group could nest specific Headers and Items, and even Group those items each with a Group Header too. Each item could warrant slots for their leading and trailing visuals. Slots are everywhere, serving levels of nested composition.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*fw2ELJZ0XRP_tV38.png" /><figcaption>Action List with a slot with two Groups, each with a slot containing three Items</figcaption></figure><h4>Slots for higher-order layout</h4><p>Slots can apply conceptually upward through layers of reusable components to compose an entire page. You could nest a Checkbox Group in an Accordion slot. You could stack Accordions in the left column slot of a reusable Page row layout component. You could assemble multiple Page Rows in a reusable Product Category layout pattern.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*HMg_e0lEbf8hfq9G.png" /><figcaption>Nested layers of reusable components, from low-level Accordions with Checkbox Groups to higher-order page rows and layout patterns nested in a page template</figcaption></figure><p>That layout hat pattern, or layout component, or increasingly smaller and customized layouts and components could be included in the Body slot of a Page component. Components with slots from the Page down afford an opportunity to position layout rules, structure, and visual styling at many reusable, independently managed levels.</p><p>Time to say goodbye to countless designers detaching instances and putting in tremendous solo efforts to scaffold, build and maintain higher-order layout.</p><h3>Architecture</h3><h4>Properties</h4><p>Architecting slots in a UI component includes specifying properties like:</p><ul><li><strong>Name</strong>, for both general “default” slots flowing children as well as specific, named slots in areas like header, footer, actions or leading visuals</li><li><strong>Description</strong>, whether guidance displayed to component users and/or spec data formalizing other properties</li><li><strong>Default value</strong> that can be a single nested instance or a deep, complicated composition to serve as a starting point and possible fallback</li><li><strong>Preferred</strong> or <strong>permitted children</strong> by both type and quantity, such as only Checkbox Items in a Checkbox Group’s slot but any quantity you need</li><li><strong>Layout</strong>, such as how slot contents arrange themselves in direction, item spacing and padding relative to the containing component</li></ul><h4>Subcomponent Parts</h4><p>An increase in component slots and custom compositions within them could lead to a decrease in the need for configurable properties and a rise of more modular yet simpler <a href="https://nathanacurtis.substack.com/p/subcomponents-753ce9f6600a">subcomponents</a>.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*jVYXG9w-eeTVpPR5.png" /></figure><p>Breaking down larger components into subcomponent parts is challenging. What level(s) are better as smaller modules? At which level does each remaining configuration belong? What happens when bigger things still need to control the smaller things inside?</p><p>A Card may have reusable Title Lockup and card-specific Reviews module. It’ll be up the component user to arrange these flexible, smaller parts instead of configuring so many properties that resulted in the brittle supercomponents pursued in the past.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*RaF-RRJ4GMn2kVSX.png" /></figure><p>For a Product Card, this could mean any array of typical nested instances used in particular ways (like how to communicate discounts using a Badge) as well as primitives with conventional visual styling (like an original price, struck through).</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*HDzSDVobNHTXf9Mo.png" /><figcaption>Nested instances and styled primitives used consistently for specific intents</figcaption></figure><h4>Ready-made examples</h4><p>Equally challenging is how to equip designers and developers to put pieces together faster. With greater composition comes the need for more examples. Not just pictures, but the actual parts in ready-made examples that both express what’s possible and easily get you most of the way there.</p><p>Systems must manage examples as an additional output to enable efficiency and experimentation. Ready-made examples are neither guidance docs nor component assets; instead, these scaffolded starting points represent a distinct deliverable of both designers and developers.</p><h4>Key challenges</h4><p>Slots architected well and used effectively will improve flexibility, empower designers, and significantly accelerate efficiency. Slots done wrong carry consequences: undermined consistency, avoidable work, component fragmentation, design and code debt. Thoughtful design systems must carefully add slots so as to not break the promise of a consistent, high-quality and efficiently produced experience.</p><p>Adding slots throughout a catalog raises questions per component like:</p><ul><li><strong>Depth</strong>: How low should a slot go in the component’s hierarchy of layers/nodes?</li><li><strong>Quantity</strong>: How many slots should a component have? Just a single general slot, or many named slots, or… both?</li><li><strong>Code Alignment</strong>: How strictly should slot depth, quantity and naming match between Figma and code libraries in web, iOS and Android?</li><li><strong>Layout</strong>: How difficult will designers find it to create intricate layout <em>inside</em> slots and hand off those details to developers?</li><li><strong>Styling</strong>: How much do you style a slot and what goes inside it by wrapping it, directly setting properties of it, and/or providing inherited theming into it?</li><li><strong>Permissiveness</strong>: How constrained should slots be in what and how much they include? Can they open up gradually over time without breaking how it works?</li></ul><p>Slots will ask more of today’s designers and developers.</p><p>Over the past decade, design systems accelerated more designers with less interface design skills to create better experiences more quickly. This enablement is in no small part due to the expansion of consistent, well crafted libraries of configurable components. Insert a component, configure its properties, arranged in a broader view to solve a problem.</p><p>Today, system users need more than props. They demand control and flexibility. That the predominant design tool of the moment — Figma — will natively support slots will push our systems towards that flexibility towards composition inside components. Ready, set, go!</p><p><em>Originally published at </em><a href="https://nathanacurtis.substack.com/p/slots-in-design-systems"><em>https://nathanacurtis.substack.com</em></a><em>.</em></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=f53698c2d745" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Analysis of Variants]]></title>
            <link>https://medium.com/@nathanacurtis/analysis-of-variants-9e440c30b93e?source=rss-799c7c7840a------2</link>
            <guid isPermaLink="false">https://medium.com/p/9e440c30b93e</guid>
            <category><![CDATA[ai]]></category>
            <category><![CDATA[design-systems]]></category>
            <category><![CDATA[ui-design]]></category>
            <category><![CDATA[json]]></category>
            <category><![CDATA[components]]></category>
            <dc:creator><![CDATA[Nathan Curtis]]></dc:creator>
            <pubDate>Tue, 07 Oct 2025 12:43:43 GMT</pubDate>
            <atom:updated>2025-11-02T01:53:48.657Z</atom:updated>
            <content:encoded><![CDATA[<h4>Generating component data that design systems teams need</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*oad9MxPqDWZ1ZYN31XVrEA.png" /></figure><p>For years, we’ve toiled to maximize design system quality through collaboration from design through handoff to production. Today, our processes are boosted with AI, with component design intent hopping back and forth between codebases, LLM chats and design tools.</p><p>Through this period, our systems must improve how we get design intent out of (and back into) design tools as a part of a system’s broader pipeline. Not just efficiently, but precisely. Not just to vibe, but to record and version. Not just for us, but them (cough cough, AI) too.</p><p>If we are to use <a href="https://medium.com/@nathanacurtis/components-as-data-2be178777f21">components as data</a>, <em>how </em>do we do it without losing or degrading it as data shifts back and forth across our tools? We need a model to describe components, and tools to transform and move that description.</p><p>The <a href="https://www.figma.com/community/plugin/1549454283615386215/anova">Anova plugin</a>, recently released in the Figma community, could be a part of that process. Built as a second generation the <a href="https://www.figma.com/community/plugin/1205622541257680763/specs">Specs plugin</a> engine, the plugin produces component data with a more refined and extensible model. This post describes the plugin’s intent to output <strong>components as data</strong>, the <strong>data model</strong> it follows, and key <strong>principles</strong> that drove it’s conception and shape.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*5R4zvurh3SDRhKVOLoNkVg.png" /></figure><h3>About the Anova plugin</h3><p>The Anova plugin creates a component specification in data form. In particular, the plugin conducts an “analysis of variants” to audit component composition, visual styling, and prop configurations across all variants.</p><p>The plugin name alludes to traditional statistical analysis of variance, and is a hat tip to my college education. Yet the plugin isn’t actually doing statistical analysis. Instead, it crawls a Figma asset to produce a result that’s deterministic, repeatable, succinct and comprehensive. This output unlocks myriad opportunities for design system pros, as described in <a href="https://medium.com/@nathanacurtis/components-as-data-2be178777f21">Components as Data</a>:</p><ol><li>Leverage component definitions in AI LLMs</li><li>Version component definitions over time</li><li>Analyze components across a catalog</li><li>Inspect component precision and quality</li><li>Handoff design to development</li><li>Generate documentation</li><li>Automate precise Figma asset generation (aka, the “round trip”)</li></ol><h3>Modeling the data</h3><p>The Anova plugin’s engine is a more polished and better built second generation of the <a href="https://www.figma.com/community/plugin/1205622541257680763/specs">Specs plugin</a>, which launched in 2023 and has output similar if less refined data for over a year.</p><p>The model of the plugin’s data output conforms to an <a href="https://github.com/DirectedEdges/anova/blob/main/anova.schema.json">available JSON schema</a> and can be formatted as YAML or JSON. The data includes things you expect from a spec: an anatomy of elements, props and an analysis of how structure, styles and configurations shift by variant. It also hints at things you wouldn’t expect too, like a summary of invalid variants combinations.</p><h4>Anatomy</h4><p>The anatomy data includes a straightforward list of elements by type as well as growing metadata (such as component dependencies).</p><pre>anatomy:<br>  root:<br>    type: container<br>  label:<br>    type: text<br>  icon:<br>    type: instance<br>    instanceOf: DS Icon</pre><h4>Props</h4><p>The props section summarizes properties including type, enums, defaults and other relevant prop information.</p><pre>props:<br>  label:<br>    type: string<br>    default: &quot;{Label}&quot;<br>  appearance:<br>    type: string<br>    default: critical<br>    enum:<br>      - critical<br>      - warning<br>      - success<br>      - info<br>  size:<br>    type: string<br>    default: large<br>    enum:<br>      - small<br>      - medium<br>      - large</pre><h4>Variant-by-variant analysis</h4><p>The plugin evaluates a Figma asset a variant at a time. The plugin starts wih the default variant, identifying each element of the anatomy that is present from the root component layer down through the layer hierarchy to assess layer styles, layout structure and other properties.</p><pre>default:<br>  elements:<br>    root:<br>      styles:<br>        fills: DS Color/Alert/Basic/Background filled<br>        cornerRadius: DS Shape/Border radius/Pill<br>        itemSpacing: DS Space/Item spacing/0_5x<br>        paddingLeft: DS Space/Padding/0_5x<br>        paddingRight: DS Space/Padding/0_5x<br>        paddingTop: DS Space/Padding/0_25x<br>        paddingBottom: DS Space/Padding/0_25x<br>    label:<br>      styles:<br>        fills: DS Color/Text/Primary<br>        textStyleId: Body/Large<br>      propReferences:<br>        characters:<br>          $ref: &quot;#/props/Label&quot;</pre><p>From that established default, successive variants are evaluated, compared to other variants serving as baselines, and reduced into a succinct spec across all variants.</p><pre>variants:<br>  - configuration:<br>      size: small<br>    elements:<br>      root:<br>        styles:<br>          itemSpacing: DS Space/Item spacing/0_25x<br>          paddingLeft: DS Space/Padding/0_25x<br>          paddingRight: DS Space/Padding/0_25x<br>          paddingTop: DS Space/Padding/0_125x<br>          paddingBottom: DS Space/Padding/0_125x<br>      label:<br>        styles:<br>          textStyleId: Body/Small<br>  - configuration:<br>      appearance: success<br>    elements:<br>      root:<br>        styles:<br>          fills: DS Color/Alert/Success/Element<br>      label:<br>        styles:<br>          fills: DS Color/Text/Primary Inverse</pre><p>From the resulting variants data, you can layers styles and other data based on one or more matched configurations in a manner very similar to CSS’ cascade.</p><p>For example, if this component was configured as both size:small and type:success, then the data would layer in three matches (the default then matches for size and type) to resolve as:</p><pre>elements:<br>  root:<br>    styles:<br>      fills: DS Color/Alert/Success/Element<br>      cornerRadius: DS Shape/Border radius/Pill<br>      itemSpacing: DS Space/Item spacing/0_25x<br>      paddingLeft: DS Space/Padding/0_25x<br>      paddingRight: DS Space/Padding/0_25x<br>      paddingTop: DS Space/Padding/0_125x<br>      paddingBottom: DS Space/Padding/0_125x<br>  label:<br>    styles:<br>      fills: DS Color/Text/Primary Inverse<br>      textStyleId: Body/Small    </pre><h4>Invalid variant combinations</h4><p>The invalidVariantCombinations section summarizes prop combinations that are invalid based on the Figma asset. For example, an interactive component typically cannot be disabled and hover at the same time. Depending on how you’ve built your component in Figma, those combinations can be determined and summarized.</p><pre>invalidConfigurations:<br>  - disabled: true<br>    state: hover<br>  - disabled: true<br>    state: active<br>  - disabled: true<br>    focused: true</pre><h3>Principles</h3><p>Extensibility, interoperability, validation, and portability are table stakes for any data structure. On top of that, four more principles drove decisions: determinism, completeness, succinctness, and human-readability.</p><h4>✅ Deterministic instead of stochastic</h4><p><strong>The problem:</strong> Data extracted from Figma’s Dev Mode MCP Server is impressive, but isn’t designed to produce a durable spec unless your spec is a React and Tailwind implementation. The extracted data, transformed further via LLMs, yields unpredictable results: sometimes imprecise, often incomplete, and frustratingly different run to run.</p><p>For example, I’ve observed an LLM starting with an Alert component’s appearance:success|critical|warning|info property behaving unpredictably. Over repeated runs, it renamed options (information), added options (neutral), remove options (warning) and renamed the property itself (to type or variant)! A design system can’t rely on an unstable workflow for a canonical component description.</p><pre>props:<br>  appearance:<br>    type: string<br>    default: critical<br>    enum:<br>      - critical<br>      - warning<br>      - success<br>      - info</pre><p><strong>The plugin’s approach:</strong> The plugin extracts only the raw, intentional data directly from the asset. No guessing. No machine prediction. The same input yields the same output, every time. And each time, it’s easy to compare it to past versions to affirm and commit to the differences. You designed it to be appearance:success|critical|warning|info, so you get appearance:success|critical|warning|info.</p><h4>✅ Complete instead of partial</h4><p><strong>The problem:</strong> The data derived from <a href="https://www.figma.com/community/plugin/1205622541257680763/specs">Specs Figma plugin</a> ouptut is powerful. People upload screenshots of it to LLMs and it kinda works! However, it evaluates prop effects in isolation. It doesn’t inspect every variant in depth to find every potential effect on style and structure.</p><p>For example, it’s easier to document a component’s background color when hover:true or selected:true. How about when <em>both</em> are true? How about when both are true, and the component is also set to appearance:info? Did the component change more? These interactions are rare and harder to analyze, but they shouldn’t be missed by a shallow analysis.</p><pre>variants:<br>  - configuration:<br>      hover: true<br>    elements:<br>      root:<br>        styles:<br>          backgroundColor: (a color)<br>  - configuration:<br>      hover: true<br>      selected: true<br>    elements:<br>      root:<br>        styles:<br>          backgroundColor: (a second color)<br>  - configuration:<br>      hover: true<br>      selected: true<br>      appearance: info<br>    elements:<br>      root:<br>        styles:<br>          backgroundColor: (a third color)</pre><p><strong>The plugin’s approach:</strong> The plugin can inspect every variant in-depth and then reduce what’s accumulated into a set of matches that layer into a rendered style. Instead of disjointed snapshots relying on one prop, you get the entire picture no matter the (valid) prop combination.</p><h4>✅ Succinct instead of bloated</h4><p><strong>The problem: </strong>Figma provides access to a complete picture of component assets via its REST API. Unfortunately, its variant architecture is very bloated. To express a disabled:true state for a component like Text Input, could mean 24 more variants each with ~15 layers per variant each with ~40 properties.</p><p>Ask Figma’s REST API for component information, and you’ll get 14,400 additional properties in hierarchical data! 99.99% of that data tells you nothing new, but it needs to be processed and examined to make sure. All because a designer expressed a simple intent of “When disabled, set the root layer’s opacity to 0.36.”</p><pre>variants:<br>  - configuration:<br>      disabled: true<br>    elements:<br>      root:<br>        styles:<br>          opacity: 0.36</pre><p><strong>The plugin’s approach:</strong> Instead of duplicating entire variants, it records only the difference: <em>what changes when disabled</em>. That’s compact, lossless, and easier to maintain.</p><h4>✅ Human-readable instead of gobbledygook</h4><p><strong>The problem:</strong> Even if you get deterministic and complete data, it’s usually encoded in ways that only a machine can love — long and noisy JSON dumps with no obvious hierarchy of what matters.</p><pre>title: {component name}<br>anatomy:<br>  {element name}:<br>     type: {type}<br>     instanceOf: {main component name}<br>  ...<br>props:<br>  {prop name}:<br>     type: {type}<br>     default: {default}<br>  ...<br>default:<br>  elements:<br>    {element name}:<br>       styles:<br>         {style name}: {value}<br>variants:<br>  - configuration:<br>      {prop name}: {value}<br>    elements:<br>      {element name}:<br>        styles:<br>          {style name}: {value}</pre><p><strong>The plugin’s approach:</strong> Outputs are structured so a human can scan them. Defaults come first. Overrides are grouped by condition. Names are consistent. Reading the data feels like reading a spec.</p><p>I’ll acknowledge right now that designers aren’t in love with reading a spec as data. It does require onboarding (a few good docs rich with examples seem to be enough). Yet, I’ve been pleasantly surprised at how quickly specs-as-data sprout up next to assets. It’s value becomes even clearer when Figma comments start showing up above the spec rather than asset to get things done.</p><p>Ideally, if Anova data proves valuable to the community, the plugin could go in many directions. At the forefront, I’d expect to integrate this new processing engine into the Specs plugin (or vice versa, overlaying the spec outputs onto Anova) in the future, consolidating the two.</p><p>I also can’t imagine this living long without strong, direct integration with other tools. This suggests that MCP server and/or Figma REST API integration could prove useful directions to pursue. Yet, for now, it’s certainly useful enough to share, get feedback, and grow.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=9e440c30b93e" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Components as Data]]></title>
            <link>https://medium.com/@nathanacurtis/components-as-data-2be178777f21?source=rss-799c7c7840a------2</link>
            <guid isPermaLink="false">https://medium.com/p/2be178777f21</guid>
            <category><![CDATA[components]]></category>
            <category><![CDATA[json]]></category>
            <category><![CDATA[design-systems]]></category>
            <category><![CDATA[ai-tools]]></category>
            <category><![CDATA[figma]]></category>
            <dc:creator><![CDATA[Nathan Curtis]]></dc:creator>
            <pubDate>Tue, 23 Sep 2025 17:00:51 GMT</pubDate>
            <atom:updated>2025-09-27T00:41:50.460Z</atom:updated>
            <content:encoded><![CDATA[<h4>How to define components independent of platforms to scale a system’s impact</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*IieL7QAXi9y1uNSifF5Z4Q.png" /></figure><p>Nearly a decade ago, I wrote of my passions stirred by crafting <a href="https://medium.com/eightshapes-llc/tokens-in-design-systems-25dd82d58421">tokens in design systems</a>. Those (sub?)atomic, minimal decisions were invigorating as we put structure to visual choices as data to spread across a system. The muse of that story? The Pill component.</p><p>This year, my team initiated a catalog-wide component-by-component refactor. This time, again, we started with the Pill component. It’s as if the Pill offers us a choice: see the truth of our explicit decisions, or stay in an illusion that manual handoffs and divergent tools carry our intentions into the work of others without failure. Ok, maybe that’s a bit heavy handed. Enough with the heady metaphors.</p><p>Throughout the project, my role is to architect how we record component decisions as structured data independent of any platform, including Figma. I’m responsible for ensuring consistent, scalable, and interoperable components that flow into and from Figma and a pipeline of generated, cross-platform code. It’s delightfully complicated. Tokens feels quaint by comparison.</p><p>This slot prop. That container element. Both are familiar and feel simple. Yet conveying visibility and children from one to the other, binding and unbinding references across an array of variants? That hits different. Chats evoke nullability. We’re overdosing on overloading. Figma’s threshold of what you can express and how you express it feels a barrier. Huh, hold up. What’s … nullability?</p><p>These days, I live much more in a text editor than a UI to plan, design, validate and deliver components as data with AI at my side. In this post, I provide a glimpse of components expressed as data and follow with why treating using data matters across a component’s life cycle in the era of AI.</p><h3>Defining Components in Data</h3><p>A component definition in data is a structured description of a UI component expressed in a neutral format (like YAML or JSON) instead of hard-coded in design tools or platform-specific code. Data breaks a component into parts like an anatomy of elements, props, styles, layout and how each varies when configurations change.</p><h4>Anatomy</h4><p>A component’s elements of various types (like container) organized into a hierarchy comprise its anatomy. Element concepts correspond to platform-specific constructs, such as a Figma FRAME layer or HTML DIV, SPAN, or SECTION.</p><pre>anatomy:<br>  root:<br>    type: container<br>  content:<br>    type: container<br>  leadingVisual:<br>    type: slot<br>  label:<br>    type: text</pre><h4>Props</h4><p>Props to configure a component’s behavior and appearance and can be various data types, such as booleans, strings, enums or slots.</p><pre>props:<br>  disabled:<br>    type: boolean<br>    default: false<br>  selected:<br>    type: boolean<br>    default: false<br>  state:<br>    type: string<br>    default: rest<br>    enum:<br>      - rest<br>      - hover<br>      - active<br>  leadingVisual:<br>    type: slot<br>    nullable: true<br>    oneOf:<br>      - icon<br>      - avatar<br>      - image<br>  label:<br>    type: string<br>    default: Label<br>  accessibilityLabel:<br>    type: string</pre><p>Within a seemingly simple prop list, subtleties complicate conversations for designers expressing ideas in Figma.</p><ul><li>Aren’t disabled and selected technically enumerated VARIANT props with enumerated values for true and false? <em>Yes.</em></li><li>Is leadingVisual an INSTANCE_SWAP prop, and don’t we need another BOOLEAN prop to control its visibility? <em>Yes (that’s how slots work today in Figma) and yes (the need for a </em><em>BOOLEAN relates to the </em><em>nullable property).</em></li><li>How do we even represent accessibility labels? <em>Expose a </em><em>TEXT prop in the Props panel but not visually. There’s a trick for that.</em></li></ul><p>Those conversations highlight the act of translating a component definition to a platform, in this case Figma.</p><h4>Styles</h4><p>Styling is directly expressed in data in a human-readable way, too.</p><pre>default:<br>  elements:<br>    root:<br>      children:<br>        - content<br>      styles:<br>        height: foundations/size/8x<br>        backgroundColor: foundations/color/surface/primary<br>        borderColor: foundations/color/outline/primary<br>        borderWeight: foundations/size/0_25x<br>        verticalAlign: CENTER<br>        itemSpacing: 4<br>        paddingLeft: foundations/spacing/4x<br>        paddingRight: foundations/spacing/4x<br>        layoutDirection: HORIZONTAL<br>        layoutSizingHorizontal: HUG<br>        cornerRadius: foundations/shape/circle</pre><p>Here, a root element (in Figma parlance, the COMPONENT or INSTANCE layer) has a range of default styles that mix <strong>raw</strong> values (4, HUG) and <strong>token </strong>references (foundations/size/8x).</p><p>Yet, the element also omits presumed <strong>initial values </strong>(paddingTop: 0) and has <strong>implied values</strong> too (layoutSizingVertical must be FIXED because height is set). Even within styling alone, our team’s vocabulary must level up to describe concepts we’ve implicitly used before but never named.</p><h4>Variants</h4><p>Things get more interesting as prop configurations apply. In this simple example, a Pill&#39;s hover state changing the root’s background color.</p><pre>variants:<br>  - configuration:<br>      state: hover<br>    elements:<br>      root:<br>        styles:<br>          backgroundColor: foundations/color/interactive/hover</pre><p>Yet, variants can get complicated quickly, with two or more props interacting in a configuration to impact many elements at a time.</p><h4>Broad, Detailed and yet Incomplete</h4><p>When put together, these models combine to form a fuller picture of a component, in a structure like:</p><pre>{component name}:<br>  anatomy:<br>    {element name}<br>    ...<br>  props:<br>    {property name}<br>    ...<br>  default:<br>    {element name}:<br>      styles:<br>        {style name}: {style value}<br>    ...<br>  variants:<br>    - configuration:<br>        {prop name}: {nondefault prop value}<br>        ...<br>      elements:<br>        {element name}:<br>          styles:<br>            {style name}: {style value}<br>     ...</pre><p>Simple components (Divider 👀) may only need 20–50 lines of data. On the other hand, sophisticated core component like Alert, Text Input or Card often require 500 lines or more.</p><p>Yet, even with over 1,000 lines of data, a picture could remain incomplete, lacking considerations like:</p><ul><li><strong>Binding</strong> configurations to an element’s values</li><li><strong>Motion</strong> and nontrivial <strong>Interaction</strong> that designers <em>could</em> express in Figma (using <a href="https://www.figma.com/plugin-docs/api/properties/nodes-reactions/">reactions</a>) but rarely do.</li><li><strong>Accessibility </strong>that Figma lacks the ability to express in a structured way, although plugins help with that.</li><li><strong>Non-visual configurations</strong>, such as an Alert&#39;s autohide duration or TextArea&#39;s maxRows that a designer could decide for handoff.</li></ul><p>Varyingly, teams expand the shape of data to include more and more of these considerations through a combination of Figma capabilities, plugins and team-specific conventions. That said, teams continue to pair component data with a separate, unstructured document to “handoff” a complete component definition. For now, anyway.</p><h4>A component catalog</h4><p>Teams produce, store and version data for an entire component catalog in a database or (usually, in my experience) as a JSON or YAML file.</p><pre>components:<br>  alert:<br>    ...<br>  banner:<br>    ...<br>  breadcrumb:<br>    ...<br>  button:<br>    ...<br>  card:<br>    ...<br>  icon:<br>    ...<br>  iconButton:<br>    ...<br>  pill:<br>    ...<br>  tabs:<br>    ...<br>  textArea:<br>    ...<br>  textInput:<br>    ...</pre><p>A core.yaml file for a design system’s core components may include 30–50 components (and their subcomponents, too) and be 10,000s lines long. Want to store a component per file? Sure, tool it up that way. Want to separate concerns of component API from theming via tokens? Sure, as you will. You decide.</p><h3>The Impact of Components as Data</h3><p>Definining components in data form rather than passing unstructured artifacts between collaborators unlocks many opportunities across a component’s life cycle.</p><h4>Leverage components in LLMs</h4><p>AI is everywhere, and it favors structured data. So express components that way. An LLM can answer questions about how the component works, compare it to implementations, and propose improvements via prompts.</p><p>Sure, you could leverage Figma’s Dev Mode MCP Server. But beware: that’s a stochastic, incomplete, and imprecise component description biased towards one platform (like React) and framework (like Tailwind). More formally approaching component data makes component knowledge reusable, scalable, and consistently interpretable across contexts.</p><h4>Inspect component precision and quality</h4><p>With countless design decisions woven into our Figma assets, it can be hard to wire up every detail without errors. Data exposes errant design decisions, making components easier to audit.</p><pre>variants:<br>  - configuration:<br>      state: hover<br>    elements:<br>      root:<br>        styles:<br>          backgroundColor: #045bbc  ## Seriously? Token please!</pre><p>If I had a nickel for every time I detected a raw value in a stray variant when a token is needed (like the hover backgroundColor above), I’d be rich. Seeing components as data make inspection straightforward and precise, raising the quality of both design and code implementations.</p><h4>Generate components across code platforms</h4><p>Instead of hard-coded spec documents or screenshots, developers receive machine-readable definitions. These definitions of structure, styles, and prop behaviors can be used to scaffold code directly. This reduces or even eliminates back-and-forth to ensures product matches design intent.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*mnrbQr8uzCYeaoR6B6ctNw.png" /><figcaption>Workflow translating Figma assets into data as machine-readable inputs to generate code</figcaption></figure><h4>Generate Figma assets, too</h4><p>And this isn’t just for code implementations. Teams generate Figma assets too. Soon to be gone are the tedious, manual hours to produce countless variants.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*6jctXAVAkwu0pxNv0t8t-w.png" /><figcaption>Starting with data and treating Figma assets as output rather than input</figcaption></figure><p>Instead, Figma component assets can be automated from a component definition in data that I plan in an hour and iterate with teammates for another. While we may go back and forth between Figma and data to refine and experiment, designers are increasingly focusing on architecture more and pointing and clicking and dragging and setting values in the Figma UI less.</p><h4>Generate examples and documentation</h4><p>The same data can be used to automatically create component reference pages, usage guidelines, and visual previews. This removes the need for manually maintaining documentation that quickly falls out of sync. As components evolve, the documentation updates with them, staying consistent and trustworthy.</p><h4>Version component definitions over time</h4><p>Component definitions as structured data be tracked in version control systems like Git. This allows teams to see how components evolve, compare differences, and roll back if necessary. It creates a durable record of a component’s lifecycle, just like other source code.</p><h4>Analyze components across a catalog</h4><p>With many components defined in the same format, you can prompt AI to find patterns and gaps like:</p><blockquote>How and how often is the <em>foundations/color/surface/secondary</em> token used?<br>Are enumerated options for <em>state</em> handled consistently?<br>Are <em>accessibilityLabels</em> applied across all potential cases?</blockquote><p>This enables data-driven insights into a system’s health and coverage.</p><p>As an architect at heart, I’m so excited that my work has evolved into increasingly formal structures to describe UI components. This era of AI demands that we shift and evolve how design systems work. It’s difficult to imagine returning to a time when I architected components only in a visual tool like Figma. Instead, my mind races faster seeing those impassioned decisions as data, moving through the connections we create.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=2be178777f21" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Purposeful vs Aesthetic Naming]]></title>
            <link>https://medium.com/@nathanacurtis/purposeful-vs-aesthetic-naming-4390870ef463?source=rss-799c7c7840a------2</link>
            <guid isPermaLink="false">https://medium.com/p/4390870ef463</guid>
            <dc:creator><![CDATA[Nathan Curtis]]></dc:creator>
            <pubDate>Mon, 23 Jun 2025 12:46:56 GMT</pubDate>
            <atom:updated>2025-06-23T19:22:49.103Z</atom:updated>
            <content:encoded><![CDATA[<h4>Favoring semantics isn’t always ideal, and blending both is worse</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*cAOQVFeHogVRamtgKNe-4A.png" /><figcaption>What is orange, anyway?</figcaption></figure><p>Our design system effort was gaining momentum, and we’d reached a crossroads I’d seen coming a mile away.</p><p>“So, your main, most important brand color is red?” I asked.</p><p>“Yes,” the collaborator replied calmly.</p><p>“Then, what color will we use for errors?”</p><p>“Red,” they answered decisively.</p><p>“The <em>same</em> red?”</p><p>“Yes.”</p><p>“Got it. In mockups everywhere, I also see <em>that </em>red used to distinguish a sale price. So, we communicate things are on sale with … <em>that </em>red too?”</p><p>“Yes.”</p><p>“Ok, to be sure. Imagine I’m designing for a product that’s on sale, and the user configures an invalid quantity. In tight proximity, the UI will signal three things (brand, sale, error) all with the <em>same </em>red?”</p><p>“Yes.”</p><p>This tension between visual aesthetics and purposeful intent appears throughout interface design — in tokens, composition, and, as this article explores, component props and options.</p><p>In this post, I’ll contrast <strong>purposeful vs aesthetic naming</strong> schemes for component properties, describe <strong>hybrid approaches</strong> that are best avoided, and conclude with <strong>related techniques</strong> that are sometimes brought to bear.</p><h3>Comparing purposeful and aesthetic naming</h3><p>Consider a Badge component that can appear in different colors : red, green, blue, yellow, white, and gray. How should this visual variation be controlled? Typically, you create a set of options based on either purpose or aesthetics.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Wv8S7fxhgaxWTHziIoRIDQ.png" /><figcaption>A Badge component of various colors</figcaption></figure><h4>Purposeful options</h4><p>Purposeful props use specific, self-documenting values that convey narrow meaning and intent. For example, a Badge may be offer choices like error, success, info, warning and new.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*fR6kmhHZ4aA8YBDLhnH43A.png" /><figcaption>Purposeful options</figcaption></figure><p>Purposeful naming focuses on <strong>what role a component serves</strong>, which approach offers several compelling advantages:</p><ol><li><strong>Self-documenting intent</strong>: When you see severity=&quot;error&quot;, you immediately understand component purpose without needing to reference docs or examples. The prop tells a clear story of intent.</li><li><strong>Consistency across contexts</strong>: Purpose-driven props ensure that all “error” states look and behave consistently across components to create a more cohesive user experience.</li><li><strong>Durability across redesigns</strong>: Visual treatments change, but semantic meaning tends to remain stable. A component using variant=&quot;warning&quot; will survive brand refreshes better than one tied to color=&quot;yellow&quot;.</li><li><strong>Built-in accessibility</strong>: Purpose-driven naming naturally supports accessibility considerations, such as screen readers announcing information like “error status” rather than just “red badge.”</li></ol><h4>Aesthetic options</h4><p>Aesthetic-driven options use visual terms like color (red) or scale (1X, …) that lack semantic intent.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*8_iIJhW_Cy9kuq-5yZTeFQ.png" /><figcaption>Aesthetic options</figcaption></figure><p>Aesthetic naming isn’t wrong — it serves different needs and contexts like:</p><ol><li><strong>Visual control and flexibility</strong>: Designers may need flexible control over appearance that doesn’t map neatly to semantics. Sometimes you need a light gray divider, and forcing semantic meaning feels artificial.</li><li><strong>Decorative use</strong>: Some components serve purely visual roles where structural meaning is secondary, irrelevant or not yet defined.</li><li><strong>Migration and legacy support</strong>: When retrofitting design systems onto existing products, aesthetic props can ease the transition by matching appearances that already exist.</li><li><strong>Coverage over semantic gaps</strong>: Sometimes semantics simply don’t exist yet, or the use case is too specific to warrant a semantic abstraction.</li></ol><h4>Comparative examples across visual properties</h4><p>This choice of between purpose versus aesthetic structures arises often across components for characteristics beyond just color, such as varying:</p><ul><li><strong>Text input</strong>’s border weight to create more or less minimal look</li><li><strong>Card</strong>’s shadow strength to create a raised or overlay appearance</li><li><strong>Text</strong>’s font attributes to imply text role, hierarchy and structure</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/866/1*8n6T45PiRYZAhTpzZFjL3g.png" /><figcaption>Component property examples comparing purposeful vs aesthetic options</figcaption></figure><p>In addition, the choice may vary by component, and that’s ok. For example, a Badge component is more atomic and require more visual variety (orange! purple!) and flexible use. This suggests that an aesthetic naming system is preferred. On the other hand, an Alert component is more composed, has more limited options, and the need to use it flexibly is far more limited. As a result, Alerts almost always leverage purposeful variant names.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*uZItas-8CHvB-oQerBGWig.png" /><figcaption>Different components may result in different schemes</figcaption></figure><h3>Blending approaches</h3><p>When teams encounter the limitations of pure purpose or pure aesthetics, they sometimes stray towards blending both approaches into a single component property. Two common but problematic patterns — <strong>Purpose-first </strong>and <strong>Hybrid</strong> — are generally best avoided.</p><h4>Purpose-first</h4><p>Purpose-first options follow purposeful options (error, success, warning) with aesthetic fallbacks (white, black, light-gray) for cases lacking clear semantic meaning.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*BYMQPDYiYrpDsMd9iMPk7A.png" /><figcaption>Purpose-first options</figcaption></figure><p><strong>Benefits:</strong></p><ul><li>Guides decision-making with clear hierarchy</li><li>Covers gaps where semantics don’t apply</li><li>Easier to document than forcing semantics everywhere</li></ul><p><strong>Drawbacks:</strong></p><ul><li>Increases cognitive load with mixed mental models</li><li>Creates ambiguous boundaries between “purposeful” and “aesthetic”</li><li>Unclear extensibility as new options are needed</li></ul><p>Consider purpose-first enumerations with particular caution, generally avoiding them if possible.</p><h4>A hybrid trap</h4><p>The most problematic approach combines <strong>all</strong> purposeful and aesthetic options into one massive enum: variant=&quot;error&quot; | &quot;success&quot; | &quot;red&quot; | &quot;green&quot; | &quot;white&quot; | &quot;black&quot; | &quot;light-gray&quot; | &quot;dark-gray&quot;.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*gFIv7bP71atS6VvHQ7UwSA.png" /><figcaption>Hybrid enumerated options, where both Error and Red options result in the same visual outcome</figcaption></figure><p>This leads to:</p><ul><li><strong>Cognitive paralysis</strong> from too many similar options</li><li><strong>Maintenance debt</strong> as the option list grows unwieldy</li><li><strong>Fragmented consistency</strong> that use different values for the same case</li><li><strong>Accessibility confusion</strong> when semantic and aesthetic values conflict</li></ul><p>A system that tries to be both flexible and meaningful may sound ideal — but in practice, it’s not. Don’t go there.</p><h3>Additional techniques</h3><p>When confronting the tradeoffs of purposeful and aesthetic naming, teams also often debate the merits of escape hatches, migration-oriented deprecation, and separating the two into multiple properties.</p><h4>Escape hatches</h4><p><strong>Escape hatches</strong> provide semantic options as the primary interface, supplemented by style override props for edge cases. For example, offering an interface to customize the styling of relevant properties.</p><pre>interface BadgeProps {<br>  variant: &#39;error&#39; | &#39;success&#39; | &#39;warning&#39; | &#39;info&#39;;<br>  customStyles?: {<br>    backgroundColor?: string;<br>    textColor?: string;<br>  };<br>}</pre><p>This isn’t for the faint of heart (that is, design system professionals wanting firm control to limit uncontrollable designs). The model of exposing such overrides varies by team, whether it’s documented for everyone or a “back door” few know about. Regardless, escape hatches are a technique design systems apply make the common configurable and yet the uncommon visually composable.</p><h4>Migration-oriented deprecation</h4><p>When migrating from one system generation to another, <strong>deprecation</strong> can introduce semantic options while sustaining aesthetic ones with the intention to phase them out later.</p><pre>interface BadgeProps {<br>  variant: &#39;error&#39; | &#39;success&#39; | &#39;warning&#39; | &#39;info&#39;;<br>  /** @deprecated Use severity prop instead */<br>  color?: &#39;red&#39; | &#39;green&#39; | &#39;yellow&#39; | &#39;blue&#39;;<br>}</pre><p>Exercise this with caution. The migration is eased for sure, but there’s dangling properties spread throughout production code. It’s just kicking the can down the road — and eventually, you’ll have to clean up the mess.</p><h4>Multiple properties</h4><p>That said, never create competing props that could conflict, such as severity and color that require you to identify which takes precedence. In this case, it’d probably be color, which results in an interface where you can specify variant of success and a purple color, and … purple wins?</p><pre>// DON&#39;T DO THIS<br>interface BadgeProps {<br>  variant?: &#39;error&#39; | &#39;success&#39;;<br>  color?: &#39;red&#39; | &#39;green&#39;;  // What if both are specified?<br>}</pre><p>Separating the <em>same concern</em> into multiple props is a terrible idea. Not only do the properties interact, but the component’s property shape is muddled. Don’t bother, please.</p><p>In general, I favor purpose over aesthetics because design systems use meaning to result in more consistent, accessible, and maintainable experiences. However, that principle doesn’t always mean purposeful is better, and I’ve worked with teams that justifiably used aesthetic naming schemes for some components. Don’t force artificial semantic meaning where none exists — sometimes a gray divider is just a gray divider or… just a divider.</p><p>Aesthetic props offer short-term flexibility, but often lead to long-term debt. Semantic investments, by contrast, tend to pay off as systems grow. Whatever approach you choose, be consistent. The best component API is one that guides users toward good decisions while remaining flexible enough to handle legitimate edge cases.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=4390870ef463" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[The Sorry State of States]]></title>
            <link>https://medium.com/@nathanacurtis/the-sorry-state-of-states-89dd4668737e?source=rss-799c7c7840a------2</link>
            <guid isPermaLink="false">https://medium.com/p/89dd4668737e</guid>
            <category><![CDATA[user-interface-design]]></category>
            <category><![CDATA[figma-plugin]]></category>
            <category><![CDATA[components]]></category>
            <category><![CDATA[figma]]></category>
            <category><![CDATA[design-systems]]></category>
            <dc:creator><![CDATA[Nathan Curtis]]></dc:creator>
            <pubDate>Tue, 03 Dec 2024 19:00:17 GMT</pubDate>
            <atom:updated>2024-12-04T12:21:50.669Z</atom:updated>
            <content:encoded><![CDATA[<h4>Today’s Figma assets show design could align better with code</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*PWZH4UmVTFnGz7vWBh18zQ.png" /></figure><p>A few years back, I wrote <a href="https://medium.com/eightshapes-llc/crafting-ui-component-api-together-81946d140371">Crafting component API together</a>. Figma had become and remains the hegemonic design tool, and its capabilities for shaping components with a useful and usable API continue to strengthen. Libraries have taken deeper hold.</p><p>Yet, even the best system designers are missing opportunities to mimic how code actually works. No clearer is this than in the sorry state of the state prop of many interactive elements like text input, text area, dropdown, checkbox and radio button.</p><p>This post explores how design systems architect states in Figma assets inconsistent with how code works. The text input offers lessons about how to model props, from <strong>partial sets</strong> of option combinations and <strong>interdependent props</strong> to <strong>booleans versus enumerated</strong> options and just how far we should go — or not go — to purely model Figma assets.</p><h3>The State of States Today</h3><p>States is a generic term that designers and developers apply to a wide swath of situations. <a href="http://in/ericwbailey">Eric Bailey</a>’s lengthy list of <a href="https://ericwbailey.design/published/all-the-user-facing-states/">all the user facing states</a> highlights this well. There’s 38 in all, from rest, hover and active through disabled, readonly, selected, deselected to less common considerations like loading, ghost origin, and dirty.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/484/1*kaOZS9Zi-oPM-MVh80C9cA.png" /><figcaption>Excerpt of example states from Eric Bailey’s <a href="https://ericwbailey.design/published/all-the-user-facing-states/">All the user-facing states</a></figcaption></figure><p>Curious Chrome inspectors could select a text input, right click to select Inspect, and find a bevy of element states (:active, :hover, :focus, … ) including a robust set of HTML <a href="https://developer.mozilla.org/en-US/docs/Learn/Forms/Form_validation">form validation</a> hooks (:disabled, :valid, :invalid, … ) that front end developers can take advantage of with CSS combinations.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/516/1*O_WvqIJHvQGrwzc65kWyNw.png" /><figcaption>Chrome inspector’s states of a text input, including specific element states</figcaption></figure><p>Trouble is, the term states is exceedingly generic. All possible states aren’t alternatives. Instead, available states are a mishmash of interdependent concerns often with logical relationships and used in combination.</p><p>Yet when used in design critiques discussions, design specification section headers, and particularly in Figma asset properties: state becomes a glorious catch-all of insufficiently modeled ideas.</p><figure><img alt="Visual designs of rest, hover and focus states of a text input" src="https://cdn-images-1.medium.com/max/1024/1*98isutcS69qd0O4-5k36Sw.png" /></figure><p>For a text input, of course we’ll show hover and active. Given that, we’ll pause and ponder whether to call the first one base (don’t), default (that’s ok), enabled or initial (better) or rest (best?). Nah, let’s go with resting I guess. Our impulse is to move on.</p><figure><img alt="Visual designs of disabled, error and success states of a text input" src="https://cdn-images-1.medium.com/max/1024/1*CNNd7X86RLFTSljVn28tVA.png" /></figure><p>Then complications arise. What about disabled? Of course, that’s needed. And readonly? Oh, I’d not thought of that. Obviously error state is a must. The states set grows gradually, stabilizing when we’re satisfied we’ve captured enough. Designers can be forgiven for not solving for every single “Eric Bailey State.” I never have. That list is crazy long!</p><h4>States Today in Figma Assets</h4><p>I examined the Text input / Input / etc Figma components published on the Figma community made by the following design systems:</p><ul><li><a href="https://www.figma.com/community/file/1035203688168086460/material-3-design-kit">Material 3 Design Kit</a></li><li><a href="https://www.figma.com/community/file/912837788133317724/material-ui-for-figma-and-mui-x">Material UI for Figma (and MUI X)</a></li><li>Salesforce <a href="https://www.figma.com/community/file/854593583696357016/components-for-web-lightning-design-system-v1">Components for Web | Lightning Design System v1</a></li><li>Github <a href="https://www.figma.com/community/file/854767373644076713/primer-web">Primer Web</a></li><li>IBM <a href="https://www.figma.com/community/file/1157761560874207208/v11-carbon-design-system">Carbon Design System</a></li><li>Atlassian <a href="https://www.figma.com/community/file/1182078880306369227/ads-components">ADS Components</a></li><li>Oracle <a href="https://www.figma.com/community/file/1425260295705487251/rds-toolkit-24c">Redwood</a></li><li>Newskit <a href="https://www.figma.com/community/file/1225806088244139801/newskit-component-library-and-theme-v5-0">Component Library</a></li><li>Shopify <a href="https://www.figma.com/community/file/1293611962331823010/polaris-components">Polaris Components</a></li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*JTO-FfRp8J9UE0SBs-E-5g.png" /><figcaption>Text input Figma components from Atlassian, Github and Shopify, normalized and simplified to include only properties relevant for states to enable comparison</figcaption></figure><p>state property patterns matched what I observe in teams I consult with:</p><ul><li><strong>Hover</strong>: Six of ten support a state:hover (or state:hovered) option.</li><li><strong>Active</strong>: Two support a state:active option.</li><li><strong>Focus</strong>: Eight of ten support state:focus and none offered focus as a separate boolean property.</li><li><strong>Disabled</strong>: Nine of ten support state:disabled and only one (Atlassian) distinguished isDisabled as a separate boolean property.</li><li><strong>Read only</strong>: Six of ten support state:readonly, while none offered readonly as a boolean property.</li><li><strong>Error</strong> and <strong>Success</strong>: Eight of ten support an state:error (or similarly named validation) option, while one (Atlassian) offered error as a separate boolean property.</li></ul><p>Components occasionally included other state options like warning, skeleton, and typing. One even included filled, which drifts towards the adjacent state challenge of value and placeholder properties not covered here.</p><p>No Figma assets supported plausible state combinations like readonly + focus or hover + error.</p><h4>States Today in Code Libraries</h4><p>A similar review of Text input component code from those libraries yields a different prevailing model.</p><ul><li><strong>Hover</strong> and <strong>Active</strong>: Most code libraries implement these implicitly as states that respond to user interaction.</li><li><strong>Disabled </strong>and<strong> Read only</strong>: Nearly every code library implements these props, enough to consider both props as conventional.</li><li><strong>Error </strong>and <strong>Success</strong>: Many code libraries implement an error (or inInvalid, hasError or similar) boolean prop to present an error display. GitHub Primer expands from a binary to enumerated validationStatus prop to distinguish error from success. Some code libraries implement an error prop for error text.</li></ul><p>Shopify Polaris’ React component implement <a href="https://www.typescriptlang.org/docs/handbook/interfaces.html">Typescript interfaces</a> for disabled and readonly suggesting that an intentional convention across components. This library also implements a forceable focused.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*ksYSRaBl6r5Y9gq3iFuiVw.png" /><figcaption>Comparing how assets work today versus how they’d work if aligned with code</figcaption></figure><h4>So design and code are different. So what?</h4><p>The evidence is clear. Beyond interactive states like hover and active, Figma assets and code components offer distinct API signatures. Actually, let’s be more precise: design <em>assets</em> <em>published for reuse by product designers</em> are different from code assets that product developers use.</p><p>It could be that the design solution handed off by the system designer to a system developer is perfectly consistent with what happened in code. Nah. My experience suggests otherwise. Design iterations and specifications (often automated with the <a href="https://www.figma.com/community/plugin/1205622541257680763/eightshapes-specs">EightShapes Specs plugin</a>) almost always reveal the same “States as kitchen sink” approach. Why should we care?</p><h4>Corrosive impacts on efficiency, usability and satisfaction</h4><p>At a minimum, most designers are aware of the common pitfalls of imprecise and/or incomplete design delivery. This leads to challenges like:</p><ol><li><strong>Handoff friction</strong> as product designers deliver to product developers using published Figma assets that use different models from code.</li><li><strong>Poorly organized props</strong> in Figma assets that are harder to use, littering one or a few props with various choices that are actually independent.</li><li><strong>Continued distrust</strong> <strong>and disrespect</strong> of developers seeing designers as less or ill-equipped to model component props effectively.</li></ol><p>That last one hurts, perpetuating an at times justified “don’t touch my stuff” attitude that some developers persist have when instead we could be working to <a href="https://medium.com/eightshapes-llc/crafting-ui-component-api-together-81946d140371">craft component API, together</a>. That’s a subject for another day.</p><h4>Limiting impacts on automation</h4><p>Less visible to some but far more important to many of my current collaborators are the negative impacts to taking advantage of Figma’s API to automate and cleanse increasing areas of a system’s surface. Poorly modeled properties can:</p><ol><li><strong>Limit automation</strong> opportunities to audit and report on alignment across design and code libraries.</li><li><strong>Limit the ability to use assets as data</strong> to inform, serve as a source of truth, or even automate code development.</li><li><strong>Increase costs of mapping</strong> complicated (and brittle?) transformations in tools like <a href="https://help.figma.com/hc/en-us/articles/23920389749655-Code-Connect">Figma’s Code Connect</a> that could be avoided.</li></ol><p>My belief about API alignment across libraries including design has only hardened further since I <a href="https://medium.com/eightshapes-llc/crafting-ui-component-api-together-81946d140371">wrote about it in 2021</a>. When I see so many revered design systems unnecessarily diverge from code (just like those I work on too), I want us all to do better. This particular challenge isn’t hard.</p><h3>Modeling Prop Combinations and Interactions</h3><p>So let’s dig in, step by step, to think through stateful properties and how they work. We’ll start with the cleanly combined nature of selected and state found in radio buttons and checkboxes. From there, we’ll use Text input’s disabled, readonly, and validation states to learn how properties combine and interact with one another.</p><h4>Complete sets of combination</h4><p>Some types of states combine to form a complete set of relevant combinations. For example, Checkbox and Radio button combine interactive state (rest, hover, active and focus) and selected state (not selected and selected) into eight combinations.</p><p>The following table illustrates that for every combination of state and selected, the combination exists (depicted as ✅) and could warrant a distinct visual design.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Jm05v1pIaQZ_WmFmk7lmLA.png" /><figcaption>Combination table of state versus selected</figcaption></figure><p>To Radio button states in a Figma component, one could include a state property with options for hover, active, focus and selected. However, that would omit possible combinations like selected and hover simultaneously. Those <em>could </em>be added as additional state options like hover selected, but risks sliding down the slippery slope of providing all combinations via compound option names. Better to separate concerns with distinct Figma variant properties for selected (even if it’s options are true and false, the visual design varies) and state.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*_uzdglmWmTDLQ4Dhd2PWTg.png" /><figcaption>Radio buttonwith selected as a separate prop versus as options of a state prop</figcaption></figure><p>Checkbox’s potential of a third checked state — indeterminate — results in 12 possible combinations, make the enumerated state list of compound terms less desirable. Additionally, the checked property would shift from a binary variant to one revealing enumerated options of not checked (default), indeterminate and checked.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*krjtipY6DwWKqDqg5XSQhQ.png" /><figcaption>Checkbox with selected as a separate prop versus as options of a state prop</figcaption></figure><p>To those brave enough to review Eric Bailey’s states list in detail, you may notice even more relevant considerations such as Deselected. For most teams, it’s impractical to include Deselected (having been changed from Selected) as distinct from Rest (neither selected nor interacted with).</p><h4>Partial sets of combinations</h4><p>The disabled property is different, as a variant set to true or (by default) false. Disabled controls are essentially at rest, visually distinct and hover, active and focus states are irrelevant.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*uPw26gJ3W8XZqKSR6c122w.png" /><figcaption>Combination table of state versus disabled</figcaption></figure><p>As a result, the designer has a choice: separate disabled from interactive state or include disabled as an option of state. Either choice results in a partial set of five out of eight possible combinations, so long as the Figma asset doesn’t implement disabled states not at rest.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Es0LLX4sitgAq3wHEsd9GA.png" /><figcaption>Text input with disabled as a separate prop versus as an option of a state prop</figcaption></figure><p>Would it be convenient to stuff a disabled option into the state dimension? Sure, it feels easy. Yet, that’s not how code works. Plus, collapsing disabled into state reduces the model’s clarity and meaning, and disables (pun intended) you from properly modeling other relationships, as we’ll see next.</p><h4>Interdependent properties</h4><p>The plot thickens with readonly, also conventionally a boolean property in code. Like disabled, readonly is false by default. Unlike disabled, readonly supports rest <em>and</em> focus but typically not hover and active.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*8kDC0LT6J3JOG8J12Cd2kw.png" /><figcaption>Combination table of state versus disabled and readonly</figcaption></figure><p>Additionally, disabled and readonly never occur simultaneously. When both readonly <em>and</em> disabled are set to true, disabled takes precedence and readonly is ignored, making these properties interdependent.</p><p>If a designer implements all seven valid combinations, Figma handles this case well enough. Since it takes precedence, disabled should be ordered first, followed by readonly, followed by state. Should a component user set disabled to false, the component would revert any other state to rest.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*j7RQtWABdX40Mu0eDa0ULw.png" /><figcaption>Text input with readonly as a separate prop versus as an option of a state prop</figcaption></figure><p>Could both disabled and readonly be collapsed into options of a state property? Yes, but properties combining multiple dimensions into a one property with compound names doesn’t match code and doesn’t scale well.</p><h4>Choosing enumerated or boolean props</h4><p>Error and success validation states raise more questions. Both disabled and readonly are delightfully binary, easily represented with true and false values (even if built as Figma variant properties).</p><p>Some design systems only offer error states, which raises the already familiar choice (and recommendation) to offer an error variant property one can set to false (default) or true.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*vxdc3lzsoAt5VnxZej56dQ.png" /></figure><p>The combination table below does raise interesting questions: can an input be set to both error : true and either readonly : true or disabled : true? From a purist’s perspective, yes, probably.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*5fVngudjyccTI3EkAo0vTA.png" /><figcaption>Combination table of state versus error, disabled and readonly</figcaption></figure><p>But such combinations of error (in HTML, invalid?) withdisabled or readonly carries heavier considerations like:</p><ul><li>Competing visual cues: what signals it’s in error versus disabled?</li><li>Conflicting resolution: if an input is in error, the user should be able to interact with it to resolve the issue. If it’s disabled, they cannot.</li></ul><p>These are user experience design issues rather than API design issues. Guidance may suggest avoiding the combination unless it’s necessary and intuitive to users and encourage other UI patterns instead. For the Figma component and it’s attendant communications to implementing developers, however, at least a conversation if not explicit asset is warranted to clarify what happens if both are set to true.</p><p>Properties evolve further if an input also implements a success state (often combining a green color with a checkmark icon) that’s the opposite of an error state (that could use red color and an X icon).</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*zCBj9CIXCY7ZMZWugH1bAw.png" /></figure><p>In this case, error (or, invalid) is mutually exclusive from success (or, valid), and a visualized success state is different than showing neither an error&#39;s red or success&#39;s green. Therefore, consider an enumerated validation variant property with options for none (default), error and success.</p><h4>Standalone prop versus or option of another prop</h4><p>All this time, focus has been presumed a mutually exclusive option in a set that also includes rest, hover and active. In fact, an element can be both hover+focus or active+focus simultaneously.</p><p>Should focus (true,false) be a separate property from iteractive state (rest, hover, active)?</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*4CWwfwd6_ZThgfub4MkECg.png" /><figcaption>Combination table of state versus disabled, readonly and focus</figcaption></figure><p>A designer converted to be a purist by preceding sections may be incorrectly led to further separate concerns and add a focus variant property set to false by default. That’s likely going too far.</p><p>In a practical sense, separating a focus property from a state property isn’t practically necessary, because:</p><ul><li><strong>Focus is almost always triggered client-side, not a developer’s configuration</strong>: focus, like hover, is an interactive state based on user interaction. Although some libraries offer it, most implementing developers don’t find themselves forcing focus with a prop, unlike disabled, readonly or error.</li><li><strong>Focus impacts distinct visual attributes, usually</strong>: focus typically impacts visual attributes (such as a container shadow or a showing a separate focus ring element) are distinct from those impacted by hover or active (usually, a container’s background or stroke color).</li><li><strong>Focus overrides the same visual attributes, otherwise</strong>: Even if focus impacts container stroke weight and color as hover does, once the element has focus, the weaker visual cues relevant to hover or active matter far less if at all. focus takes precendence over hover as disabled did over readonly, and there’s no relevant third, distinct appearance for focus + hover.</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/836/1*_RCGYFqIfu1e05AljV1bcA.png" /><figcaption>Hover, active, and multiple focus states grouped as a set in Chrome’s inspector</figcaption></figure><ul><li><strong>Conventionally related as a set: </strong>The three are very closely related CSS pseudo classes, presented as and usually pursued as illustrated by their presence. If we’re going to distinguish focus, might as well distinguish hover from active. While we’re at it, is it time to further distinguish focus-within? I’ve never encountered a developer coding that yet, let alone a designer solving for it. We can all aspire for greatness, someday?</li></ul><p>All but one code examples assessed lack a focused property. Only Shopify Polaris’ offered a focused property to force the focused state. I’m guessing at purpose: maybe interactions with elements slotted inside the input must force the focus state of the parent container? Additionally, Shopify Polaris’ focused property is additive to the focus interactive state triggered without applying the property.</p><p>I’m unconvinced that separating focus:true, false from an interactive state:rest, hover and active is necessary. That is, until collaboration fails (it won’t) or automation between libraries requires it (it could, someday).</p><p>Ending there is a useful illustration: the pursuit of perfect alignment — and a perfect model for configuring our design — loses steam before perfection. That three year old blog post was more than comfortable with diverging state across design and code assets.</p><p>Today, the threshold has moved towards deeper integration and stronger alignment. That’s the same journey many teams will be on over their years pursing systems. Maybe someday they’ll converge. Maybe soon.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=89dd4668737e" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Managing Design Systems with  Many Core Libraries]]></title>
            <link>https://medium.com/@nathanacurtis/managing-design-systems-that-make-many-core-libraries-28b80444865e?source=rss-799c7c7840a------2</link>
            <guid isPermaLink="false">https://medium.com/p/28b80444865e</guid>
            <category><![CDATA[native-app-development]]></category>
            <category><![CDATA[product-management]]></category>
            <category><![CDATA[figma]]></category>
            <category><![CDATA[design-systems]]></category>
            <category><![CDATA[components]]></category>
            <dc:creator><![CDATA[Nathan Curtis]]></dc:creator>
            <pubDate>Mon, 28 Oct 2024 15:47:56 GMT</pubDate>
            <atom:updated>2024-10-28T21:40:13.426Z</atom:updated>
            <content:encoded><![CDATA[<h3>Managing Design Systems with Many Core Libraries</h3><h4>How you align design and engineering and synchronize releases depends on the frameworks, platforms and teams involved</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Q06rPUwx7x715G7mObjYXA.png" /></figure><p>Design systems come in many shapes and sizes, especially evident by how core catalogs of foundations and UI components are implemented across more than one code library.</p><p>As a system scales to meet expanding needs, it often grows to offer parallel component code libraries for web, iOS and Android along with commensurate Figma assets for designers. Four “core libraries” (three code, one design), parity of all relevant components, expanding and evolving over time. Let’s roll up our sleeves.</p><p>This post explores how expanding to support many platforms and frameworks impacts how you support and align it with a shared design source-of-truth. Success gets complicated as libraries increase, challenging how teams collaborate, designers test, everyone aligns API, and users still expect to see synced features each release.</p><p>The example of IBM’s Carbon design system offers a tantalizing public example of a core library implemented across many frameworks in parallel. Such a model inspires, even if it’s not necessarily a target to emulate for simpler problems most systems face.</p><h3>Describing core libraries of design and code</h3><p>A <strong>core library</strong> refers to a library of reusable assets implementing a design system’s core components like Text input, Button and Checkbox.</p><h4>Platforms and frameworks</h4><p>Each library implementation targets a specific <strong>platform</strong> (such as design, web, iOS and Android) and is built with a particular <strong>framework</strong> (such as Figma or Sketch, React or Lit or Angular, SwiftUI or Jetpack Compose).</p><h4>Team model: central and/or federated?</h4><p>For smaller design systems, design and code implementations are usually maintained by <strong>central</strong> teams dedicated to the work. As additional code implementations arise supporting other platforms and frameworks, the more likely each will be made by <strong>federated</strong> maintainers and contributors.</p><h4>Design source-of-truth: specifications?</h4><p>Designers and developers using a core libraries expect that library to support all core components like button, text input and checkbox. Each component is expected to implement a common <a href="https://medium.com/eightshapes-llc/component-specifications-1492ca4c94c"><strong>design specification</strong></a> (that may include platform– and/or framework–specific considerations).</p><h4>Code source-of-truth: the reference implementation?</h4><p>In addition, one code library may serve as a <strong>reference implementation:</strong> a working component demonstrating how it should be correctly implemented and used. The reference is usually produced by the central team, showcases best practices, and reflects a recommended API. Such a “canonical” reference provides federated teams implementing additional libraries with a reasonable technical design to align with.</p><h3>Example models, from simple to complicated</h3><p>Managing and aligning one code library with design is delightfully simple compared to when two or more code libraries begin to scale. As a manager of design system work, it’s up to me to solve for concerns across libraries that include:</p><ul><li><strong>Roadmap</strong>: How do we align features across code libraries over time?</li><li><strong>Collaboration</strong>: How do we enable collaborative best practices between design and multiple engineering teams, especically when federated?</li><li><strong>API</strong>: How do we align API architecture across frameworks, platforms?</li><li><strong>Testing</strong>: How do we integrate designers into testing code outputs?</li><li><strong>Release synchronization</strong>: Do we align releases and communications across libraries? If not, what does that mean?</li></ul><p>The example models that follow will progress from simple to complicated to highlight how these concerns get more complicated.</p><h4>One code library, by a central team</h4><p>The majority of design systems I’ve led support one design library (these days, Figma) and one code library (such as React) through the work of a central team. Production aligns three primary outputs — (1) Figma assets, (2) React code packages, and (3) docs published to the “doc site” — released in synchronization in a <a href="http://Step-by-Step">step-by-step process</a>.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*6EmLdKgyOGGCacyQru20Ig.png" /><figcaption><a href="http://Step-by-Step">Steps to design and produce library outputs</a> for a design system feature</figcaption></figure><ul><li><strong>Roadmap</strong>, <strong>collaboration</strong>, <strong>designer VQA</strong> and <strong>release synchronization</strong>? As easy as it gets managing a single central team.</li><li><strong>API alignment</strong>? While <a href="https://medium.com/eightshapes-llc/crafting-ui-component-api-together-81946d140371">crafting components with aligned features and API</a> challenges designers and developers, a smaller group producing React and Figma can figure it out.</li></ul><h4>Many web core libraries, by a central team</h4><p>A central team could implement multiple web code libraries, such as releasing parallel Angular, Web Components, and vanilla HTML/CSS libraries.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*IlhQKJ-k5CSKUEQ8c_94lw.png" /><figcaption>One engineering team producing Angular and Web components sharing a common CSS styling architecture, all three of which made available to adopters</figcaption></figure><ul><li><strong>Roadmap</strong> and <strong>collaboration</strong>? No different.</li><li><strong>API alignment:</strong> Vagaries of different web frameworks can fray API alignment subtly. When they differ, which should Figma assets favor?</li><li><strong>Designer VQA</strong>: As frameworks suggest an internal code waterfall, when are the right time(s) for design to test near-complete dev assets?</li><li><strong>Release synchronization</strong>: Is it ok to release some web code changes before others? While they remain locked together in a single, synced release, this setup could tempt teams to release one before others.</li></ul><p>Code could also diverge due to per-framework conventions, feature requests or fix cadences. However, these low risks can be mitigated by team processes and a single, directly responsible dev lead.</p><h4>Core libraries across platforms, by separate central teams</h4><p>A “team of teams” responsible for three libraries serving web, iOS and Android is very common in today’s design systems. More often than not, each platform’s library has a distinct dev lead and or more additional developers. Anecdotally in my experience, web has often 2× the developers of iOS or Android, for whatever reason.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*tFWHVZ7misJx0Rui_x4myw.png" /><figcaption>Three platform libraries made by separate engineering teams centrally managed as a larger “team of teams”</figcaption></figure><p>Given the multiple dev teams and leads, things get more complicated.</p><ul><li><strong>Roadmap</strong>: Centralized but diversified into groups, persisting a shared roadmap takes a bit more effort.</li><li><strong>Collaboration</strong>: Distinct dev leads per “platform team” need their own ceremonies, which can begin to diverge decisions and understanding. Are there routines where designers should participate? Previously <a href="https://danmall.com/posts/hot-potato-process/">“hot potato” behaviors</a> give way to increasing focus on handoffs and specs for provisional decision making. Are all three dev leads in handoff meetings, or do we need <em>multiple</em> handoffs?</li><li><strong>API alignment:</strong> Systems must allow for platform-specific conventions, so it’s up to leads to agree on guardrails of what’s shared or not. In this setup, I lean even more into component, property and option naming.</li><li><strong>Designer VQA</strong>: A designer responsible for specs gets called back into visually test different platforms at different times. Review timing is less predictable and more disruptive. Tracking needs deliberate attention.</li><li><strong>Release synchronization</strong>: The tug of independent releases strengthens considerably, allowing for code enhancements and fixes to release quickly to support business needs.</li></ul><p>Once multiple development teams and/or platforms get involved, it’s often time to invoke a <strong>“Release individually, communicate collectively”</strong> model.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*zhLNMpP8CTs3bKY31MfYjQ.png" /><figcaption>Release communications occurring when all outputs are done, even if some (here, React and iOS) release quietly prior when ready</figcaption></figure><p>Here, React and iOS could release days or even weeks prior to Android, the Figma library and documentation site. Once Android is done, Figma and doc site materials complete the “Release” and<a href="https://medium.com/eightshapes-llc/design-system-communications-ca679ffc36d3"> communications</a> across Slack, email and formal doc can broadcast new feature availability to the masses. This strikes a balance between enabling teams that need component code as soon as possible with a system driving (perceived) alignment across platforms.</p><p>If the gap between platforms is longer, then releases separate by platform. This is almost always the case when libraries are federated.</p><h4>Web library by central team, iOS and Android federated</h4><p>In my experience, it’s less common for iOS and Android to be centrally managed with and allocated with the same dedicated capacity as developers supporting a design system’s web code. Instead, I’m used to coordinating more loosely with iOS and Android library leads. These libraries emerge to serve their “main app,” and the benefit to teams making other apps is a secondary concern at best.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*npwLN42z8612EC9dv-2Jmg.png" /></figure><p>When working with those making federated libraries, ways-of-working diverge far more. Considerations include:</p><ul><li><strong>Roadmap</strong>: Very often, the “main app” product leaders get involved. Different interests — deliver a library (my outcome), “main app” integration (their outcome) — become clear. Artifacts to plan, distinguish and connect those outcomes become essential.</li><li><strong>Collaboration</strong>: It’s very difficult to integrate federated dev leads into routine (weekly?) handoffs from design to the central dev team(s). Integrating them into critiques that precede handoff? Even more so. Therefore, collaborative value rises to the fore: do these libraries justify a separate handoff meeting? How about a separate planning meeting, and how often (tip: it ebbs and flows)?</li><li><strong>API alignment:</strong> In this example, web code undoubtedly becomes the reference library, especially if synced strongly with design specs. However, results are uneven in getting iOS and Android dev leads to use that reference. To that end, I’ll work involve web dev lead to lean into handoffs and coordination too.</li><li><strong>Designer VQA</strong>: No different, if spread more widely across the calendar.</li><li><strong>Release synchronization</strong>: Releases aren’t synced, and trying to sync them is the wrong focus. Federated releases tend to lag central ones by months, quarters or even a year. So your communication challenge is two fold: set expectations clearly and clearly communicate the status of each item in each library to those that use them.</li></ul><h4>Case study: IBM Carbon as the federated dream</h4><p>I’ve not contributed to IBM Carbon, but have watched its impressive progress for years. IBM Carbon supports code libraries across many web frameworks, each with a public code repositories that provide a clear glimpse into it’s evolving catalog.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*X2Ipu0mSw5AZViWrg5MTjQ.png" /></figure><p>In 2022, I analyzed commit activity across public repositories of IBM Carbon’s core libraries supporting Vanilla HTML &amp; CSS, <a href="https://github.com/carbon-design-system/carbon?tab=readme-ov-file">React</a>, <a href="https://github.com/carbon-design-system/carbon-components-angular">Angular</a>, <a href="https://github.com/carbon-design-system/carbon-components-svelte">Svelte</a>, Web components (now integrated into the <a href="https://github.com/carbon-design-system/carbon?tab=readme-ov-file">core library</a>) and <a href="https://github.com/carbon-design-system/carbon-components-vue">Vue</a>. The libraries emerged over years, with varying levels of activity and growth over time.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*DHKsw1OQlGc5vN8vutPbsg.png" /><figcaption>Table of IBM library metadata as of 2022, including age and quantity of core maintainers, recurring contributors, and light/one-time contributors</figcaption></figure><p>Per contributor commits made evident one or few core maintainer(s), additional contributors and a long tail of one-commit wonders.</p><p>Conversation with <a href="https://medium.com/@joshblack">Josh Black</a>, the dev lead in charge of the React library at the time, confirmed that React served as the reference implementation and the other libraries were not supported by the core team and released independently. A recent conversation with current team members confirmed that the central team had taken responsibility for and integrated the Web Components library. Other library implementations live on.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*L0p_zRkU1miduwgoM6Gu1w.png" /><figcaption>Github.com commit activity across React/Vanilla, Angular, Vue, Web components, Carbon for IBM.com and Svelte libraries, scaled to match vertical axis scale</figcaption></figure><p>Commit activity across repos visualized over time revealed trends like:</p><ul><li>Some libraries like React + Vanilla and then Carbon for IBM.com evidenced persistent activity, whereas Angular seemed to fade in 2021.</li><li>As React + Vanilla spiked in late 2018 (due to <a href="https://medium.com/@nathanacurtis/design-system-generations-65f99960dc3d">generational change</a>?), Angular similarly spiked as Vue and Web components entered the scene.</li><li>Vue and Web Component activity was lower than React + Vanilla , yet seemed continuous enough to trust each was being maintained.</li></ul><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*u7KfDZ5S1SQOcRYnxCcx2Q.png" /><figcaption>IBM Carbon’s main documentation site (left), alongside screenshots of Storybook site navigation for various implementations</figcaption></figure><p><a href="https://medium.com/@nathanacurtis/the-fallacy-of-federated-design-systems-23b9a9a05542">Despite my best intentions</a>, there are situations where a federated dream is possible. However, my gut says IBM Carbon is more an exception than rule.</p><p>Virtually every other design system in the world will not achieve or even aim for IBM’s massive scale. Yet, seeing the models at play — central versus federated, web versus native, growth and strategic change over time — offer lessons we can all take away.</p><p>So get at it. Clearly communicate your system’s scope of core library support. Chip away at collaborative best practices to agree on API, critique each other’s ideas, test and ship as one. We’re in this together.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=28b80444865e" width="1" height="1" alt="">]]></content:encoded>
        </item>
    </channel>
</rss>