Travis Arnold recently presented how JSX and compiler technologies can be used conjointly to make the handoff between designers and developers more efficient. While the ideas presented are not yet implemented in any publicly available tool or library, the ideas of Arnold, who describes himself as a designer/developer, may serve to illustrate possible avenues for improved collaboration between designers and developers.
Arnold explained:
I would like to talk to you about empowering more people to write UI for any platform using JSX. […] Very few designers currently work in a medium that will end up in production. Many tools attempt to abstract design aspects into code but fail to expose a declarative model that can be used as a source of truth. These tools are fantastic for doing illustration and icon work but break down when we can’t easily mix code into the process.
Many developers and designers have noted prevailing inefficiencies of the design-to-development process. At one end, design tools like Zeplin, Invision, or Figma are commonly used by designs to create attractive visual designs and animations — but will not produce code for the whole interface, often requiring developers to code from scratch. At the other end, no-code tools (e.g., WebFlow) have emerged that generate production-ready code directly from a designer’s design. While they work great in some contexts, such tools have been criticized for generating code that some developers have a hard time understanding and modifying. Arnold continued:
If we look at a typical workflow between teams, there’s an inherent disconnect in our process. A designer creates something making hundreds of decisions then the work is handed off for a developer to implement. Finally, we ship an end product to production.
Basic information about primitives like layout and hierarchy must be accessed imperatively and translated. This causes duplicated work and results in sources scattered across multiple tools, not to mention it’s a waste of valuable time. These decisions are encoded in one way or another and we should be able to use them easily in the final product.
To ensure a smoother handoff process, Arnold describes in his talk JSX for Designers how designers can use a design DSL with a JSX syntax to express design concepts such as layout, style, dimensions, or space. Arnold provides the following sample code:
export default function App() {
return (
<Stack as="figure" background="gray.100" cornerRadius="xl">
<Image
source="/react-finland.jpg"
width="32px"
height="32px"
alt="React Finland Logo"
/>
<Stack spaceYStart={6} spaceBetween={4}>
<Stack as="blockquote">
<Text size="large" weight="semibold">
“React makes it painless to create interactive UIs.”
</Text>
</Stack>
<Stack as="figcaption">
<Text color="cyan.600">React</Text>
<Text color="gray.500">
A JavaScript library for building user interfaces
</Text>
</Stack>
</Stack>
</Stack>
In the previous code, <Stack/>
tags presumably encode a layout primitive that describes a component that stacks its children. Heydon Pickering, author of the Bruck prototyping library, ventured a taxonomy of layout patterns that can be reused by developers and designers alike to solve common design problems. Pickering illustrates the Stack layout pattern as follows:
The potential remit of the Stack layout can hardly be overestimated. Anywhere elements are stacked one atop another, it is likely a Stack should be in effect. […]
A form uses the large Stack spacing to separate whole fields, and a nested small Stack spacing to separate field labels from their inputs and errors
The Bruck’s prototyping library and its layout primitives can be tried out in Bruck’s playground. An example of usage of a <s-tack>
web component is as follows:
Arnold advocated compiler components that couple design and development concerns in a cohesive whole. Arnold explained:
This is done by using well-defined prop boundaries that can be statically analyzed, providing a rich source of truth for layout and styles. You can get started with compiler components quickly by using the
createComponent
function. This function accepts a configuration that describes how your component works across various platforms. In most front-end systems, we deal with the same problems: themes, transforms, polymorphism, variants, assets, and overrides.
Arnold provided the following code as illustration:
In Arnold’s vision, a compiler would be able to perform static analysis to understand intent; and multi-platform code generation. In the previous code, the Text
component would compile to a <span>
tag on the web and a <Text>
tag on mobile. The variants
property encodes the customization and default options for the component user.
Interested developers may review the full talk online. The talk provides many additional examples, code samples, and illustrations. React Finland 2021 took place online between the 30th of August and the 3rd of September.