The ability to version, manage, and distribute design libraries in Abstract is one of our users' favorite features. Libraries can be small and useful so you don't repeat yourself as you gain momentum on a growing project, or they can be the backbone of a design system for an enterprise team’s many products. Managing libraries in Abstract enables teams to scale their design component libraries very efficiently. By considering some of the following best practices, you can be sure to set your team up for success when working with libraries in Abstract.
Leverage clear and predictable naming conventions that communicate intended library use.
For quick visibility and performant files, organize in a way that uses several small files rather than few larger ones. We recommend one component type per file.
Patterns that touch many projects shouldn’t change often and belong in a Design System project. Patterns that are context-specific and might be updated relatively frequently belong in a per-project library alongside the files where their instances are used.
The more you can organize reusable patterns into library files (and thus move edits to the source symbol level) the smaller your merge conflicts will be.
Leverage Sketch plugins to make using and analyzing your libraries easier.
Organize and name your libraries
Projects and sections
We see users have the most success with their libraries when they are built on the foundation of a centralized design system. This design system is most often given its own project consisting entirely of library files, with each component type distributed into its own file. These component files are then linked to any project that needs them. When an organization needs to utilize multiple central libraries or multiple themes on top of a library, it’s a good idea to have a section to contain them.
In this way of organizing, the answer of where a component lives is relatively self-evident. Instead of scrolling through large files or digging through dozens of pages within one file, you get a quickly digestible index of your components in the main branch files view of the project. This technique also helps scope the change management of a design system in clear ways, limiting the footprint of changes to single files or pages of files, which lessens the likelihood of merge conflicts. More on that later.
Naming for interoperability
As it is in programming, naming things is hard. But investing in clear naming conventions returns a much lighter mental load in your day-to-day design work. Abstract and several other design tools work with the common convention of slash separated naming.
This convention mirrors a directory structure and helps provide context into a component's category and its behavior in relation to other related components. For example, a button component could be named button-group/large or a color could be named Color/Red/Red-10. The benefits of this approach are maximized when the way you name your components is informed by the ways your engineering colleagues implement them in code. In this example below, a developer can recognize red-10 from their convention and quickly know what they're working with instead of fussing with less human-readable RGB or hex values.
Naming for intent
In addition to naming a component for what it is and why your team needs it, sometimes it's important to communicate how it should be used. Or maybe you've run into an outlier in your pattern library and you'd like to convey its uniqueness. Leveraging emojis or clear and efficient abbreviations is a effective way to accomplish this. Check out these two examples:
1. Testing or deprecated components
It's likely that at some point, you’d like to test out some experimental components, or any other type of symbols that haven't yet been approved. In this situation, it could be a good idea to append an emoji onto the component name to tag it as experimental and “not approved”. Internally at Abstract, our team uses the crystal ball emoji, giving these components names like "Desktop Inputs 🔮". That way, this component can be merged into our Design System project's main branch and linked to any other project while still having its acceptance status implied wherever it is seen. The same convention could also be applied to old components that need to be used on older legacy projects but not anywhere else.
Another example where usage instructions can be implied is in the case of templates. Like reusable components, templates help you to not start from scratch on common types of screens you might need to design. Unlike reusable components, however, templates are made with the express purpose of being altered beyond simply overriding. They can be anything from groupings of pre-defined library components to entire layouts. In these cases, it would make sense to communicate that a symbol is intended to be detached within its name. Internally at Abstract, our team uses the broken heart emoji, as in "Menu/2 Select 💔", indicating that after you insert this selection menu, you’re supposed to detach the symbol and customize it to your specific context.
Linked libraries vs. per-project libraries
Generally, it’s a good idea to have foundational designs that are reused in many projects (and thus shouldn’t change often) in a designated design system project. You can utilize these throughout your organization through linked libraries. To promote stability and healthy change management, updates to these far-reaching pieces should happen through a more formal branch, commit, review, and merge process. Context-specific arrangements of these pieces, along with other patterns that don’t get utilized elsewhere are best organized in per-project libraries that can be changed on the fly within branches, without having to leave Sketch.
In the example above, the Project Components.sketch is a per-project library file that contains context-specific arrangements of symbol instances from Colors.sketch, Iconography.sketch, Buttons.sketch and Typography.sketch.
Merging per-project libraries
One potentially unexpected benefit of using libraries more is a cleaner merge process. In general, the more your designs are organized into components distributed through library files, the fewer merge conflicts you'll encounter. This is because if you make decisions and edits on the component level (in their library files), the changes that might be eligible for a merge conflict are limited to that smaller number of source symbols rather than the many possible compositions of their instances.
Example: Collaboration on the same artboard with no conflicts
Suppose you have a project for a website. You and a collaborator want to make changes to the same artboard in a file called Homepage.sketch. Let’s say you need to update the navigation while your collaborator edits the footer. If you make changes directly to the mockup in Homepage.sketch, you need to accept or reject changes prior to merge that would overwrite the other person's version of the artboard.
Instead, you can work in separated library files to avoid these merge conflicts entirely. If you scope your updates to the source symbols in a Navigation.sketch library file while your collaborator does the same in a Footers.sketch library file, you can both merge to the main branch (or a shared parent branch) with no conflicts from the other. To fully update the targeted mockup, you only need to open Homepage.sketch, accept the library updates, and merge.
Plugins we love
Sleuth, which integrates with our SDK, is a great way to get a sense of how well your team is adopting your design system.
Sketch Runner is the tool of choice for many teams, including ours, for quickly finding and placing symbols.
Symbol Swapper is a quick and efficient way to update symbols in bulk.
- Automate Sketch is a productivity powerhouse plugin that helps you make your workflows more efficient.
If the developers you collaborate with use Storybook for UI development, they might find it useful to use our Storybook add-on to display component mockups from Abstract directly next to their live components.