Component-driven UI development with Django and Storybook

This video features Thibaud Colas at DjangoCon Europe 2022 in Porto, Portugal.

Component-driven UI development with Django and Storybook
0:25:05
Published October 14, 2022
2,991 views

Component-driven UI development with Django and Storybook by Thibaud Colas

In the modern JavaScript landscape, component-focused UI frameworks are the norm. We’ll look at how the team behind Wagtail brought component-driven development from React to Django templates with Storybook, speeding up the development process and simplifying maintenance of large pattern libraries.

Summary

Component-driven development builds pages by composing small, reusable UI components, making it easier to maintain consistent interfaces, design systems, and visual behaviour across a Django project. Thibaud Colas argues that Django templates should offer more of the tooling associated with React, including isolated component previews, interactive states, accessibility checks, unit-style tests, and visual regression testing. Using Wagtail and the open-source Storybook Django package, he demonstrates how Django components can be documented and tested in Storybook, integrated with Percy, and composed with template tags that support arbitrary inner content. He also highlights gaps in Django’s template language, including the lack of flexible component slots and multiline template tags, and shows experimental solutions using custom tags and a browser-based PyScript preview.

Key takeaways

  • Component-driven development starts with small reusable pieces and combines them into increasingly complex page templates.
  • Storybook Django lets teams preview Django templates in isolation, edit their context interactively, and share component states with designers and stakeholders.
  • Structured components make automated accessibility testing and Percy-based visual regression testing practical in continuous integration.
  • Custom Django template tags can provide component slots for arbitrary HTML and nested template content, addressing limitations in Django’s built-in include and inheritance patterns.
  • Wagtail uses these techniques to manage a large design system and maintain a highly customizable administration interface.

Summarised automatically from the transcript.

Transcript

4,266 words · auto-generated Show

Automatically transcribed, so expect mistakes in names and technical terms.

0:00

I'm I'm Joe. My pronouns are he, him. I'm super happy to be here. I was initially hoping to put in 2020, like quite a lot of you I'm sure. And it's honestly amazing to finally be there in the Touch the touch the stage, see the people in person is so much nicer in my opinion. Honestly big kudos to the organizers for making this happen over the last few years. but definitely even better for them to follow through and make that happen here in Porto as was the plan. So I'm Thibault. I'm um a developer working at Torchbox in the UK. I work on Wagtail, which is DMS based on Django, as well as uh also contributing to Django's own accessibility team

0:47

And today I'm here to talk about my take on UI development within Django projects. You might not think of Django as something of a UI framework But definitely there's plenty of people who spend a lot of their their day in Django, in Django templates in particular, and I'm actually pretty happy to go through that. And um we'll look at some of the tools we put together to um I guess make this simpler. Quick word from our sponsors. Um my colleague Sage was here earlier today as well saying that Toshbox, our employer, is hiring He's already said that. I just wanted to mention that we do work with pretty cool people in the public sector and non-profit space as well as people who sponsor our CMS Wagtail.

1:32

So yeah Very much open to remote applications as well. So component driven development. It feels like quite a big big term, but it's really not that complex. It's essentially the idea of creating small components once one after the other, starting with the simplest ones, then gradually over time increasing complexity by combining those components until you actually arrive at pages. So if you think of um a CMS like Wagtail, the whole point of the CMS is to help you create pages. There's definitely plenty of commonality between the different pages that you have on the site, so it will be a bit pointless to try and reinvent each and every page in isolation. Instead we basically create small parts of the page and then decide how we combine them into the actual page level templates.

2:24

So not really not really anything too new, but I think it's interesting nonetheless to have this as a term to compare this as a methodology with things like um test-driven development. Obviously when you talk about UI development, it can be quite hard for you to test what you're producing um r or uh in any other way than visually. So it's important to have those methodologies in there, even if what you do is visual testing. And um yes, definitely nothing super new either. Um people who have done quite a bit of front-end development might have heard of atomic design in the past. It was a very similar idea of combining small uh atoms into larger and larger components and then eventually creating pages have a small illustration here with um uh the Instagram

3:10

UI so to the left you can see the tiny atoms, the icons, the buttons and so on, then gradually you combine those into the actual view um that end users look at And um yes, so React as well is well worth mentioning because to me that's the one framework on the UI side of uh full-stack development that brought uh components as one of the foundational pieces of how we structure our projects. I won't go too too b to too deep into React, but basically there are three things in particular that I personally find invaluable that it might not have brought to the table but it definitely popularized quite a bit. Thing number one reusable components as D1 API you create uh your apps from

3:55

Number two, the UI developer tools. Um the React dev tools that we have in the browser are some of the most advanced, or at least they definitely were some of the most advanced in uh uh front-end frameworks world back when it was introduced and um UI testing tools as well uh it's part of continuous integration were very much a new thing. in the front-end world with with React. And um lastly is kind of uh following through from the from the other two, but this idea that um from then on with frameworks like React. you can think of each unit of UI code as something that you can actually write unit tests for some very traditional inputs, outputs. And um yeah we can definitely have the same things for Django. And definitely that's the goal here.

4:42

I want to bring some of those capabilities to Django projects. Before we look at how we do that, I feel like it's interesting to Further make the case that we do want those things in Django, we don't just want Django to be compatible with some of those frameworks So the chart we we're looking at here um took me took me quite a while to put together, but it's there, the data is there. Um the big line the big line that's Green or yeah, I know brownish, the big one. That's Django, and that's Django's uh performance as far as the core web vitals scores, which are um free metrics introduced by Google That's Django 's performance over time compared to some of the other frameworks in this space.

5:28

Took the same ones as Sage had mentioned this morning. So basically the further up the better. And we can see that Django is is quite well placed, but definitely depending on the tool you use you will get different results. Obviously the scores there are the the median scores, so it just gives you a sense of like statistically what you're likely to achieve with a given framework, but it doesn't constrain you necessarily, if at all, on if you actually invest the time, how good of a score you can get. or on the contrary, how bad of the score you can get. So performance, a very clear example of um the impact of any one technology's uh UI capabilities or for end

6:13

users And um accessibility as well, something that's uh very close to my heart. So now we're looking at the median lighthouse accessibility scores for again those four same frameworks. We can see that the average across sorry the median across all frameworks that this tracks is at eighty-three points and Django is right about there and definitely other tools based on what they provide uh score better or or worse. Flask is at uh 71 points as an example, so definitely Flask something that has no opinions about frontend at all. scores quite bad which kind of makes sense. Django, uh in my opinion, there's definitely no reason for it to not score as well as more recent tools like remix.

7:03

So that's why we want this to be a happening in Django and not just compatible with Django with other tools And um in in my uh journey through this, the way I I try to bring this through Django is via my my work with WhiteScale, which is our open source CMS that's based on Django. With Wagtail, we're essentially creating administration UI for people's websites that has to be quite advanced and at the same time very heavily customizable by people who are familiar with Django. So it's quite hard to reconcile those two things and that's why we needed pretty advanced tooling, at least in my opinion. So just as a point of reference, this is the Wivetale main

7:48

page editing interface as of a year and a half ago. And this is the same interface as of today. So obviously if you haven't spent time with Vital yourself, you might not see each and every one of the changes here. But you can definitely see that there's been quite a lot happening over time for us to refine this user experience. And That's why we need tools like Django to have support for those methodologies because when you start to push Django towards its limits on the UI side, you do need more help. And um one key key term I haven't mentioned here this with this component-driven development is uh design systems. So might be a term you're familiar with from the UI and design world as well.

8:37

This idea that uh you first as an organization define all of your components in isolation and then you will be able to replicate that across many different platforms. So that's what we went through with Wagtail and here we're looking at uh all of our shades of buttons And that's essentially it for the main part of the presentation. And now I'll spend as much time as I can get away with on demos of all those tools and hopefully give you a bit more of a backstory on how they work behind the scenes. So I haven't mentioned uh storybook yet, which is definitely in the title of my talk. We'll look at that shortly I forgot to mention by the way all the slides here are available online right away.

9:23

So it's at torchbox. com slash 2022-components if you want to have a look at the links and so on at the same time So we'll start our demo quite simply by looking at Ritel 's design system again. And I'm not looking at our Figma. Uh yeah, we do we do quite like Figma, uh at least for now. I'll leave it at that. It solved quite a few problems for us. Uh definitely makes it super easy to view uh each and every one of the millions of different components and their variations we have in White Tails design systems. And then essentially my job as a UI developer is to translate each and every one of these. into something that looks more or less the same

10:08

and also we can maintain that many of them in code, which is definitely a challenge actually for an open source project. That's why again the tools that I'm talking about today are in my opinion quite parranted. So that 's just a bird's eye view. Now I'll I'll move into uh my personal favorite view of this which is my my spreadsheets where I track all of my lovely components, eighty-free of them, I track where they are used, and I also track their states of I guess updatedness like how maintainable they are and so on. And that's again something that really there's no reason why this has to live in a spreadsheet spreadsheet. We could just have better development tools that factor in these type of considerations. Knowing in Django for example

10:54

where a template include might be used That's very valuable information and would definitely be great for Django templates to have support for those types of use cases And um yeah, now we'll look at the actual tool. So it's uh it's a package called Storybook Django, very very clever, I know, um that combines combines both. We're looking at the Storybook UI right now. For people who might not have seen Storybook before, it's uh coming primarily from the React world initially, and then gained for support for all of the other modern JavaScript frameworks. So you can preview all of your UI components in isolation and test at different states. So Nothing to actually realize, but what we're looking at right now is a preview of a React

11:40

component. And then side by side next to it I have the preview of my Django components. And really, at least from the UI, you can't really tell what they are built with, which is the whole point. You shouldn't need to care at this point in time when looking at this what a given component is built with. The whole point of a tool like this is to again make it much easier to maintain many components, but also that you can put this into the hands of Designers, people who are stakeholders and just want to look at or this specific variation of that component. Do we have it already Do we need to change a lot based on our recent uh specification changes, uh things like that? And it's not just a static demo that you can navigate, you can actually interact with the fields at the bottom here to change each and every one of the little bits of information that are displayed on the page.

12:31

So here I'm changing the CTA label at the very bottom of my info box components. And again that's exactly what we tried to bring to Django. So I might actually demo a simpler component for this. quote block components which is just a Django template and this as well I can edit just as much as I want. And um I have plenty of other interesting goodies in here as a UI developer. So I can change the the background that sits behind each of the components. I can also change the the viewport size, I can configure this based on my projects. agreed upon screen sizes that we test with which is very helpful and I can also run tests which is where this to me really starts to shine

13:17

It's definitely useful to have a repository of everything you have to visually test like this, but it's even better if you can actually automate some of that testing and take some of the pain away from manual like cross-browser making sure this looks right before after any design changes. So automated tests I have in in there. I have accessibility tests for all of my components. And that's both in the browser, in this UI, but also something I can run in continuous integration. So just by virtue of having structured my components like these I can actually run a test suite across the 80 or so components I have in there and check that none of them have any accessibility issues across all of the different states

14:02

I've I have defined test cases for in here. So for example here I can run a test based on whether the quote has an attribution at the bottom or not. Not super relevant here obviously but you you get my point. I also have uh step step-by-step interaction tests in there. Well maybe I don't. I look for them at some other points, but uh essentially many different forms of of testing and one that I I want to demo a bit more than the rest. is visual regression testing. So here I'm switching back to my terminal and at the very bottom you can see I've made two changes to my uh storybook Django project and it's just to install this library called pair

14:49

Percy that has built-in support for Storybook Percy is a pretty cool visual regression testing tool and all I have to do if I already use Storybook is basically tell Percy where my storybook is hosted, which right now is locally run that one command and again Percy is going to go through all of those storybook stories one by one regardless of what they are built with and take screenshots of them, compare them against a baseline version. So again you can imagine that if I was doing this by hand It would be very time consuming and it's definitely much, much, much better that I can do this on like literally every build that touches our CI pipeline. and essentially have much more confidence and um if I'm honest

15:35

have much more confidence for UI things in particular is quite valuable. I feel like in the Django world definitely people are familiar with unique testing of of backend logic, but UI still is uh uh not as not as mature in lots of cases. So I'm looking at the Percy UI now. I won't spend too much time on there but just to show you that it does actually work. So in this case it took 40 screenshots of all of my component variations and I can scroll through them and again the idea being that if I had made some UI changes, I would see them in this kind of view And this is made possible by um having the structured component library. Now I felt like it would be interesting for us to look at an actual actual demo of how you make those types of changes and an actual template.

16:23

If I look at how this code is structured in my IDE, I can say see this stories file, that's where my storybook metadata about the components and where all of my test cases are defined for this one component. The the template itself is basically just a vanilla Django template, no surprises dear. You'll notice that I took the liberty of putting the components JavaScript and style sheets and documentation all in the same templates folder. Not sure how people feel about this, but to me at least it's quite cool. Um yeah, some of my colleagues I feel like find find this quite stressful to look at. Yeah, make make of it what you want. And then yeah, so essentially

17:09

all I do in my my storybook um example for this is load my specific HTML templates. Then tell it to render with my storybook Django library and then configure the different test scenarios for it by providing different context data So context, just the Django views, rendering, context, nothing too fancy here. I can actually also override the the tags from Django, the template tags, which is quite helpful if I don't want to have to mock-up the whole of the context that I need for a given component. And we'll look at a very simple component straight from Wagtail, which is our help block for my next example. So I'll just make sure I'm okay with time. And switch over to the correct view in here.

17:56

Yeah, so that's my help block. My help block is a very simple component, it just has kind of this theme based on its uh status. I can see the status at the very bottom I can I can edit this just as much as I want. I think the predefined ones are critical. Warning. You can also check what happens without a status. It probably shouldn't shift like that when it doesn't have one, but erase the bug for that later. And um what's actually really cool about this component is something I haven't mentioned at all, which is that with this component we managed to solve one of the big issues we have with Django templates. So I'll switch over to an example of where we use this component so you can see what I mean. So

18:42

you'll notice this isn't just uh include helpblock. html. Instead of that I'm using this special template tag called help block just after the name of the template and end help block I think I can probably already see what is going on here, which is that whatever is between those two tags gets rendered inside the headblock If you spent more than a month or so in UI development, this feels like very, very basic functionality that Django itself actually doesn't have. The only way to pass HTML around components like this in Django is via inheritance with the extends tag and blocks There is no way to include a component with arbitrary HTML, and there is no way to include a component with arbitrary templates inside the contents of that component.

19:33

And you could see that here if I wanted to translate this line right there with my trends tag, well I'd have no way to do that with vanilla Django templates. So this is exactly the type of problem we run into and I think ought to be addressed much closer to Django Core than per project And uh the good news is uh there's plenty of people who have solved those problems, um one of whom being my my colleague Mitch. So Uh I didn't do any of this, he did, thank you, thank you, Mitch. Uh Mitch created those template tags that allow us to go through more. I I wanna say advanced but really it's quite fundamental patterns of UI development. So he's created those tags that start with a hash sign and a slash for the end

20:20

tag that make it easy to include arbitrary content within a given component. And there are lots of libraries that do this, not just uh not just sleepers, but definitely I would recommend um Trying this out if you had the chance to see what they look like in practice. The hash and the slash that might might put you off a bit. There's actually another way to do this that is much simpler. We'll switch to my last demo to look at what this other way is. So one of the things I I built a couple of hours ago for for this talk was this um Django templates live preview that is built up on PyScript, which I'm sure you've heard of. So this is actually running Django and Django templates in the browser. So I'll now load Django in there and we'll get to see

21:08

what this this template tag that Mitch put together does It does take quite a bit of time to load. It's about 30 megabytes, so just you can you can access this on your computer, on your phone, but you've you've been warned. Don't go through your roaming allowance. Um so yeah, I can I can make changes in there. It's just a very straightforward code editor and there's no back-end request here. It's just all in the browser thanks to PyScript and the product is built upon called uh Pyodide. And um I can completely change this template. Uh I 'm the boss here really. Um And uh same from your side, you can definitely play with this and try out different variations of the templates. And yeah, the one the one variation I really want everyone here to try

21:53

is this fragment template tag that Mitch has introduced. So I'll first switch to um I guess an example of how I would have done this in the past. I have my button um htbed include that's completely vanilla Django template here. I give it two props slash attributes slash parameters which is label and um what's that Tell you what, there's actually one other thing that really annoys me with Django templates is that all has to be in a single line like this. I feel like I have to spend quite a bit of time on this because I've heard it mentioned as a feature of the language in the past that it forces you to move back to the Python and simplify things in the template.

22:39

But yeah If you're a UI developer, a button HTML element can easily have a class name, an ID two or three area attributes, there's really no reason for those not to be able to fit into multiple lines if they can in HTML. So that's my uh rant slash feature request multi-line template tags. Anyway, so yes, sorry. That's how you do it with Vanilla Django. And um with Mitch 's template tag We can introduce this fragment which means I don't have to change my actual components so far here. I can still include my button It's the exact same line here at the bottom, even though we can't see some of it for some reason.

23:29

And um the one thing that has changed is where this my label comes from comes from. If I look at my previous example with Vanilla Django My label was called button label and came from a variable assignment to this translate tag output. That's very important if I want my button labels with dated. And there is no other way to do it in Django than like this or completely move the label to the Python, which is a bit silly. And what Mitch allows me to do is to actually create this temporary variable that contains arbitrary template syntax and HTML. So here I'm combining the output of translates with another icon component. And you can see how this can get essentially as complex as you need it to be based on what you want to build.

24:15

It might not be a case for a button to have two labels and an icon in the middle like this, obviously, but sometimes there is, and it's important to have this kind of flexibility in uh the base language, again in my opinion. And that's me. This is ready to play, live, online, just costs thirty megabytes of data, so do be careful with your roaming allowance. Storybook Django as well is a library we've open sourced quite a few months ago now and that we do use to actually implement Wagtail. So It's definitely quite well tested. And I'd love to work on any of this or anything else related to UI development with anyone who be there at the sprints. Thanks very much

Questions this talk answers

What is component-driven UI development?

It means building UI from small components, starting with simple pieces and combining them into increasingly complex components and page-level templates. This avoids reinventing each page in isolation and makes shared UI easier to maintain.

Discussed at 1:32

Why bring component-based UI development and testing to Django?

Django projects can benefit from reusable components, browser developer tools, and unit-style UI testing just as frontend frameworks do. This is especially useful when pushing Django templates toward complex, customizable interfaces such as Wagtail’s administration UI.

Discussed at 3:55

What is Storybook Django used for?

Storybook Django lets developers preview Django template components in isolation, inspect different states, and interactively change their context data. The same Storybook interface can show Django and React components without requiring users to care how they were implemented.

Discussed at 10:54

How can you test Django UI components automatically?

Storybook Django can run accessibility tests across components and their defined states, both in the browser and in continuous integration. It can also support interaction tests and visual regression testing through Percy.

Discussed at 13:17

How does visual regression testing work with Storybook Django and Percy?

Percy visits each Storybook story, takes screenshots, and compares them with a baseline version. This allows every build in the CI pipeline to detect unintended visual changes across all component variations.

Discussed at 14:49

How can Django templates pass arbitrary HTML into a reusable component?

Vanilla Django templates generally require inheritance with `extends` and `block` for this pattern, so they cannot directly include a component containing arbitrary template content. The talk demonstrates custom fragment-style template tags that create a temporary value from arbitrary HTML and template syntax, which can then be passed into the component.

Discussed at 19:33

Presenters

Note: We understand that names change, people change, and bodies change. We respect each individual's journey and privacy. If you have any concerns about a video or need us to remove content, please don't hesitate to contact us. We will handle your request with care and promptly address any issues.

More videos by Thibaud Colas

More videos from DjangoCon Europe