From UI-kit to design system
The experience of the Ivy online cinema
When, at the beginning of 2017, we first thought about creating our own system for delivering design to code, many spoke about this and some even did it. However, little is known about the experience of building cross-platform design systems to this day, and there are no clear and proven recipes describing technologies and methods for such a transformation of the design implementation process into an already working product. And “components in code” often means very different things.
Meanwhile, the company doubled its staff from year to year - it was necessary to scale the design department and optimize the processes of creating and transferring layouts to development. We multiply all this by a “zoo” of platforms that need to be supported, and we get a semblance of a Babel crowding, which is simply not capable of “doing normally” and generating income. Platform development often proceeded in parallel, and the same functionality could go out on different platforms with a lag of several months.
Separate sets of layouts for each platform
Traditionally, we started with problems that the design system would help to solve and formulated requirements for its design. In addition to creating a single visual language, increasing the speed of prototyping and development, improving the quality of the product as a whole, it was vitally necessary to unify the design as much as possible. This is necessary so that the development of functionality becomes possible immediately on all our platforms simultaneously: Web, iOS, Android, Smart TV, tvOS, Android TV, Windows 10, xBox One, PS4, Roku - without working on each of them individually . And we did it!
When the principal agreements of the product and development departments were reached, we sat down to select the technological stack and study the details of the entire process - from the layout to the release. To fully automate the process of transferring design to development, we investigated the option with a parser of component parameters directly from Sketch files with layouts. It turned out that finding the pieces of code we needed and extracting the parameters we needed was a complicated and dangerous undertaking. Firstly, designers will have to be extremely careful in naming all layers of the source code, secondly, it works only for the simplest components, and thirdly, dependence on other people's technology and code structure of the original Sketch layout jeopardizes the future of the entire project. We decided to abandon automation in this area. So the first person appeared in the design system team,
The matter remained small: where and how to store data, how to transfer it to development, and how to interpret it in development on all platforms supported by us. The evening ceased to be languid ... The result of regular meetings of the working group, consisting of designers and team leaders from each platform, was the agreement on the following.
We manually parse the visual into atomic elements: fonts, colors, transparency, indents, fillets, icons, pictures, and durations for animations. And we collect from this button, inputs, checkboxes, bank card widgets, etc. We assign non-semantic names to styles of any of the levels, except for icons, for example, city names, names of nymphs, Pokemon, car brands ... There is only one condition - the list should not be exhausted earlier , what styles will end with - show mast go he! You shouldn’t get carried away with semantics so that you don’t have to add a middle button between “small” and “medium”, for example.
The developers left to think about how to store and transfer data so that it fits all platforms, and the design had to design interface elements that could look equally good and work effectively across the entire fleet of supported devices.
Earlier, we managed to “run through” most of the design elements in an application for Windows 10, which at that time was a new platform for us, that is, rendering and development from scratch was required. By drawing it, we were able to prepare and test most of the components and understand which of them were to be included in the future Ivy design system. Without such a sandbox, such an experience could be gained only by a large number of iterations on already working platforms, and this would have taken more than a year.
Reusing the same components on different platforms reduces the number of layouts and the data array of the design system at times, so the design had to solve another problem that had not been previously described in the practice of product design and development - how, for example, to reuse the button for phones and tablets on TVs? And what in principle should be with the sizes of fonts and elements on such different platforms?
Obviously, it was necessary to design a cross-platform modular grid that would set the text and element sizes we needed for each particular platform. For the reference point for the grid, we selected the size and number of movie posters that we want to see on a particular screen and, based on this, formulated a rule for constructing grid columns, provided that the width of one column is equal to the width of the poster.
Now you need to bring all the large screens to the same size of the layout and fit them into the general grid. Apple TV and Roku are being developed in the size of 1920x1080, Android TV - 960x540, Smart TV, depending on the vendor they are the same, and there are 1280x720. When the application is rendered and displayed on Full HD screens, 960 is multiplied by 2, 1280 by 1.33, and 1920 is displayed as is.
Omitting boring details, we came to the conclusion that in general all screens, including TV screens in terms of elements and their sizes, are covered by one design layout, and all TV screens are a special case of a common cross-platform grid, and consist of five or six columns, like an average tablet or desktop. Who cares about the details, go to the comments.
A single UI for all platforms
Now, to draw a new feature, we do not need to draw layouts for each platform, plus adaptability options for each of them. It is enough to show one layout and its adaptability for all platforms and devices of any width: telephones - 320–599, everything else - 600–1280.
Of course, no matter how we would like to come to a completely unified design, each platform has its own unique features. Despite the fact that both the web and Smart TV use the ReactJS + TypeScript stack, the Smart TV application runs on legacy WebKit and Presto clients, and therefore cannot use common styles with the web. And email newsletters are completely forced to work with table layout. At the same time, none of the non-html platforms uses or plans to use React Native or any of its analogues, for fear of performance degradation, since we have too many custom layouts, collections with complex update logic, images and videos. Therefore, a common scheme is not suitable for us - to supply ready-made CSS styles or React components. Therefore, we decided to transfer data in JSON format,
The declarative nature of the description also suggests that if the platform is technically unable to use any property or its value, it can ignore it. In terms of terminology, we made a kind of Esperanto language: we took something from Android, some from SVG, some from CSS.
If it is necessary to display elements in a different way on a particular platform, we have implemented the ability to transfer the corresponding data generation as a separate JSON file. For example, the state is “in focus” for Smart TV, it dictates a change in the position of the text under the poster, so for this platform this component in the value of the “indent” property will contain the 8 indent points it needs. Although this complicates the infrastructure of the design system, it gives an additional degree of freedom, leaving us the opportunity to manage the visual “dissimilarity” of the platforms ourselves, and not be hostages to the architecture we created.
Iconography in a digital product is always a voluminous and not the easiest subproject, often having a separate designer. There are always many glyphs, each of them has several sizes and colors, moreover, platforms need them, as a rule in different formats. In general, there was no reason not to bring all this into the design system.
Glyphs are loaded in vector SVG format, and color values are automatically replaced with variables. Client applications can get them ready to use - in any format and color.
On top of JSON with data, we wrote a tool for previewing components - a JS application that passes JSON data through its markup and style generators on the fly and displays various variations of each component in the browser. In fact, the preview is exactly the same client as the platform applications, and works with the same data.
Understanding how a particular component works is easiest by interacting with it. Therefore, we did not use tools like the Storybook, but did an interactive preview - you can touch, hover, click ... When you add a new component to the design system, it appears in the preview so that the platforms have something to focus on when introducing it.
Based on the data that is delivered in the form of JSON to the platforms, component documentation is automatically generated. The list of properties and possible types of values in each of them are described. After auto-generation, the information can be clarified manually, add a text description. Preview and documentation are provided with cross-references to each other at the level of each component, and all the information falling into the documentation is available to developers in the form of additional JSON files.
Another need was the ability to replace and upgrade existing components over time. The design system has learned to tell developers which properties or even whole components cannot be used and remove them as soon as they are no longer used on all platforms. There is still a lot of “manual” labor in this process, but we are not standing still.
Undoubtedly, the interpretation of the design system data in the code of all the platforms supported by us became the most extensive stage in complexity. If, for example, modular grids on the web are not new, then developers of native mobile applications for iOS and Android sweated pretty hard before they figured out how to live with it.
For layout of the iOS application screens, we use two basic mechanisms that iviUIKit provides: free layout of elements and layout of collections of elements. We use VIPER, and all interaction with iviUIKit is concentrated in View, and the majority of interaction with Apple UIKit is concentrated in iviUIKit. The sizes and arrangement of elements are specified in terms of columns and syntactic constructions working on top of native iOS SDK constants, making them more applied. This especially simplified our life when working with UICollectionView. We wrote some customizable layouts for layouts, including quite complex ones. The client code turned out minimum and it became declarative.
To generate styles in the Android project, we use Gradle, turning the design system data into XML format styles. At the same time, we have several generators of various levels:
After the designers have drawn a new component or reworked an existing one, these changes fall into the design system. The developers of each platform are finalizing their code generation, providing support for changes. After that, it can be used in the implementation of new functionality, where this component is necessary. Thus, interaction with the design system does not occur in real time, but only at the time of assembling new releases. This approach also allows you to better control the process of data transfer and guarantees the performance of the code in client development projects.
Soon, as a design system, a year became a part of the infrastructure serving the development of the Ivy online cinema, and some conclusions can already be drawn:
Preview the components of the Ivy design system - design.ivi.ru
When, at the beginning of 2017, we first thought about creating our own system for delivering design to code, many spoke about this and some even did it. However, little is known about the experience of building cross-platform design systems to this day, and there are no clear and proven recipes describing technologies and methods for such a transformation of the design implementation process into an already working product. And “components in code” often means very different things.
Meanwhile, the company doubled its staff from year to year - it was necessary to scale the design department and optimize the processes of creating and transferring layouts to development. We multiply all this by a “zoo” of platforms that need to be supported, and we get a semblance of a Babel crowding, which is simply not capable of “doing normally” and generating income. Platform development often proceeded in parallel, and the same functionality could go out on different platforms with a lag of several months.
Separate sets of layouts for each platform
Traditionally, we started with problems that the design system would help to solve and formulated requirements for its design. In addition to creating a single visual language, increasing the speed of prototyping and development, improving the quality of the product as a whole, it was vitally necessary to unify the design as much as possible. This is necessary so that the development of functionality becomes possible immediately on all our platforms simultaneously: Web, iOS, Android, Smart TV, tvOS, Android TV, Windows 10, xBox One, PS4, Roku - without working on each of them individually . And we did it!
Design → Data
When the principal agreements of the product and development departments were reached, we sat down to select the technological stack and study the details of the entire process - from the layout to the release. To fully automate the process of transferring design to development, we investigated the option with a parser of component parameters directly from Sketch files with layouts. It turned out that finding the pieces of code we needed and extracting the parameters we needed was a complicated and dangerous undertaking. Firstly, designers will have to be extremely careful in naming all layers of the source code, secondly, it works only for the simplest components, and thirdly, dependence on other people's technology and code structure of the original Sketch layout jeopardizes the future of the entire project. We decided to abandon automation in this area. So the first person appeared in the design system team,
The matter remained small: where and how to store data, how to transfer it to development, and how to interpret it in development on all platforms supported by us. The evening ceased to be languid ... The result of regular meetings of the working group, consisting of designers and team leaders from each platform, was the agreement on the following.
We manually parse the visual into atomic elements: fonts, colors, transparency, indents, fillets, icons, pictures, and durations for animations. And we collect from this button, inputs, checkboxes, bank card widgets, etc. We assign non-semantic names to styles of any of the levels, except for icons, for example, city names, names of nymphs, Pokemon, car brands ... There is only one condition - the list should not be exhausted earlier , what styles will end with - show mast go he! You shouldn’t get carried away with semantics so that you don’t have to add a middle button between “small” and “medium”, for example.
Visual language
The developers left to think about how to store and transfer data so that it fits all platforms, and the design had to design interface elements that could look equally good and work effectively across the entire fleet of supported devices.
Earlier, we managed to “run through” most of the design elements in an application for Windows 10, which at that time was a new platform for us, that is, rendering and development from scratch was required. By drawing it, we were able to prepare and test most of the components and understand which of them were to be included in the future Ivy design system. Without such a sandbox, such an experience could be gained only by a large number of iterations on already working platforms, and this would have taken more than a year.
Reusing the same components on different platforms reduces the number of layouts and the data array of the design system at times, so the design had to solve another problem that had not been previously described in the practice of product design and development - how, for example, to reuse the button for phones and tablets on TVs? And what in principle should be with the sizes of fonts and elements on such different platforms?
Obviously, it was necessary to design a cross-platform modular grid that would set the text and element sizes we needed for each particular platform. For the reference point for the grid, we selected the size and number of movie posters that we want to see on a particular screen and, based on this, formulated a rule for constructing grid columns, provided that the width of one column is equal to the width of the poster.
Now you need to bring all the large screens to the same size of the layout and fit them into the general grid. Apple TV and Roku are being developed in the size of 1920x1080, Android TV - 960x540, Smart TV, depending on the vendor they are the same, and there are 1280x720. When the application is rendered and displayed on Full HD screens, 960 is multiplied by 2, 1280 by 1.33, and 1920 is displayed as is.
Omitting boring details, we came to the conclusion that in general all screens, including TV screens in terms of elements and their sizes, are covered by one design layout, and all TV screens are a special case of a common cross-platform grid, and consist of five or six columns, like an average tablet or desktop. Who cares about the details, go to the comments.
A single UI for all platforms
Now, to draw a new feature, we do not need to draw layouts for each platform, plus adaptability options for each of them. It is enough to show one layout and its adaptability for all platforms and devices of any width: telephones - 320–599, everything else - 600–1280.
Data → Development
Of course, no matter how we would like to come to a completely unified design, each platform has its own unique features. Despite the fact that both the web and Smart TV use the ReactJS + TypeScript stack, the Smart TV application runs on legacy WebKit and Presto clients, and therefore cannot use common styles with the web. And email newsletters are completely forced to work with table layout. At the same time, none of the non-html platforms uses or plans to use React Native or any of its analogues, for fear of performance degradation, since we have too many custom layouts, collections with complex update logic, images and videos. Therefore, a common scheme is not suitable for us - to supply ready-made CSS styles or React components. Therefore, we decided to transfer data in JSON format,
So the property ofrounding: 8
the Windows 10 application converts toCornerRadius="8"
, webborder-radius: 8px
, Android -android:radius="8dp"
, iOS -self.layer.cornerRadius = 8.0
.
Properties ofoffsetTop: 12
the same web client in different cases can be interpreted astop
,margin-top
,padding-top
ortransform
The declarative nature of the description also suggests that if the platform is technically unable to use any property or its value, it can ignore it. In terms of terminology, we made a kind of Esperanto language: we took something from Android, some from SVG, some from CSS.
If it is necessary to display elements in a different way on a particular platform, we have implemented the ability to transfer the corresponding data generation as a separate JSON file. For example, the state is “in focus” for Smart TV, it dictates a change in the position of the text under the poster, so for this platform this component in the value of the “indent” property will contain the 8 indent points it needs. Although this complicates the infrastructure of the design system, it gives an additional degree of freedom, leaving us the opportunity to manage the visual “dissimilarity” of the platforms ourselves, and not be hostages to the architecture we created.
Pictograms
Iconography in a digital product is always a voluminous and not the easiest subproject, often having a separate designer. There are always many glyphs, each of them has several sizes and colors, moreover, platforms need them, as a rule in different formats. In general, there was no reason not to bring all this into the design system.
Glyphs are loaded in vector SVG format, and color values are automatically replaced with variables. Client applications can get them ready to use - in any format and color.
Preview
On top of JSON with data, we wrote a tool for previewing components - a JS application that passes JSON data through its markup and style generators on the fly and displays various variations of each component in the browser. In fact, the preview is exactly the same client as the platform applications, and works with the same data.
Understanding how a particular component works is easiest by interacting with it. Therefore, we did not use tools like the Storybook, but did an interactive preview - you can touch, hover, click ... When you add a new component to the design system, it appears in the preview so that the platforms have something to focus on when introducing it.
Documentation
Based on the data that is delivered in the form of JSON to the platforms, component documentation is automatically generated. The list of properties and possible types of values in each of them are described. After auto-generation, the information can be clarified manually, add a text description. Preview and documentation are provided with cross-references to each other at the level of each component, and all the information falling into the documentation is available to developers in the form of additional JSON files.
Deprecator
Another need was the ability to replace and upgrade existing components over time. The design system has learned to tell developers which properties or even whole components cannot be used and remove them as soon as they are no longer used on all platforms. There is still a lot of “manual” labor in this process, but we are not standing still.
Customer development
Undoubtedly, the interpretation of the design system data in the code of all the platforms supported by us became the most extensive stage in complexity. If, for example, modular grids on the web are not new, then developers of native mobile applications for iOS and Android sweated pretty hard before they figured out how to live with it.
For layout of the iOS application screens, we use two basic mechanisms that iviUIKit provides: free layout of elements and layout of collections of elements. We use VIPER, and all interaction with iviUIKit is concentrated in View, and the majority of interaction with Apple UIKit is concentrated in iviUIKit. The sizes and arrangement of elements are specified in terms of columns and syntactic constructions working on top of native iOS SDK constants, making them more applied. This especially simplified our life when working with UICollectionView. We wrote some customizable layouts for layouts, including quite complex ones. The client code turned out minimum and it became declarative.
To generate styles in the Android project, we use Gradle, turning the design system data into XML format styles. At the same time, we have several generators of various levels:
- Basic . Parsing data of primitives for higher-level generators.
- Resource . Download pictures, icons, and other graphics.
- Component . They are written for each component, which describes what properties and how to translate into styles.
Application releases
After the designers have drawn a new component or reworked an existing one, these changes fall into the design system. The developers of each platform are finalizing their code generation, providing support for changes. After that, it can be used in the implementation of new functionality, where this component is necessary. Thus, interaction with the design system does not occur in real time, but only at the time of assembling new releases. This approach also allows you to better control the process of data transfer and guarantees the performance of the code in client development projects.
Summary
Soon, as a design system, a year became a part of the infrastructure serving the development of the Ivy online cinema, and some conclusions can already be drawn:
- This is a large and difficult project to implement, requiring constant allocated resources.
- This allowed us to create our own unique cross-platform visual language that meets the objectives of the online video service.
- We no longer have visually and functionally lagging platforms.
Preview the components of the Ivy design system - design.ivi.ru