Challenge
If it wasn’t obvious for everybody the thing it would kill Element as a company is if we don’t manage to increase the core quality of the app to be as good or better than Slack, or Teams, or WhatsApp, or Discord. It's just that simple.
— Matthew, Element Sync Feb. 7 2022
Our enduring primary focus in Product Engineering has been to try and level up the quality of the core app experience. Frankly, nothing is more important. If we can’t make using the app a wonderful experience, the ecosystem won’t grow, and our customers will not migrate.
— Neil, Platform and Product Engineering: Friday Brief - 2022-02-11
What are we trying to accomplish?
→ Enabling teams to create high-quality, high-performing products faster and consistently.
Why are we doing this?
→ We’ll always lag behind competitors if we don’t manage to address the existing debt and focus on delivering high-quality products, thus putting the company’s sustainability at risk.
What’s stopping us from delivering high-quality products?
- Entropy and debt.
- Gaps in quality in the product pipeline.
How can we deliver high-quality, high-performing products faster?
Proposed solution
- Fixing product debt. Polish the core experience of our products, and make it a coherent one across platforms.
- Fixing the product pipeline. Provide solid foundations for consistently delivering high-quality products and experiences.
Fixing product debt
Address debt across all platforms.
We’ll need to balance quick wins with more in-depth redesigns. We can go a long way in some areas with a design facelift to make them more “visually appealing” (e.g., Chatterbox). However, other functionally broken areas will require a more in-depth redesign to make them “functionally appealing” first before polishing the visual layer.
- Quick redesigns — Quick wins. Low engineering effort. Improve what we already have, making sure it’s meeting a quality checklist.
- Design overhauls — More involved redesigns with a higher engineering effort.
Fixing the product pipeline
- How do we define quality?
- How do we deliver on it?
Making sure we’re building new stuff on top of solid foundations — libraries, tooling, and workflows.
- Primitives: Provide the right primitives as design tokens and core components.
- Documentation: Giving proper visibility to the system, for designers and engineers.
- Collaboration: Speak the same language. Streamline the feedback loop between design and engineering.
Design system
“A design system is a tool to bring design and engineers together. It is key to position it not as a tool for designers, but as a tool for product design and engineering.”
5 Design System Fails—And Their Fixes
A note on scope for the design system:
“The design system embodies important standards from across an organization, but doesn’t necessarily define or own those standards.”
Design Systems are for user interfaces
While design systems are generally more focused on design execution and operations, a product’s actual design process is typically more complex, requiring additional stages and input from other roles — from strategy to research, ideation, and implementation.
For that reason, the design system documentation may be extended to include related guidelines for other areas or just reference them where necessary. Setting some boundaries will help keep the design system more manageable and prevent it from becoming as encompassing as a company handbook.
- Brand
- Content
- Writing (e.g., voice and tone, copywriting, UX writing)
- Illustration
- Media (e.g., photography, video)
- Design
- Principles
- Research (e.g., user research, usability testing)
- Product (e.g., UI, iconograpy, motion, sound)
- Marketing (e.g., product site, publications, help center, social)
- Email (e.g., transactional, lifecycle, drip, newsletters)
- Engineering
Component quality checklist
How do we define quality?
Proposed solution
A checklist on quality principles that everyone can refer to.
- Usable — Checked against usability heuristics. User tested as necessary.
- Inclusive — Complies with a sensible baseline for accessibility.
- Localizable — Accounts for different languages and locales. Bidirectionality (LTR, RTL) is handled properly.
- Responsive — Adapts to a wide range of display contexts.
- Coherent — Follows the design system principles and guidelines. Offers a coherent cross-platform experience while still respecting the target platform conventions.
- Themable — Supports theming when necessary.
- Delightful — Copywriting is clear and concise, with a touch of personality. Looks and feels polished. Follows natural transitions when changing its state.
- Documented — Has clear documentation for each component state for both designers and engineers.
- Tested — It’s tested for robustness (code reliability, performance, security, cross-client compatibility).
A note on accessibility:
We acknowledge that accessibility can be a complex, moving target. You can always improve on it, but you’ll hardly ever hit the 100% mark.
We aim for a sensible baseline that addresses the most relevant concerns and integrate that into our core practices.
📝 TODO. Define accessibility baseline.
Design system documentation
How can we radiate information more efficiently, avoid knowledge silos, keep everyone in sync, and help surface design inconsistencies?
Proposed solution
Centralize the design system documentation in a place that can serve all parties (designers, engineers, product managers, content creators, etc.). It should be easy to refer to and contribute.
- At an early stage, the documentation could live in Figma.
- At a later stage, we should consider moving the detailed documentation to Storybook, with MDX, via the Docs addon.
Examples of design systems documented with Storybook Docs addon:
If we end up outgrowing Storybook Docs or it no longer best serve our needs, we could consider alternative approaches:
- Dedicated design system management platforms like zeroheight, or Supernova.
- Custom site. Ultimate flexibility, but potentially higher maintenance cost. It could be anything, ranging from headless CMSs and frontend frameworks to static site generators, low-code platforms, or more traditional CMSs (Gatsby, Next.js, Eleventy, Jekyll, Webflow, custom WordPress…).
Additional tools to explore:
Cross-referencing design and code. Showing the component design beside what’s actually built.
Design system versioning
- How do we track and communicate changes?
- How do we distribute and consume the components?
Areas to consider:
- Versioning and distribution — Packages and managing dependencies.
- Managing releases — Commit messages, changelog, and roadmap.
- Component status — Implementation stage and component health.
- Evolving the design system — Branching. Refactoring, deprecation, and planning for migrations. Dealing with legacy components and experimental ones.
📝 TODO. Expand section.
Design system governance
- How do we handle contributions and requests?
- How do we plan for successful adoption?
- How do we mature it?
📝 TODO. Expand section.
Design: component library
- Organization — File, page, and layer organization: separate files for tokens and components, all components in same page vs separate pages.
- Platforms
- Component architecture — Base components. Variants. Composable components (components with slots for swapping child components).
- Adaptivity — Component responsive behavior.
- Theming — Light and dark themes.
- Versioning
📝 TODO. Expand section.
Engineering: component explorer
“The components should only be concerned with presenting the UI and should not contain any business logic. Ideally the library enables the simulation of all possible states a component might take in the application. A component library also serves as a “workshop” where developers can build, test, and iterate on components in isolation.”
A Developer’s Guide to Design Systems
“Storybook makes it dead simple to mock hard-to-reach states and edge cases.”
Storybook — Use cases
- How can we make sure that Engineering is following the design spec and meeting the quality guidelines when implementing the components?
- How can we easily explore and review all the available states for components, including the hard-to-reach ones?
Proposed solution
Live component explorer that can be easily inspected for layout and visual issues by designers and engineers.
Component explorers serve both as catalogs and playgrounds for live components, making it easier to explore, document, and test the components in isolation and keep iterating on them over time with more confidence.
- Explore: For discovering and browsing components in one place.
- Document: Visual and textual documentation, states and behavior documentation, and API documentation. Optionally, as an advanced feature, a code playground would allow everyone — but especially engineers — to test and combine components in live sandboxes.
- Test: Inspect the layout and styles against the design spec, and help out with testing for the component quality checklist on responsiveness, accessiblity, internationalization (localization, bidrectionality), theming, and visual regressions.
- Web: Storybook.
- iOS/Android: Custom component catalog app with an in-app design inspector. Alternatively, though more experimental, Storybook for Native combined with Appetize.io for rendering the screens.
Examples of custom component catalogs for native apps:
Example in-app inspectors for runtime view debugging:
More on Storybook for Native coupled with Appetize.io:
This setup could be simplified if using React Native, by using Expo for rendering the screens in Storybook — related quick example on Twitter.
Engineering: component foundations
How can we make sure that both the design decisions and the quality guidelines make their way to the implemented components?
Design tokens
How can we communicate global design decisions more clearly between design and engineering?
Proposed solution
- Token naming: Scalable naming convetnion.
- Token tiers: Different token tiers for immutable vs functional tokens.
Tools to explore
Keep authoring them manually for each target platform or automate it with Amazon’s Style Dictionary:
Component style library
Not strictly necessary, but may be worth considering if it really helps.
- Web: CSS utility library (a la Tailwind), and/or CSS-only component library.
Component framework
How can we make sure the components are implemented according to the quality guidelines?
Proposed solution
Reuse solid component foundations that do all the heavy-lifting on accessibility and best practices for us.
Tools to explore
- Web: Explore how we could benefit from a headless, accessible, composable component foundations. Headless components come unstyled — contrary to styled component libraries such as Material UI or Chakra UI, where you would have to fight with their styles — but include all the foundations and primitives for creating solid, accessible custom styled components. Popular examples include Adobe React Aria, or Reakit. Other lightweight alternatives include Radix by Modulz, or Headless UI by Tailwind Labs.
- iOS/Android: Leverage each platform’s native UI kits and APIs as much as possible. Any custom component should meet the component quality guidelines.
QA
Design QA: design implementation review
How can designers check if the implemented user interfaces are actually following the design specs?
Proposed solution
Make it easy for designers to test apps — web or native — in a variety of devices and inspect them for visual bugs (e.g., layout, styles).
Web
- Web apps can easily be inspected with desktop browser’s integrated developer tools, even those web apps running in a mobile browser. A lightweight, more straightforward alternative to built-in developer tools is using visual inspection extensions such as VisBug or CSS Peeper.
- For advanced responsive testing it may be convenient to use a dedicated extension (e.g., Responsive Viewer) or browser (e.g., Polypane and Sizzy).
- For testing on multiple operating systems and devices, it is advisable to use a cloud testing service such as BrowserStack or Sauce Labs.
iOS/Android: Running the app
- Native apps and test builds can run side by side on physical devices.
- For testing on multiple operating systems and devices, the most straightforward path is to make use of real device cloud services such as BrowserStack — App Live or Sauce Labs — Real Device Cloud. Alternatively, it can also be performed on desktop emulators and simulators, such as Android Studio AVD and Xcode Simulator, but the setup is more complex, especially for Xcode Simulator.
iOS/Android: Inspecting the app
- A simple way to assess the visual implementation of native apps is by using visual measuring and annotation tools such as shottr, PixelSnap, or xScope. However, some hard limitations apply as these tools can only work on images rather than the rendered UI tree. So, for example, these tools can’t inspect every style (e.g., font size, line-height, corner radius, drop shadows, gradient values) or property (e.g., actual tappable area).
- If more detailed visual inspection and debugging is needed — in a similar fashion to browser developer tools — this can be achieved via runtime view debugging tools. The simplest, more convenient ones can be run directly in your device — Developer Assistant on Android, or Hyperion on iOS — and more advanced ones, but complex to setup, are run from the desktop — Android Studio Layout Inspector and Layout Validation, Xcode Accessibility Inspector and Debug View Hierarchy, or third-party tools such as Sherlock or Reveal.
Visual QA: visual regression testing
How can we make sure that nothing gets broken when a designer or an engineer introduces changes to the system?
Proposed solution
Use visual regression testing tools that help detecting breaking changes in the design and code libraries.
- Design: Figma’s native branching and merging feature. Available in the Organization and Enterprise plans.
- Web: Visual regression testing platforms like Chromatic, provided by the makers of Storybook. Popular alternatives include Percy, or Applitools.
- iOS/Android: Visual regression testing platforms like Kobiton. Alternatively, consider creating home-grown solutions based on open-source tools, or making use of crowdsourced testing platforms like Rainforest.
More on Figma banching and merging:
Functional QA: end-to-end testing, automated UI testing
“Manually testing isn’t investing. It’s spending money to get a one-time feedback, that’s it. Automated tests give us continuous feedback over time. And that Return on Investment (ROI) of your tests is exactly what we want to strive for.”
“As important as testing is, it is also a question of cost vs. benefit. We don’t want to blindly test everything but the most critical parts, and create tests that give us the most benefit”
Challenging the Testing Pyramid, from Cypress blog.
How can we spend less time on manual UI testing and avoid doing it repeatedly for every change?
Proposed solution
Could we automate some functional, UI testing tasks with tools like Cypress and Appium?
- Focus on the critical paths.
- Don’t take and all or nothing approach.
There’s always going to be some manual testing involved, but if we can automate the most critical paths that would be a huge time saver.
Cypress can test anything that runs in a browser. It can also run accessibility, visual regression, email, and other types of tests via plugins. Popular alternatives includes Microsoft Playwright, and WebdriverIO.
Appium is a popular open source framework for automated mobile app UI testing. It lets you write automated UI tests for native, hybrid, and mobile web apps running on both iOS and Android platforms, using the same API that Appium provides. Alternatively, we could leverage each platform’s UI testing framework, that is, XCTest for iOS, and Espresso for Android.
Contributions QA: handling community contributions and requests
📝 TODO. Complete section.
Priority and delivery planning
Core experience
Core components
The foundations for our product features and experiences.
Tokens
- Color system and theming
- Type system
- Spacing and sizing system
- Material/surface
Base UI components
- Forms and controls: text input, text area, toggle/switch, checkbox, radio groups, dropdown/select, datalist, slider.
- Actions: buttons, links.
- Navs: (pills, tabs, pagination, sliders, back to top…)
- Collapsibles: disclosure.
- Overlays: modals, popovers, tooltips, toasts.
- Feedback and state: alerts, badges/labels, progress, spinners.
Other
Product-specific components
Account
Main navigation and settings.
- Account: settings, feedback.
- Spaces: navigate, create, manage, explore, and settings.
- Rooms: navigate, create, manage, explore, and settings.
Room
Main content area.
- Timeline
- Composer
- Room actions (top bar): voice/video calls, search, export chat, share room, settings.
- Right sidebar: pinned messages, threads, notifications, people, files, widgets.
Product and service portfolio
- Element: Web, Android, iOS
- Element Call: Web
- Element extensions: Hookshot, Stickers, and other first-party integrations and widgets.
- Other ongoing experiments: Hydrogen, Chatterbox
- EMS: Web
- Professional services: custom branding/theming?, which platforms?
- Web properties: element.io, matrix.org, matrix.to
- Email
💡 Needs to be explored further
Should we keep separate implementations of the design system?
Let’s say, for instance, that Element Web keeps implementing their own custom components in React, gradually improving their codebase, while in the EMS admin we use a third-party component library that we theme according to the design system.
That would help us avoid undesired coupling between teams dealing with complex, legacy codebases.
Actual first-hand experience of how we could repurpose a third-party component library to improve the EMS admin:
Turned Vuetify, a Vue.js Material Design library, into a custom themed component library that doesn’t look any more like Material Design.
You get all the benefits of ready-made, accessible, and performant UI components and only have to care about the visual layer. In addition, updates and improvements to the components would come almost free, as long as those don’t break the styling hooks, which we could track with Storybook and Chromatic for automated visual regression testing.
What projects would actually benefit from sharing the same implementation?