The anatomy and physiology of a component
A component model defines the architecture required to build a component. A model requires feature data properties, style properties, layout definition, and rules for how the component accepts and handles that data.
Modeling is especially critical when working with dynamic content, authorization permissions, and features that roll out over multiple stages. Component leveling helps separate areas that only use style data, and areas that hold stateful data.
This is a model I built to show the levels and corresponding data required to define each component within a system. The nesting organization is fundamental to building scalable components and standardized architecture.
The product level is the result of the model and is the component rendered to the DOM. When modifying features or product UX, the product level is the affected outcome regardless of which level(s) within the model have been modified.
Absolutely — but it’s not the same thing. The model above uses an “atomic” approach, but data isn't always defined within atomic levels.
Atomic Design and this framework are logical approaches to use in tandem.
Data models aren’t always thought of as a designer’s responsibility, but that couldn’t be further from the truth. Components handle everything rendered to the DOM, and designers must account for how that data needs to be rendered.
Starting to design by modeling a component helps account for all feature rules and data required — and can help identify any holes in the delivered feature requirements.
Ultimately, engineers are building components and need complete design requirements. Engineers and designers don’t work in identical workflows and that needs to be accounted for when developing handoff processes.
Engineers often work with design deliveries in the confines of a sprint. This workflow may mean an engineer is only looking at the data required within the context of their assigned ticket and isn’t privy to the full scope of a component’s potential behavior across the product.
Because systems are living ecosystems, component data may be forward-looking, only relevant in specific contexts, and accounts for interactions between a collection of components.
When building components, the delivered component must include all possible data the design system has defined. When an instance of that component is required, engineers can draw from the requirements for the current context.
I like to use the Button component when illustrating modeling logic because it’s an easy component for almost everyone to understand.
This is how I built the button component. The structure here shows the leveled breakdown of data definition.
BUTTON/Button Elements/Base/Button Text
BUTTON/Button Elements/Base Buttons
BUTTON/Button Elements/Semantic
In this case, we have 3 sizes which we can name “small, medium, large” at the base level. Once the button is at a contextual level, naming needs to be more specific to the application. For example, buttons may be named “default, small, and large.”
When adding button sizes we don’t have to think of the contextual application when modifying base components. We can add “extra small,” for example. This also allows us to define different contextual rules in different areas of the application. What is “default” in one system level area may be different than another.
Sizing is handled by the text’s rem value. The rem value means little on its own, but the value is set with the understanding that sizing rules built in subsequent layers will use sizing values relative to those rem values.
Padding set in a value relative to the text’s rem value means that the padding value only needs to be defined in one place. If the padding value needs to be edited, only one area of the rule needs to be targeted. A system could easily add more button sizes and only need to declare that size in the text size’s value.
Slash naming convention lets you nest your component levels into neatly organized folders. You can pull a component from the top-level folder and expand the nested folders to see what the component is comprised of.
In this example, we’re using the Primary Button component. There are 3 sizes, styled states, and the option to have the button span the full width of its container. While it’s possible to exclude full width as a property and control the width behavior when applying the component, adding the property in the button component gives us the ability to identify a clear product rule that we can declare when the component is applied.
These are the properties we need to select from when applying the component. We’ll also want to determine the button’s content (icon, icon placement) and whether or not we want the default spacing value or another value we’ve declared a level down. To declare values within the nested component, we just need to click into those layers and set what’s required.
Slash naming convention lets you nest your component levels into neatly organized folders. You can pull a component from the top level folder and expand the nested folders to see what the component is comprised of.
Figma has some amazing features that you can take advantage of to build nested components. While Figma is many organizations’ tools of choice at the moment, the logic behind this approach isn’t confined to any application.
The system architecture logic behind these requirements is key to building a scalable system that avoids declaring current product patterns and styles within its foundational architecture.
Scaling always needs to be considered when building systems. A system, by design, needs to be a living ecosystem that can change to meet product and business requirements.
Identifying which parts of a system can be accounted for in a universal framework simplifies which properties are unique to the product's design system.
Maintaining a product's system is much simpler when the framework properties are set and tucked away in dedicated sections.
Props apply to all variants of a component.
Boilerplate design system components that aren’t unique to the product.
This is a model I built to show the levels and corresponding data required to define each component within a system. The nesting organization is fundamental to building scalable components and standardized architecture.
The product level is the result of the model and is the component rendered to the DOM. When modifying features or product UX, the product level is the affected outcome regardless of which level(s) within the model have been modified.
Absolutely — but it’s not the same thing. The model above uses an “atomic” approach, but data isn't always defined within atomic levels.
Atomic Design and this framework are logical approaches to use in tandem.
Data models aren’t always thought of as a designer’s responsibility, but that couldn’t be further from the truth. Components handle everything rendered to the DOM, and designers must account for how that data needs to be rendered.
Starting to design by modeling a component helps account for all feature rules and data required — and can help identify any holes in the delivered feature requirements.
Ultimately, engineers are building components and need complete design requirements. Engineers and designers don’t work in identical workflows and that needs to be accounted for when developing handoff processes.
Engineers often work with design deliveries in the confines of a sprint. This workflow may mean an engineer is only looking at the data required within the context of their assigned ticket and isn’t privy to the full scope of a component’s potential behavior across the product.
Because systems are living ecosystems, component data may be forward-looking, only relevant in specific contexts, and accounts for interactions between a collection of components.
When building components, the delivered component must include all possible data the design system has defined. When an instance of that component is required, engineers can draw from the requirements for the current context.
Slash naming convention lets you nest your component levels into neatly organized folders. You can pull a component from the top-level folder and expand the nested folders to see what the component is comprised of.
In this example, we’re using the Primary Button component. There are 3 sizes, styled states, and the option to have the button span the full width of its container. While it’s possible to exclude full width as a property and control the width behavior when applying the component, adding the property in the button component gives us the ability to identify a clear product rule that we can declare when the component is applied.
These are the properties we need to select from when applying the component. We’ll also want to determine the button’s content (icon, icon placement) and whether or not we want the default spacing value or another value we’ve declared a level down. To declare values within the nested component, we just need to click into those layers and set what’s required.
Slash naming convention lets you nest your component levels into neatly organized folders. You can pull a component from the top level folder and expand the nested folders to see what the component is comprised of.
Figma has some amazing features that you can take advantage of to build nested components. While Figma is many organizations’ tools of choice at the moment, the logic behind this approach isn’t confined to any application.
This is a model I built to show the levels and corresponding data required to define each component within a system. The nesting organization is fundamental to building scalable components and standardized architecture.
The product level is the result of the model and is the component rendered to the DOM. When modifying features or product UX, the product level is the affected outcome regardless of which level(s) within the model have been modified.
Absolutely — but it’s not the same thing. The model above uses an “atomic” approach, but data isn't always defined within atomic levels.
Atomic Design and this framework are logical approaches to use in tandem.
Data models aren’t always thought of as a designer’s responsibility, but that couldn’t be further from the truth. Components handle everything rendered to the DOM, and designers must account for how that data needs to be rendered.
Starting to design by modeling a component helps account for all feature rules and data required — and can help identify any holes in the delivered feature requirements.
Ultimately, engineers are building components and need complete design requirements. Engineers and designers don’t work in identical workflows and that needs to be accounted for when developing handoff processes.
Engineers often work with design deliveries in the confines of a sprint. This workflow may mean an engineer is only looking at the data required within the context of their assigned ticket and isn’t privy to the full scope of a component’s potential behavior across the product.
Because systems are living ecosystems, component data may be forward-looking, only relevant in specific contexts, and accounts for interactions between a collection of components.
When building components, the delivered component must include all possible data the design system has defined. When an instance of that component is required, engineers can draw from the requirements for the current context.
I like to use the Button component when illustrating modeling logic because it’s an easy component for almost everyone to understand.
This is how I built the button component. The structure here shows the leveled breakdown of data definition.
BUTTON/Button Elements/Base/Button Text
BUTTON/Button Elements/Base Buttons
BUTTON/Button Elements/Semantic
Slash naming convention lets you nest your component levels into neatly organized folders. You can pull a component from the top-level folder and expand the nested folders to see what the component is comprised of.
In this example, we’re using the Primary Button component. There are 3 sizes, styled states, and the option to have the button span the full width of its container. While it’s possible to exclude full width as a property and control the width behavior when applying the component, adding the property in the button component gives us the ability to identify a clear product rule that we can declare when the component is applied.
These are the properties we need to select from when applying the component. We’ll also want to determine the button’s content (icon, icon placement) and whether or not we want the default spacing value or another value we’ve declared a level down. To declare values within the nested component, we just need to click into those layers and set what’s required.
Slash naming convention lets you nest your component levels into neatly organized folders. You can pull a component from the top level folder and expand the nested folders to see what the component is comprised of.
The system architecture logic behind these requirements is key to building a scalable system that avoids declaring current product patterns and styles within its foundational architecture.
Scaling always needs to be considered when building systems. A system, by design, needs to be a living ecosystem that can change to meet product and business requirements.
Identifying which parts of a system can be accounted for in a universal framework simplifies which properties are unique to the product's design system.
Maintaining a product's system is much simpler when the framework properties are set and tucked away in dedicated sections.
This is a model I built to show the levels and corresponding data required to define each component within a system. The nesting organization is fundamental to building scalable components and standardized architecture.
The product level is the result of the model and is the component rendered to the DOM. When modifying features or product UX, the product level is the affected outcome regardless of which level(s) within the model have been modified.
Props apply to all variants of a component.
Boilerplate design system components that aren’t unique to the product.
Contextual components that include system patterns and styles
Style libraries defined for the application. These are based on brand or product standards.
Style libraries defined for the application. These are based on brand or product standards.
Absolutely — but it’s not the same thing. The model above uses an “atomic” approach, but data isn't always defined within atomic levels.
Atomic Design and this framework are logical approaches to use in tandem.
Data models aren’t always thought of as a designer’s responsibility, but that couldn’t be further from the truth. Components handle everything rendered to the DOM, and designers must account for how that data needs to be rendered.
Starting to design by modeling a component helps account for all feature rules and data required — and can help identify any holes in the delivered feature requirements.
Ultimately, engineers are building components and need complete design requirements. Engineers and designers don’t work in identical workflows and that needs to be accounted for when developing handoff processes.
Engineers often work with design deliveries in the confines of a sprint. This workflow may mean an engineer is only looking at the data required within the context of their assigned ticket and isn’t privy to the full scope of a component’s potential behavior across the product.
Because systems are living ecosystems, component data may be forward-looking, only relevant in specific contexts, and accounts for interactions between a collection of components.
When building components, the delivered component must include all possible data the design system has defined. When an instance of that component is required, engineers can draw from the requirements for the current context.
I like to use the Button component when illustrating modeling logic because it’s an easy component for almost everyone to understand.
This is how I built the button component. The structure here shows the leveled breakdown of data definition.
BUTTON/Button Elements/Base/Button Text
BUTTON/Button Elements/Base Buttons
BUTTON/Button Elements/Semantic
In this case, we have 3 sizes which we can name “small, medium, large” at the base level. Once the button is at a contextual level, naming needs to be more specific to the application. For example, buttons may be named “default, small, and large.”
When adding button sizes we don’t have to think of the contextual application when modifying base components. We can add “extra small,” for example. This also allows us to define different contextual rules in different areas of the application. What is “default” in one system level area may be different than another.
Sizing is handled by the text’s rem value. The rem value means little on its own, but the value is set with the understanding that sizing rules built in subsequent layers will use sizing values relative to those rem values.
Padding set in a value relative to the text’s rem value means that the padding value only needs to be defined in one place. If the padding value needs to be edited, only one area of the rule needs to be targeted. A system could easily add more button sizes and only need to declare that size in the text size’s value.
Figma has some amazing features that you can take advantage of to build nested components. While Figma is many organizations’ tools of choice at the moment, the logic behind this approach isn’t confined to any application.
Slash naming convention lets you nest your component levels into neatly organized folders. You can pull a component from the top-level folder and expand the nested folders to see what the component is comprised of.
In this example, we’re using the Primary Button component. There are 3 sizes, styled states, and the option to have the button span the full width of its container. While it’s possible to exclude full width as a property and control the width behavior when applying the component, adding the property in the button component gives us the ability to identify a clear product rule that we can declare when the component is applied.
These are the properties we need to select from when applying the component. We’ll also want to determine the button’s content (icon, icon placement) and whether or not we want the default spacing value or another value we’ve declared a level down. To declare values within the nested component, we just need to click into those layers and set what’s required.
The system architecture logic behind these requirements is key to building a scalable system that avoids declaring current product patterns and styles within its foundational architecture.
Scaling always needs to be considered when building systems. A system, by design, needs to be a living ecosystem that can change to meet product and business requirements.
Identifying which parts of a system can be accounted for in a universal framework simplifies which properties are unique to the product's design system.
Maintaining a product's system is much simpler when the framework properties are set and tucked away in dedicated sections.
This is a model I built to show the levels and corresponding data required to define each component within a system. The nesting organization is fundamental to building scalable components and standardized architecture.
The product level is the result of the model and is the component rendered to the DOM. When modifying features or product UX, the product level is the affected outcome regardless of which level(s) within the model have been modified.
This is how I built the button component. The structure here shows the leveled breakdown of data definition.
BUTTON/Button Elements/Base/Button Text
BUTTON/Button Elements/Base Buttons
BUTTON/Button Elements/Semantic
This is a model I built to show the levels and corresponding data required to define each component within a system. The nesting organization is fundamental to building scalable components and standardized architecture.
The product level is the result of the model and is the component rendered to the DOM. When modifying features or product UX, the product level is the affected outcome regardless of which level(s) within the model have been modified.
In this case, we have 3 sizes which we can name “small, medium, large” at the base level. Once the button is at a contextual level, naming needs to be more specific to the application. For example, buttons may be named “default, small, and large.”
When adding button sizes we don’t have to think of the contextual application when modifying base components. We can add “extra small,” for example. This also allows us to define different contextual rules in different areas of the application. What is “default” in one system level area may be different than another.
Sizing is handled by the text’s rem value. The rem value means little on its own, but the value is set with the understanding that sizing rules built in subsequent layers will use sizing values relative to those rem values.
Padding set in a value relative to the text’s rem value means that the padding value only needs to be defined in one place. If the padding value needs to be edited, only one area of the rule needs to be targeted. A system could easily add more button sizes and only need to declare that size in the text size’s value.
Figma has some amazing features that you can take advantage of to build nested components. While Figma is many organizations’ tools of choice at the moment, the logic behind this approach isn’t confined to any application.
A model provides a consistent approach to follow. Modeling helps to standardize system design and facilitates asynchronous design across a design team.
Having a model as a guide eliminates the cognitive load of needing to think of every component as a unique model. With a model established, we can know the parts of a component that are required before a component is required for our system.