Collective #581

Inspirational Website of the Week: NT On Nathan Taylor’s portfolio everything is interactive! A true digital pleasure. Our pick this week. Get inspired Magical Rainbow Gradients with CSS Houdini and React Hooks A great tutorial by Josh Comeau about a very Read more

All Things Smashing: Monthly Update

dreamt up by webguru in Uncategorized | Comments Off on All Things Smashing: Monthly Update

All Things Smashing: Monthly Update

All Things Smashing: Monthly Update

Iris Lješnjanin



We can’t repeat enough how wonderful the web performance community is! There are good folks who help make the web faster, and their efforts matter indeed. With the new year sinking in and everyone’s resolutions still being put to the test, personal goals such as reproducing bugs and fixing issues suddenly become something we all have in common: improving the web for everyone involved.

As various areas of performance become more and more sophisticated and complicated throughout the years, Vitaly refines and updates his front-end performance checklist every year. This guide covers pretty much everything from performance budgets to single-page apps to networking optimizations. It has proved to be quite useful to folks in the past years — anyone can edit it (PDF, MS Word Doc and Apple Pages) and adjust it to their own personal needs or even use it for their organization.

Now, without further ado, let’s see what’s been cooking at Smashing!

Exciting Times: New Smashing Book

The cover of the upcoming Smashing Book named “Ethical Design Handbook”Are you ready for the next Smashing book? Well, just like all the printed books we’ve published, each and every is crafted to deliver in-depth knowledge and expertise shared by experts and practitioners from the industry. The Ethical Design Handbook will not be any different. Written by Trine Falbe, Martin Michael Frederiksen and Kim Andersen, the book will be pre-released late January.

As always, there will be a pre-order discount available. We expect to ship printed hardcover copies late February, but in the meantime, feel free to subscribe to the book mailing list so that you can be one of the first folks to get your hands on the book!

Less Speaking, More Time For Questions

Our SmashingConfs are known to be friendly, inclusive events where front-end developers and designers come together to attend live sessions and hands-on workshops. From live designing to live debugging, we want you to ask speakers anything — from naming conventions to debugging strategies. For each talk, we’ll have enough time to go into detail, and show real examples from real work on the big screen.

A photo of Dan Mall standing on stage explaining code shown on the screen behind him

Dan Mall, Brad Frost and Ian Frost coding live on stage at SmashingConf in NYC. (Image credit: Drew McLellan) (Watch video)

If you’re eager not to miss out on one of our SmashingConfs, then early-bird tickets are still available. And if you need a lil’ help convincing your boss to send you to an event, let us know! We’ve got your back. 😉

A Taste Of Smashing… Offscreen

Smashing Podcast moderated by Drew McLellanWe’ve reached our 7th episode of the Smashing Podcast! We’re so proud and thrilled to have our dear friends and colleagues, Drew McLellan and Bethany Andrew, managing the bi-weekly interview show so brilliantly! The feedback has been overwhelmingly positive, and now we’re excited for many more!

Shining The Spotlight On TypeScript

Smashing TVIn less than two weeks (Jan. 29), we’ll be hosting a Smashing TV webinar with Stefan Baumgartner who’ll shed light on what type-checking has in store for folks creating and using the web. TypeScript has been one of the most hyped technologies in 2019 — it’s now time to look beyond the hype!

Mark your calendars and join us at 17:00 London time — we’d love to hear your thoughts and experiences you’ve had in your career.

We publish a new article every day on various topics that are current in the web industry. Here are some that our readers seemed to enjoy the most and have recommended further:

Best Picks From Our Newsletter

With the start of a brand-new decade, we decided to start off with topics dedicated to web performance. There are so many talented folks out there working on brilliant projects, and we’d love to spread the word and give them the credit they deserve!

Note: A huge thank you to Cosima Mielke for writing and preparing these posts!

Which Metrics Matter Most?

First Meaningful Paint, Time to Interactive, First Input Delay, SpeedIndex. With so many performance metrics floating around, it’s not easy to strike just the right balance for a project. And most of the time, these metrics alone will be too generic and not precise enough, so we’ll need to complement them with custom ones as well. In small and large companies it’s common to define important pixels in the UI, measure how fast we can start render them, and how quickly we can provide input responsiveness for them.

Every project could benefit from a mix of at least 4 metrics. Time To Interactive (TTI) is the key metrics for understanding how much wait a user has to experience to use the site without a lag. First Input Delay (FID) complements TTI very well as it describes the missing part of the picture: what happens when a user actually interacts with the site.

A graph showing JavaScript fetch, parse, and compile loading phases

JavaScript fetch, parse, and compile loading phases (Image credit)

Total Blocking Time (TBT) helps quantify the severity of how non-interactive a page is prior to it becoming reliably interactive. And Cumulative Layout Shift (CLS) highlights how often users experience unexpected layout shifts (reflows) when accessing the site. All these metrics will appear in Lighthouse v6 as it starts rolling out in 2020.

Additionally, you can look into FrustrationIndex that looks at the gaps between metrics instead of looking at them individually, ad weight impact and Component-Level CPU costs. Note that First Meaningful/Contentful Paint are being replaced with Largest Contentful Paint, and the role of SpeedIndex has decreased with new metrics showing up.

The Impact Of Performance Optimization

It’s no secret that performance has a direct impact on user experience and business metrics and that sometimes, even a seemingly small web performance optimization like shaving off a few milliseconds load time can lead to a better conversion rate. To demonstrate this impact, WPO Stats collects case studies and experiments from products and e-commerce sites — stories of successes and of things that went wrong. Inspiring!

UX Speed Calculator

An open-source visualization tool that helps explain the relationship between page speed, conversion and bounce rates. (Image credit)

To support your performance optimizations with some hard figures and help you better grasp their impact, Sergey Chernyshev built the UX Speed Calculator. It lets you see how speed distribution, error rate, bounce rate, and conversion rate intertwine for the values you enter. A handy little helper.

Automatically Compress The Images In Your PRs

Image optimization is probably one of the easiest tasks on your performance optimization checklist. However, if you have a lot of images to optimize, it can also take up quite some time, and in the hurry, some images might even make it into production skipping this step.

Image Actions

“State of the Web: Video Playback Metrics” by Doug Sillars (Image credit)

To change that, the team at Calibre built a GitHub action that automatically compresses all the JPEGs, PNGs, and WebP images in your pull requests. It’s fast, efficient, and, for near-lossless compression, it uses the best image compression algorithms available: mozjpeg and libvips. A real timesaver.

Resources To Stay On Top Of Performance

A lot of people in the web community are committed to performance and to helping spread the word about it. One of them is Tim Kadlec. In his podcast Chasing Waterfalls, he invites people who work to make the web faster for everyone. Three episodes have already been released, with Reefath Rajali sharing insights into PayPal’s performance journey, Malek Kalim exploring how to scale a culture of performance across an organization, and Katie Hempenius talking about performance budgets, third-party challenges, JavaScript, and a lot of other things that impact performance.

Chasing Waterfalls podcast hosted by Tim Kadlec

Conversations with the people working to make the web faster for everyone, hosted by Tim Kadlec. (Image credit)

Another handy resource to keep you on top of web performance comes from Ben Schwarz and Karolina Szczur. Together they curate the Performance Newsletter, delivering web performance tools, talks, and other resources to your inbox twice a month. There’s also an archive of previous newsletter issues for you to catch up on until the next issue will be sent out.

Each and every issue of the Smashing Newsletter is written and edited with love and care. No third-party mailings or hidden advertising — you’ve got our word.

Smashing Editorial
(cm, vf, ra, il)

Source: Smashing Magazine, All Things Smashing: Monthly Update

Collective #581

dreamt up by webguru in Uncategorized | Comments Off on Collective #581










Collective Item image

Is reduce() bad?

Jake and Surma discuss the array function reduce() and answer the question if it’s good to use it.

Watch it



Collective Item image

CSS4 is here!

Peter-Paul Koch proposes that web developers start saying “CSS4 is here!”, for the marketing effect.

Read it










Collective #581 was written by Pedro Botelho and published on Codrops.


Source: Codrops, Collective #581

The Mythical Mythical Man-Month

dreamt up by webguru in Uncategorized | Comments Off on The Mythical Mythical Man-Month

The Mythical Mythical Man-Month

The Mythical Mythical Man-Month

John Foreman



As a product leader at a tech company, I am a bottomless pit of need. My job as the Chief Product Officer at Mailchimp is to bring the product to market that’s going to win in a very competitive space. Mailchimp’s aspirations are high, and to realize them we need to deliver a substantial amount of product to the market. Oftentimes to many at the company, it feels like we are doing too much. We’re always at the edge of the wheels coming off.

And when you’re doing too much and you decide to do more than even that, you will inevitably begin to hear The Mythical Man-Month referenced. It’s like one of those stress-relief balls where if you squeeze one end, then out pops the Mythical Man-Month at the other end.

Published by Frederick Brooks back in 1975 (you remember 1975, right? When software development 100% resembled software development in 2020?), this book is rather famous amongst software engineers. Specifically, there’s one point in the entire book that’s famous (I’m not convinced people read anything but this point if they’ve read the book at all):

“…adding more men lengthens, not shortens, the schedule.”

Easy fix. I’ll just staff women to projects from now on (see the Return of the King and the fight against the Witch King of Angmar).

But let’s assume that Brooks’ point holds regardless of the gender identification of the software engineers in question. Here’s the point: software is difficult to build with lots of complex interdependencies. And everyone needs to work together to get it done.

As I add people to a team, they need to be onboarded and grafted into the project. Someone’s gotta carve off the right work for them. The team has to communicate to make sure their stuff all works together, and each additional person increases that communication complexity geometrically. And at some point, adding people becomes a burden to the project — not a benefit.

Here’s the graph from the book illustrating that point:

As you add people to tasks with complex interdependencies, progress grinds to a halt

Add people to go slow (Large preview)

This is absolutely a fair point. That’s why I hear it so much at work. Exhausted individual contributors and exhausted leaders alike will toss it out — we can’t go faster, we can’t do more, stop the hiring, read The Mythical Man-Month and despair! The only solution is apparently to stop growing and kill some projects.

When I as CPO say, “we’re going to do this thing!” the reply then is often, “OK, so then what are we going to kill?” The Mythical Man-Month turns product development into a zero-sum game. If we want one thing, we must stop another. Now, that’s an actual myth, and I call hogwash.

And taken to its pathologically misinterpreted (we’ll get to this) conclusion, the book apparently says that the fastest tech company is one that employs all of four people — four men, apparently. Anything more just slows it all down. Someone should send Amazon, Apple, and Google copies of the book, so they can fix their obviously bloated orgs.

The only problem with this approach is that in a space where the competition is growing and iterating and executing — merely tamping organizational growth — editing and focusing the workload to match can be a recipe for extinction. You’ll be more sane and less stressed — right until you’re out of a job.

And as the owner of product management for my company, I’m not unsympathetic with this need to slow down and focus. We must ruthlessly prioritize! No doubt. But running a product is an exercise in contradiction. I must prioritize what I’ve got while simultaneously scheming to get more done. But what am I to do in the face of the Mythical Man-Month?

Surprisingly, the answer to this question comes from Brooks’ same book. Here’s another graph in the same chapter:

Partitionable tasks requiring communication can still add workers and go faster

(Large preview)

There is a battle in scaling product development. If the work you’re trying to accomplish is purely partitionable, then go ahead and add people! If your work is all connected, then at some point adding people is just wrong.

If someone says that I absolutely have to kill a project in order to start another one, that’s just not the case. If the two projects require very little communication and coordination, then we can scale away.

This is why adding cores to a CPU can increase the experienced speed of your computer or phone up to a point — something engineers should know all about. Sure, adding cores won’t help me complete a complex single-threaded computation. But it may help me run a bunch of independent tasks.

The conflict for a product executive then between scaling and ruthless prioritization can be managed.

  1. You ruthlessly prioritize in places that are single-threaded (the backlog for a product team let’s say).
  2. You scale by adding more cores to handle independent work.

Very rarely, however, is anything fully-independent of all else at a company. At the bare minimum, your company is going to centralize supporting functions (global IT, legal, HR, etc.) leading to bottlenecks.

It’s All About Dependency Management

The job of a product executive then becomes not only creating a strategy, but executing in a way that maximizes value for the customer and the business by ensuring throughput and reducing interdependency risk as much as possible. “As much as possible” being key here. That way you can make the company look as much like the latter graph rather than the former. Interdependency is a disease with no cure, but its symptoms can be managed with many treatments.

One solution is to assemble a strategic direction for the company that minimizes or limits dependency through a carefully-selected portfolio of initiatives. The funny thing here is that many folks will push back on this. Let’s say I have two options, one where I can execute projects A, B, and C that have very little coordination (let’s say they impact different products), and another option with projects D1, D2, and D3 that have tons of interdependencies (let’s say they all impact the same product). It’s often the case that the Mythical Man-Month will be invoked against the former plan rather than the latter. Because on paper it looks like more.

Indeed, it’s less “focused.” But, it’s actually less difficult from a dependency perspective and hence fairs better with added personnel.

Keep in mind, I’m not saying to choose a bunch of work for the company that’s not related. Mailchimp will not be building a microwave oven anytime soon. All work should drive in the same long-term direction. This approach can increase customer experience risk (which we’ll discuss later) as well as the burden on global functions such as customer research. Keep an eye out for that.

Another treatment is to create a product and program management process that facilitates dependency coordination and communication where necessary without over-burdening teams with coordination if not required. Sometimes in attempting to manage coordination so we can do more we end up creating such onerous processes that we end up doing less. It’s a balance between doing too little coordination causing the pieces to not inter-operate and doing too much coordination causing the pieces to never get built because we’re all in stand-ups for eternity.

The contention in the Mythical Man-Month is that as you add folks to a software project, the communication needs to increase geometrically. For example, if you have 3 people on the project, that’s 3 lines of communication. But if you have 4, that’s 6 lines of communication. One extra person, in this case, leads to double the communication! Fun. (This is, of course, an over-simplification of communication on software development projects.)

Different people have different roles and hence receive different amounts of autonomy. Perhaps the project manager needs to communicate with everyone on the team. But does an engineer working on the API need to communicate with the product marketer? Or can the marketer just go through the product manager? A good process and meeting cadence can then eliminate unnecessary communication and meetings. The point is that Brooks’ intercommunication formula is an upper bound on coordination, not a death sentence.

Finally, use tools, principles, and frameworks combined with independent work over actual collaboration to combat interdependency symptoms. For example, if I can coordinate two teams’ key performance indicators (KPIs, i.e. measurements of success) to incentivize movement in more-or-less the same direction, then their independent work is more likely to end up “closer together” than if their KPIs incentivize orthogonal movement. This won’t ensure things fit together perfectly, only that the work I need to do to make them fit together in the future is less than it might otherwise be. Other examples might include using “even-over” statements, design systems, and automated testing.

So there’s a start. But interdependencies take on lots of forms beyond code. Let me give an example from Mailchimp.

Customer Experience Risk: The Hidden (But Acceptable?) Cost Of Firewalling Work

Since Mailchimp’s customer is often a small business owner who’s a marketing novice (and there are millions of small business owners turned marketers worldwide), we must deliver an experience that is seamless and immediately understandable end-to-end. We’re not afforded the luxury of assembling a Frankenstein’s monster of clouds via acquisition the way that enterprise players can. We can’t paper over poorly-integrated software with consultants and account managers.

As a consumer product (think Instagram or a Nintendo Switch or a Roomba), we have to be usable out of the box. For an all-in-one marketing platform meant to power your business, that’s hard! And that means each thing Mailchimp builds must be seamlessly connected from an experience perspective.

But, perfectly partitioning projects then introduces experience risk. It’s not that the code can’t be written independently. That can be achieved, but there’s still a risk that the products will look like they’ve been built by different teams, and that experience can be really damn confusing for the user. We bump up against Conway’s law — our customers can tell where one team’s work ends and the other team’s work begins.

So you try to connect everyone’s work together — not just on the back-end but on the front-end, too. In the ecosystem era, dominated by CX excellence from players like Apple, this has become almost table stakes in the consumer space. But this is a Mythical Man-Month nightmare, though not from an engineering perspective this time. It’s from a service design perspective. As we add more people to all of this “end-to-end” connected work, everything slows to a collaborative crawl.

Other than the third fix I noted above, using tools and frameworks rather than over-watchers and stage-gates, there is another release valve: make some deliberate customer experience trade-offs. Specifically, where are we comfortable releasing an experience that’s disconnected from the rest (i.e. that’s sub-par)? Accepting risk and moving forward is the product leader’s job. And so you use some criteria to sort it out (perhaps it’s not holding new, low-traffic areas of the app to the same experience standards as your “cash cows”), and make a decision (e.g. iteration and learning over polish on adjacent innovations). This, of course, extends beyond design.


You can always short-circuit Brooks’ law by choosing to firewall efforts, including efforts that, in a perfect world, shouldn’t be firewalled!

I’ll caveat this by saying the software I build doesn’t kill anyone. I wouldn’t advocate this approach if I were building a medical device. But at a marketing software company, I can deliberately isolate teams knowing that I’ve increased the odds of incompatibility as a trade-off for scaling up personnel and moving faster.

I’m sad to admit that the Mythical Man-Month is a reality at my company, and I suspect at yours as well. But it’s manageable — that’s the bottom line. Parallelization and dependency mitigation offer us a way out that limits the near-mythical status of the Mythical Man-Month. So the next time the stark dichotomy is raised at your company (scale to go slower or give up your aspirations) remember that if you’re smart about how you line up the work, you can still grow big.

Don’t Forget About The Softer Side Of Scaling

Keep in mind that managing the Mythical Man-Month will not stop engineers from invoking it like dark magic. They’re invoking the principle not only because there’s some truth in it, but because scaling just sucks (always) from an emotional and cognitive perspective. If I think I’m paid to write code and solve customer problems, the last thing I wanna do is change up my routine and figure out how to work with new people and a larger team.

As you scale your company, remember to empathize with the pain of scaling and change. A team that adds even a single member becomes a whole new team from a trust and cultural perspective. People are tired of this change. That means that while you go about managing and mitigating the Mythical Man-Month, you’ll need to manage the emotions surrounding growth. That’s perhaps the most critical task of all.

Strong belief in the Mythical Man-Month by a team in and of itself can bring its conclusions into reality. It’s basically the equivalent of the belief in flying in Peter Pan. If the team believes that scaling will slow them and they don’t buy into the change, they will indeed slow down.

So as you work to manage dependencies and introduce tools to help scale, make sure you clearly communicate the why behind the practices. Get folks involved in selecting the work and processes that mitigate man-month issues, because when they’re part of the change and their outlook changes, suddenly scaling becomes at least culturally possible.

Smashing Editorial
(ra, il)

Source: Smashing Magazine, The Mythical Mythical Man-Month

Smashing Podcast Episode 7 With Amy Hupe: What Is A Government Design System?

dreamt up by webguru in Uncategorized | Comments Off on Smashing Podcast Episode 7 With Amy Hupe: What Is A Government Design System?

Smashing Podcast Episode 7 With Amy Hupe: What Is A Government Design System?

Smashing Podcast Episode 7 With Amy Hupe: What Is A Government Design System?

Drew McLellan



Amy HupeHave you ever wondered how design systems are used within a government? Also, if you’d want to document a design system the best way you could, how would you do it? I spoke to Design Systems advocate, Amy Hupe, who shares her advice and lessons learned.

Show Notes

Weekly Update

Transcript

Drew McLellan: She’s a Content Specialist and Design Systems Advocate who spent the last three years working as Senior Content Designer at the Government Digital Service. In that time, she’s led content strategy for the GOV.UK design system, including a straightforward and inclusive approach to documentation. She’s previously worked for consumer advocacy company, Which? where she wrote about everything from composting to conveyancing. And a new role for 2020 sees her take up as Project Manager for Babylon Health Design System, DNA.

Drew: She’s a skilled cook, an Instagrammer, and knows how to use language to make services accessible and inclusive. But did you know she once sang backing vocals for Billy Ray Cyrus? My smashing friends, please welcome Amy Hupe. Hello Amy. How are you?

Amy Hupe: I am smashing. Thank you.

Drew: So I wanted to talk to you today about the role of design systems within government organizations generally, but specifically the GOV.UK design system, which I know you’ve done a lot of work with. I guess first of all, what does the GOV.UK design system encompass? And what was your involvement with it while you were at GDS?

Amy: So it encompasses all kinds of things. So I think the most obvious representation of it is the kind of website side, which is GOV.UK/design-system. And there you’ll find all of the kind of documentation. So all of the design guidelines, and the components and patterns, and you’ll see some of the code, lots of examples and lots of advice on how to use it. But thinking kind of more broadly than that, it also encompasses things like the prototype kit, which is a prototyping tool that is used in government to make HTML and CSS prototypes. So quite high fidelity prototypes and it also has its own kind of front end framework, which is called GOV.UK Front End. So that’s all the code that they use to build the services.

Amy: But then I like to think of design systems more holistically. So as well as all of that stuff, there’s also all the processes that sit around it. So things like how people contribute to it and how people come to know that it exists. Things like adoption and awareness and all that sort of stuff. So all of the things that enable people to design and build services in government is how I would define it.

Drew: So what was your involvement while you were at GDS with that? Where did you slot into that system?

Amy: It all kind of happened by chance, I guess. So I joined as a content designer in January 2017, and my intention when I came to GDS was actually to join the Gov UK content teams. So I thought I was going in to start writing guidance for system, and that was my dream. That was what I wanted to do. Then I arrived on day one and got plunked into this little protect team, called the Service Manual Patterns and Tools team.

Amy: At that point the design system didn’t exist, but we had our design patterns and some bits and pieces knocking about in different places. There was an ambition to try and pull those things together. So I was put into that team as a content designer. I didn’t know what a design pattern was, didn’t know anything about code, didn’t know anything really about web design at all. All I really knew was content.

Amy: So it was a pretty steep learning curve and I spent the next six months to a year, I think, helping the team to prototype it and figure out how it would be organized and laid out and how we would write our guidance, and all that sort of stuff. Then, in the midst of all of that as well as working on the content, I also started to look into the contribution side. So how people would contribute to it and how people would come to discover it and, get in touch with us, and what we would do when they did get in touch with us to try and make it better.

Drew: So what does designing content in that sort of context to be involve? What were the sort of daily tasks you were tackling?

Amy: So all kinds of things really. I mean there were weeks at a time I think where I didn’t write a single word and it was more just going out to research and meeting our users and try sort of understand what it was that they wanted from a design system. So yeah, without getting too far into it, there had been attempts to make something like the GOV.UK design system before, which is how we ended up with this kind of slightly disparate set of resources.

Amy: For one reason or another, these things ended up quite spread out, and it was never really one of them that was seen as the central place to go for this stuff. So a lot of it, it was just trying to understand what had happened before and why those things hadn’t necessarily taken off in the way that we had hoped that they would. Trying to understand which bits of our existing landscape were working for people and which bits weren’t.

Amy: So a lot of it was going out with our research [inaudible 00:05:07], and sitting in user research interviews, and taking notes and talking to people, and just understanding what it was that they needed. Then there were days where I did actually get to sit at a keyboard and write some guidance about some stuff, which was nice too. But yeah, it was very different for me. As you mentioned in the intro, my background was working at Which? So it was much more a traditional editorial role and I was used to working on long form content, and just writing really long articles, and pieces. So yeah, it was quite a big change. It was a big leap from that.

Drew: So your users in this context are people who are working in different government organizations? Is that right? Different departments within the government?

Amy: Yeah. Yeah, that’s right. So people working in, I think there’s 25 different ministerial departments in government, and then there’s lots of agencies and local government departments as well. So we were trying to spread out and talk to a really wide range of people from across the civil service. So yeah, lots of traveling in those early days.

Drew: Do you think that designing or working on a design system for a government, essentially, is any different from a design system for a small company or a big sort of enterprise company?

Amy: I think so. I mean I think from what I can kind of gather from conversations I’ve had, and conferences I’ve been to and stuff, every design system is slightly different and the context is always slightly different, and government is no different in that respect. But yeah, I suppose some of the unique challenges to working on something for government, is first of all the scale of it. So the audience is probably the biggest that you could have because government is so big, and all the different kinds of departments and the geographical spread of those organizations. So the scale of it is definitely something that’s slightly different.

Amy: I think also the fact that it’s not commercially competitive. So we weren’t trying to keep everything under wraps. Everything was done in the open as far as possible. Yeah, it’s all run as a big open source project, which was a slightly unusual concept for me. It took me a little while to get used to that.

Amy: Certainly when we first released it, we would see bits of our guidance and code popping up in other people’s design systems. It took a little while for me to feel all right about that. I think at first I was like, “What’s going on? Why are these people taking our stuff?” But actually now, I really like that. I see that as a big compliment, and I think it’s really good to reuse what you can. But yeah, that’s a strange kind of world to enter when you’ve been used to working in a more commercial setting, I guess.

Drew: I suppose the fact that it’s a essentially publicly funded system, means that is uniquely suited to the public taking it and using it, but also worldwide did you see a lot of use outside of the UK?

Amy: Yeah, yeah, there’s been some really exciting projects across the world that have picked it up. So I know that the New Zealand government have used quite a lot of it. I’m not sure what stage they’re at the moment, but certainly I saw their early data design system and they really used a lot of our guidance and our code, our layouts and things. I think the Dutch government is also using the GOV.UK design system primarily as its first proof of concept. The Australian government started with all of our contribution guidelines and have sort of adapted them based on their research. So we’ve been able to take some of that stuff back in. Yeah, so it’s gone pretty global. It’s exciting.

Drew: Would you factor in the fact that people would be using it when making decisions about the sort of next phase of things? Would it factor into your decisions that it’s actually your audience suddenly isn’t just UK government, it actually could potentially be a worldwide audience?

Amy: It’s definitely a consideration and I think at times that definitely made us as a team quite nervous about certain things that we were doing because the our audience and the scope of it suddenly got much bigger when we were thinking about all the different people that were using it. But personally I think you can’t get too caught up in that primarily we are there to serve the UK government. So it’s not practical to consider all of the potential audiences for it. I kind of think it’s up to the teams to adapt it how they need to for their own, their own users. But yeah, definitely it does make you think quite carefully about just throwing things out there before they’re kind of ready tested and stuff.

Drew: So were there any other sort of surprises in working on this design system other than the fact that it was then taken and used more broadly than you’d initially expected? Did anything else spring out and surprise you about it?

Amy: One thing that definitely stood out to me was the range of people in our audience. So not just the size of the audience, but like the variation in people’s level of knowledge, their skills, their confidence, the different kinds of jobs that they did and the kind of contexts in which they were working. I think there’s definitely a lot of variation in there. I think my perception going in was that I had this vision of this like designer front end developer in my head, somebody who has lots of technical knowledge and actually that’s just one type of user. There are lots of other people like content designers and things weren’t necessarily an expected audience for it, but have turned out to be key users.

Amy: So I think, yeah, that that was definitely a surprise to me. Then thinking about how we could cater to all those people with such a broad set of needs with the design system was definitely quite a big challenge. Yeah, I think that was probably my biggest surprise. Then I guess alongside that just how much people had seen to adopt it as their own. So I think after we launched pretty quickly, I was really pleasantly surprised at how many people I would see going out on advocating for it within their own departments and teams and people trying to contribute to it and people getting in touch with us to ask how they could kind of adapt it for their own users. It felt really community owned from day one and that was not necessarily something I expected, but something that was ready really good to see.

Drew: I guess much of the role of a design system is as a way of sort of documenting the design decisions that have been made so that those decisions can be then implemented and understood, and used by people. So I guess a design system is as much as anything, a documentation artifact isn’t it? It’s taking those decisions that have been made and explaining them in a way that people can reuse them. How did you approach as a team they design system as a sort of documentation artifact? How did you document what you were doing?

Amy: So I think it was about getting as much as we could get in a really clear picture of what people needed from that documentation. So this comes back to that point that I made about it being quite a broad reaching audience because there’s a whole range of different needs that people talk about documenting a component or a pattern like it’s a kind of single task. But actually there are loads of different ways that you can do that and there are loads of different needs that you need to take into consideration. So we have people who, for example would just, they would say, “Oh I want to see the research behind this.” For some people that means a number. They want to know that it’s being used in 20 different services so that they can tell their product manager that it’s worth investing the time and the money in implementing it within their service.

Amy: And that’s for them it’s just about getting that evidence-based backing for the decision that they’re trying to kind of push through. But then there’s other people who really care about understanding the research and whether it’s appropriate for their context and what additional research they might need to fill in to fill any gaps that have been missed or perhaps that they are dealing with in their unique situation. So I think the approach was to try and understand all of those different needs and to try and get a sense of priority amongst those and understand like how we could cater to all of the various different requirements that people had from the documentation. It’s not just one kind of one thing that fits everybody.

Amy: So figuring out how to kind of address all of those needs and to signpost the content really well in a way that meant that people could skip over the bits that weren’t relevant for them as well. Because when you are trying to serve such a broad audience, obviously you end up providing quite a lot of information. So making sure it’s really well signposted and organized I think was quite key to what we were doing.

Drew: So am I right in understanding that different departments within the government aren’t actually compelled to adopt the design system? You actually have to effectively sell it into them and persuade them to use it?

Amy: Yeah, so it’s slightly complicated. So in government there’s something called the government service standard and it’s a standard which all government services with over a certain number of users are required to meet in order to get funding and then to go into Alpha and then Beta and then live. One of the points on the service standard ,I left three weeks ago and it’s already dropped out of my head to which number it is, but one of the points of the service standard, it talks about reusing patterns and components and trying to reuse what’s there already. So sort of under that point they are compelled to use it, but it’s loose and it depends on who the assessor is. It’s not sort of heavily mandated. We would all always sort of advocate for doing what’s best in the specific context rather than just reusing patterns out of the box for the sake of it to tick a point on a service assessment. So it’s difficult to force it. So the approach was always much more collaborative and it was always about building support and building advocacy for the design system not shoving it down people’s throats.

Drew: I guess to that end, one of the ways that you’ve managed to do that is by encouraging contribution. Is that right?

Amy: Yeah, definitely. So I’m a big fan of contribution to design systems. I think it’s something that’s really interesting and yeah, certainly in the team we did a lot of work to make it possible to contribute to the GOV.UK design system. One of the real kind of benefits that we saw from that was The net advocates for the design system increasing. So when you get somebody to contribute to it and they then feel kind of more invested in it and what we received, those people would then go out to their teams and they would become our best sales people almost because they’d feel like they had a little piece of it and they had sort of something to show people and they would then encourage more people to contribute. So that effect ends up being quite exponential. Yeah. So we put a lot of effort into making that possible.

Drew: What sort of things did you do to encourage contribution?

Amy: We started really early. So way before we had a public design system, we started to engage with people who we thought would be interested contributors. I should mention here, we had a brilliant service designer on the team. She joined us in, I’m not going to get the dates correct in any way at the moment, but I think she worked with us in the whole of sort of 2018 and her name’s Ignatia and she just did a fantastic job of going around and engaging people. So one of the things that she did was to go and identify all of the different patterns in government and all of the different variations of those patterns. So going out and kind of saying, okay, there’s, there’s 10 different ways to ask for an address in government. Let’s look at them all together and decide which we think is the most appropriate approach.

Amy: How can we consolidate these into one? She ran a big workshop to try and get people looking at those and doing that kind of consolidation as a team. I think definitely her approach to building collaboration in way before we actually released anything to the public really helped with that because it meant that people already have that kind of awareness of it and many people had already contributed to it in some fashion or another before we actually took it public. So put us a few steps ahead. So I think that was really important. And just persistence, like a lot of persistence from the whole team in kind of helping people to contribute. I think there’s an idea that if you get people to contribute to a design system that’s a pretty sweet gig cause you can just get people to do all the work for you.

Amy: And you just sit there and you make your level code fixes and everybody’s actually giving you all the good stuff. But actually as anyone who’s worked on a design system will know, it’s incredibly complex. It’s very difficult to make a centralized solution that works for multiple different teams, and really, unless you’ve worked on a design system, it’s not reasonable to expect anyone to really understand what that takes. So there’s a lot of hand holding. There’s a lot of work involved in supporting contributors to contribute, I think I said this before, but it probably takes longer, I think, to help somebody to contribute to a design system then it would to just make the thing yourself in the centralized team. But I think recognizing the value that it brings and being persistent in your efforts to make people aware of contribution and help them to do it, help them to feel kind of motivated to do it. I think, yeah, that that persistence was really sort of key to our, our success in that area.

Drew: And just practically speaking with managing those contributions from the community, were there any tools or processes or anything that helped with that?

Amy: Yeah, so we had quite a strict process, I would say. Strict in so far as maybe, strict is the wrong word, comprehensive is probably a better word. So yeah, we have a set of contribution criteria which are in the design system. So everything’s as open as possible so people know what to expect. So there’s a set of criteria that we developed with the various people from the government community outside of our team, so again, like trying to involve people in the creation of these processes I think is really important. So there’s a set of criteria that all contributions to the design system have to meet and to make sure that we were being fairly unbiased, I suppose, and fair in terms of making the decisions about whether things met those criteria or not, we enlisted the support of a working group, which was a panel of representatives from across government. All from kind of different departments and different disciplines and people with different levels of seniority.

Amy: So everybody would have a slightly different perspective on the contributions and we would get together with them once a month and ask them to review any new contributions and decide whether or not they had met the criteria. So yeah, it was a sort of process designed to try and democratize the design of the design system I suppose, and to make it representative and ensure that it wasn’t just our team sitting in the middle making all the decisions without really understanding how it would affect the teams using those things.

Amy: Yeah, that was our sort of process. One more post I should mention is there’s a community backlog on GitHub, which anybody can use it. You don’t have to work in government to go and see it. It’s accessible from the design system and it’s basically a place where we try to host all of the research and all of the experimental stuff and the examples that go into their components and patterns in the design system. So again, it’s about pushing for that transparency and working in the open as much as possible so that people can have a voice and they can influence things before they’ve actually been published.

Drew: And do you think that process has worked well? If you were embarking on the same thing again, do you think you’d adopt a similar process or is there anything that didn’t work?

Amy: I think I would adopt a similar process but perhaps go into with slightly different expectations. What I would say is maybe slightly more realistic expectations and having said what I said about how we think that contributing will make things easier and faster. I was definitely in that camp. I think I thought that there would be a spike of work in the beginning to get people familiar with contributing and then over time we’d be able to be more hands off and people would just get the hang of it and it would be fine. But actually that never really materialized. There was always a lot of work involved in helping people to contribute and as I say, I think that that’s sort of to be expected. I don’t think you can really get away from that, but I still think it’s valuable.

Amy: I still think it’s worth investing that time, but perhaps not with an idea that you’re going to speed things up or that you’re going to be able to scale quicker or more from having contribution. So yeah, I think the process worked well. I do think it needs to be tailored to different organizations, so I’m starting a new role on Monday funnily enough, I’m working on another design system and I don’t expect to be able to pick up that process and just move it over there. I think everything has to be tailored to the organization and the context that you’re dealing with, but there’s definitely elements of it that I would like to try and bring over. But yeah, with slightly tempered expectations, I think.

Drew: I’ve talked a couple of episodes ago with Hayden Pickering about designing components, particularly within a design system to be accessible. That’s something you’ve got a lot of experience with too, I believe. Obviously accessibility is really, really crucial when working within a government design system, but many of us would argue that it’s really, really crucial wherever you’re working. Do you think design systems play a role in the accessibility of a design or the implementation of a design?

Amy: So there’s a brilliant talk by Tatiana Mack about building inclusive design systems that touches on this and that was sort of really influential to me and she talks about the sort of multiplication effect of design systems. So we have, with design systems, we’re telling people what good looks like and we’re giving people kind of quick ways to implement what we’re telling people best practices is. So that can work either way. It can work really well if you give people good design and good accessible design, then you have the potential to multiply that accessible design and to make things more accessible and more inclusive by default.

Amy: If you make decisions that exclude people in a design system, in that centralized space, which becomes the start point for people designing services, then you really have the potential to proliferate that exclusionary design. So I definitely think that design systems play a role in promoting and multiplying accessibility. But I think that it all starts with the intention of the teams working on and using the design system to make that happen. A design system is really it’s just the kind of vehicle I suppose and the intention needs to be there to make things accessible.

Drew: One of the things that always fascinates me, particularly with design systems that have such a large and varied audience like the the GFI UK design system, is the process of proliferating changes across the system. So if you, for example, find an accessibility improvement that you could make in a particular pattern and you make it in the design system, how do you ensure that that gets rolled out across such a broad audience? Is that something you’ve got any experience with?

Amy: Yeah. So again, I think that we kind of in the GOV.UL design system team, we put a lot of consideration into how that would work. I have to be honest, a lot of it is to do with how it’s technically implemented and I’m definitely not the right person to talk so much about the technical aspect of the team. I find there’s sort of two camps with design systems and there’s a camp which is like let’s get stuff out there as quickly as possible. Let’s just make it open soon as we can and that will stop duplication of effort and multiplication of effort and then we can iterate it as we go along. Then I think that there’s a slightly more sort of let’s move a bit more slowly camp, which I think I’m in, which favors holding off on releasing stuff until you have a certain level of confidence in it.

Amy: And I think that’s quite important because I think that in general, if you’re designing products and services, then starting with the minimal thing and then iterating as you go I think works great, but I think when you’re building something central that’s designed for lots and lots of people to sort of reuse and give to lots of different audiences, you very quickly use control of the thing and the way that it’s being used. So I think that having a certain amount of confidence in something before you release it and having a kind of assurance process in place, that means that you’ve got some confidence that it’s accessible before it goes out there is quite key and then hopefully the thing is slightly more stable and I think that’s really important for trust. I think trust is quite important when we’re talking about making changes to design systems because if we’re releasing changes all the time, then that makes the system quite unstable to use and I think that that breaks down trust and then people aren’t so likely to install updates and things.

Amy: Whereas I think if you can show that you’re being considerate about what you’re releasing and you’re releasing changes only when necessary, then you have that Goodwill and then people are more willing to make updates and stuff I think. But yeah, I mean I know that a lot of work went into making sure that the update process was fairly smooth and easy to implement in the GPV.UK design system. I’m just not the right person to talk about it, I think.

Drew: So we talked briefly about documentation. If I was looking to document a design system and if I wanted to do a really good job of it, is there anything that you would advise me to do to make sure I was documenting stuff well?

Amy: I never think it’s possible to kind of just give a blanket statement here because it really does need to cater to like the specific audience that you’re dealing with. My thing is to always aim to be just a little bit more inclusive than you maybe feel that you need to be. So if you’re thinking about, especially in a smaller organization that’s maybe scaling, I think that you have to be just as considerate as your future audience and your potential audience as your current audience. So if you have a small organization and you’ve got 10 front end developers and they all know the same sort of stuff and they’re able to talk to each other and communicate fairly freely, then your documentation may not to be as comprehensive as it within the larger organization.

Amy: But I think that in order to help a design system scale and to make sure that it’s equipped to do that, you have to think about who might join the organization in the future and who do you need to kind of leave the door open for? Who do you need to make things clear to? So I think always aim to be a little bit clearer than you feel you need to be in the moment. I think really testing documentation a lot is useful, so there’s lots of different ways to test content and documentation and I think that it’s really important to go out and make sure that it makes sense to other people. I think Caroline Darret always says that if you understand it well enough to know it’s correct, then you know too much to say that it’s clear.

Amy: Have I said that correctly? If you know it well enough to know it’s correct, then you know it too well to say that it’s clear, that’s better I think. And I really sort of agree with that. I think that to write good documentation you have to have pretty good subject matter knowledge or you need to or you end up developing that subject matter knowledge over time and through the process of writing it. By the time you’ve got that subject matter knowledge, it’s really hard to judge whether or not you’ve conveyed it in a way that’s clear to somebody who doesn’t. So going out and testing it with people who don’t know the subject matter like you do and getting them to actually try and use it in a practical task I think is really important. Yeah, that that’s my sort of number one thing. You’ll learn way more by putting it in front of people then you’ll learn by reading around and looking at what other people have done I think.

Drew: And in doing that you’re obviously going to get feedback on that documentation. Do you have any suggestions for how you would approach fixing things based on that feedback? Is there anything specific that you’d be looking for in the feedback to understand how well your documentation had worked?

Amy: Yeah, I mean there’s a few things I think to watch out for. I think it’s is really important to separate preferences and people perhaps not liking the documentation from people actually not being able to use it. So I think any task-based testing with documentation is better because it might be that actually somebody complains their way through an entire guide but they still complete the task that you’ve set them. That’s not to say that that doesn’t matter. If they wanted to do the thing but they actually hated the process, then you of course need to take that into consideration. But I think that some people and I’m probably one of them just can’t help themselves and will start, especially if it’s a content designer, I think we can’t kind of ever quite put that content design mentality aside.

Amy: So I definitely have a tendency to start live editing stuff if I’m supposed to be participating as research candidate on it. So I think yeah, separating preference from actual kind of usability and blockers is quite important. I think that making sure that your really interrogating the need to make changes and to update things. I think sometimes if somebody is particularly engaged with a design system, depending on the sort of person they are, they can be quite vocal about how they think it could be better or how they think that how they would’ve done it perhaps or how it could be clearer. I think it can be quite, especially if you’re sort of trying to build Goodwill and you’re in that early stage with the design system, it can be quite tempting to just immediately respond to that feedback and do what they say or try and make it clearer.

Amy: But then you can end up building it too far in the direction of the loud minority and I think actually really saying like how many people have got this problem? What evidence do we have that this isn’t working for people? And does that warrant a kind of update? I think yeah, trying to resist the temptation to respond to every comment and bit of criticism that you receive is quite important too, yeah.

Drew: I suppose I’m a common theme here with design systems that enable consistent design and give you a reusable resource in your design and about accepting contributions that make those designs stronger and implementing accessible design choices and documenting your design to make it easy to access and use. It really all comes back to sort of inclusion, would you say that was fair that including people as much as possible?

Amy: Definitely. Yeah. I mean I think that a good design system is a representative design system and I don’t think it’s possible to achieve representation by acting on people’s behalf. I think you really need to try and involve people in the process as much as possible. I think often for people working on design systems and certainly it was the case for us at the GOV.UK design system, you tend to be one step removed from your organizations end users. So if you think for the GOV.UK design system, the people that the design system is ultimately there to serve are members of the public and citizens and people using government services. But we in our team, we’re really working directly with those people. Most of the time our direct users are people working in the civil service. So making sure that you’ve got really strong feedback loops between your direct users and then their users to ensure that it’s representative I think is really important and I think that’s where inclusion comes in and yeah, I completely agree. I think it’s a really central thing, like I can’t imagine how you could build a successful design system without a focus on that.

Drew: Is there anything else that you’d like to share with us about your work on the GOV.UK design system?

Amy: I think my sort of main takeaway from working on it is that, I hate using the word physical when I’m talking about anything on the web, but the the visual representation of a design system I think can end up being the thing that we all get really fixated on. We look at how it’s coded and we look at how it’s organized and what it looks like and how it’s documented and what the design is. I think that obviously that stuff is really important. I think that it’s the thing that you can look at and show people and share. So it’s easy to see why we get fixated on that. But I really think that the most important factor of it is the people. I think that having inclusive processes and making sure that you’re kind of fostering safe discussion spaces and that you’re giving people an opportunity to get involved in the work and to participate and feel motivated to help you with it and to feel this sense of ownership over it.

Amy: I think all of that stuff is really important and all of that stuff really happens outside of the code and outside of the documentation. So yeah, I think my key takeaway from working on the GOV.UK design system is how much of it is really just people work and not really anything to do with guidance and code.

Drew: Here’s at Smashing we’re all about learning. So what have you been learning lately?

Amy: Lately I’ve been learning a lot about productivity and focus. I think definitely towards the end of last year I became aware that I was really plate spinning and luckily I don’t think I smashed any of those plates but I found myself kind of working quite chaotically and moving around lots of different projects and saying yes to everything. So this year is the year that I want to really improve my focus. So I’m trying to learn a little bit about mindfulness and organization and how to say no to things strategically so that I don’t get overwhelmed and too distracted. I’ve started bullet journaling so I’ve really become the full 2020 cliche at this point. So that’s what I’m learning at the moment.

Drew: If you dear listener, would like to hear more from Amy, you can follow her on Twitter where she’s @Amy_Hupe or find her on the web at amyhupe.co.uk. Thanks for joining us today. Amy, do you have any parting words for us?

Amy: Stay cool. What? Why did I say that? Just came out, it just came out.

Smashing Editorial
(dm, ra, il)

Source: Smashing Magazine, Smashing Podcast Episode 7 With Amy Hupe: What Is A Government Design System?

Collective #580

dreamt up by webguru in Uncategorized | Comments Off on Collective #580





Collective item image

Theme UI Gallery

Theme UI is a library for building “consistent, themeable React apps based on constraint-based design principles”.

Check it out





Collective item image

Goodbye, Clean Code

Dan Abramov shares his insights from a “clean code” experience and what he learned along the way.

Read it


Collective item image

Aria Tablist

Zero dependency plain JavaScript module for WCAG compliant tablists. Also great for accordions.

Check it out





Collective item image

/uses

A list of /uses pages detailing developer setups, gear, software and configs.

Check it out


Collective item image

Hiding Elements On The Web

An article by Ahmad Shadeed on how to go about hiding elements in HTML & CSS, that covers accessibility, animation and use cases.

Read it








Collective #580 was written by Pedro Botelho and published on Codrops.


Source: Codrops, Collective #580

An Introduction To React’s Context API

dreamt up by webguru in Uncategorized | Comments Off on An Introduction To React’s Context API

An Introduction To React’s Context API

An Introduction To React’s Context API

Yusuff Faruq



For this tutorial, you should have a fair understanding of hooks. Still, before we begin, I’ll briefly discuss what they are and the hooks we’ll be using in this article.

According to the React Docs:

Hooks are a new addition in React 16.8. They let you use state and other React features without writing a class.”

That is basically what a React hook is. It allows us to use state, refs and other React features in our functional components.

Let us discuss the two hooks we will encounter in this article.

The useState Hook

The useState hook allows us to use state in our functional components. A useState hook takes the initial value of our state as the only argument, and it returns an array of two elements. The first element is our state variable and the second element is a function in which we can use the update the value of the state variable.

Let’s take a look at the following example:

import React, {useState} from "react";

function SampleComponent(){
   const [count, setCount] = useState(0);
}

Here, count is our state variable and its initial value is 0 while setCount is a function which we can use to update the value of count.

The useContext Hook

I will discuss this later in the article but this hook basically allows us to consume the value of a context. What this actually means will become more apparent later in the article.

Yarn Workspaces

Yarn workspaces let you organize your project codebase using a monolithic repository (monorepo). React is a good example of an open-source project that is monorepo and uses Yarn workspaces to achieve that purpose. Learn more →

Why Do We Need The Context API?

We want to build a “theme toggler” component which toggles between light mode and dark mode for our React app. Every component has to have access to the current theme mode so they can be styled accordingly.

Normally, we would provide the current theme mode to all the components through props and update the current theme using state:

import React from "react";
import ReactDOM from "react-dom";

function App() {
  return (
    <div>
      <Text theme= "blue" />
      <h1>{theme}</h1>
    </div>
  );
}

function Text({theme}) {
return(
  <h1 style = {{
     color: `${theme}`
  }}>{theme}</h1>
);
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

In the code sample above, we created a Text Component which renders an h1 element. The color of the h1 element depends on the current theme mode. Currently, the theme is blue. We can toggle between blue and red themes by using state.

We will create a state called “theme” using the useState hook. The useState hook will return the current value of the theme and a function which we can use to update the theme.

So, let us create our theme state:

const [theme, setTheme] = React.useState("blue");

We will also add a button element to our App component. This button will be used to toggle the themes and it needs a click event handler. So, let us write the click event handler like so:

const onClickHandler = () => {
  setTheme();
}

Now, we want to set the new theme to Red if the current theme is Blue, and vice versa. Instead of using an if statement, a more convenient way to do this is with the help of the ternary operator in JavaScript.

setTheme( theme === "red"? "blue": "red");

So now, we have written our onClick handler. Let’s add this button element to the App component:

<button onClick = {onClickHandler}>Change theme</button>

Let us also change the value of the theme props of the Text component to the theme state.

<Text theme={theme}/>

Now, we should have this:

import React from "react";
import ReactDOM from "react-dom";

import "./styles.css";


function App() {
  const[theme, setTheme] = React.useState("red");

  const onClickHandler = () => {
  setTheme( theme === "red"? "blue": "red");
  }

  return (
    <div>
      <Text theme={theme}/>
      <button onClick = {onClickHandler}>Change theme</button>
    </div>
  );
}

function Text({theme}) {
return(
  <h1 style = {{
     color: `${theme}`
  }}>{theme}</h1>
);
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

We can now toggle between our two themes. However, if this was a much larger application, it would be difficult to use the theme in deeply nested components and the code becomes unwieldy.

Introducing The Context API

Let me introduce the Context API. According to the React documentation:

“Context provides a way to pass data through the component tree without having to pass props down manually at every level.”

For a more in-depth definition, it provides a way for you to make particular data available to all components throughout the component tree no matter how deeply nested that component may be.

Let us look at this example:

const App = () => {
  return(
    <ParentComponent theme = "light"/>
  );
}

const ParentComponent = (props) => (
  <Child theme = {props.theme} />
)

const Child = (props) => (
  <Grandchild theme = {props.theme} />
)

const Grandchild = (props) => (
  <p>Theme: {props.theme}</p>
)

In the example above, we specified the application theme using a props in the ParentComponent called theme. We had to pass that props to all components down the component tree to get it where it is needed which is the GrandChild component. The ChildComponent had nothing to do with the theme props but was just used as an intermediary.

Now, imagine the GrandChild component was more deeply nested than it was in the top example. We would have to pass the theme props the same way we did here which would be cumbersome. This is the problem that Context solves. With Context, every component in the component tree has access to whatever data we decide to put in our context.

Let’s Get Started With Context

It’s time to replicate the theme toggling button we built at the beginning of the article with the Context API. This time, our theme toggler will be a separate component. We will build a ThemeToggler component which switches the theme of our React app using Context.

First, let us initialize our React app. (I prefer using create-react-app but you can use whatever method you prefer.)

Once you have initialized your React project, create a file called ThemeContext.js in your /src folder. You can also create a folder called /context and place your ThemeContext file in there if you want.

Now, let us move on.

Creating Your Context API

We will create our theme context in our ThemeContext.js file.

To create a context, we use React.createContext which creates a context object. You can pass in anything as an argument to React.createContext. In this case, we are going to pass in a string which is the current theme mode. So now our current theme mode is the “light” theme mode.

import React from "react";

const ThemeContext = React.createContext("light");
export default ThemeContext;

To make this context available to all our React components, we have to use a Provider. What is a Provider? According to the React documentation, every context object comes with a Provider React component that allows consuming components to subscribe to context changes. It is the provider that allows the context to be consumed by other components. That said, let us create our provider.

Go to your App.js file. In order to create our provider, we have to import our ThemeContext.

Once the ThemeContext has been imported, we have to enclose the contents of our App component in ThemeContext.Provider tags and give the ThemeContext.Provider component a props called value which will contain the data we want to make available to our component tree.

function App() {
  const theme = "light";
  return (
    <ThemeContext.Provider value = {themeHook}>
      <div>
      </div>
    </ThemeContext.Provider>
  );
}

So now the value of “light” is available to all our components (which we will write soon).

Creating Our Theme File

Now, we will create our theme file that will contain the different color values for both our light and dark themes. Create a file in your /src folder called Colors.js.

In Colors.js, we will create an object called AppTheme. This object will contain the colors for our themes. Once you are done, export the AppTheme object like so:

const AppTheme = {
    light: {
        textColor: "#000",
        backgroundColor: "#fff"
    },
    dark: {
        textColor: "#fff",
        backgroundColor: "#333"
    }
}

export default AppTheme;

Now it’s time to start creating our different React components.

Creating Our React Components

Let’s create the following components:

  • Header
  • ThemeToggler
  • MainWithClass
Header.jsx
import React from "react";
import ThemeToggler from "./ThemeToggler";

const headerStyles = {
    padding: "1rem",
    display: "flex",
    justifyContent: "space-between",
    alignItems: "center"
}
const Header = () => {
    return(
        <header style = {headerStyles}>
            <h1>Context API</h1>
            <ThemeToggler />
        </header>
    );
}

export default Header;
ThemeToggler.jsx

(For now, we will just return an empty div.)

import React from "react";
import ThemeContext from "../Context/ThemeContext";

const themeTogglerStyle = {
    cursor: "pointer"
}
const ThemeToggler = () => {
        return(
            <div style = {themeTogglerStyle}>
            </div>
    );
}

export default ThemeToggler;

Consuming Context With Class-Based Components

Here, we will use the value of our ThemeContext. As you may already know, we have two methods of writing components in React: through functions or classes. The process of use context in both methods is different so we will create two components to serve as the main section of our application: MainWithClass and MainWithFunction.

Let us start with MainWithClass.

MainWithClass.jsx

We will have to import our ThemeContext and AppTheme. Once that is done, we will write a class that returns our JSX from a render method. Now we have to consume our context. There are two methods to do this with class-based components:

  1. The first method is through Class.contextType.

    To use this method, we assign the context object from our ThemeContext to contextType property of our class. After that, we will be able to access the context value using this.context. You can also reference this in any of the lifecycle methods and even the render method.

    import React, { Component } from "react";
    import ThemeContext from "../Context/ThemeContext";
    import AppTheme from "../Colors";
    
    class Main extends Component{
        constructor(){
            super();
        }
        static contextType = ThemeContext;
        render(){
            const currentTheme = AppTheme[this.context];
            return(
                <main></main>
            );
        }
    
    }
    

    After assigning ThemeContext to the contextType property of our class, I saved the current theme object in the currentTheme variable.

    Now, we will grab the colors from the currentTheme variable and use them to style some markup.

    render() {
            const currentTheme = AppTheme[this.context];
            return (
                <main style={{
                    padding: "1rem",
                    backgroundColor: `${currentTheme.backgroundColor}`,
                    color: `${currentTheme.textColor}`,
    
                }}>
                    <h1>Heading 1</h1>
                    <p>This is a paragraph</p>
                    <button> This is a button</button>
                </main>
    

    That’s it! This method, however, limits you to consuming only one context.

  2. The second method is ThemeContext.Consumer that involves the use of a Consumer. Each context object also comes with a Consumer React component which can be used in a class-based component. The consumer component takes a child as a function and that function returns a React node. The current context value is passed to that function as an argument.

    Now, let us replace the code in our MainWithClass component with this:

    class Main extends Component {
        constructor() {
            super();
            this.state = {
            }
        }
        render(){
                   return(
                        <ThemeContext.Consumer>
                       {
                        (theme) => {
                            const currentTheme = AppTheme[theme];
                            return(
                                <main style = {{
                                    padding: "1rem",
                                    backgroundColor: `${currentTheme.backgroundColor}`,
                                    color: `${currentTheme.textColor}`,
                                
                                }}>
                                    <h1>Heading 1</h1>
                                    <p>This is a paragraph</p>
                                    <button> This is a button</button>
                                </main>
                            )
                           
                        }
                    }
                </ThemeContext.Consumer>
            );
        }
    
    }
    

    As you can see, we used the current value of our ThemeContext which we aliased as “theme” and we grabbed the color values for that theme mode and assigned it to the variable currentTheme. With this method, you can use multiple Consumers.

Those are the two methods of consuming context with class-based components.

Consuming Context With Functional Components

Consuming context with functional components is easier and less tedious than doing so with class-based components. To consume context in a functional component, we will use a hook called useContext.

Here is what consuming our ThemeContext with a functional component would look like:

const Main = () => {
    const theme = useContext(ThemeContext);
    const currentTheme = AppTheme[theme];
    return(
        <main style = {{
            padding: "1rem",
            backgroundColor: `${currentTheme.backgroundColor}`,
            color: `${currentTheme.textColor}`,
        
        }}>
            <h1>Heading 1</h1>
            <p>This is a paragraph</p>
            <button> This is a button</button>
        </main>
    );
}

export default Main;

As you can see, all we had to do was use our useContext hook with our ThemeContext passed in as an argument.

Note: You have to use these different components in the App.js file in order to see the results.

Updating Our Theme With The ThemeToggler Component

Now we are going to work on our ThemeToggler component. We need to be able to switch between the light and dark themes. To do this, we are going to need to edit our ThemeContext.js. Our React.createContext will now take an object resembling the result of a useState hook as an argument.

const ThemeContext = React.createContext(["light", () => {}]);

We passed an array to the React.createContext function. The first element in the array is the current theme mode and the second element is the function that would be used to update the theme. As I said, this just resembles the result of a useState hook but it is not exactly the result of a useState hook.

Now we will edit our App.js file. We need to change the value passed to the provider to a useState hook. Now the value of our Theme Context is a useState hook whose default value is “light”.

function App() {
  const themeHook = useState("light");
  return (
    <ThemeContext.Provider value = {themeHook}>
      <div>
        <Header />
        <Main />
        
      </div>
    </ThemeContext.Provider>
  );
}

Writing Our ThemeToggler Component

Let us now actually write our ThemeToggler component:

import React,{useContext} from "react";
import ThemeContext from "../Context/ThemeContext";

const themeTogglerStyle = {
    cursor: "pointer"
}
const ThemeToggler = () => {
    const[themeMode, setThemeMode] = useContext(ThemeContext);
    return(
        <div style = {themeTogglerStyle} onClick = {() => {setThemeMode(themeMode === "light"? "dark": "light")}}>
            <span title = "switch theme">
                {themeMode === "light" ? "🌙" : "☀️"}
            </span>
        </div>
    );
}

export default ThemeToggler;

Since the value of our theme context is now a hook whenever we call useContext on it, it will return an array. Using destructuring, we were able to grab the elements from the array. We then wrote an onClick event handler for our ThemeToggler. With that code, whenever the theme toggler is clicked, it will switch the theme of our application.

Now we will edit the different versions of our Main component.

Editing Our MainWithClass Component

  1. The version of the MainWithClass component that uses the Class.contextType method:
    import React, { Component } from "react";
    import ThemeContext from "../Context/ThemeContext";
    import AppTheme from "../Colors";
    
    class Main extends Component{
        constructor(){
            super();
        }
        static contextType = ThemeContext;
        render(){
            const currentTheme = AppTheme[this.context[0]];
            return(
                <main style={{
                    padding: "1rem",
                    backgroundColor: `${currentTheme.backgroundColor}`,
                    color: `${currentTheme.textColor}`,
    
                }}>
                    <h1>Heading 1</h1>
                    <p>This is a paragraph</p>
                    <button> This is a button</button>
                </main>
    
            );
        }
    
    }
    
  2. The version of the MainWithClass component that uses the ThemeContext.Consumer method:
    import React, { Component } from "react";
    import ThemeContext from "../Context/ThemeContext";
    import AppTheme from "../Colors";
    
    class Main extends Component {
        constructor() {
            super();
            this.state = {}
        }
        render() {
            return (
                <ThemeContext.Consumer>
                    {
                        ([theme]) => {
                            const currentTheme = AppTheme[theme];
                            return(
                                <main style = {{
                                    padding: "1rem",
                                    backgroundColor: `${currentTheme.backgroundColor}`,
                                    color: `${currentTheme.textColor}`,
                                
                                }}>
                                    <h1>Heading 1</h1>
                                    <p>This is a paragraph</p>
                                    <button> This is a button</button>
                                </main>
                            )
                           
                        }
                    }
                </ThemeContext.Consumer>
            );
        }
    
    }
    export default Main;
    

Editing Our MainWithFunction Component

The MainWithFunction Component should be edited as the following:

import React, { useContext } from "react";
import ThemeContext from "../Context/ThemeContext";
import AppTheme from "../Colors";


const Main = () => {
    const theme = useContext(ThemeContext)[0];
    const currentTheme = AppTheme[theme];
    return(
        <main style = {{
            padding: "1rem",
            backgroundColor: `${currentTheme.backgroundColor}`,
            color: `${currentTheme.textColor}`,        
        }}>
            <h1>Heading 1</h1>
            <p>This is a paragraph</p>
            <button> This is a button</button>
        </main>
    );
}

export default Main;

Conclusion

That’s it! We have succeeded in implementing two theme modes for our React app using the Context API.

In the process, we have learned:

  • What the Context API is and the problem it solves;
  • When to use the Context API;
  • Creating Context and consuming it in both functional and class-based components.

Further Reading on SmashingMag:

Smashing Editorial
(dm, il)

Source: Smashing Magazine, An Introduction To React’s Context API

Understanding CSS Grid: Grid Lines

dreamt up by webguru in Uncategorized | Comments Off on Understanding CSS Grid: Grid Lines

Understanding CSS Grid: Grid Lines

Understanding CSS Grid: Grid Lines

Rachel Andrew



In the first article in this series, I took a look at how to create a grid container and the various properties applied to the parent element that make up your grid. Once you have a grid, you have a set of grid lines. In this article, you will learn how to place items against those lines by adding properties to the direct children of the grid container.

We will cover:

  1. The placement properties grid-column-start, grid-column-end, grid-row-start, grid-row-end and their shorthands grid-column and grid-row.
  2. How to use grid-area to place by line number.
  3. How to place items according to line name.
  4. The difference between the implicit and explicit grid when placing items.
  5. Using the span keyword, with a bit of bonus subgrid.
  6. What to watch out for when mixing auto-placed and placed items.

Basic Concepts Of Line-Based Positioning

To place an item on the grid, we set the line on which it starts, then the line that we want it to end on. Therefore, with a five-column, five-row grid, if I want my item to span the second and third column tracks, and the first, second and third row tracks I would use the following CSS. Remember that we are targetting the line, not the track itself.

.item {
  grid-column-start: 2;
  grid-column-end: 4;
  grid-row-start: 1;
  grid-row-end: 4;
}

This could also be specified as a shorthand, the value before the forward slash is the start line,m the value after is the end line.

.item {
  grid-column: 2 / 4;
  grid-row: 1 / 4;
}

On CodePen you can see the example, and change the lines that the item spans.

See the Pen Grid Lines: placement shorthands by Rachel Andrew (@rachelandrew) on CodePen.

See the Pen Grid Lines: placement shorthands by Rachel Andrew (@rachelandrew) on CodePen.

Note that the reason our box background stretches over the entire area is because the initial values of the alignment properties align-self and justify-self are stretch.

If you only need your item to span one track, then you can omit the end line, as the default behavior is that items span one track. We see this when we auto place items as in the last article, each item goes into a cell – spanning one column and one-row track. So to cause an item to span from line 2 to 3 you could write:

.item {
  grid-column: 2 / 3;
}

It would also be perfectly correct to miss off the end line:

.item {
  grid-column: 2;
}

The grid-area Shorthand

You can also place an item using grid-area. We’ll encounter this property again in a future article, however, when used with line numbers it can be used to set all four lines.

.item {
  grid-area: 1 / 2 / 4 / 4;
}

The order of those line numbers is grid-row-start, grid-column-start, grid-row-end, grid-column-end. If working in a horizontal language, written left to right (like English), that’s top, left, bottom, right. You may have realized this is the opposite of how we normally specify shorthands such as margin in CSS – these run top, right, bottom, left.

The reason for this is that grid works in the same way no matter which writing mode or direction you are using, and we’ll cover this in detail below. Therefore, setting both starts then both ends makes more sense than mapping the values to the physical dimensions of the screen. I don’t tend to use this property for line-based placement, as I think the two-value shorthands of grid-column and grid-row are more readable when scanning through a stylesheet.

Lines On The Explicit Grid

I mentioned the explicit versus the implicit grid in my last article. The explicit grid is the grid that you create with the grid-template-columns andgrid-template-rows properties. By defining your column and row tracks, you also define lines between those tracks and at the start and end edges of your grid.

Those lines are numbered. The numbering starts from 1 at the start edge in both the block and inline direction. If you are in a horizontal writing mode, with sentences which begin on the left and run towards the right this means that line 1 in the block direction is at the top of the grid, and line 1 in the inline direction is the left-hand line.

Item is shown in position with the Firefox Grid Inspector highlighting the lines

The item placed on the grid

If you are working in a horizontal RTL language – as you might be if working in Arabic – then line 1 in the block direction is still at the top, but line 1 in the inline direction is on the right.

The item is now placed from the right-hand side of the grid

The same placement with direction: rtl

If you are working in a Vertical Writing Mode, and in the image below I have set writing-mode: vertical-rl, then line 1 will be at the start of the block direction in that writing mode, in this case on the right. Line 1 in the inline direction is at the top.

The entire grid is now rotated 90 degrees

The same placement in writing-mode: vertical-rl

Therefore, grid lines are tied to the writing mode and script direction of the document or component.

The end line of your explicit grid is number -1 and lines count back in from that point, making line -2 the second from the last line. This means that if you want to span an item across all tracks of the explicit grid you can do so with:

.item {
  grid-column: 1 / -1;
}

Lines On The Implicit Grid

If you have created implicit grid tracks then they also count up from 1. In the example below, I have created an explicit grid for columns, however, row tracks have been created in the implicit grid, where I am using grid-auto-rows to size these to 5em.

The item with a class of placed has been placed to span from row line 1 to row line -1. If we were working with an explicit grid for our two rows, then the item should span two rows. Because the row tracks have been created in the implicit grid, line -1 resolved to line 2, and not line 3.

See the Pen Grid Lines: explicit vs. implicit grid by Rachel Andrew (@rachelandrew) on CodePen.

See the Pen Grid Lines: explicit vs. implicit grid by Rachel Andrew (@rachelandrew) on CodePen.

There is currently no way to target the last line of the implicit grid, without knowing how many lines you have.

Placing Items Against Named Lines

In the last article I explained that in addition to line numbers, you can optionally name lines on your grid. You name the lines by adding a name or names inside square brackets between your tracks sizes.

.grid {
  display: grid;
  grid-template-columns: [full-start] 1fr [main-start] 2fr 2fr [main-end full-end];
}

Once you have some named lines, you can swap out the line number for a name when placing your items.

.item {
  grid-column: main-start / main-end;
}

See the Pen Grid Lines: naming lines by Rachel Andrew (@rachelandrew) on CodePen.

See the Pen Grid Lines: naming lines by Rachel Andrew (@rachelandrew) on CodePen.

If your line has several names, you can pick whichever one you like when placing your item, all of the names will resolve to that same line.

Note: There are some interesting things that happen when you name lines. Take a look at my article “Naming Things In CSS Grid Layout” for more.

What Happens If There Are Multiple Lines With The Same Name?

You get some interesting behavior if you have multiple lines that have the same name. This is a situation that could happen if you name lines within repeat() notation. In the example below I have an 8 column grid, created by repeating 4 times a pattern of 1fr 2fr. I have named the line before the smaller track sm and the larger track lg. This means that I have 4 lines with each name.

In this situation, we can then use the name as an index. So to place an item starting at the second line named sm and stretching to the third line named lg I use grid-column: sm 2 / lg 3. If you use the name without a number that will always resolve to the first line with that name.

See the Pen Grid Lines: naming lines by Rachel Andrew (@rachelandrew) on CodePen.

See the Pen Grid Lines: naming lines by Rachel Andrew (@rachelandrew) on CodePen.

Using The span Keyword

There are situations where you know that you want an item to span a certain number of tracks, however, you don’t know exactly where it will sit on the grid. An example would be where you are placing items using auto-placement, but want them to span multiple tracks rather than the default 1. In this case, you can use the span keyword. In the example below, my item starts on line auto, this is the line where auto-placement would put it, and it then spans 3 tracks.

.item {
  grid-column: auto / span 3;
}

See the Pen Grid Lines: span keyword by Rachel Andrew (@rachelandrew) on CodePen.

See the Pen Grid Lines: span keyword by Rachel Andrew (@rachelandrew) on CodePen.

This technique will become very useful once we have wide support of the subgrid value for grid-template-columns and grid-template-rows. For example, in a card layout where the cards have a header and main content area in which you want to align with each other, you can cause each card to span 2 rows, while still allowing for the usual auto-placement behavior. The individual cards will use subgrid for their rows (i.e. getting two rows each). You can see this in the below example if you use Firefox, and read my article CSS Grid Level 2: Here Comes Subgrid to learn more about subgrid.

See the Pen Grid Lines: span keyword and subgrid by Rachel Andrew (@rachelandrew) on CodePen.

See the Pen Grid Lines: span keyword and subgrid by Rachel Andrew (@rachelandrew) on CodePen.

/

A grid of cards with the Firefox Grid Inspector showing they each sit over two rows of the grid

The example in Firefox using the Grid Inspector

Layering Items With Line-Based Placement

Grid will auto-place items into empty cells on the grid, it won’t stack items into the same cell. However, by using line-based placement you can put items into the same grid cell. In this next example, I have an image that spans two-row tracks, and a caption which is placed in the second track and given a semi-transparent background.

See the Pen Grid Lines: card with layered elements by Rachel Andrew (@rachelandrew) on CodePen.

See the Pen Grid Lines: card with layered elements by Rachel Andrew (@rachelandrew) on CodePen.

Items will stack up in the order that they appear in the document source. So in the above example, the caption comes after the image and therefore displays on top of the image. If the caption had come first then it would end up displaying behind the image and we wouldn’t be able to see it. You can control this stacking by using the z-index property. If it was important for the caption to be first in the source, then you can use z-index, with a higher value for the caption than the image. This would force the caption to display on top of the image so that it can be read.

Mixing Line-Based And Auto-Placement

You need to take a little extra care if you are mixing placed items with auto-placed ones. When items are fully auto-placed in grid, they will place themselves sequentially onto the grid, each finding the next available empty space to put themselves into.

See the Pen Grid Lines: auto-placement by Rachel Andrew (@rachelandrew) on CodePen.

See the Pen Grid Lines: auto-placement by Rachel Andrew (@rachelandrew) on CodePen.

The default behavior is always to progress forwards, and to leave a gap if an item does not fit on the grid. You can control this behavior by using the property grid-auto-flow with a value of dense. In this case, if there is an item that fits a gap already left in the grid, it will be placed out of source order in order to fill the gap. In the example below using dense packing, item 3 is now placed before item 2.

See the Pen Grid Lines: auto-placement and dense packing by Rachel Andrew (@rachelandrew) on CodePen.

See the Pen Grid Lines: auto-placement and dense packing by Rachel Andrew (@rachelandrew) on CodePen.

Note that this behavior can cause problems for users who are tabbing through the document as the visual layout will be out of sync with the source order that they are following.

Auto-placement works slightly differently if you have already placed some items. The placed items will be positioned first, and auto-placement will then look for the first available gap to start placing items. If you have left some whitespace at the top of your layout by way of an empty grid row, then introduce some items which are auto-placed, they will end up in that track.

To demonstrate in this final example I have placed with the line-based positioning properties, items 1 and 2 leaving the first row empty. Later items have moved up to fill the gaps.

See the Pen Grid Lines: auto-placement mixed with placed items by Rachel Andrew (@rachelandrew) on CodePen.

See the Pen Grid Lines: auto-placement mixed with placed items by Rachel Andrew (@rachelandrew) on CodePen.

This behavior is worth understanding, as it can mean that items end up in strange places if you introduce some new elements to your layout which haven’t been given a placement on the grid.

Wrapping Up

That is pretty much all you need to know about grid lines. Remember that you always have numbered lines, no matter how else you are using grid you can always place an item from one line number to another. The other methods we will look at in future articles are alternate ways to specify your layout, but are based on the grid created by numbered lines.

Smashing Editorial
(il)

Source: Smashing Magazine, Understanding CSS Grid: Grid Lines

Collective #579

dreamt up by webguru in Uncategorized | Comments Off on Collective #579









Collective item image

EscherSketch

A really nice tool for drawing and exploring symmetrical patterns and designs. It can export pictures, pattern tiles for fabric and wallpaper design, and SVG for further editing.

Check it out




Collective item image

Publish

A static site generator built specifically for Swift developers. It enables entire websites to be built using Swift, supporting themes, plugins and more customization options.

Check it out


Collective item image

Whack-a-mole!

Andrew Burton coded this offline-first PWA version of Whack-a-mole for his children. The source code can be found here.

Check it out





Collective item image

22120

An archivist browser controller that caches everything you browse, a library server with full text search to serve your archive.

Check it out






Collective #579 was written by Pedro Botelho and published on Codrops.


Source: Codrops, Collective #579

How To Create And Deploy Angular Material Application

dreamt up by webguru in Uncategorized | Comments Off on How To Create And Deploy Angular Material Application

How To Create And Deploy Angular Material Application

How To Create And Deploy Angular Material Application

Shubham



Angular is one of the popular choices while creating new web applications. Moreover, “Material Design” specs have become a go-to choice for creating minimal and engaging experience today. Thus, any new “Angular” project mostly uses the “Angular Material Design Library” to use the components which follow the material design specifications. From smooth animations to proper interaction feedback, all of this is already available as part of the official material design library for angular.

After the web application is developed, the next step is to deploy it. That is where “Netlify” comes into the picture. With its very easy to use interface, automatic deployment, traffic splitting for A/B testing and various other features, Netlify is surely a great tool.

The article will be a walkthrough of creating an Angular 8 web application using the official Angular Material Design library. We will be creating a QR Code generator web application completely based on Angular while hosted on Netlify.

Files for this tutorial can be found on GitHub and a demo version is deployed here.

Getting Started

  1. Install Angular 8,
  2. Create a Github account,
  3. Install Git on your computer,
  4. Create a Netlify account.

Note: I will be using VSCode and Microsoft Windows as the preferred IDE and OS, though the steps would be similar for any other IDE on any other OS.

After the above prerequisites are complete, let’s begin!

Mocks & Planning

Before we begin creating the project, it would be beneficial to plan ahead: What kind of UI would we want in our application? Will there be any reusable pieces? How will the application interact with external services?

First, check the UI mocks.

Homepage (Large preview)

Creating a QR Page (Large preview)

History page (Large preview)

These are the three different pages which will be contained in the application. The homepage will be the starting point of our application. Creating a QR page should deal with the creation of a new QR code. The History page will show all the saved QR codes.

The mockups not only provide an idea of the look and feel of the application, but they also segregate the responsibility of each page.

One observation (from the mocks) is that it seems that the top navigation bar is common across all the pages. Thus, the navigation bar can be created as a reusable component and reused.

Now that we have a fair bit of an idea as to how the application will look and what can be reused, let’s start.

Creating A New Angular Project

Launch VSCode, then open a terminal window in VSCode to generate a new Angular project.

Terminal in VSCode (Large preview)

The terminal will open with a default path as shown in the prompt. You can change to a preferred directory before proceeding; in the case of Windows, I will use the cd command.

Navigating to the preferred path (Large preview)

Moving forward, angular-cli has a command to generate new projects ng new <project-name>. Just use any fancy project name you like and press enter, e.g. ng new qr.

This will trigger the angular-cli magic; it will provide a few options to configure some aspects of the project, for instance, adding angular routing. Then, based on the selected options, it will generate the whole project skeleton which can be run without any modification.

For this tutorial, enter Yes for routing and select CSS for styling. This will generate a new Angular project:

Creating a new Angular project (Large preview)

We now have got ourselves a fully working Angular project. In order to make sure everything is working properly, we can run the project by entering this command in the terminal: ng serve. Uh oh, but wait, this results in an error. What could have happened?

ng serve error (Large preview)

Don’t worry. Whenever you create a new project using angular-cli, it generates the whole skeleton inside a folder named after the project name specified in the command ng new qr. Here, we will have to change the current working directory to the one just created. In Windows, use the command cd qr to change directory.

Now, try running the project again with the help of ng serve:

Project running (Large preview)

Open a web browser, go to the URL http://localhost:4200 to see the project running. The command ng serve runs the application on port 4200 by default.

TIP: To run it on a different port, we use the command ng serve --port <any-port> for instance, ng serve --port 3000.

This ensures that our basic Angular project is up and running. Let’s move on.

We need to add the project folder to VSCode. Go to the “File” menu and select “Open Folder” and select the project folder. The project folder will now be shown in the Explorer view on the left.

Adding Angular Material Library

To install the Angular material library, use the following command in the terminal window: ng add @angular/material. This will (again) ask some questions such as which theme you want, whether you want default animations, whether touch support is required, among others. We will just select the default Indigo/Pink theme, Yes to adding HammerJS library and browser animations.

Adding Angular material (Large preview)

The above command also configures the whole project to enable support for the material components.

  1. It adds project dependencies to package.json,
  2. It adds the Roboto font to the index.html file,
  3. It adds the Material Design icon font to your index.html,
  4. It also adds a few global CSS styles to:
    • Remove margins from the body,
    • Set height: 100% into the HTML and body,
    • Set Roboto as the default application font.

Just to be sure that everything is fine you can run the project again at this point, though you will not notice anything new.

Adding Home Page

Our project skeleton is now ready. Let’s start by adding the homepage.

(Large preview)

We want to keep our homepage simple, just like the above picture. This home page uses a few angular material components. Let’s dissect.

  1. The top bar is a simple HTML nav element which contains material style button, mat-button, with an image and a text as its child. The bar color is the same as the primary color which was selected while adding Angular material library;
  2. A centered image;
  3. Another, mat-button, with just a text as its child. This button will allow users to navigate to the history page;
  4. A count badge, matBadge, attached to the above button, showing the number of QR codes saved by the user;
  5. A floating action button, mat-fab, at the bottom right corner having the accent color from the selected theme.

Digressing a little, let’s add other required components and services first.

Adding Header

As planned previously, the navigation bar should be reused, let’s create it as a separate angular component. Open terminal in VSCode and type ng g c header (short for ng generate component header) and press Enter. This will create a new folder named “header” which will contain four files:

  • header.component.css: used to provide styling for this component;
  • header.component.html: for adding HTML elements;
  • header.component.spec.ts: for writing test cases;
  • header.component.ts: to add the Typescript-based logic.

Header component (Large preview)

To make the header look like as it was in the mocks, add the below HTML in header.component.html:

<nav class="navbar" [class.mat-elevation-z8]=true>
   <div>
       <button *ngIf="showBackButton" aria-hidden=false mat-icon-button routerLink="/">
           <mat-icon style="color: white;">
               <i class="material-icons md-32">arrow_back</i>
           </mat-icon>
       </button>
       <span style="padding-left: 8px; color: white;">{{currentTitle}}</span>
   </div>
   <button *ngIf="!showBackButton" aria-hidden=false mat-button class="button">
       <img src="../../assets/qr-icon-white.png" style="width: 40px;">
       <span style="padding-left: 8px;">QR Generator</span>
   </button>
   <button *ngIf="showHistoryNav" aria-hidden=false mat-button class="button" routerLink="/history">
       <span style="padding-left: 8px;">History</span>
   </button>
</nav>

TIP: To add elevation for any material component use [class.mat-elevation-z8]=true, the elevation value can be changed by changing z value, in this case it is z8. For instance, to change the elevation to 16, use [class.mat-elevation-z16]=true.

In the above HTML snippet, there are two Angular material elements being used: mat-icon and mat-button/mat-icon-button. Their usage is very simple; first, we need to add those two as modules in our app.module.ts as shown below:

Module import for mat-icon and mat-button (Large preview)

This will allow us to use these two Angular material elements anywhere in any component.

For adding material buttons, the following HTML snippet is used:

<button mat-button>
Material Button
</button>

There are different types of material button elements available in the Angular material library such as mat-raised-button, mat-flat-button, mat-fab and others; just replace the mat-button in the above code snippet with any other type.

Types of material buttons. (Large preview)

The other element is mat-icon which is used to show icons available in the material icon library. When the Angular material library was added in the beginning, then a reference to the material icon library was added as well, which enabled us to use icons from the vast array of icons.

The usage is as simple as:

<mat-icon style="color: white;">
<i class="material-icons md-32">arrow_back</i>
</mat-icon>

The nested <i> tag can be used to change the icon size (here it’s md-32) which will make the icon size 32px in height and width. This value can be md-24, md-48, and so on. The value of the nested <i> tag is the name of the icon. (The name can be found here for any other icon.)

Accessibility

Whenever icons or images are used, it is imperative that they provide sufficient information for accessibility purposes or for a screen-reader user. ARIA (Accessible Rich Internet Applications) defines a way to make web content and web applications more accessible to people with disabilities.

One point to note is that the HTML elements which do have their native semantics (e.g. nav) do not need ARIA attributes; the screenreader would already know that nav is a navigation element and read it as such.

The ARIA specs is split into three categories: roles, states and properties. Let’s say that a div is used to create a progress bar in the HTML code. It does not have any native semantics; ARIA role can describe this widget as a progress bar, ARIA property can denote its characteristic such as it can be dragged. ARIA state will describe its current state such as the current value of the progress bar. See the snippet below:

<div id="percent-loaded" role="progressbar" aria-valuenow="75" aria-valuemin="0" aria-valuemax="100"> </div>

Similarly, a very commonly used aria attribute: aria-hidden=true/false is used. The value true makes that element invisible to screen-readers.

Since most of the UI elements used in this application have native semantic meaning, the only ARIA attributes used are to specify ARIA visibility states.For detailed information, refer to this.

The header.component.html does contain some logic to hide and show back button depending on the current page. Moreover, the Home button also contains an image/logo which should be added to the /assets folder. Download the image from here and save it in the /assets folder.

For styling of the navigation bar, add the below css in header.component.css:

.navbar {
   position: fixed;
   top: 0;
   left: 0;
   right: 0;
   z-index: 2;
   background: #3f51b5;
   display: flex;
   flex-wrap: wrap;
   align-items: center;
   padding: 12px 16px;
}
.button {
   color: white;
   margin: 0px 10px;
}

As we want to keep the header component reusable across other components, thus to decide what should be shown, we will require those as parameters from other components. This requires usage of @Input() decorator which will bind to the variables we used in header.component.html.

Add these lines in the header.component.ts file:

// Add these three lines above the constructor entry.
 @Input() showBackButton: boolean;
 @Input() currentTitle: string;
 @Input() showHistoryNav: boolean;

 constructor() { }

The above three bindings will be passed as a parameter from other components which the header component will be using. Its usage will be more clear once we move forward.

Moving on, we need to create a homepage that can be represented by an Angular component. So let’s start by creating another component; type ng g c home in the terminal to auto-generate the home component. As previously, a new folder named “home” will be created containing four different files. Before proceeding to modify those files, let’s add some routing information to angular routing module.

Adding Routing

Angular provides a way to map URL to a specific component. Whenever some navigation happens, the Angular framework monitors the URL and based on the information present in the app-routing.module.ts file; it initializes the mapped component. This way different components are does not need to shoulder the responsibility of initializing other components. In our case, the application has three pages navigable by clicking on different buttons. We achieve this by leveraging the routing support provided by the Angular framework.

The home component should be the starting point of the application. Let’s add this information to the app-routing.module.ts file.

Routing Home Component. (Large preview)

The path property is set as an empty string; this enables us to map the application URL to the homepage component, something like google.com which shows the Google homepage.

TIP: Path value never starts with a/”, but instead uses an empty string even though path can be like search/coffee.

Moving back to the homepage component, replace the content of home.component.html with this:

<app-header [showBackButton]="false" [currentTitle]=""></app-header>
<app-profile></app-profile>

<!-- FAB Fixed -->
<button mat-fab class="fab-bottom-right" routerLink="/create">
   <mat-icon>
       <i class="material-icons md-48">add</i>
   </mat-icon>
</button>

There are three parts to the home component:

  1. The reusable header component <app-header> here.
  2. Profile component <app-profile> here.
  3. The floating action button at the bottom right.

The above HTML snippet shows how the reusable header component is used in other components, we just use the component selector and pass in the required parameters.

Profile component is created to be used as the body for the home page, we will create it soon.

The floating action button with + icon is a kind of Angular material button of type mat-fab on the bottom right of the screen. It has the routerLink attribute directive which uses the route information provided in the app-routing.module.ts for navigation. In this case, the button has the route value as /create which will be mapped to create component.

To make the create button float on bottom right, add the below CSS code in home.component.css:

.fab-bottom-right {
   position: fixed;
   left: auto;
   bottom: 5%;
   right: 10%;
}

Since profile component is supposed to manage home page body, we will leave home.component.ts intact.

Adding Profile Component

Open terminal, type ng g c profile and press enter to generate profile component. As planned earlier, this component will handle the main body of the home page. Open profile.component.html and replace its content with this:

<div class="center profile-child">
   <img class="avatar" src="../../assets/avatar.png">
   <div class="profile-actions">
       <button mat-raised-button matBadge="{{historyCount}}"    matBadgeOverlap="true" matBadgeSize="medium" matBadgeColor="accent"
           color="primary" routerLink="/history">
           <span>History</span>
       </button>
   </div>
</div>

The above html snippet shows how to use the matBadge element of the material library. To be able to use it here, we need to follow the usual drill of adding MatBadgeModule to app.module.ts file. Badges are small pictorial status descriptor for UI elements such as buttons or icons or texts. In this case, it is used with a button to show count of QR saved by the user. Angular material library badge has various other properties such as setting the position of the badge with matBadgePosition, matBadgeSize to specify size, matBadgeColor to set the badge color.

One more image asset needs to be added to the assets folder. Download and save the same to the assets folder of the project.

Open profile.component.css and add this:

.center {
   top: 50%;
   left: 50%;
   position: absolute;
   transform: translate(-50%, -50%);
}


.profile-child {
   display: flex;
   flex-direction: column;
   align-items: center;
}


.profile-actions {
   padding-top: 20px;
}


.avatar {
   border-radius: 50%;
   width: 180px;
   height: 180px;
}

The above CSS will achieve the UI as planned.

Moving on, we need some kind of logic to update the history count value as it will reflect in the matBadge used earlier. Open profile.component.ts and add the highlighted snippet appropriately:

export class ProfileComponent implements OnInit {

 historyCount = 0;
 constructor(private storageUtilService: StorageutilService) { }

 ngOnInit() {
   this.updateHistoryCount();
 }


 updateHistoryCount() {
   this.historyCount = this.storageUtilService.getHistoryCount();
 }
}

We have added StorageutilService but we have not created such service till now. Ignoring the error, we have completed our profile component which also finishes off our home page component. We will revisit this profile component after creating our storage utility service. Okay then let’s do so.

Local Storage

HTML5 provides web storage feature which can be used to store data locally. This provides much more storage compared to cookies, at least 5MB vs 4KB. There are two types of web storage with different scope and lifetime: Local and Session. The former can store data permanently while the latter is temporary and for a single session. The decision to select the type can be based on the use case, in our scenario we want to save across sessions, so we will go with Local storage.

Each piece of data is stored in a key/value pair. We will use the text for which the QR is generated as the key and the QR image encoded as a base64 string as the value. Create an entity folder, inside the folder create a new qr-object.ts file and add the code snippet as shown:

QR entity model. (Large preview)

The content of the class:

export class QR {
  
   text:           string;
   imageBase64:    string;

   constructor(text: string, imageBase64: string) {
       this.imageBase64 = imageBase64;
       this.text = text;
   }

}

Whenever the user saves the generated QR, we will create an object of the above class and save that object using the storage utility service.

Create a new service folder, we will be creating many services, it’s better to group them together.

Services Folder. (Large preview)

Change the current working directory to services, cd services, to create a new service use ng g s <any name> this is a shorthand to ng generate service <any name>, type ng g s storageutil and press enter. This will create two files: storageutil.service.ts and storageutil.service.spec.ts. The latter is for writing unit tests. Open storageutil.service.ts and add this:

private historyCount: number;
 constructor() { }

 saveHistory(key : string, item :string) {
   localStorage.setItem(key, item)
   this.historyCount = this.historyCount + 1;
 }

 readHistory(key : string) : string {
   return localStorage.getItem(key)
 }

 readAllHistory() : Array {
   const qrList = new Array();

   for (let i = 0; i < localStorage.length; i++) {
     const key = localStorage.key(i);
     const value = localStorage.getItem(key);
     if (key && value) {
       const qr = new QR(key, value);
       qrList.push(qr);
     }
   }
   this.historyCount = qrList.length;
   return qrList;
 }

 getHistoryCount(): number {
   if (this.historyCount) {
     return this.historyCount;
   }
   this.readAllHistory();
   return this.historyCount;
 }

 deleteHistory(key : string) {
   localStorage.removeItem(key)
   this.historyCount = this.historyCount - 1;
 }

Import the qr-object class to correct any errors. To use the local storage feature, there is no need to import anything new just use the keyword localStorage to save or get value based on a key.

Now open profile.component.ts file again and import the StorageutilService class to properly finish off the profile component.

Running the project, we can see the home page is up as planned.

Adding Create QR Page

We have our homepage ready, though the create/add button does not do anything. Worry not, the actual logic was already written. We used a routerLink directive to change the base path of the URL to /create but there was no mapping added to the app-routing.module.ts file. Let’s create a component which will deal with the creation of new QR codes, type ng g c create-qr and press enter to generate a new component.

Open the app-routing.module.ts file and add the below entry to the routes array:

{ path: 'create', component: CreateQrComponent },

This will map the CreateQRComponent with the URL /create.

Open create-qr.components.html and replace the contents with this:

<app-header [showBackButton]="showBackButton" [currentTitle]="title" [showHistoryNav]="showHistoryNav"></app-header>


<mat-card class="qrCard" [class.mat-elevation-z12]=true>
   <div class="qrContent">
      
       <!--Close button section-->
       <div class="closeBtn">
           <button mat-icon-button color="accent" routerLink="/" matTooltip="Close">
               <mat-icon>
                   <i class="material-icons md-48">close</i>
               </mat-icon>
           </button>
       </div>

       <!--QR code image section-->
       <div class="qrImgDiv">
           <img *ngIf="!showProgressSpinner" style="padding: 5px 5px;" src={{qrCodeImage}} width="200px" height="200px">
           <mat-spinner *ngIf="showProgressSpinner"></mat-spinner>
           <div class="actionButtons" *ngIf="!showProgressSpinner">
               <button mat-icon-button color="accent" matTooltip="Share this QR" style="margin: 0 5px;">
                   <mat-icon>
                       <i class="material-icons md-48">share</i>
                   </mat-icon>
               </button>
               <button mat-icon-button color="accent" (click)="saveQR()" matTooltip="Save this QR" style="margin: 0 5px;">
                   <mat-icon>
                       <i class="material-icons md-48">save</i>
                   </mat-icon>
               </button>
           </div>
       </div>
      
       <!--Textarea to write any text or link-->
       <div class="qrTextAreaDiv">
           <mat-form-field style="width: 80%;">
               <textarea matInput [(ngModel)]="qrText" cdkTextareaAutosize cdkAutosizeMinRows="4" cdkAutosizeMaxRows="4"
                   placeholder="Enter a website link or any text..."></textarea>
           </mat-form-field>
       </div>

       <!--Create Button-->
       <div class="createBtnDiv">
           <button class="createBtn" mat-raised-button color="accent" matTooltip="Create new QR code" matTooltipPosition="above"
               (click)="createQrCode()">Create</button>
       </div>
   </div>
</mat-card>

The above snippet uses many of the angular material library elements. As planned, it has one header component reference wherein the required parameters are passed. Next up is the main body of the create page, it consists of one angular material card or mat-card centered and elevated up to 12px as [class.mat-elevation-z12]=true is used. The material card is just another kind of container that can be used as any other div tag. Although the material library provides some properties to lay out well-defined information in a mat-card such as image placement, title, subtitle, description and action as can be seen below.

Card example. (Large preview)

In the above html snippet, we have used mat-card just as any other container.

Another material library element used is matTooltip, it is just another tooltip with ease of use, displayed when the user hovers over or longpresses an element. Just use the snippet below to show tooltip:

matTooltip="Any text you want to show"

It can be used with icon buttons or any other UI element to convey extra information. In application context, it is displaying information about the close icon button. To change the placement of the tooltip matTooltipPosition is used, e.g.

matTooltip="Any text you want to show" matTooltipPosition="above"

Besides matTooltip, mat-spinner is used to show loading progress. When the user clicks on the create button, a network call is made, this is when the progress spinner is shown. When the network call returns with result, we just hide the spinner. It can be used simply like this:

<mat-spinner *ngIf="showProgressSpinner"></mat-spinner>

showProgressSpinner is a boolean variable which is used to show/hide the progress spinner. The library also provides some other parameters like [color]=’accent’ to change color, [mode]=’indeterminate’ to change the progress spinner type. An indeterminate progress spinner will not show the progress of the task while a determinate one can have different values to reflect task progress. Here an indeterminate spinner is used as we do not know how long the network call will take.

The material library provides a variant of textarea conforming to the material guideline but it can only be used as a descendent of mat-form-field. Usage of material textarea is just as simple as the default HTML one, like below:


<mat-form-field>
   <textarea matInput placeholder="Hint text"></textarea>
</mat-form-field>

matInput is a directive which allows native input tag to work with mat-form-field. The placeholder property allows adding any hint text for the user.

TIP: Use cdkTextareaAutosize textarea property to make it auto-resizable. cdkAutosizeMinRows, cdkAutosizeMaxRows to set rows and columns and all three together to make textarea auto-resize till it reaches the max rows and columns limit set.

To use all these material library element, we need to add them in the app.module.ts file.

Create QR module imports. (Large preview)

There is a placeholder image being used in the html, download and save it to the assets folder.

The above html also requires css styling, open create-qr.component.ts file and add:

.qrCard {
   display: flex;
   flex-direction: column;
   align-items: center;
   position: absolute;
   top: 50%;
   left: 50%;
   transform: translate(-50%, -50%);
   width: 20%;
   height: 65%;
   padding: 50px 20px;
}

.qrContent {
   display: flex;
   flex-direction: column;
   align-items: center;
   width: 100%;
}

.qrTextAreaDiv {
   width: 100%;
   display: flex;
   flex-direction: row;
   justify-content: center;
   padding: 0px 0px;
   position: absolute;
   bottom: 10%;
}

.createBtn {
   left: 50%;
   transform: translate(-50%, 0px);
   width: 80%;
}

.createBtnDiv {
   position: absolute;
   bottom: 5%;
   width: 100%;
}


.closeBtn {
   display: flex;
   flex-direction: row-reverse;
   align-items: flex-end;
   width: 100%;
   margin-bottom: 20px;
}

.closeBtnFont {
   font-size: 32px;
   color: rgba(0,0,0,0.75);
}

.qrImgDiv {
   top: 20%;
   position: absolute;
   display: flex;
   flex-direction: column;
   align-items: center;
   justify-content: center;
   width: 100%;
}
.actionButtons {
   display: flex;
   flex-direction: row;
   padding-top: 20px;
}

Let’s wire up the UI with logic, open create-qr.component.ts file and add the below code, leaving those lines which are already present:

export class CreateQrComponent implements OnInit {

 qrCodeImage = '../../../assets/download.png';
 showProgressSpinner = false;
 qrText: string;
 currentQR;
 showBackButton = true;
 title = 'Generate New QR Code';
 showHistoryNav = true;

 constructor(private snackBar: MatSnackBar,
     private restutil: RestutilService,
     private storageService: StorageutilService) { }

 ngOnInit() {
 }

 createQrCode() {
   //Check if any value is given for the qr code text
   if (!!this.qrText) {     
     //Make the http call to load qr code
     this.loadQRCodeImage(this.qrText);
   } else {
     //Show snackbar
     this.showSnackbar('Enter some text first')
   }
 }

 public loadQRCodeImage(text: string) {
   // Show progress spinner as the request is being made
   this.showProgressSpinner = true;
   // Trigger the API call
   this.restutil.getQRCode(text).subscribe(image =>{
     // Received the result - as an image blob - require parsing
     this.createImageBlob(image);
   }, error => {
     console.log('Cannot fetch QR code from the url', error)
     // Hide the spinner - show a proper error message
     this.showProgressSpinner = false;
   });
 }

 private createImageBlob(image: Blob) {
   // Create a file reader to read the image blob
   const reader = new FileReader();
   // Add event listener for "load" - invoked once the blob reading is complete
   reader.addEventListener('load', () => {
     this.qrCodeImage = reader.result.toString();
     //Hide the progress spinner
     this.showProgressSpinner = false;
     this.currentQR = reader.result.toString();
   }, false);
   // Read image blob if it is not null or undefined
   if (image) {
     reader.readAsDataURL(image);
   }
 }

 saveQR() {
   if (!!this.qrText) {
     this.storageService.saveHistory(this.qrText, this.currentQR);
     this.showSnackbar('QR saved')
   } else {
     //Show snackbar
     this.showSnackbar('Enter some text first')
   }
  
 }

 showSnackbar(msg: string) {
   //Show snackbar
   this.snackBar.open(msg, '', {
     duration: 2000,
   });
 }
}

To provide users contextual information, we also use MatSnackBar from the material design library. This shows up as a popup from below the screen and stays for a few seconds before disappearing. This is not an element rather a service that can be invoked from the typescript code. The above snippet with method name showSnackbar shows how to open up a snackbar, but before it can be used, we need to add the MatSnackBar entry in app.module.ts file just like we did for other material library elements.

TIP: In recent angular material library versions, there is no straightforward way to change the snackbar styling, instead one has to make two additions to the code, first is to use the below CSS to alter background and foreground colors:

::ng-deep snack-bar-container.snackbarColor {
   background-color: rgba(63, 81, 181, 1);
}
::ng-deep .snackbarColor .mat-simple-snackbar {
   color: white;
 }

Second is to use a property called panelClass to set the style to the above CSS class:

this.snackBar.open(msg, '', {
     duration: 2000,
     panelClass: ['snackbarColor']
   });

The above two combinations will allow custom styling to the material design library snackbar component.

This completes the create qr page but there is one piece still missing. Checking the create-qr.component.ts file, it will show an error regarding the missing piece. The missing piece to this puzzle is the RestutilService which is responsible for fetching the qr code image from the third-party API.

In the terminal, change the current directory to services, type ng g s restutil and press enter. This will create the RestUtilService files, open the restutil.service.ts file and add this snippet:

private edgeSize = '300';
 private BASE_URL = 'https://api.qrserver.com/v1/create-qr-code/?data={data}!&size={edge}x{edge}';

 constructor(private httpClient: HttpClient) { }

 public getQRCode(text: string): Observable {
   // Create the url with the provided data and other options
   let url = this.BASE_URL;
   url = url.replace("{data}", text).replace(/{edge}/g, this.edgeSize);
   // Make the http api call to the url
   return this.httpClient.get(url, {
     responseType: 'blob'
   });
 }

The above service fetches the qr image from the third party API and since the response is not of json type, but an image, so we specify the responseType as ‘blob’ in the above snippet.

Angular provides HttpClient class to communicate with any HTTP supporting server. It provides many features like filtering the request before it is fired, getting back the response, enabling the processing of the response via callbacks and others. To use the same, add an entry for HttpClientModule in app.module.ts file.

Finally, import this service in the create-qr.component.ts file to complete the create.

There is a problem with the above create qr logic. If the user uses the same text to generate the QR again and again, it will result in a network call. One way to redress this is caching the request based, thus serving the response from the cache if the request text is same.

Caching Request

Angular provides a simplified way of making HTTP calls, HttpClient, along with HttpInterceptors to inspect and transform HTTP requests or responses to and from servers. It can be used for authentication or caching and many such things, multiple interceptors can be added and chained for further processing. In this case, we are intercepting requests and serving the response from the cache if the qr text is same.

Create an interceptor folder, then create a file cache-interceptor.ts:

Cache interceptor. (Large preview)

Add the below code snippet to the file:

import { Injectable } from '@angular/core';
import { HttpInterceptor, HttpResponse, HttpRequest, HttpHandler, HttpEvent } from '@angular/common/http';
import { tap } from 'rxjs/operators';
import { of, Observable } from 'rxjs';

@Injectable({
 providedIn: 'root'
})
export class RequestCachingService implements HttpInterceptor {
 private cacheMap = new Map<string, HttpResponse<any>>();

 constructor() { }

 intercept(req: HttpRequest, next: HttpHandler): Observable<HttpEvent<any>> {
   const cachedResponse = this.cacheMap.get(req.urlWithParams);
  
   if (cachedResponse) {
     return of(cachedResponse);
   }

   return next.handle(req).pipe(tap(event => {
     if (event instanceof HttpResponse) {
       this.cacheMap.set(req.urlWithParams, event);
     }
   }))
  
 }
}

In the above code snippet, we have a map with the key being the request URL, and the response as the value. We check if the current URL is present in the map; if it is, then return the response (the rest is handled automatically). If the URL is not in the map, we add it.

We are not done yet, an entry to the app.module.ts is required for its proper functioning. Add below snippet:

import { HttpClientModule, HTTP_INTERCEPTORS  } from '@angular/common/http';
import { CacheInterceptor } from './interceptor/cache-interceptor';


providers: [
   { provide: HTTP_INTERCEPTORS, useClass: CacheInterceptor, multi: true }
 ],

This adds the caching feature to our application. Let’s move on to the third page, History page.

Adding History Page

All the saved QR codes will be visible here. To create another component, open terminal type ng g c history and press enter.

Open history.component.css and add the below code:

.main-content {
   padding: 5% 10%;
}
.truncate {
   width: 90%;
   white-space: nowrap;
   overflow: hidden;
   text-overflow: ellipsis;
}
.center-img {
   position: absolute;
   top: 50%;
   left: 50%;
   transform: translate(-50%, -50%);
   display: flex;
   flex-direction: column;
   align-items: center;
}

Open history.component.html and replace the content with this:

<app-header [showBackButton]="showBackButton" [currentTitle]="title" [showHistoryNav]="showHistoryNav"></app-header>

<div class="main-content">
   <mat-grid-list cols="4" rowHeight="500px" *ngIf="historyList.length > 0">
       <mat-grid-tile *ngFor="let qr of historyList">
           <mat-card>
               <img mat-card-image style="margin-top: 5px;" src="{{qr.imageBase64}}">
               <mat-card-content>
                   <div class="truncate">
                       {{qr.text}}
                   </div>
               </mat-card-content>
               <mat-card-actions>
                       <button mat-button (click)="share(qr.text)">SHARE</button>
                       <button mat-button color="accent" (click)="delete(qr.text)">DELETE</button>
               </mat-card-actions>
           </mat-card>
       </mat-grid-tile>
   </mat-grid-list>
   <div class="center-img" *ngIf="historyList.length == 0">
       <img src="../../assets/no-see.png" width="256" height="256">
       <span style="margin-top: 20px;">Nothing to see here</span>
   </div>
</div>

As usual, we have the header component at the top. Then the rest of the body is a grid list that will show all the saved QR codes as individual mat-card. For the grid view, we are using mat-grid-list from the angular material library. As per the drill, before we can use it, we have to first add it to the app.module.ts file.

Mat grid list acts as a container with multiple tile children called mat-grid-tile, in the above html snippet, each tile is created using mat-card using some of its properties for generic placement of other UI elements. We can provide the number of columns and rowHeight, which is used to calculate width automatically. In the above snippet we are providing both the number of columns and the rowHeight value.

We are using a placeholder image when the history is empty, download it and add to the assets folder.

To implement the logic for populating all these information, open history.component.ts file and add the below snippet in the HistoryComponent class:

showBackButton = true;
 title = 'History';
 showHistoryNav = false;
 historyList;

 constructor(private storageService: StorageutilService,
 private snackbar: MatSnackBar ) { }

 ngOnInit() {
   this.populateHistory();
 }

 private populateHistory() {
   this.historyList = this.storageService.readAllHistory();
 }

 delete(text: string) {
   this.storageService.deleteHistory(text);
   this.populateHistory();
 }

 share(text: string) {
   this.snackbar.open(text, '', {duration: 2000,})
 }

The above logic just fetches all the saved QR and populates the page with it. Users can delete the saved QR which will delete the entry from the local storage. This finishes off our history component or does it? We need to add the route mapping for this component, open app-routing.module.ts and add a mapping for the history page as well:

{ path: 'history', component: HistoryComponent },

The whole route array should look like this by now:

const routes: Routes = [
 { path: '', component: HomeComponent },
 { path: 'create', component: CreateQrComponent },
 { path: 'history', component: HistoryComponent },
];

It is a good time to run the application to check the complete flow, open terminal and type ng serve and press enter, go to localhost:4200 to verify the working of the application.

Add To Github

Before proceeding to the deployment step, it would be good to add the project to a Github repository.

  1. Open Github
  2. Create a new repository
  3. Github new repository. (Large preview)
  4. In VS Code use the terminal and follow the first set of commands mentioned in the quick start guide to push all the project files
  5. Github add project. (Large preview)

Just refresh the page to check if all the files are visible. From this point any git changes such as commit, pull/push will be reflected in this newly created repository.

Netlify & Deployment

Our application runs in our local machine, but to enable others to access it, we should deploy it on a cloud platform and register it to a domain name. This is where Netlify comes into play. It provides continuous deployment services, integration with Github and many more features to benefit from. Right now, we want to enable global access to our application, let’s get started.

  1. Sign-up on Netlify.
  2. From the dashboard, click on New site from Git button.
  3. Netlify new site. (Large preview)
  4. Click on Github in the next screen.
  5. Netlify select git provider. (Large preview)
  6. Authorize Netlify to be able to access your Github repositories.
  7. Netlify github authorization. (Large preview)
  8. Search for and select the newly created qr repository.
  9. Netlify github repository selection. (Large preview)
  10. Netlify, in the next step, allows us to choose the Github repository branch for deployments. Normally one uses the master branch but one can also have a separate release branch which contains only release related and stable features.
  11. Netlify build and deploy. (Large preview)

Since, this is an angular web application, add ng build --prod as the build command. Publish directory will be dist/qr as mentioned in the angular.json file.

Angular build path. (Large preview)

Now click on the Deploy site button which will trigger a project build with the command ng build --prod and will output the file to dist/qr.

Since we provided the path information to Netlify, it will automatically pick up the correct files for servicing the web application. Netlify adds a random domain to our application by default.

Netlify site deployed. (Large preview)

You can click on the link provided in the above page, to access our application from anywhere. Finally, our application is deployed.

Custom Domain

In the above image, the URL for our application is shown, the sub-domain is randomly generated. Let’s change it. Click on Domain settings button then in the custom domains section click on the 3-dot menu and select Edit site name.

Custom domain. (Large preview)

This will open a popup wherein a new site name can be entered, this name should be unique across the Netlify domain. Enter any site name, which is available and click save.

Site name. (Large preview)

Now the link to our application will be updated with the new site name.

Split Testing

Another cool feature offered by Netlify is split testing, it enables traffic splitting so that different sets of users will interact with different application deployments. We can have new features added to a different branch and split the traffic to this branch deployment, analyze traffic and then merge the feature branch with the main deployment branch. Let’s configure it.

The prerequisite to enabling split testing is a Github repository with at least two branches. Head over to the app repository in Github, created earlier, create a new branch, a.

Create new branch. (Large preview)

The repository will now have a master branch and a branch. Netlify needs to be configured to do branch deployments, open Netlify dashboard and click on Settings, on the left side click on Build & Deploy, then Continuous Deployment, then on the right side in the Deploy contexts section, click on Edit settings.

Branch deployments. (Large preview)

In the Branch deploys sub-section select the option Let me add individual branches, and enter the branch names and save it.

Branch deploy is another useful feature provided by Netlify, we can select which Github repository branches to deploy, we can also enable preview for every pull request to the master branch before merging. This is a neat feature enabling developers to actually test their changes out live before adding their code changes to the main deployment branch.

Now, click on Split Testing tab option at the top of the page, the split testing configurations will be presented here.

Split testing. (Large preview)

We can select the branch, other than the production branch, in this case a. We can also play around with the settings of splitting traffic, based on the traffic percentage each branch has been allotted, Netlify will re-route some users to the application deployed using a branch and others to the master branch. After configuring, click on Start test button to enable traffic splitting.

TIP: Netlify may not recognize that the connected Github repository has more than one branch and may give this error:

Split testing error. (Large preview)

To resolve this, just reconnect to the repository from the Build & Deploy options.

Netlify provides a lot of other features as well, we just went through some of its useful features to demonstrate the ease of configuring different aspects of Netlify.

This brings us to the end of our journey, we have successfully created an Angular Material design based web application and deployed it on Netlify.

Conclusion

Angular is a great and popular framework for web application development, with the official Angular material design library it is much easier to create applications which adhere to the material design specs for a very natural interaction with the users. Moreover, the application developed with a great framework should use a great platform for deployment, Netlify is just that. With constant evolution, great support and with a plethora of features it surely is a great platform to bring web applications or static sites to the masses. Hopefully, this article will provide help in getting started with new Angular project from just a thought to deployment.

Next Steps

Smashing Editorial
(dm, yk, il)

Source: Smashing Magazine, How To Create And Deploy Angular Material Application

The Split Personality Of Brutalist Web Development

dreamt up by webguru in Uncategorized | Comments Off on The Split Personality Of Brutalist Web Development

The Split Personality Of Brutalist Web Development

The Split Personality Of Brutalist Web Development

Frederick O'Brien



Of all the design trends to hit the internet in recent years, brutalism is surely the most eye-catching, and the most poorly defined. A variety of major brands have embraced ‘brutalist’ aesthetics online. There are even directories for those interested in seeing a selection of them in one place. The style has well and truly entered the mainstream.

Desktop homepage of Bloomber.com

Bloomberg.com’s stark, no-nonsense design went live in 2016 and was refined in 2018. It is often touted as a leading example of brutalism’s growth online. (Large preview)

Indeed, brutalist web design has grown so quickly that there does not seem to be a clear consensus on what the style actually is. To some it means practicality, to others audacity. Much like the architecture it takes its name from, brutalist web development has become two competing philosophies in one. Neither is necessarily ‘right’, but knowing the difference is important. It may even be sensible to start calling them different things.

A Brief(ish) History Of Brutalism

Before we get ahead of ourselves, let’s recap the term ‘brutalist’ — where it came from and what it means. Brutalism is a style of architecture that took off after World War II, reaching its peak in the ‘50s and ‘60s. Championing simple, geometric designs and bared building materials, the trend was in large part a reaction against the ornate, over-designed structures of preceding decades.

The name comes from béton brut, which is French for raw or rough concrete. Concrete is a common material for brutalist structures, lending itself as it does to the style’s no-frills approach. Other materials can be and are used, but concrete is especially common. Whatever structures are made of, embellishments are deemed unnecessary. The form and the materials are enough.

The United Kingdom, with its fondness for grey, drab things, particularly took to the style. Notable examples of brutalist architecture here include the Royal National Theatre, the Barbican Estate, and Balfron Tower. It has proven especially popular for public buildings — libraries, theatres, universities, housing estates, and so on.

 The Royal National Theatre in London

The National Theatre in London. Designed by Denys Lasdun and opened in 1976, it is a textbook example of brutalist architecture. It is both one of the most hated and most loved buildings in Britain. Photograph by Henry Hemming. (Large preview)

Although there is not a catch-all definition that everyone agrees on, deference is often paid to English architectural critic Rayner Barnam, whose 1955 essay ‘On the New Brutalism’ attempted to outline the core ideas of the style. In anticipation of those of you who would not read the whole thing, Barnham boiled the philosophy down to the following:

In the last resort what characterizes the New Brutalism in architecture as in painting is precisely its brutality, its je-m’ en-foutisme, its bloody-mindedness.

Loosely translated, je-m’ en-foutisme translates as ‘don’t give a damn attitude. To be sure, brutalist buildings are unconcerned about conventional standards of beauty. They are also rather divisive. Where some gush over their firm, utilitarian character, others decry ugliness, impersonality, and, well, brutality.

Love it or hate it, brutalist architecture celebrates rawness. Indeed, Barnam opened his essay with a quote by Swiss-French architect Le Corbusier: “Architecture is the establishing of moving relationships with raw materials.” Le Corbusier’s Unité d’habitation housing designs inspired a generation of brutalist architects.

Balconies at La Maison du Fada in Marseille

Balconies at La Maison du Fada in Marseille, France. Designed by Le Corbusier and completed in 1952, it was a pioneering example of brutalist residential design. Photograph by Jean-Pierre Dalbéra. (Large preview)

So in short, brutalist architecture not only reduces construction to its fundamental materials, it finds beauty in that simplicity. Critics say it’s a bit in your face, a bit impersonal, a bit totalitarian even. The dual meaning of ‘raw’ and ‘brutal’ has clouded the definition, but as a rule, the goal is rawness and the result is perceived by some as brutal.

The style has waned in popularity since its postwar heyday, but it endures as one of the most distinctive around. A good few have attained listed status, and I for one am glad they have. A city of brutalist buildings would be a bit much, but a city without any is poorer for it.

Further Reading

Practicality Or Audacity?

So what’s all this got to do with web development? The philosophy, mainly, and the way it has splintered. Brutalism has found new life online, especially in the last three or four years. A slew of sites have taken on the brutalist moniker, and with the trend’s rise have come accompanying aw(ww)ards, articles, and directories.

Browsing through these things you may well get the impression that not everyone is talking about the same thing. That’s because they aren’t. In the world of web development, ‘brutalist’ has grown to encompass a variety of styles. It’s a disservice to designers to keep lumping together such different approaches. I have separated web brutalism into two types below, but as we shall see even that may not be enough.

Type One: l’Internet Brut

The first type of brutalist web design has much more in common with its architectural forebears. Think of it as l’Internet brut, where the raw materials are HTML and, to a lesser extent, CSS. The backgrounds are light, the text is black, and the hyperlinks are blue. There’s some wriggle room, but that’s the gist of it. No faffing about. Short of displaying actual code you couldn’t get much rougher.

The first ever website

In the beginning was the Style, and the Style was with Brutalism, and the Style was Brutalism. (Large preview)

There are countless examples of this style, big and small. The first ever website is an inadvertent disciple, while more recently Brutalist Web Design by programmer David Bryant Copeland puts forward a lovely little manifesto for the style.

Going up in the world, other websites with strong brutalist streaks include:

Although the raw materials of these sites are very similar, they don’t all look the same. They are shaped around their content and purpose. Like their architectural cousins, there’s actually a huge variety in form.

Craigslist’s London homepage as it appears in 2020

A proper l’Internet brut website. It even has grey! (Large preview)

As you can see with the Craigslist homepage above, there is very little in the way of excess, and possibly even less in the way of style. It’s barely changed in 20(!) years, because it hasn’t needed to. Take a look at the code and even a novice like me can follow how the pages are put together. You don’t have to guess how it’s built because it’s all right there in front of you.

With sites like this you’ll often notice an overlap with the ‘publicly minded’ leaning on a lot of these websites — marketplaces, forums, encyclopedias. It’s oddly appropriate to see a site like Wikipedia take on the digital form of, say, Robin Hood Gardens. Bloomberg has plenty of company in the news space as well. Papers like The New York Times and The Washington Post have embraced similarly blunt, functional designs in recent years. News design has always had a strong brutalist streak.

Desktop homepage of The Washington Post website

The Washington Post’s revamped website rolled out in 2015. Newspaper designer Mario Garcia praised it at the time for ‘avoiding clutter and crowdedness.’ (Large preview)

It bears mentioning here that several of the sites used as examples here didn’t set out to be brutalist. Much like Villa Göth, which is widely considered the source of the term brutalism, they set out to be practical and simple. They were adopted, so to speak. Their success is what inspired (and continues to inspire) architects and developers alike. They’re so unconcerned about appearances that they became shining examples of brutalist design without even realizing it!

Sites in this vein don’t always scream beauty, but there is an elegance to their functionality. They are unconcerned and unpretentious, shaped for their purpose using the raw elements of the web. (Pun intended.)

Type Two: l’Internet Fou

This is the split. Right here. Those of you with even a passing interest in web design trends will know what we’ve looked at so far fails to account for a huge number of ‘brutalist’ sites. As Vitaly Friedman noted in Smashing Book 6:

Brutalism in architecture is characterized by unconcerned aesthetics, not intentionally broken aesthetics. When applied to web design, this style often goes along with deliberately broken design conventions and guiding principles.

The rise of ‘brutalist’ design over the last few years has had a lot more to do with brutalness than with rawness. This is the madder world, at times bordering on anarchy. Here design conventions are subverted and usability is an afterthought — and that’s not when it’s being actively sabotaged. These are the sites that prompt articles titled ‘Style Over Substance’, and for The Washington Post to sum up the style as ‘intentionally ugly.’

Desktop homepage of art magazine Toiletpaper

The homepage of artists’ magazine Toiletpaper. (Large preview)

Desktop homepage of self-described brutalist website JI SOO EOM

JI SOO EOM, another site found in the Brutalist Websites directory. (Large preview)

In the suitably migraine-inducing article ‘Brutalism: BrutAl wEbsIteS for mOdern dAy webMAsTeRS’, Awwwards describes this second strain as follows:

Brutalism in web design laughs in the face of rationalism and functionality, in the world of design it can be defined as freestyle, ugly, irreverent, raw, and superficially decorative, etc.

I hope it isn’t controversial to say that this is an altogether different approach to type one. At a stretch, you might argue that this approach is more the domain of artists and graphic designers, and that art is, therefore, the rawest form their websites can take, but that would be a stretch. There’s no question brutalist architecture can drift into ‘statement’ territory, but that’s not its natural realm.

The Brutalist Websites directory suggests, ‘Brutalism [online] can be seen as a reaction by a younger generation to the lightness, optimism, and frivolity of today’s web design.’ There are shades of the founding brutalist ethos in this, but it is more irreverent and subversive. They can be very beautiful in their own way, but also cut from a completely different cloth from the Craigslists of this world.

This Town Ain’t Big Enough For The Two Of Us

So there you have it. When brutalist web design isn’t going all in on rationalism and functionality, it’s laughing in the face of rationalism and functionality. All clear?

The term has grown to encompass approaches that are in many senses at odds with each other. Indeed, Pascal Deville, the founder of the Brutalist Websites directory, thinks the style has splintered into three micro-stylistics: the purists, the UX minimalists and the anti-ists (or artists). Having vetted hundreds of submissions over the years, he’d know better than just about anyone else. He says:

The purists reference strongly to the architectural characteristics of Web Brutalism, such as the concept of ‘truth to materials’ and the use of the purest markup elements available. The UX minimalists, in contrast, see efficiency and performance as the main driver of Web Brutalism and even believe that the radical limitation of possibilities can boost conversions. The ‘anti-ists’ or artists see web design as an (still) undervalued form of art and don’t show much respect the status quo and mostly get bad press.

What is a ‘proper’ brutalist website? To an extent, the answer depends on the context. If a website belongs to an artist then something brash may be more appropriate than something unconcerned. Generally speaking, though, it seems to me that the sensibilities of the ‘anti-ist’ type are actually much closer to something like Dadaism, with all its absurdity and mirth and mess, or the avant-garde leanings of Expressionism.

Small Dada Evening by Kurt Schwitters and Theo van Doesburg

Small Dada Evening by Kurt Schwitters and Theo van Doesburg. (Large preview)

Typical Vertical Mess as Depiction of the Dada Baargeld by Johannes Theodor Baargeld

Typical Vertical Mess as Depiction of the Dada Baargeld by Johannes Theodor Baargeld. Which branch of ‘brutalist’ web design do these look more like to you? (Large preview)

I don’t want this to come across as a game of semantics, where different styles are filed away neatly into little boxes. What I am more concerned with is highlighting different approaches so that each may be given the space needed to flourish. As Deville acknowledges, the creative potential of the web is still being explored. ‘It’s a new form of art and I’m very happy to experience first hand,’ he says. ‘It’s happening now.’

This has practical consequences as well. Whether you’re a developer talking to a client or a client talking to a developer, it pays to be clear which version of brutalist web design you’re on about. If you’re a real champ you’ll naturally refer them to this article. Otherwise, visual examples like the one below are likely your best bet for getting to the point.

Example to two different brutalist website styles

They’re both ‘brutalist’ so be sure what you’re asking for. The design on the left is a project by Constantin Grosnov. (Large preview)

Beyond that, maybe we should start giving different styles different names. I appreciate this would be rather inconvenient to a lot of people. Domains have been bought, awards awarded, and articles written, but going forward the label seems too restrictive. It can no longer contain so many approaches. If nothing else, the split personality of brutalist web development shows how much terrain remains to be explored in web design.

There are countless schools of art — Brutalism, Expressionism, Romanticism, Art Deco, Futurism, Dadaism, Impressionism, absurdism, modernism, minimalism, and on and on and on. They find form through paintings, buildings, literature… why not websites? As the links below show, I’m not alone in asking this. With every new development style, ‘anti-mainstream’ becomes less adequate for describing what designers are doing. They are starting to explore the philosophy of web design in ways that haven’t been done before.

The ‘Dadaist’ strain of brutalist web design has one thing absolutely right: the scope for what a website can be is far, far too narrow. The web is an infinite sandbox, and embracing the breadth of possibilities within it can only be a good thing. That starts with expanding our vocabulary.

Smashing Editorial
(ra, yk, il)

Source: Smashing Magazine, The Split Personality Of Brutalist Web Development

1 2 3 4 5 6 7 8 9 10 ... 82 83   Next Page »