Beneath The Autumn Leaves (October 2019 Wallpapers Edition)

dreamt up by webguru in Uncategorized | Comments Off on Beneath The Autumn Leaves (October 2019 Wallpapers Edition)

Beneath The Autumn Leaves (October 2019 Wallpapers Edition)

Beneath The Autumn Leaves (October 2019 Wallpapers Edition)

Cosima Mielke



Misty mornings, pumpkins, leaves shining in bright red, yellow, and orange hues — these are just some of the things about October that inspired artists and designers to participate in this month’s wallpapers challenge.

The monthly challenge has been going on for more than nine years already, and each time anew, creatives from all across the globe submit their designs to it to cater for some variety on your desktop and mobile screens — and for a bit of fresh inspiration, of course.

In this collection, you’ll find their wallpaper designs for October 2019. They come in versions with and without a calendar so that you can continue to use your favorite even after the month has ended. Speaking of favorites: As a little extra goodie, we compiled some favorites from past wallpapers editions at the end of this post. A big thank-you to everyone who shared their designs with us this time around. Happy October!

Please note that:

  • All images can be clicked on and lead to the preview of the wallpaper,
  • We respect and carefully consider the ideas and motivation behind each and every artist’s work. This is why we give all artists the full freedom to explore their creativity and express emotions and experience through their works. This is also why the themes of the wallpapers weren’t anyhow influenced by us but rather designed from scratch by the artists themselves.

Submit your wallpaper

We are always looking for designers and artists to be featured in our wallpapers posts. So if you’re feeling creative, please don’t hesitate to submit your design. We’d love to see what you’ll come up with for November. Join in! →

First Scarf And The Beach

“When I was little my parents always took me and my sister for a walk at the beach in Nieuwpoort, we didn’t really do those beach walks in the summer but always when the sky started to turn grey and the days became colder. My sister and I always took out our warmest scarfs and played in the sand while my parents walked behind us. I really loved those Saturday or Sunday mornings where we were all together. I think October (when it’s not raining) is the perfect month to go to the beach for ‘uitwaaien’ (to blow out), to walk in the wind and take a break and clear your head, relieve the stress or forget one’s problems.” — Designed by Gwen Bogaert from Belgium.

First Scarf And The Beach

Rain And Acorns

“Waiting at the bus stop when it’s raining in October can be a sad and wet experience. The bus is late, the dry spot is taken by other people and you’re just standing there in the rain with your hands in your pockets with nowhere to go. Acorns must have a hard time like that too! Waiting in the rain for the squirrels to come and pick them up.” — Designed by Casey Dulst from Belgium.

Rain And Acorns

Transitions

“To me, October is a transitional month. We gradually slide from summer to autumn. That’s why I chose to use a lot of gradients. I also wanted to work with simple shapes, because I think of October as the ‘back to nature/back to basics month’.” — Designed by Jelle Denturck from Belgium.

Transitions

Autumn Is In The Air

“October reminds me of autumn, the season where you see fall leaves, squirrels, the weather that’s changing. Ever walked into the woods when it’s autumn? You can hear the magical sound of the wind blowing away the leaves. The woods are the most beautiful at fall, everything starts to color into yellow, orange, and brown. And you can meet some nice squirrels at the corner of a tree.” — Designed by Delphine Wylin from Belgium.

Autumn Is In The Air

The Return

Designed by Ricardo Gimenes from Sweden.

The Return

Sleepy Hedgehog

“Hedgehogs usually start to hibernate around October. This little hedgehog is celebrating Halloween on his own terms, while he is asleep.” — Designed by Aaron Harinck from Belgium.

Sleepy Hedgehog

The Month Of Tricks And Treats

“The fiery pumpkins blaze in the dark. The bonfires, the songs, the dancing around and the sumptuous feast. There is so much to look forward to this month.” — Designed by Mobile App Development from India.

The Month Of Tricks And Treats

Turtles In Space

“Finished September, with October comes the month of routines. This year we share it with turtles that explore space.” — Designed by Veronica Valenzuela from Spain.

Turtles In Space

Halloween House Call

“Halloween brings a nighttime of fun for all the family. With trick-or-treating round the neighborhood, it’s a pastime families love to take part in nationwide. We wanted to celebrate this event by coming up with a design concept that would pay homage to the most iconic Halloween fruit of them all, the mighty Pumpkin! What better way to look forward to this spooktacular night than with a geometric art pumpkin calendar. Enjoy your night, whatever you have planned!” — Designed by Ever Increasing Circles from the United Kingdom.

Halloween House Call

Create More

“The colors of the sun inspired me.” — Designed by Hitesh Puri from India.

Create More

Sober October

“Every year when October begins, my family and I light up the fireplace for the first time. This time of the year the leaves start falling and it starts to become cold outside which makes it even cosier.” — Designed by Jasper Vermeulen from Belgium.

Sober October

Brexit

“October 2019 will always be remembered as Brexit-month so I wanted to create a wallpaper that’s inspired by Brexit. At the same time I wanted to stay away from the classic Brexit/Europe colours. I came up with a pop-up window to imply that maybe, before really exiting the EU, the UK should reconsider what they are doing. ‘Is it ok to take this huge decision while people are screaming for another referendum’ is only one of the questions I want the British government to ask themselves.” — Designed by Nand Rogge from Belgium.

Brexit

Month Of Gratitude

“As autumn advances, the leaves descend in great gratitude, they return to Earth to rise again. Under the shedding tree the students and teachers learn, for a teacher sheds her years so that the students can grow.” — Designed by Mindster from India.

Month Of Gratitude

Disarmament Week

“According to research, 44 million Americans own firearms. The last week of October is Disarmament Week, so we are inspired by states like Liechtenstein, who abolished army and don’t use weapons. This monthly calendar is dedicated to all those who follow this trend. If the whole world was like Liechtenstein, we would be happier and cheerful. So, let’s all stand together against guns and bombs and establish a world without ammunition.” — Designed by PopArt Studio from Serbia.

Disarmament Week

Apples

“Apples are known all throughout the world yet barely anyone knows about Apple Day. For this reason I decided to put Apple Day in an extra spotlight and create a calendar about it. I hope others may enjoy apples as much as I do.” — Designed by Miguel De Pelsmaeker from Belgium.

Apples

Wandering In Woods

“The icy mountains keeping the body frozen, yet the mind wandering over the expansive woods.” — Designed by Sweans Technologies from London.

Wandering In Woods

Oktoberfest

“When I think about October, I immediately say ‘Oktoberfest’, partly for the obvious October part, but mostly for the ‘fest’ one. As we all know, Oktoberfest is a German traditional celebration dedicated to beer, that annually gathers friends from everywhere around the world, all having in common the passion for good beer (in large quantities), traditional food and the fun factor. And what can be more entertaining than having fun with your friends while drinking beer in an authentic German scenario?” — Designed by Loredana Codau (@loricacucrizanteme on Instagram) from Romania.

Oktoberfest

Oldies But Goodies

Hidden in our wallpapers archives, we rediscovered some nearly-forgotten treasures from past editions. May we present… (Please note that these designs don’t come with a calendar.)

Shades Of Gold

“We are about to experience the magical imagery of nature, with all the yellows, ochers, oranges, and reds coming our way this fall. With all the subtle sunrises and the burning sunsets before us, we feel so joyful that we are going to shout it out to the world from the top of the mountains.” — Designed by PopArt Studio from Serbia.

Shades Of Gold

Flying Home For Halloween

“You can only fully master the sky wearing an aviator hat and goggles. Like this little bat, flying home to celebrate Halloween with his family and friends.” — Designed by Franke Margrete from the Netherlands.

Flying Home For Halloween

Hanlu

“The term ‘Hanlu’ literally translates as ‘Cold Dew.’ The cold dew brings brisk mornings and evenings. Eventually the briskness will turn cold, as winter is coming soon. And chrysanthemum is the iconic flower of Cold Dew.” — Designed by Hong, ZI-Qing from Taiwan.

Hanlu

Strange October Journey

“October makes the leaves fall to cover the land with lovely auburn colors and brings out all types of weird with them.” — Designed by Mi Ni Studio from Serbia.

Strange October Journey

Fallen Woods

Designed by Dan Ioanitescu from Canada.

Desktop Wallpaper - October 2012

Autumn Gate

“The days are colder, but the colors are warmer, and with every step we go further, new earthly architecture reveals itself, making the best of winters’ dawn.” — Designed by Ana Masnikosa from Belgrade, Serbia.

Autumn Gate

Discovering The Universe!

“Autumn is the best moment for discovering the universe. I am looking for a new galaxy or maybe… a UFO!” — Designed by Verónica Valenzuela from Spain.

Discovering The Universe!

All The Things

“During our recent rebrand, everyone in our team got their very own icon, each one has been custom illustrated by a lovely man called Paul, who wears glasses. The icons have all been chosen to represent something personal to each individual as well as all the other usual suspects you’d expect from an iconset.” — Designed by Engage Interactive from the United Kingdom.

All the things

Exploration

“In my travels to Selinsgrove, PA this past month, I had another opportunity to appreciate the beauty that surrounded me: trees, mountains, streams, rivers and fauna. This exploration was the inspiration for this piece encouraging others to explore new places and cherish the experience of being outdoors.” — Designed by Gabrielle Gorney from the United States.

Exploration

Dreaming

“The moment when you just walk and your imagination fills up your mind with thoughts.” — Designed by Gal Shir from Israel.

Dreaming

Say “Bye” To Summer

“And hello to Autumn! The Summer heat and high season is over. It’s time to pack our backpacks and head for the mountains — there are many treasures waiting to be discovered!” Designed by Agnes Sobon from Poland.

Desktop Wallpaper - October 2012

Haunted House

Designed by Mad Fish Digital from the United States.

Trick Or Treat

Mushrooms

“Autumn is the mushroom season. Be vigilant. Do not abuse.” Designed by Cheloveche.ru from Russia.

Free Desktop Wallpaper - October 2011

Save Water, Drink Rain

Designed by Marika Smirnova from Russia.

Smashing Wallpaper - october 11

Autumn Colors

“I love the autumn colors and making pictures, this is a collage of bits and pieces of various autumn photos from previous seasons. Enjoy!” — Designed by Agnes Swart from the Netherlands.

Autumn colors

A Time For Reflection

“‘We’re all equal before a wave.’ (Laird Hamilton)” — Designed by Shawna Armstrong from the United States.

A Time for Reflection

Join In Next Month!

Thank you to all designers for their participation. Join in next month!

Source: Smashing Magazine, Beneath The Autumn Leaves (October 2019 Wallpapers Edition)

SmashingConf 2020 – San Francisco, Freiburg, New York And Austin

dreamt up by webguru in Uncategorized | Comments Off on SmashingConf 2020 – San Francisco, Freiburg, New York And Austin

SmashingConf 2020 – San Francisco, Freiburg, New York And Austin

SmashingConf 2020 – San Francisco, Freiburg, New York And Austin

Rachel Andrew



We’ve been running SmashingConf since 2012, when we held our very first conference in Freiburg, Germany. Since then, we’ve continued to experiment and improve on our conference experience. Our aim is that you enjoy your time with us, but also return to work with new insights and knowledge. Each time we hope to leave you with practical takeaways that will help you in your own work and want to share with your team.

What is a SmashingConf like? It’s hard to explain until you have been there, however ,this video compilation from Toronto might just give you an idea!

https://player.vimeo.com/api/player.js

Experimenting With Presentation Formats

Back in 2018, we began to experiment with the live-coding format. While not every presentation at SmashingConf was live-coded, many presenters brought a live element to their talk. Some speakers opted to present without slides completely, and these interactive sessions have been incredibly popular with audiences. Being able to watch an expert doing their work, seeing the tools they use and the choices they make in real time, brought many subjects to life.

“I love the fact that this talk format also kind of rid me of the expectation that it needed to be flawless.”

Sara Soueidan

Many of our speakers enjoyed the chance to try something different on stage; some have gone so far as to decide to make live-coding part of how they present in the future.

“I didn’t expect this, but I’m now seriously considering this format as a way I do talks at other conferences.”

Dan Mall

Not every talk fits a live-coding format, of course. Throughout 2019, we feel that we’ve found a great balance of practical live-coded (or live-designed) sessions, more traditional presentations with slides, and some which have mixed the two approaches. SmashingConf audiences are a mixture of designers and developers, of visual thinkers and those who learn best from seeing a lot of code.

As Dan Mall noted in his write-up of his live-coded talk:

“A few designers felt validated in their processes by seeing mine […]

“A few developers said design felt less intimidating now, both to understand as well as to try.”

In mixing up the formats as well as the subjects being discussed, we hope to bring parts of the industry to life — even for those who don’t normally work in that area.

Vitaly interviewing Val Head on stage at Smashing Conf Freiburg 2019

Talks are usually followed by an interview. (Photo credit: Drew McLellan)

In addition to playing with the format of presentations, we encourage audiences to engage with the speakers and each other. Talks are followed by an interview on stage — with the emcee posing questions asked by the audience. We publish a live Google Doc, so everyone can share their thoughts and ideas with the speakers as well as each other. Most of our speakers will attend the entire event, and enjoy the chance to chat with attendees. We believe everyone has useful knowledge to share — whether on stage or from the comfort of your seat!

Looking Forward To 2020

SmashingConf has always taken a holistic approach to the web. We believe that we all do better work when we work together and understand something of the roles of other team members. In 2020, we hope to build on the successes of 2019 by continuing to bring you some of the best live sessions — mixed with case studies, opportunities for networking, and surfacing some topics that are sometimes forgotten when focusing on design and development! We’ll cover topics such as HTML email, internationalization and localization, how to provide more accurate estimates, privacy, security, refactoring, debugging and the way designers and developers think as they work through their tasks and challenges.

We’re currently working hard on curating the line-up for all of the events next year. So, the big question is… where will you join us?

San Francisco, Freiburg, New York Or Austin!

The Smashing Cat will soon be on its way to Austin for the first time. We’re really excited about heading to Texas and about our events in cities we already know and love. Over the next few months, we’ll be announcing speakers and schedules for all of the events, but early-bird tickets are already available for San Francisco, Austin, and Freiburg 2020.

This year’s events have all been sold out well in advance of the conference dates, so mark the following dates in your calendars, have a chat with your boss, and work out where you will be heading to spend a fun and educational few days with the Smashing crew!

San Francisco, USA

Smashing San FranciscoSmashingConf SF will be taking place on April 21–22 where we’ll be bringing back two full days packed with front-end, UX and all that jazz! Live sessions on performance, accessibility, security, interface design, debugging and fancy CSS/JS techniques — and a few surprises along the way, of course! 🎸

Austin, USA

Smashing AustinSmashingConf Austin will be taking place in the wonderful ZACH Theatre on June 9–10, 2020. Tacos, cats, and a friendly community — see ya in Austin, I reckon? 🌮

Freiburg, Germany

Smashing FreiburgWe will be returning to our hometown for SmashingConf Freiburg on the 7-8 September 2020. We pour our hearts into creating friendly, inclusive events that are focused on real-world problems and solutions. Our focus is on front-end and UX, but we cover all things web — be it UI design or machine learning. The Freiburg edition is, of course, no exception!

New York, USA

Join us for SmashingConf NYC on the 20-21 October 2020. This event is always a popular one, so watch out for tickets going on sale very soon!

Smashing Editorial
(ra, vf, il)

Source: Smashing Magazine, SmashingConf 2020 – San Francisco, Freiburg, New York And Austin

Frankenstein Migration: Framework-Agnostic Approach (Part 2)

dreamt up by webguru in Uncategorized | Comments Off on Frankenstein Migration: Framework-Agnostic Approach (Part 2)

Frankenstein Migration: Framework-Agnostic Approach (Part 2)

Frankenstein Migration: Framework-Agnostic Approach (Part 2)

Denys Mishunov



In this article, we’ll be putting all the theory to the test by performing step-by-step migration of an application, following the recommendations from the previous part. To make things straightforward, reduce uncertainties, unknowns, and unnecessary guessing, for the practical example of migration, I decided to demonstrate the practice on a simple to-do application.

It’s time to put the theory to the test

It’s time to put the theory to the test. (Large preview)

In general, I assume that you have a good understanding of how a generic to-do application works. This type of application suits our needs very well: it’s predictable, yet has a minimum viable number of required components to demonstrate different aspects of Frankenstein Migration. However, no matter the size and complexity of your real application, the approach is well-scalable and is supposed to be suitable for projects of any size.

A default view of a TodoMVC application

A default view of a TodoMVC application (Large preview)

For this article, as a starting point, I picked a jQuery application from the TodoMVC project — an example that may already be familiar to a lot of you. jQuery is legacy enough, might reflect a real situation with your projects, and most importantly, requires significant maintenance and hacks for powering a modern dynamic application. (This should be enough to consider migration to something more flexible.)

What is this “more flexible” that we are going to migrate to then? To show a highly-practical case useful in real life, I had to choose among the two most popular frameworks these days: React and Vue. However, whichever I would pick, we would miss some aspects of the other direction.

So in this part, we’ll be running through both of the following:

  • A migration of a jQuery application to React, and
  • A migration of a jQuery application to Vue.

Our goals: results of the migration to React and Vue

Our goals: results of the migration to React and Vue. (Large preview)

Code Repositories

All the code mentioned here is publicly available, and you can get to it whenever you want. There are two repositories available for you to play with:

  • Frankenstein TodoMVC
    This repository contains TodoMVC applications in different frameworks/libraries. For example, you can find branches like vue, angularjs, react and jquery in this repository.
  • Frankenstein Demo
    It contains several branches, each of which represents a particular migration direction between applications, available in the first repository. There are branches like migration/jquery-to-react and migration/jquery-to-vue, in particular, that we’ll be covering later on.

Both repositories are work-in-progress and new branches with new applications and migration directions should be added to them regularly. (You’re free to contribute as well!) Commits history in migration branches is well structured and might serve as additional documentation with even more details than I could cover in this article.

Now, let’s get our hands dirty! We have a long way ahead, so don’t expect it to be a smooth ride. It’s up to you to decide how you want to follow along with this article, but you could do the following:

  • Clone the jquery branch from the Frankenstein TodoMVC repository and strictly follow all of the instructions below.
  • Alternatively, you can open a branch dedicated to either migration to React or migration to Vue from the Frankenstein Demo repository and follow along with commits history.
  • Alternatively, you can relax and keep reading because I am going to highlight the most critical code right here, and it’s much more important to understand the mechanics of the process rather than the actual code.

I’d like to mention one more time that we’ll strictly be following the steps presented in the theoretical first part of the article.

Let’s dive right in!

  1. Identify Microservices
  2. Allow Host-to-Alien Access
  3. Write An Alien Microservice/Component
  4. Write Web Component Wrapper Around Alien Service
  5. Replace Host Service With Web Component
  6. Rinse & Repeat For All Of Your Components
  7. Switch To Alien

1. Identify Microservices

As Part 1 suggests, in this step, we have to structure our application into small, independent services dedicated to one particular job. The attentive reader might notice that our to-do application is already small and independent and can represent one single microservice on its own. This is how I would treat it myself if this application would live in some broader context. Remember, however, that the process of identifying microservices is entirely subjective and there is no one correct answer.

So, in order to see the process of Frankenstein Migration in more detail, we can go a step further and split this to-do application into two independent microservices:

  1. An input field for adding a new item.
    This service can also contain the application’s header, based purely on positioning proximity of these elements.
  2. A list of already added items.
    This service is more advanced, and together with the list itself, it also contains actions like filtering, list item’s actions, and so on.

TodoMVC application split into two independent microservices

TodoMVC application split into two independent microservices. (Large preview)

Tip: To check whether the picked services are genuinely independent, remove HTML markup, representing each of these services. Make sure that the remaining functions still work. In our case, it should be possible to add new entries into localStorage (that this application is using as storage) from the input field without the list, while the list still renders the entries from localStorage even if the input field is missing. If your application throws errors when you remove markup for potential microservice, take a look at the “Refactor If Needed” section in Part 1 for an example of how to deal with such cases.

Of course, we could go on and split the second service and the listing of the items even further into independent microservices for each particular item. However, it might be too granular for this example. So, for now, we conclude that our application is going to have two services; they are independent, and each of them works towards its own particular task. Hence, we have split our application into microservices.

2. Allow Host-to-Alien Access

Let me briefly remind you of what these are.

  • Host
    This is what our current application is called. It is written with the framework from which we’re about to move away from. In this particular case, our jQuery application.
  • Alien
    Simply put, this one’s a gradual re-write of Host on the new framework that we are about to move to. Again, in this particular case, it’s a React or Vue application.

The rule of thumb when splitting Host and Alien is that you should be able to develop and deploy any of them without breaking the other one — at any point in time.

Keeping Host and Alien independent from each other is crucial for Frankenstein Migration. However, this makes arranging communication between the two a bit challenging. How do we allow Host access Alien without smashing the two together?

Adding Alien As A Submodule Of Your Host

Even though there are several ways to achieve the setup we need, the simplest form of organizing your project to meet this criterion is probably git submodules. This is what we’re going to use in this article. I’ll leave it up to you to read carefully about how submodules in git work in order to understand limitations and gotchas of this structure.

The general principles of our project’s architecture with git submodules should look like this:

  • Both Host and Alien are independent and are kept in separate git repositories;
  • Host references Alien as a submodule. At this stage, Host picks a particular state (commit) of Alien and adds it as, what looks like, a subfolder in Host’s folder structure.

React TodoMVC added as a git submodule into jQuery TodoMVC application

React TodoMVC added as a git submodule into jQuery TodoMVC application. (Large preview)

The process of adding a submodule is the same for any application. Teaching git submodules is beyond the scope of this article and is not directly related to Frankenstein Migration itself. So let’s just take a brief look at the possible examples.

In the snippets below, we use the React direction as an example. For any other migration direction, replace react with the name of a branch from Frankenstein TodoMVC or adjust to custom values where needed.

If you follow along using the original jQuery TodoMVC application:

$ git submodule add -b react git@gitlab.com:mishunov/frankenstein-todomvc.git react
$ git submodule update --remote
$ cd react
$ npm i

If you follow along with migration/jquery-to-react (or any other migration direction) branch from the Frankenstein Demo repository, the Alien application should already be in there as a git submodule, and you should see a respective folder. However, the folder is empty by default, and you need to update and initialize the registered submodules.

From the root of your project (your Host):

$ git submodule update --init
$ cd react
$ npm i

Note that in both cases we install dependencies for the Alien application, but those become sandboxed to the subfolder and won’t pollute our Host.

After adding the Alien application as a submodule of your Host, you get independent (in terms of microservices) Alien and Host applications. However, Host considers Alien a subfolder in this case, and obviously, that allows Host to access Alien without a problem.

3. Write An Alien Microservice/Component

At this step, we have to decide what microservice to migrate first and write/use it on the Alien’s side. Let’s follow the same order of services we identified in Step 1 and start with the first one: input field for adding a new item. However, before we begin, let’s agree that beyond this point, we are going to use a more favorable term component instead of microservice or service as we are moving towards the premises of frontend frameworks and the term component follows the definitions of pretty much any modern framework.

Branches of Frankenstein TodoMVC repository contain a resulting component that represents the first service “Input field for adding a new item” as a Header component:

Writing components in the framework of your choice is beyond the scope of this article and is not part of Frankenstein Migration. However, there are a couple of things to keep in mind while writing an Alien component.

Independence

First of all, the components in Alien should follow the same principle of independence, previously set up on the Host’s side: components should not depend on other components in any way.

Interoperability

Thanks to the independence of the services, most probably, components in your Host communicate in some well-established way be it a state management system, communication through some shared storage or, directly via a system of DOM events. “Interoperability” of Alien components means that they should be able to connect to the same source of communication, established by Host, to dispatch information about its state changes and listen to changes in other components. In practice, this means that if components in your Host communicate via DOM events, building your Alien component exclusively with state management in mind won’t work flawlessly for this type of migration, unfortunately.

As an example, take a look at the js/storage.js file that is the primary communication channel for our jQuery components:

...

fetch: function() {
  return JSON.parse(localStorage.getItem(STORAGE_KEY) || "[]");
},
save: function(todos) {
  localStorage.setItem(STORAGE_KEY, JSON.stringify(todos));
  var event = new CustomEvent("store-update", { detail: { todos } });
  document.dispatchEvent(event);
},

...

Here, we use localStorage (as this example is not security-critical) to store our to-do items, and once the changes to the storage get recorded, we dispatch a custom DOM event on the document element that any component can listen to.

At the same time, on the Alien’s side (let’s say React) we can set up as complex state management communication as we want. However, it’s probably smart to keep it for the future: to successfully integrate our Alien React component into Host, we have to connect to the same communication channel used by Host. In this case, it’s localStorage. To make things simple, we just copied over Host’s storage file into Alien and hooked up our components to it:

import todoStorage from "../storage";

class Header extends Component {
  constructor(props) {
    this.state = {
      todos: todoStorage.fetch()
    };
  }
  componentDidMount() {
    document.addEventListener("store-update", this.updateTodos);
  }
  componentWillUnmount() {
    document.removeEventListener("store-update", this.updateTodos);
  }
  componentDidUpdate(prevProps, prevState) {
    if (prevState.todos !== this.state.todos) {
      todoStorage.save(this.state.todos);
    }
  }
  ...
}

Now, our Alien components can talk the same language with Host components and vice versa.

4. Write Web Component Wrapper Around Alien Service

Even though we’re now only on the fourth step, we have achieved quite a lot:

  • We’ve split our Host application into independent services which are ready to be replaced by Alien services;
  • We’ve set up Host and Alien to be completely independent of each other, yet very well connected via git submodules;
  • We’ve written our first Alien component using the new framework.

Now it’s time to set up a bridge between Host and Alien so that the new Alien component could function in the Host.

Reminder from Part 1: Make sure that your Host has a package bundler available. In this article, we rely on Webpack, but it doesn’t mean that the technique won’t work with Rollup or any other bundler of your choice. However, I leave the mapping from Webpack to your experiments.

Naming Convention

As mentioned in the previous article, we are going to use Web Components to integrate Alien into Host. On the Host’s side, we create a new file: js/frankenstein-wrappers/Header-wrapper.js. (It’s going to be our first Frankenstein wrapper.) Keep in mind that it’s a good idea to name your wrappers the same as your components in Alien application, e.g. just by adding a “-wrapper” suffix. You”ll see later on why this is a good idea, but for now, let’s agree that this means that if the Alien component is called Header.js (in React) or Header.vue (in Vue), the corresponding wrapper on the Host’s side should be called Header-wrapper.js.

In our first wrapper, we begin with the fundamental boilerplate for registering a custom element:

class FrankensteinWrapper extends HTMLElement {}
customElements.define("frankenstein-header-wrapper", FrankensteinWrapper);

Next, we have to initialize Shadow DOM for this element.

Please refer to Part 1 to get reasoning on why we use Shadow DOM.

class FrankensteinWrapper extends HTMLElement {
  connectedCallback() {
    this.attachShadow({ mode: "open" });
  }
}

With this, we have all the essential bits of the Web Component set up, and it’s time to add our Alien component into the mix. First of all, at the beginning of our Frankenstein wrapper, we should import all the bits responsible for the Alien component’s rendering.

import React from "../../react/node_modules/react";
import ReactDOM from "../../react/node_modules/react-dom";
import HeaderApp from "../../react/src/components/Header";
...

Here we have to pause for a second. Note that we do not import Alien’s dependencies from Host’s node_modules. Everything comes from the Alien itself that sits in react/ subfolder. That is why Step 2 is so important, and it is crucial to make sure the Host has full access to assets of Alien.

Now, we can render our Alien component within Web Component’s Shadow DOM:

...
connectedCallback() {
  ...
  ReactDOM.render(<HeaderApp />, this.shadowRoot);
}
...

Note: In this case, React doesn’t need anything else. However, to render the Vue component, you need to add a wrapping node to contain your Vue component like the following:

...
connectedCallback() {
  const mountPoint = document.createElement("div");
  this.attachShadow({ mode: "open" }).appendChild(mountPoint);
  new Vue({
    render: h => h(VueHeader)
  }).$mount(mountPoint);
}
...

The reason for this is the difference in how React and Vue render components: React appends component to referenced DOM node, while Vue replaces referenced DOM node with the component. Hence, if we do .$mount(this.shadowRoot) for Vue, it essentially replaces the Shadow DOM.

That’s all we have to do to our wrapper for now. The current result for Frankenstein wrapper in both jQuery-to-React and jQuery-to-Vue migration directions can be found over here:

To sum up the mechanics of the Frankenstein wrapper:

  1. Create a custom element,
  2. Initiate Shadow DOM,
  3. Import everything needed for rendering an Alien component,
  4. Render the Alien component within the custom element’s Shadow DOM.

However, this doesn’t render our Alien in Host automatically. We have to replace the existing Host markup with our new Frankenstein wrapper.

Fasten your seatbelts, it may not be as straightforward as one would expect!

5. Replace Host Service With Web Component

Let’s go on and add our new Header-wrapper.js file to index.html and replace the existing header markup with the newly-created <frankenstein-header-wrapper> custom element.

...
<!-- <header class="header">-->
<!--   <h1>todos</h1>-->
<!--   <input class="new-todo" placeholder="What needs to be done?" autofocus>-->
<!-- </header>-->

<frankenstein-header-wrapper></frankenstein-header-wrapper>
...
http://js/frankenstein-wrappers/Header-wrapper.js
    

Unfortunately, this won’t work as simple as that. If you open a browser and check the console, there is the Uncaught SyntaxError waiting for you. Depending on the browser and its support for ES6 modules, it will either be related to ES6 imports or to the way the Alien component gets rendered. Either way, we have to do something about it, but the problem and solution should be familiar and clear to most of the readers.

5.1. Update Webpack and Babel where needed

We should involve some Webpack and Babel magic before integrating our Frankenstein wrapper. Wrangling these tools is beyond the scope of the article, but you can take a look at the corresponding commits in the Frankenstein Demo repository:

Essentially, we set up the processing of the files as well as a new entry point frankenstein in Webpack’s configuration to contain everything related to Frankenstein wrappers in one place.

Once Webpack in Host knows how to process the Alien component and Web Components, we’re ready to replace Host’s markup with the new Frankenstein wrapper.

5.2. Actual Component’s Replacement

The component’s replacement should be straightforward now. In index.html of your Host, do the following:

  1. Replace <header class="header"> DOM element with <frankenstein-header-wrapper>;
  2. Add a new script frankenstein.js. This is the new entry point in Webpack that contains everything related to Frankenstein wrappers.
...
<!-- We replace <header class="header"> -->
<frankenstein-header-wrapper></frankenstein-header-wrapper>
...
http://./frankenstein.js

That’s it! Restart your server if needed and witness the magic of the Alien component integrated into Host.

However, something still seemd to be is missing. The Alien component in the Host context doesn’t look the same way as it does in the context of the standalone Alien application. It’s simply unstyled.

Unstyled Alien React component after being integrated into Host

Unstyled Alien React component after being integrated into Host (Large preview)

Why is it so? Shouldn’t the component’s styles be integrated with the Alien component into Host automatically? I wish they would, but as in too many situations, it depends. We’re getting to the challenging part of Frankenstein Migration.

5.3. General Information On The Styling Of The Alien Component

First of all, the irony is that there is no bug in the way things work. Everything is as it’s designed to work. To explain this, let’s briefly mention different ways of styling components.

Global Styles

We all are familiar with these: global styles can be (and usually are) distributed without any particular component and get applied to the whole page. Global styles affect all DOM nodes with matching selectors.

A few examples of global styles are <style> and <link rel="stylesheet"> tags found into your index.html. Alternatively, a global stylesheet can be imported into some root JS module so that all components could get access to it as well.

The problem of styling applications in this way is obvious: maintaining monolithic stylesheets for large applications becomes very hard. Also, as we saw in the previous article, global styles can easily break components that are rendered straight in the main DOM tree like it is in React or Vue.

Bundled Styles

These styles usually are tightly coupled with a component itself and are rarely distributed without the component. The styles typically reside in the same file with the component. Good examples of this type of styling are styled-components in React or CSS Modules and Scoped CSS in single file components in Vue. However, no matter the variety of tools for writing bundled styles, the underlying principle in most of them is the same: the tools provide a scoping mechanism to lock down styles defined in a component so that the styles don’t break other components or global styles.

Why Could Scoped Styles Be Fragile?

In Part 1, when justifying the use of Shadow DOM in Frankenstein Migration, we briefly covered the topic of scoping vs. encapsulation) and how encapsulation of Shadow DOM is different from scoping styling tools. However, we did not explain why scoping tools provide such fragile styling for our components, and now, when we faced the unstyled Alien component, it becomes essential for understanding.

All scoping tools for modern frameworks work similarly:

  • You write styles for your component in some way without thinking much about scope or encapsulation;
  • You run your components with imported/embedded stylesheets through some bundling system, like Webpack or Rollup;
  • The bundler generates unique CSS classes or other attributes, creating and injecting individual selectors for both your HTML and corresponding stylesheets;
  • The bundler makes a <style> entry in the <head> of your document and puts your components’ styles with unique mingled selectors in there.

That’s pretty much it. It does work and works fine in many cases. Except for when it does not: when styles for all components live in the global styling scope, it becomes easy to break those, for example, using higher specificity. This explains the potential fragility of scoping tools, but why is our Alien component completely unstyled?

Let’s take a look at the current Host using DevTools. When inspecting the newly-added Frankenstein wrapper with the Alien React component, for example, we can see something like this:

Frankenstein wrapper with Alien component inside. Note unique CSS classes on the Alien’s nodes.

Frankenstein wrapper with Alien component inside. Note unique CSS classes on the Alien’s nodes. (Large preview)

So, Webpack does generate unique CSS classes for our component. Great! Where are the styles then? Well, the styles are precisely where they are designed to be — in the document’s <head>.

While Alien component is within Frankenstein wrapper, its styles are in document’s head.

While Alien component is within Frankenstein wrapper, its styles are in document’s <head>. (Large preview)

So everything works as it should, and this is the main problem. Since our Alien component resides in Shadow DOM, and as explained in Part #1, Shadow DOM provides full encapsulation of components from the rest of the page and global styles, including those newly-generated stylesheets for the component that cannot cross the shadow border and get to the Alien component. Hence, the Alien component is left unstyled. However, now, the tactics of solving the problem should be clear: we should somehow place the component’s styles in the same Shadow DOM where our component resides (instead of the document’s <head>).

5.4. Fixing Styles For The Alien Component

Up until now, the process of migrating to any framework was the same. However, things start diverging here: every framework has its recommendations on how to style components, and hence, the ways of tackling the problem differ. Here, we discuss most common cases but, if the framework you work with uses some unique way of styling components, you need to keep in mind the basic tactics such as putting the component’s styles into Shadow DOM instead of <head>.

In this chapter, we are covering fixes for:

  • Bundled styles with CSS Modules in Vue (tactics for Scoped CSS are the same);
  • Bundled styles with styled-components in React;
  • Generic CSS Modules and global styles. I combine these because CSS Modules, in general, are very similar to the global stylesheets and can be imported by any component making the styles disconnected from any particular component.

Constraints first: anything we do to fix styling should not break the Alien component itself. Otherwise, we lose the independence of our Alien and Host systems. So, to address the styling issue, we are going to rely on either bundler’s configuration or the Frankenstein wrapper.

Bundled Styles In Vue And Shadow DOM

If you’re writing a Vue application, then you’re most probably using single file components. If you’re also using Webpack, you should be familiar with two loaders vue-loader and vue-style-loader. The former allows you to write those single file components while the latter dynamically injects the component’s CSS into a document as a <style> tag. By default, vue-style-loader injects the component’s styles into the document’s <head>. However, both packages accept the shadowMode option in configuration which allows us to easily change the default behavior and inject styles (as the option’s name implies) into Shadow DOM. Let’s see it in action.

Webpack Configuration

At a bare minimum, the Webpack configuration file should contain the following:

const VueLoaderPlugin = require('vue-loader/lib/plugin');
...
module: {
  rules: [
    {
      test: /.vue$/,
      loader: 'vue-loader',
      options: {
        shadowMode: true
      }
    },
    {
      test: /.css$/,
      include: path.resolve(__dirname, '../vue'),
      use: [
        {
          loader:'vue-style-loader',
          options: {
            shadowMode: true
          }
        },
        'css-loader'
      ]
    }
  ],
  plugins: [
    new VueLoaderPlugin()
  ]
}

In a real application, your test: /.css$/ block will be more sophisticated (probably involving the oneOf rule) to account for both Host and Alien configurations. However, in this case, our jQuery is styled with simple <link rel="stylesheet"> in index.html, so we don’t build styles for Host via Webpack, and it’s safe to cater for Alien only.

Wrapper Configuration

In addition to Webpack configuration, we also need to update our Frankenstein wrapper, pointing Vue to the correct Shadow DOM. In our Header-wrapper.js, rendering of the Vue component should include the shadowRoot property leading to shadowRoot of our Frankenstein wrapper:

...
new Vue({
  shadowRoot: this.shadowRoot,
  render: h => h(VueHeader)
}).$mount(mountPoint);
...

After you update the files and restart your server, you should be getting something like this in your DevTools:

Styles bundled with Alien Vue component placed within Frankenstein wrapper with all unique CSS classes preserved.

Styles bundled with Alien Vue component placed within Frankenstein wrapper with all unique CSS classes preserved. (Large preview)

Finally, styles for the Vue component are within our Shadow DOM. At the same time, your application should look like this:

Header component starts to look more like it should. However, something is still missing.

Header component starts to look more like it should. However, something is still missing. (Large preview)

We start getting something resembling our Vue application: styles bundled with the component, are injected into the wrapper’s Shadow DOM, but the component still looks not as it is supposed to. The reason is that in the original Vue application, the component is styled not only with the bundled styles but also partially with global styles. However, before fixing the global styles, we have to get our React integration to the same state as the Vue one.

Bundled Styles In React And Shadow DOM

Because there are many ways one can style a React component, the particular solution to fix an Alien component in Frankenstein Migration depends on the way we style the component in the first place. Let’s briefly cover the most commonly used alternatives.

styled-components

styled-components is one of the most popular ways of styling React components. For the Header React component, styled-components is precisely the way we style it. Since this is a classic CSS-in-JS approach, there is no file with a dedicated extension that we could hook our bundler onto as we do for .css or .js files, for example. Luckily, styled-components allow the injection of component’s styles into a custom node (Shadow DOM in our case) instead of the document’s headwith the help of the StyleSheetManager helping component. It is a pre-defined component, installed with the styled-components package that accepts target property, defining “an alternate DOM node to inject styles info”. Exactly what we need! Moreover, we do not even need to change our Webpack configuration: everything is up to our Frankenstein wrapper.

We should update our Header-wrapper.js that contains the React Alien component with the following lines:

...
import { StyleSheetManager } from "../../react/node_modules/styled-components";
...
const target = this.shadowRoot;
ReactDOM.render(
  <StyleSheetManager target={target}>
    <HeaderApp />
  </StyleSheetManager>,
  appWrapper
);
...

Here, we import the StyleSheetManager component (from Alien, and not from Host) and wrap our React component with it. At the same time, we send the target property pointing to our shadowRoot. That’s it. If you restart the server, you have to see something like this in your DevTools:

Styles bundled with React Alien component placed within Frankenstein wrapper with all unique CSS classes preserved.

Styles bundled with React Alien component placed within Frankenstein wrapper with all unique CSS classes preserved. (Large preview)

Now, our component’s styles are in Shadow DOM instead of <head>. This way, the rendering of our app now resembles what we have seen with the Vue app previously.

After moving bundled styles into Frankenstein wrapper, the Alien React component begins to look better. However, we’re not there yet.

After moving bundled styles into Frankenstein wrapper, the Alien React component begins to look better. However, we’re not there yet. (Large preview)

Same story: styled-components are responsible just for the bundled part of the React component’s styles, and the global styles manage the remaining bits. We get back to global styles in a bit after we review one more type of styling components.

CSS Modules

If you take a closer look at the Vue component that we have fixed earlier, you might notice that CSS Modules is precisely the way we style that component. However, even if we style it with Scoped CSS (another recommended way of styling Vue components) the way we fix our unstyled component doesn’t change: it is still up to vue-loader and vue-style-loader to handle it through shadowMode: true option.

When it comes to CSS Modules in React (or any other system using CSS Modules without any dedicated tools), things get a bit more complicated and less flexible, unfortunately.

Let’s take a look at the same React component which we’ve just integrated, but this time styled with CSS Modules instead of styled-components. The main thing to note in this component is a separate import for stylesheet:

import styles from './Header.module.css'

The .module.css extension is a standard way to tell React applications built with the create-react-app utility that the imported stylesheet is a CSS Module. The stylesheet itself is very basic and does precisely the same our styled-components do.

Integrating CSS modules into a Frankenstein wrapper consists of two parts:

  • Enabling CSS Modules in bundler,
  • Pushing resulting stylesheet into Shadow DOM.

I believe the first point is trivial: all you need to do is set { modules: true } for css-loader in your Webpack configuration. Since, in this particular case, we have a dedicated extension for our CSS Modules (.module.css), we can have a dedicated configuration block for it under the general .css configuration:

{
  test: /.css$/,
  oneOf: [
    {
      test: /.module.css$/,
      use: [
        ...
        {
          loader: 'css-loader',
          options: {
            modules: true,
          }
        }
      ]
    }
  ]
}

Note: A modules option for css-loader is all we have to know about CSS Modules no matter whether it’s React or any other system. When it comes to pushing resulting stylesheet into Shadow DOM, however, CSS Modules are no different from any other global stylesheet.

By now, we went through the ways of integrating bundled styles into Shadow DOM for the following conventional scenarios:

  • Vue components, styled with CSS Modules. Dealing with Scoped CSS in Vue components won’t be any different;
  • React components, styled with styled-components;
  • Components styled with raw CSS Modules (without dedicated tools like those in Vue). For these, we have enabled support for CSS modules in Webpack configuration.

However, our components still don’t look as they are supposed to because their styles partially come from global styles. Those global styles do not come to our Frankenstein wrappers automatically. Moreover, you might get into a situation in which your Alien components are styled exclusively with global styles without any bundled styles whatsoever. So let’s finally fix this side of the story.

Global Styles And Shadow DOM

Having your components styled with global styles is neither wrong nor bad per se: every project has its requirements and limitations. However, the best you can do for your components if they rely on some global styles is to pull those styles into the component itself. This way, you have proper easy-to-maintain self-contained components with bundled styles.

Nevertheless, it’s not always possible or reasonable to do so: several components might share some styling, or your whole styling architecture could be built using global stylesheets that are split into the modular structure, and so on.

So having an opportunity to pull in global styles into our Frankenstein wrappers wherever it’s required is essential for the success of this type of migration. Before we get to an example, keep in mind that this part is the same for pretty much any framework of your choice — be it React, Vue or anything else using global stylesheets!

Let’s get back to our Header component from the Vue application. Take a look at this import:

import "todomvc-app-css/index.css";

This import is where we pull in the global stylesheet. In this case, we do it from the component itself. It’s only one way of using global stylesheet to style your component, but it’s not necessarily like this in your application.

Some parent module might add a global stylesheet like in our React application where we import index.css only in index.js, and then our components expect it to be available in the global scope. Your component’s styling might even rely on a stylesheet, added with <style> or <link> to your index.html. It doesn’t matter. What matters, however, is that you should expect to either import global stylesheets in your Alien component (if it doesn’t harm the Alien application) or explicitly in the Frankenstein wrapper. Otherwise, the wrapper would not know that the Alien component needs any stylesheet other than the ones already bundled with it.

Caution. If there are many global stylesheets to be shared between Alien components and you have a lot of such components, this might harm the performance of your Host application under the migration period.

Here is how import of a global stylesheet, required for the Header component, is done in Frankenstein wrapper for React component:

// we import directly from react/, not from Host
import '../../react/node_modules/todomvc-app-css/index.css'

Nevertheless, by importing a stylesheet this way, we still bring the styles to the global scope of our Host, while what we need is to pull in the styles into our Shadow DOM. How do we do this?

Webpack configuration for global stylesheets & Shadow DOM

First of all, you might want to add an explicit test to make sure that we process only the stylesheets coming from our Alien. In case of our React migration, it will look similar to this:

test: /.css$/,
oneOf: [
  // this matches stylesheets coming from /react/ subfolder
  {
    test: //react//,
    use: []
  },
  ...
]

In case of Vue application, obviously, you change test: //react// with something like test: //vue//. Apart from that, the configuration will be the same for any framework. Next, let’s specify the required loaders for this block.

...
use: [
  {
    loader: 'style-loader',
    options: {
      ...
    }
  },
  'css-loader'
]

Two things to note. First, you have to specify modules: true in css-loader’s configuration if you’re processing CSS Modules of your Alien application.

Second, we should convert styles into <style> tag before injecting those into Shadow DOM. In the case of Webpack, for that, we use style-loader. The default behavior for this loader is to insert styles into the document’s head. Typically. And this is precisely what we don’t want: our goal is to get stylesheets into Shadow DOM. However, in the same way we used target property for styled-components in React or shadowMode option for Vue components that allowed us to specify custom insertion point for our <style> tags, regular style-loader provides us with nearly same functionality for any stylesheet: the insert configuration option is exactly what helps us achieve our primary goal. Great news! Let’s add it to our configuration.

...
{
  loader: 'style-loader',
  options: {
    insert: 'frankenstein-header-wrapper'
  }
}

However, not everything is so smooth here with a couple of things to keep in mind.

Global stylesheets and insert option of style-loader

If you check documentation for this option, you notice, that this option takes one selector per configuration. This means that if you have several Alien components requiring global styles pulled into a Frankenstein wrapper, you have to specify style-loader for each of the Frankenstein wrappers. In practice, this means that you, probably, have to rely on oneOf rule in your configuration block to serve to all wrappers.

{
  test: //react//,
  oneOf: [
    {
      test: /1-TEST-FOR-ALIEN-FILE-PATH$/,
      use: [
        {
          loader: 'style-loader',
          options: {
            insert: '1-frankenstein-wrapper'
          }
        },
        `css-loader`
      ]
    },
    {
      test: /2-TEST-FOR-ALIEN-FILE-PATH$/,
      use: [
        {
          loader: 'style-loader',
          options: {
            insert: '2-frankenstein-wrapper'
          }
        },
        `css-loader`
      ]
    },
    // etc.
  ],
}

Not very flexible, I agree. Nevertheless, it’s not a big deal as long as you don’t have hundreds of components to migrate. Otherwise, it might make your Webpack configuration hard to maintain. The real problem, however, is that we can not write a CSS selector for Shadow DOM.

Trying to solve this, we might note that the insert option can also take a function instead of a plain selector to specify more advanced logic for insertion. With this, we can use this option to insert stylesheets straight into Shadow DOM! In simplified form it might look similar to this:

insert: function(element) {
  var parent = document.querySelector('frankenstein-header-wrapper').shadowRoot;
  parent.insertBefore(element, parent.firstChild);
}

Tempting, isn’t it? However, this won’t work for our scenario or will work far from optimal. Our <frankenstein-header-wrapper> is indeed available from index.html (because we added it in Step 5.2). But when Webpack processes all dependencies (incl. the stylesheets) for either an Alien component or a Frankenstein wrapper, Shadow DOM is not yet initialized in the Frankenstein wrapper: imports are processed before that. Hence, pointing insert straight to shadowRoot will result in an error.

There is only one case when we can guarantee that Shadow DOM is initialized before Webpack processes our stylesheet dependency. If Alien component does not import a stylesheet itself and it becomes up to Frankenstein wrapper to import it, we might employ dynamic import and import the required stylesheet after we set up Shadow DOM:

this.attachShadow({ mode: "open" });
import('../vue/node_modules/todomvc-app-css/index.css');

This will work: such import, combined with the insert configuration above, will indeed find correct Shadow DOM and insert <style> tag into it. Nevertheless, getting and processing stylesheet will take time, which means your users on a slow connection or slow devices might face a moment of the unstyled component before your stylesheet gets on its place within wrapper’s Shadow DOM.

Unstyled Alien component gets rendered before the global stylesheet is imported and added to the Shadow DOM.
Unstyled Alien component gets rendered before the global stylesheet is imported and added to the Shadow DOM. (Large preview)

So all in all, even though insert accepts function, unfortunately, it’s not enough for us, and we have to fall back to plain CSS selectors like frankenstein-header-wrapper. This doesn’t place stylesheets into Shadow DOM automatically, however, and the stylesheets reside in <frankenstein-header-wrapper> outside of Shadow DOM.

style-loader puts imported stylesheet into the Frankenstein wrapper, but outside of Shadow DOM.

style-loader puts imported stylesheet into the Frankenstein wrapper, but outside of Shadow DOM. (Large preview)

We need one more piece of the puzzle.

Wrapper configuration for global stylesheets & Shadow DOM

Luckily, the fix is quite straightforward on the wrapper’s side: when Shadow DOM gets initialized, we need to check for any pending stylesheets in the current wrapper and pull them into Shadow DOM.

The current state of the global stylesheet’s import is as follows:

  • We import a stylesheet that has to be added into Shadow DOM. The stylesheet can be imported in either the Alien component itself or, explicitly in the Frankenstein wrapper. In the case of migration to React, for example, the import is initialized from the wrapper. However, in migration to Vue, the similar component itself imports the required stylesheet, and we don’t have to import anything in the wrapper.
  • As pointed out above, when Webpack processes .css imports for the Alien component, thanks to the insert option of style-loader, the stylesheets get injected into a Frankenstein wrapper, but outside of Shadow DOM.

Simplified initialization of Shadow DOM in Frankenstein wrapper, should currently (before we pull in any stylesheets) look similar to this:

this.attachShadow({ mode: "open" });
ReactDOM.render(); // or `new Vue()`

Now, to avoid flickering of the unstyled component, what we need to do now is pull in all the required stylesheets after initialization of the Shadow DOM, but before the Alien component’s rendering.

this.attachShadow({ mode: "open" });

Array.prototype.slice
  .call(this.querySelectorAll("style"))
  .forEach(style => {
    this.shadowRoot.prepend(style);
  });

ReactDOM.render(); // or new Vue({})

It was a long explanation with a lot of details, but mainly, all it takes to pull in global stylesheets into Shadow DOM:

  • In Webpack configuration add style-loader with insert option pointing to required Frankenstein wrapper.
  • In the wrapper itself, pull in “pending” stylesheets after initialization of Shadow DOM, but before the Alien component’s rendering.

After implementing these changes, your component should have everything it needs. The only thing you might want (this is not a requirement) to add is some custom CSS to fine-tune an Alien component in Host’s environment. You might even style your Alien component completely different when used in Host. It goes beyond the main point of the article, but you look at the final code for the wrapper, where you can find examples of how to override simple styles on the wrapper level.

You can also take a look at the Webpack configuration at this step of migration:

And finally, our components look exactly as we intended them to look like.

Result of migrating Header component written with Vue and React. The listing of the to-do items is still jQuery application.

Result of migrating Header component written with Vue and React. The listing of the to-do items is still jQuery application. (Large preview)

5.5. Summary of fixing styles for the Alien component

This is a great moment to sum up what we have learned in this chapter so far. It might look like we had to do enormous work to fix styling of the Alien component; however, it all boils down to:

  • Fixing bundled styles implemented with styled-components in React or CSS modules and Scoped CSS in Vue is as simple as a couple of lines in Frankenstein wrapper or Webpack configuration.
  • Fixing styles, implemented with CSS Modules, starts with just one line in css-loader configuration. After that, CSS Modules are treated as a global stylesheet.
  • Fixing global stylesheets requires configuring style-loader package with insert option in Webpack, and updating Frankenstein wrapper to pull in the stylesheets into Shadow DOM at the right moment of the wrapper’s lifecycle.

After all, we have got properly styled Alien component migrated into the Host. There is just one thing that might or might not bother you depending on what framework you migrate to, however.

Good news first: If you’re migrating to Vue, the demo should be working just fine, and you should be able to add new to-do items from migrated Vue component. However, if you’re migrating to React, and try to add a new to-do item, you won’t succeed. Adding new items simply doesn’t work, and no entries are added to the list. But why? What’s the problem? No prejudice, but React has its own opinions on some things.

5.6. React And JS Events In Shadow DOM

No matter what React documentation tells you, React is not very friendly to Web Components. The simplicity of the example in the documentation doesn’t stand any criticism, and anything more complicated than rendering a link in Web Component requires some research and investigation.

As you have seen while fixing the styling for our Alien component, contrary to Vue where things fit Web Components nearly out of the box, React is not that Web Components-ready. For now, we have an understanding of how to make React components at least look good within Web Components, but there is also functionality and JavaScript events to fix.

Long story short: Shadow DOM encapsulates events and retargets them, while React does not support this behavior of Shadow DOM natively and hence does not catch events coming from within Shadow DOM. There are deeper reasons for this behavior, and there is even an open issue in React’s bug tracker if you want to dive into more details and discussions.

Luckily, smart people prepared a solution for us. @josephnvu provided the basis for the solution, and Lukas Bombach converted it into react-shadow-dom-retarget-events npm module. So you can install the package, follow instructions on the packages’ page, update your wrapper’s code and your Alien component will magically start working:

import retargetEvents from 'react-shadow-dom-retarget-events';
...
ReactDOM.render(
  ...
);
retargetEvents(this.shadowRoot);

If you want to have it more performant, you can make a local copy of the package (MIT license allows that) and limit the number of events to listen to as it is done in Frankenstein Demo repository. For this example, I know what events I need to retarget and specify only those.

With this, we are finally (I know it was a long process) done with proper migration of the first styled and fully-functional Alien component. Get yourself a good drink. You deserve it!

6. Rinse & Repeat For All Of Your Components

After we migrated the first component, we should repeat the process for all of our components. In the case of Frankenstein Demo, there is only one left, however: the one, responsible for rendering the listing of to-do items.

New Wrappers For New Components

Let’s start with adding a new wrapper. Following the naming convention, discussed above (since our React component is called MainSection.js), the corresponding wrapper in migration to React should be called MainSection-wrapper.js. At the same time, a similar component in Vue is called Listing.vue, hence the corresponding wrapper in the migration to Vue should be called Listing-wrapper.js. However, no matter the naming convention, the wrapper itself is going to be nearly identical to the one we already have:

There is just one interesting thing we introduce in this second component in React application. Sometimes, for that or another reason, you might want to use some jQuery plugin in your components. In case of our React component, we introduced two things:

  • Tooltip plugin from Bootstrap that uses jQuery,
  • A toggle for CSS classes like .addClass() and .removeClass().

    Note: This use of jQuery for adding/removing classes is purely illustrative. Please don’t use jQuery for this scenario in real projects — rely on plain JavaScript instead.

Of course, it might look weird to introduce jQuery in an Alien component when we migrate away from jQuery, but your Host might be different from the Host in this example — you might migrate away from AngularJS or anything else. Also, jQuery functionality in a component and global jQuery are not necessarily the same thing.

However, the problem is that even if you confirm that component works just fine in the context of your Alien application, when you put it into Shadow DOM, your jQuery plugins and other code that rely on jQuery just won’t work.

jQuery In Shadow DOM

Let’s take a look at a general initialization of a random jQuery plugin:

$('.my-selector').fancyPlugin();

This way, all elements with .my-selector are going to be processed by fancyPlugin. This form of initialization assumes that .my-selector is present in global DOM. However, once such an element is put into Shadow DOM, just like with styles, shadow boundaries prevent jQuery from sneaking into it. As a result, jQuery can not find elements within Shadow DOM.

The solution is to provide an optional second parameter to the selector that defines the root element for jQuery to search from. And this is, where we can supply our shadowRoot.

$('.my-selector', this.shadowRoot).fancyPlugin();

This way, jQuery selectors and, as a result, the plugins will work just fine.

Keep in mind though that the Alien components are intended to be used both: in Alien without shadow DOM, and in Host within Shadow DOM. Hence we need a more unified solution that would not assume the presence of Shadow DOM by default.

Analyzing MainSection component in our React application, we find that it sets documentRoot property.

...
this.documentRoot = this.props.root? this.props.root: document;
...

So, we check for passed root property, and if it exists, this is what we use as documentRoot. Otherwise, we fall back to document.

Here is the initialize of the tooltip plugin that uses this property:

$('[data-toggle="tooltip"]', this.documentRoot).tooltip({
  container: this.props.root || 'body'
});

As a bonus, we use the same root property to define a container for injecting the tooltip in this case.

Now, when the Alien component is ready to accept the root property, we update rendering of the component in corresponding Frankenstein wrapper:

// `appWrapper` is the root element within wrapper’s Shadow DOM.
ReactDOM.render(<MainApp root={ appWrapper } />, appWrapper);

And that’s it! The component works as fine in Shadow DOM as it does in the global DOM.

Webpack configuration for multi-wrappers scenario

The exciting part is happening in Webpack’s configuration when using several wrappers. Nothing changes for the bundled styles like those CSS Modules in Vue components, or styled-components in React. However, global styles should get a little twist now.

Remember, we said that style-loader (responsible for injecting global stylesheets into correct Shadow DOM) is inflexible as it takes just one selector at a time for its insert option. This means that we should split the .css rule in Webpack to have one sub-rule per wrapper using oneOf rule or similar, if you’re on a bundler other than Webpack.

It’s always easier to explain by using an example, so let’s talk about the one from migration to Vue this time (the one in migration to React, however, is nearly identical):

...
oneOf: [
  {
    issuer: /Header/,
    use: [
      {
        loader: 'style-loader',
        options: {
          insert: 'frankenstein-header-wrapper'
        }
      },
      ...
    ]
  },
  {
    issuer: /Listing/,
    use: [
      {
        loader: 'style-loader',
        options: {
          insert: 'frankenstein-listing-wrapper'
        }
      },
      ...
    ]
  },
]
...

I have excluded css-loader as its configuration is the same in all cases. Let’s talk about style-loader instead. In this configuration, we insert <style> tag into either *-header-* or *-listing-*, depending on the name of the file requesting that stylesheet (issuer rule in Webpack). But we have to remember that the global stylesheet required for rendering an Alien component might be imported in two places:

  • The Alien component itself,
  • A Frankenstein wrapper.

And here, we should appreciate the naming convention for wrappers, described above, when the name of an Alien component and a corresponding wrapper match. If, for example, we have a stylesheet, imported in a Vue component called Header.vue, it gets to correct *-header-* wrapper. At the same time, if we, instead, import the stylesheet in the wrapper, such stylesheet follows precisely the same rule if the wrapper is called Header-wrapper.js without any changes in the configuration. Same thing for the Listing.vue component and its corresponding wrapper Listing-wrapper.js. Using this naming convention, we reduce the configuration in our bundler.

After all of your components migrated, it’s time for the final step of the migration.

7. Switch To Alien

At some point, you find out that the components you identified at the very first step of the migration, are all replaced with Frankenstein wrappers. No jQuery application is left really and what you have is, essentially, the Alien application that is glued together using the means of Host.

For example, the content part of index.html in the jQuery application — after migration of both microservices — looks something like this now:

<section class="todoapp">
  <frankenstein-header-wrapper></frankenstein-header-wrapper>
  <frankenstein-listing-wrapper></frankenstein-listing-wrapper>
</section>

At this moment, there is no point in keeping our jQuery application around: instead, we should switch to Vue application and forget about all of our wrappers, Shadow DOM and fancy Webpack configurations. To do this, we have an elegant solution.

Let’s talk about HTTP requests. I will mention Apache configuration here, but this is just an implementation detail: doing the switch in Nginx or anything else should be as trivial as in Apache.

Imagine that you have your site served from the /var/www/html folder on your server. In this case, your httpd.conf or httpd-vhost.conf should have an entry that points to that folder like:

DocumentRoot "/var/www/html"

To switch your application after the Frankenstein migration from jQuery to React, all you need to do is update the DocumentRoot entry to something like:

DocumentRoot "/var/www/html/react/build"

Build your Alien application, restart your server, and your application is served directly from the Alien’s folder: the React application served from the react/ folder. However, the same is true for Vue, of course, or any other framework you have migrated too. This is why it is so vital to keep Host and Alien completely independent and functional at any point in time because your Alien becomes your Host at this step.

Now you can safely remove everything around your Alien’s folder, including all the Shadow DOM, Frankenstein wrappers and any other migration-related artifact. It was a rough path at moments, but you have migrated your site. Congratulations!

Conclusion

We definitely went through somewhat rough terrain in this article. However, after we started with a jQuery application, we have managed to migrate it to both Vue and React. We have discovered some unexpected and not-so-trivial issues along the way: we had to fix styling, we had to fix JavaScript functionality, introduce some bundler configurations, and so much more. However, it gave us a better overview of what to expect in real projects. In the end, we have got a contemporary application without any remaining bits from the jQuery application even though we had all the rights to be skeptical about the end result while the migration was in progress.

After the switch to Alien, Frankenstein can be retired.

After the switch to Alien, Frankenstein can be retired. (Large preview)

Frankenstein Migration is neither a silver bullet nor should it be a scary process. It’s just the defined algorithm, applicable to a lot of projects, that helps to transform projects into something new and robust in a predictable manner.

Smashing Editorial
(dm, yk, il)

Source: Smashing Magazine, Frankenstein Migration: Framework-Agnostic Approach (Part 2)

Collective #552

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























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


Source: Codrops, Collective #552

Frankenstein Migration: Framework-Agnostic Approach (Part 1)

dreamt up by webguru in Uncategorized | Comments Off on Frankenstein Migration: Framework-Agnostic Approach (Part 1)

Frankenstein Migration: Framework-Agnostic Approach (Part 1)

Frankenstein Migration: Framework-Agnostic Approach (Part 1)

Denys Mishunov



Migration, according to Oxford Learner’s Dictionary, is “the slow or gradual movement of something from one place to another.” This term describes many things and phenomena in our world — both with positive and negative tint. In software development, the word “migration,” when we need to upgrade or change technology in a project, usually falls under the latter case, unfortunately.

“Good,” “Fast,” “Cheap”. We used to pick only two in many situations when we need to make a choice either in development, in business, or in life in general. Typically, front-end migration, which is the main subject of this article, does not allow even that: “cheap” is out of reach for any migration, and you have to pick either “good” or “fast.” However, you cannot have both. Typically.

Frankenstein monster should not necessarily be terrible. He can be cute. Sometimes.

Frankenstein monster should not necessarily be terrible. He can be cute. Sometimes. (Large preview)

In an attempt of breaking the stereotypes, this article suggests a not-so-typical approach to framework-independent migration of front-end applications: the “Frankenstein Migration.” This approach allows us to combine “good” and “fast” while keeping the costs of migration at bay.

It’s not a silver bullet, nonetheless. Instead, I like to think about it as a small migration revolution. And like any other revolution, this approach might have side-effects, issues, and people full of energy to claim that this is not going to work even before they try.

We will certainly get to the potential issues of this approach further in the article, but bear with me and, maybe, you will still find one or two ideas useful for your next migration.

Furthermore, the same approach that we are going to discuss can be used for a broader range of tasks that are not directly related to migration:

  • Combining different bits of your application, written in different frameworks. It could be useful for rapid prototyping, bootstrapping, and even production-ready experiments.
  • Decoupling different features of your application in order to be able to deploy without re-building the whole application. Maybe even set your core features on the more frequent release cycle. It can be useful in large projects. In particular, those running through CI/CD every time you push things into master (that might take very long) and helps to save time on feature releases.
  • This approach might even allow you to have flexible hiring policy: you could hire smart developers even if they do not work with the framework of your project just yet. Developers can keep using tools and frameworks they are comfortable with and bring value to your company from day 1 (especially valuable in startups) while learning how your project works and picking the framework of your choice.

Nevertheless, this article is all about migration and before we dive deep into the dark waters of Frankenstein Migration, let’s see where we are with those “good” and “fast” migration alternatives to be aware of their strong as well as weak sides.

“Good” Migration: Complete Re-Write

Usually, complete re-write is considered to be a better way of migrating your applications in terms of quality. It makes sense: you’re writing your application from scratch, and hence, you can bring all of your experience and wisdom from current implementation into the new one right from the beginning, not as an afterthought. It is a big plus for this type of migration. However, there is a not-so-obvious problem with complete re-write.

To achieve this quality, you need time. Sometimes, a lot of time. Alternatively, many developers dedicated exclusively to re-write. Not every company can afford these options. Because of this, the most suitable scenario for this type of migration is either a small/personal project without a need for developing new features all the time or the project that is not mission-critical for your business.

To give you a perspective of time: once, I’ve been to a complete re-write of an application that took two years. Still, during all this time, the old project with all of its bugs was up and running. Nobody wanted to touch it and, instead, concentrated on the “new and shiny” one. Typically.

As a summary for this type of migration:

PROS:

  • Resulting quality.

CONS:

  • The time required to get that quality to the end-user;
  • The amount of work to be done during complete re-write is overwhelming, making it hard to estimate the time and resources required for this type of migration upfront.

Those who plan to migrate but cannot afford complete re-write due to time or resource constraints might want to look at the next migration type.

“Fast” Migration: Gradual Migration

Contrary to complete re-write, gradual migration does not require you to wait for the complete migration. Instead, you migrate application bit-by-bit and make those new bits available to your users as soon as they are ready. Calling this type of migration “fast” is a bit of a stretch, of course, if we talk about the whole application, but separate features clearly can be delivered to the users much faster. Though, let’s give gradual migration unbiased pros and cons as well:

PROS:

  • When it comes to delivering separate application portions to the end-user, gradual migration is indeed faster than complete re-write since we don’t need to wait for the whole application to be re-written.
  • By delivering new, migrated bits gradually, we get feedback on them (from the end-users) as we go. It allows us to catch bugs and issues faster and in a more isolated manner, comparing to complete re-write, where we deploy the migrated application as a whole and might overlook some smaller issues or bugs.

To better understand problems of gradual migration, try installing React in parallel with Vue in the same project as in Vue-to-React migration. I believe you have to truly enjoy digging configurations and solving console errors to enjoy this process. However, we don’t even need to get that deep. Let’s consider the following legacy example:

Components, no matter CSS Modules, are very vulnerable to global styles. In this simple example, we have at least four ways to break the Vue component visually.

Components, no matter CSS Modules, are very vulnerable to global styles. In this simple example, we have at least four ways to break the Vue component visually. (Source) (Large preview)

Here, we are integrating a Vue component into a Vanilla JS application as in potential Vanilla-to-Vue migration scenario. CSS Modules are responsible for the styling of the Vue component and provide proper scope for your components. As you can see, however, even though styling for the Vue component tells the subheader to be green, it is entirely off, and the example presents as many as four (but there are really many more) trivial ways of breaking component’s styling.

Also, other global styles getting into this Vue component can extend the look of our component entirely and, even though it might be seen as a feature in some projects, makes things hard to predict, maintain and is not necessarily what we want. This example reveals the most common and hard-to-tackle problem of gradual migration: the “Cascade” part of CSS can easily break components.

This artificially simplified example also reveals several other big problems related to gradual migration:

  • Because we’re combining two different systems, the result might turn out very cluttered: we have to support two different systems with their dependencies, requirements, and opinions simultaneously in the same project. Different frameworks might require the same dependencies, but in different versions that result in version conflicts.
  • Since the integrated application (Vue in our case) is rendered in the main DOM tree, global scope in JavaScript is conflicts-prone: both systems might want to manipulate DOM nodes that do not belong to them.
  • Furthermore, let me repeat this, as we are going to get to this point several times in this article: Because of the global nature of this integration, CSS overflows from one system to another without much control, polluting the global scope the same way JavaScript does.

To fix these issues (or at least to keep them at bay) we need to implement workarounds, hacks and implement development style for the whole team to follow. It all leads to lower, compromised-driven, result quality after gradual migration. It’s also harder to maintain such a project than that after complete re-write.

Both of the existing options have limitations and constraints, but we still have to pick one if migration is required. However, should this choice be as painful? Wouldn’t it be great to combine the best parts of both somehow, while minimizing the negative side-effects? Is it possible at all?

Let me introduce Frankenstein Migration to you.

Frankenstein Migration. Part1: Theory

This part of the series answers what Frankenstein Migration is. We are going to find out how it is different from other migration types. Also, most importantly, we are going to dive into the theory of technologies and approaches that make this type of migration even possible.

Why “Frankenstein”?

The name comes from the way the approach works. In essence, it provides a roadmap for two or more applications, written in entirely different frameworks, to work as one solid well-orchestrated body. Just like Victor Frankenstein built his monster in Mary Shelley’s book “Frankenstein; or, The Modern Prometheus”.

People tend to be afraid of monsters. Typically.

People tend to be afraid of monsters. Typically. (Large preview)

Keep in mind that recently different people and organizations independently have explored the problem of combining different frameworks in the same project: Micro Frontends, Allegro Tech, etc. Frankenstein Migration, however, is an independent, structured approach to migration in the first place.

There are two fundamental technologies/approaches in the heart of Frankenstein Migration:

Microservices Architecture

The main idea behind microservices (contrary to monolithic architecture) is that you architect your application with the help of isolated and independent services dedicated to one particular small job.

I’ll repeat the things you need to keep in mind:

  • “independent”
  • “one job”

Microservices architecture is a set of independent services that are all connected into a network.

Microservices architecture is a set of independent services that are all connected into a network. (Large preview)

In an application, such services get connected into a communicational network that can get new services added/removed/replaced easily at any time, and that’s what we call “microservices.” This flexible approach is well-established and widely-adopted by back-end and server architects. However, can we have real microservices on the frontend?

Let’s take a look at the main features of service in such architecture:

  • Small in size,
  • Bounded by contexts,
  • Built and released with automated processes,
  • Autonomously developed, and
  • Independently deployable.

The first three points are not a problem for front-end technologies. Pretty much all of the modern frameworks and libraries provide one or another type of abstraction to satisfy these three requirements. However, independence of services for both development and deployment has always been a problem for front-end technologies. Even in the landscape of modern frameworks that provide a paradigm of a component (like React or Vue), those components are usually still very dependent on the system and cannot be autonomous or independent from the framework that initialized them. You can always fall back to iframe, of course, and get this level of independence. However, let’s find a better — not so radical — alternative.

There is one type of component that gets close to this level of independence, and that is Web Components. So this is the second building block of Frankenstein Migration.

Web Components

People say that it’s enough to mention “Web Components” to start a fight nowadays. People like Rich Harris even write blog posts about why they don’t use Web Components. However, the purpose of this article is not to convince you that Web Components are useful or to initiate a hot debate on the topic. Web Components is not a make-everything-OK tool. As with any other tool, there might be limitations and possible side effects.

Serhii Kulykov provides a series of better-grounded articles on the subject and also curates a “Web Components the Right Way” repository in which you can find much more information for general Web Components discussion. However, when it comes to Frankenstein Migration, Web Components prove to be a very suitable instrument.

Let’s take a quick look at the main elements of Web Components that make them suitable candidates for closing gaps in microservices adoption by the frontend:

In particular, Shadow DOM is the tool capable of fixing the issues we typically meet in gradual migration and provides an actual encapsulation mechanism for component’s CSS. Previously, we mentioned that maintaining a cascade of CSS is problematic when we try to use components written with different frameworks or libraries side-by-side in the global scope.

Now, let’s see how Shadow DOM solves this problem.

CSS Scoping vs. Encapsulation. The Shadow DOM style

The encapsulation mechanism of Shadow DOM is essential for understanding as it’s different from how popular tools like CSS Modules or scoped attribute in Vue work. These tools provide scoping for styles, defined in a component, without breaking global styles and other components. However, they don’t protect components from global styles leaking into the component (the very problem of cascade discussed above) and hence, potentially breaking your components.

At the same time, styles defined within Shadow DOM are not only scoped to the current component but are also protected from global styles that don’t have explicit access to the internals of Shadow DOM no matter the specificity. To see it in action, take a look at the updated example:

Here, we moved styles out of the Vue component, straight into the Shadow DOM and that’s what’s happening (automatic though) when you set up your Vue components to work within Shadow DOM. This example shows that Shadow DOM provides a mechanism for genuinely independent components that can be used in any context (library, framework) while preserving the look and functionality of these components.

Now let’s talk through the main concepts and steps of Frankenstein Migration to see how exactly microservices and Web Components help us in the migration of front-end applications.

Let’s assume you have a project that you want to migrate to another framework.

Our demo project on a not-so-hot-anymore framework that we want to migrate.

Our demo project on a not-so-hot-anymore framework that we want to migrate. (Large preview)

It doesn’t matter what framework/library we migrate away from and what framework/library we want to get to; the principle and steps are the same for more or less any tool you pick (some generic exceptions are mentioned further in the article). That’s why Frankenstein Migration is called the “framework-agnostic” approach.

Now, where do we start?

  1. Identify Microservices
  2. Allow Host-to-Alien Access
  3. Write An Alien Component
  4. Write Web Component Wrapper Around Alien Service
  5. Replace Host Service With Web Component
  6. Rinse And Repeat
  7. Switch To Alien

1. Identify Microservices

It is the core step, essential for the whole process’ success or failure. So we should dive more in-depth here.

Technically, we have to split our existing application into microservices virtually. It is an entirely subjective process though and doesn’t have a “correct” answer. However, what does it mean in practice then?

By “virtually” I mean that in general, you don’t need to change your existing application physically: it’s enough to have structure settled in any form even if only on paper.

We have to have a clear split in our current application into services that are:

  • Independent;
  • Dedicated to one small job.

An input field for adding new items to a database could be an example of a service: it’s dedicated to one particular job (adding new items) and does the job without dependency on any other service. Alternatively, the whole listing of items already added to the database: it’s trivial in functionality and, again, doesn’t depend on other components for listing items. It doesn’t sound too complicated, I believe, but that might be a deceptive feeling.

Let’s start with the easy parts: If a framework in your current project is based on a concept of “component” (React, Vue), you probably already have a reasonable basis for this type of migration. You can treat every component of your application as a separate service in a microservices architecture.

If your project currently is on a legacy basis (e.g. such as jQuery), you should turn on your imagination and think through how you would like to structure your application, following microservices’ principles of independence and one-job per service.

We can structure our application any way we want to just as long as we follow the principles of microservices.

We can structure our application any way we want to just as long as we follow the principles of microservices. (Large preview)

Refactor If Needed

I hate my ability to repeat things multiple times, but in this case, it makes much sense: be sure that your services (or components, or containers, or whatever you prefer to call your building blocks) do not depend on other services. Otherwise, both of the services should be treated as one — for the sake of independence and isolation.

A simple test to make sure your service is appropriately independent: Remove HTML for your component/service from the Host and reload the application. If there are no JS errors in the console and the remaining part of the application works as expected, the service in question is most probably independent enough from the rest of the application.

To give you a better explanation, let’s consider the following, artificially simplified, legacy example:

index.html

<form id="form">
  <input id="inputTodo" type="text" placeholder="New Todo"/>
  <button type="submit">Add Todo</button>
</form>

<ul id="listing" class="d-none"></ul>

index.js

const form = document.getElementById("form");
form.addEventListener("submit", ev => {
  ev.preventDefault();
  const listing = document.getElementById("listing");
  const input = document.getElementById("inputTodo");
  const newEntry = document.createElement("li");
  newEntry.innerHTML = input.value;
  input.value = "";
  listing.prepend(newEntry);
  listing.classList.remove("d-none");
});

Here, #form expects #listing to be present in the markup as its submit handler updates the listing directly. Hence these two depend on each other, and we cannot split them into separate services: they are parts of the same job and help each other to serve the same purpose.

However, as a possibly better alternative, we could refactor this code to make the two components independent from each other and satisfy the requirement of independence:

index.js

function notifyAboutNewItem(ev) {
  ev.preventDefault();
  const input = document.getElementById("inputTodo");
  const event = new CustomEvent("new-todo", { detail: { val: input.value } });
  document.dispatchEvent(event);
  input.value = "";
}
function updateList(ev) {
  const listing = document.getElementById("listing");
  const newEntry = document.createElement("li");
  newEntry.innerHTML = ev.detail.val;
  listing.prepend(newEntry);
  listing.classList.remove("d-none");
}

document.getElementById("form").addEventListener("submit", notifyAboutNewItem);
document.addEventListener("new-todo", updateList);

Now, our #form and #listing components do not communicate with each other directly, but through the DOM event (it can be a state management or any other storing mechanism with notification instead): when a new item is added, notifyAboutNewItem() dispatches an event, while we subscribe #listing to listen to this event. Now any component can dispatch this event. Moreover, any component can listen to it: our components became independent from each other, and hence we can treat them separately in our migration.

Too Small For A Service?

Another thing to keep in mind: when splitting your application with already-existing components (like React or Vue) into services, some of your components might be too small for a proper service. It’s not to say they cannot be small, because nothing stops you from structuring your application as atomic as you wish, but most of the simple re-usable UI components (like the form button or input field in the previous example) are better included in broader services for the sake of minimizing work for you.

On a larger scale, you can approach Step #1 as chaotic as you wish. You don’t need to start Frankenstein Migration with the global plan: you can start with just one element of your application. For example, split some complex <section> into services. Alternatively, you can structure your app one whole route or page at a time and then, maybe, your <section> becomes one single service. It doesn’t matter much; any structure is better than heavy, hard-to-maintain monolithic application. However, I would suggest being careful with the too granular approach — it’s boring and doesn’t give you many benefits in this case.

My rule of thumb: you get the best flow of process with services that can be migrated and pushed into production in one week. If it takes less, then your services are a tad too small. If it takes longer, you might be trying to chew too many large pieces, so it’s better to split those. However, it all depends on your capacity and your project’s needs.

After virtually splitting your current application into services, we’re ready to move on to the next step.

2. Allow Host-to-Alien Access

This should come as absolutely unclear title, of course. Neither have we discussed what is Host nor have we mentioned Alien yet. So let’s clear these out first.

We have mentioned that services in our current application should be independent. However, this is not the only place where we strive for independence. Contrary to the typical gradual migration approach, where we put everything in the same pot and develop new components alongside the old ones, Frankenstein Migration requires us to develop new components outside of the current application.

Bear with me.

Further, in the article, we are going to use word Host to refer to the current application, written with the framework we’re about to migrate away from. At the same time, the new application, written with the framework we are migrating to will be called Alien, as it injects its services into Host at some point.

Host — is our current application; Alien — our migrated application on the new framework

‘Host’ is our current application while ‘Alien’ is our migrated application on the new framework. (Large preview)

Yes, we do not treat Alien as just a set of components, but as a proper application that we build over time. Technically, both Host and Alien should be two completely different applications written with any framework you want, with own dependencies, bundling tools, and so on. It is essential to avoid typical problems of gradual migration, however, there is a significant additional benefit to this approach. By keeping Host and Alien independent, we get both systems deployable anytime — should we need this at some point of migration.

There are several ways you can organize Host and Alien:

  • Different domains or IP addresses;
  • Different folders on your server;
  • git submodules;
  • And so on.

The primary condition for any scenario you pick, though, is that the Host should have access to Alien’s assets. So, if you choose to work with different domains, you have to take a look at setting up CORS for your Alien domain. If you decide to organize it as simple as different folders on your server, make sure resources from Host’s folder have access to Alien’s folder. If you go with git submodule, before adding Alien as a submodule of your Host, make sure you read the documentation and know how it works: it’s not as hard as it may sound.

Host should have access to Alien

Host should have access to Alien. (Large preview)

After you have set up your applications and provided access from Host to Alien, things go quite straightforward.

3. Write An Alien Component

The title should be self-explanatory, I believe. At this point, we have:

  • A clear overview of the services in our Host application,
  • Set up application basis for Alien, and
  • Allowed access to Alien’s assets from Host.

Now it’s time to pick a Host service we want to migrate first and re-write this service in Alien application, using the new framework. Keep in mind: we do not wait for the whole application to be re-written as in “complete re-write.” Instead, we migrate bit-by-bit as in gradual migration.

The next, practical part of the article will contain more details of actual tips on how to write your Alien component for easier integration. However, for now, you might have a question:

If Alien and Host are entirely different systems, how on Earth are we supposed to integrate our newly-written Alien service into Host?

Here is where we get to the second building block of the approach: the Web Components.

4. Write Web Component Wrapper Around Alien Service

The Web Component wrapper is the core of our integration part. Before I cover more on this, there are a couple of things to keep in mind:

  1. First of all, you are free to pick any abstraction layer you want for your Web Component. You can pick lit-element, Stencil, or really anything that gives you Web Components at the end. However, the Web Components that we need for Frankenstein Migration are so pure (they are just the wrappers and nothing more) that I think using an abstraction layer for this is overkill.
  2. Secondly, your Web Component wrapper lives on the Host’s side. So, based on the needs and requirements of your Host, you have to decide for yourself whether or not you need to polyfill Web Components. Just check the support for two technologies that we are going to rely upon:
    1. Shadow DOM, and
    2. Custom Elements.

      The support for both is quite similar, and with Edge switching to Chromium in version 75, native support for Web Components in browsers is very impressive. Nevertheless, should you need the polyfills to run your Web Components in IE11, for example, take a look at the stable polyfill.

Web Component is a pure wrapper around Alien service

Web Component is a pure wrapper around Alien service. (Large preview)

The main functions of our Web Component wrapper:

  • Setting up a boilerplate for a new Custom Element with Shadow DOM;
  • Importing our Alien component;
  • Rendering Alien component within Shadow DOM of the wrapper;
  • Importing relevant styles and putting them in the Shadow DOM together with the Alien component itself (only if required by the Alien component).

As a sneak-preview of how such component can feel like, take a look at the very basic example of importing a React component (HeaderApp) into Web Component wrapper (frankenstein-header-wrapper):

import React from "../../react/node_modules/react";
import ReactDOM from "../../react/node_modules/react-dom";
import HeaderApp from "../../react/src/components/Header";

class FrankensteinWrapper extends HTMLElement {
  connectedCallback() {
    const mountPoint = document.createElement("div");
    this.attachShadow({ mode: "open" }).appendChild(mountPoint);
    ReactDOM.render(, mountPoint);
  }
}
customElements.define("frankenstein-header-wrapper", FrankensteinWrapper);

Note: Take a closer look at the imports. We do not install React in our Host but instead import everything from Alien’s location with all of its dependencies. In this case, Alien has been added to Host as a git submodule and hence is visible to Host as a sub-folder that makes accessing its contents from Host a trivial task. Here, Alien is still a separate entity that is independent from Host though. It should explain the importance of Step #2 where we allowed access from Host to Alien.

That’s pretty much it for the functions of the wrapper. After you wrote your Web Component, imported your Alien service and rendered it within the Web Component, we need to replace our Host service with our Web Component (that brings Alien service with itself).

5. Replace Host Service With Web Component

This step is very trivial, I believe. What you need to do effectively is replace markup of your Host service with your Web Component. The next chapter will cover different ways of setting up communication between your Host and Alien (that sits within Web Component) components, but in essence, there is no rocket science here:

  1. We have to connect both services to the same storage;
  2. We have to dispatch and listen (on both sides) to events when storage gets updated.

After we’ve wrapped Alien’s service with the Web Component wrapper, it’s time to replace the corresponding Host service with the wrapper

After we’ve wrapped Alien’s service with the Web Component wrapper, it’s time to replace the corresponding Host service with the wrapper. (Large preview)

This schema should be the same no matter whether you have a state management system(s), route your communication through localStorage, or communicate with simple DOM events. By replacing your Host service with the Web Component wrapper, you finish the migration of the service and can enjoy this cute Frankenstein in your project.

However, it doesn’t smell like a real migration just yet. There has to be something else to it.

6. Rinse And Repeat

After you’ve migrated your first service, you need to go through Steps 3 to 5 for all of your services/components. All the principles and recommendations remain valid. Just continue evolving your Alien as if you do a complete re-write: you’re working on a new application in parallel with your Host. You have to be able to start and build your Alien at any time and any way you want. The only difference now is that you can push your Alien services into production on Host whenever they are ready.

At some point, you get all your services migrated, but you won’t have Host services anymore because all of them are replaced with Web Component wrappers that containing Alien services. Technically speaking, you get Alien application with remaining glue from Host. You could leave your application like this, but it’s not performant (we discuss performance tips and tricks in one of the next parts of the article) and looks quite messy, to be honest. There is a better way.

When all of the Host services got replaced with Web Component wrappers, our Host resembles Alien and it’s time for a simple trick

When all of the Host services got replaced with Web Component wrappers, our Host resembles Alien and it’s time for a simple trick. (Large preview)

I have to repeat the core idea: “At this point, you have Alien application with remaining glue from Host.” It means that instead of serving our users this not-so-cute-anymore Frankenstein, we can serve real Alien instead of Host. At this moment, Alien should represent precisely the same picture as we have in Host, but orchestrated by Alien’s natural means and without any Web Components. The only question is: “How do we do that?”

7. Switch To Alien

Remember when we said that an independence of Host and Alien is essential for this type of migration, and so we split them into two separate applications? Well, now it’s time to enjoy the benefits of that decision.

If you kept your Host and Alien independent after all Host services got replaced, you should be able to switch your server configuration to serve requests from Alien and forget about Frankenstein

If you kept your Host and Alien independent after all Host services got replaced, you should be able to switch your server configuration to serve requests from Alien and forget about Frankenstein. (Large preview)

I assume you serve your Host with a configurable web server. By “configurable”, I mean that you have control over the configuration file of your server. It allows you to control routing to your site.

If this assumption is correct, you should be able to switch your server to serve requests from your Alien’s folder instead of Host for all incoming HTTP requests. For example, in your Apache’s httpd.conf, if you used git submodule for adding a React application to your Host, you should be able to update DocumentRoot.

For example, the default setting:

DocumentRoot "/var/www/html"

becomes something like:

DocumentRoot "/var/www/html/react/dist"

That’s it! From now on, we’re directing HTTP traffic to our React subfolder.

When this configuration is confirmed to be working and your users are served your fully migrated Alien application instead of your Host, your Alien becomes your new Host. Now, the old Host and all of its Frankenstein parts (including the Web Component wrappers) are not needed anymore and can be safely thrown away! Your migration is over.

Conclusion

All in all, Frankenstein Migration — is an attempt to combine “good” and “fast” migration types in which we get high-quality results such as the complete re-write that is combined with the delivery speed of gradual migration. This way, we’re able to deliver migrated services to the end-users as soon as the services are ready.

I realize that the ideas in this article may feel provoking for some readers. Others may feel like we’re overdoing things. Keep in mind that this type of migration still needs testing with as many possible frameworks, libraries, and their combinations. The next part of this article is going to show practical examples of this approach along with code examples and git repositories for you to play with at your own pace. We wouldn’t want people to form a false opinion by claiming that it’s not going to work without even trying, would we?

Frankenstein, even if cute, has to go for now. See you in the next part, Frank.

Frankenstein, even if cute, has to go for now. See you in the next part, Frank. (Large preview)
Smashing Editorial
(dm, yk, il)

Source: Smashing Magazine, Frankenstein Migration: Framework-Agnostic Approach (Part 1)

Creating Tables In Figma

dreamt up by webguru in Uncategorized | Comments Off on Creating Tables In Figma

Creating Tables In Figma

Creating Tables In Figma

Sasha Belichenko



In this tutorial, we will talk about how tables can be created in Figma by using components and Atomic Design methodology. We will also take a look at the basic elements of the table layout and how components can be included in the component library so that they can become part of the design system you are using.

To make it easy for you, I’ve prepared a mockup example that uses all of the components we need for this tutorial.

To follow along, you will need to have at least some understanding of the basic Figma concepts, its interface, and how to work with Figma components. However, if you’re new to Figma and working with table data, I recommend watching the “Getting Started” video to help you better understand Figma end-to-end, as well as the article “How To Architect A Complex Web Table” that was published not too long ago here on Smashing Magazine.

To simplify the scope of this tutorial, let’s assume that the colors, fonts, and effects already exist as styles in the Figma project you’re about to begin. In terms of Atomic Design, they are atoms. (To learn more, the folks at littleBits wrote a great article on the topic.)

The target audience for this tutorial are designers (UX, UI) who have either already adopted Figma into their workflows or are planning to try Figma in their next design projects but aren’t sure how to get started.

So, without further ado, let’s dig in!

Quick Note: While writing this article, Figma introduced plugins. At the time of publishing, there weren’t any good ones for working with tables, but things might change fast. Who knows, maybe this article will actually help an aspiring Figma plugin developer to create a really neat Figma Tables plugin, or at least, I hope it will. 😉

Introduction

Imagine the table as an organism. The table cell is then a molecule which is comprised of individual atoms. In design terms, they’re cell properties.

So, let’s start with the cell. It has three properties:

  1. Background
  2. Border
  3. Content

Now we’ll take a closer look at each one of them.

Background

The background will be a separate component in Figma. The size doesn’t really matter since we can stretch the component as we need, but let’s begin with setting the size to 100×36 pixels.

In this component, add a rectangle of the same size as the component itself. It will be the only object inside the component. We need to attach the rectangle’s borders to the component’s borders by using constraints (set constraints to “Left & Right” and “Top & Bottom” at the right panel in the Constraints section), so that the rectangle stretches automatically to the size of the component.

If you’d like to see this in action, watch this tutorial on how the constraints work in Figma.

The Background Component

The Background Component (the ‘atom’) (Large preview)

The fill color of the rectangle will determine the background color of the cell. Let’s pick the white color for it. I recommend choosing that color from the color styles that are configured at the beginning of the project.

Background color
Changing the background color (Large preview)

Border

This one is a bit trickier than the background. You can’t just create one rectangle with a stroke. We may need different kinds of borders: one for the separate cells (with borders around), one for the whole row of cells with only top and bottom borders, or one for the table header that we might want to separate from the rest with a wider line. There are many options.

Border properties:

  • Border line (left, right, top, bottom, or absence of any of them)
  • Line width
  • Line color
  • Line style

Each line within the cell border might havea different width, color, and style. For example, the left one could be a continuous red line, and the top one a dotted grey line.

Let’s create a component with a size of 100×36 pixels (the same as we did before). Inside the component, we need to add 4 lines for each border. Now pay attention to how we are going to do this.

  1. Add a line for the bottom border with the length of the component width;
  2. Set its position to the bottom border and constraints to stretch horizontally and stick to the bottom border;
  3. For the top border, duplicate the line for the bottom border, rotate it by 180 degrees and stick to the top of the component. (Don’t forget to change its constraints to stick to the top and stretch horizontally.);
  4. Next, for the left border, simply rotate by -90 degrees and set its position and constraints to be at the left side sticking to the left border and stretching vertically;
  5. Last but not least, you can create the right border by rotating it by 90 degrees and setting its position and constraints. Set stroke color and stroke width for each line to gray (select from the color styles) and 1 pixel respectively.

Note: You may be asking yourself why we rotated the line for the bottom border. Well, when you change the stroke width for a line in Figma, it will rise. So we had to set this “rise” direction to the center of the component. Changing the line’s stroke width (in our case it is the border size) won’t expand outside the component (cell).

Now we can hide or customize the styles separately for every border in the cell.

The Border Component

A border component with 1px stroke (Large preview)

If your project has several styles for table borders (a few border examples shown below), you should create a separate component for each style. Simply create a new master component as we did before and customize it the way you need.

Border Styles

A few extra examples of border styles. Note that the white background is not included in the component. (Large preview)

The separate stroke component will save up lots of your time and add scalability. If you change the stroke color inside the master component, the whole table will adjust. Same as with the background color above, each individual cell can have its own stroke parameters.

Border’s width and color
Changing border’s width and color (Large preview)

Content

This is the most complex component of all.

We need to create all possible variations of the table content in the project: plain text, a text with an icon (left or right, different alignment), checkboxes, switches, and any other content that a cell may possibly contain. To simplify this tutorial, please check the components in the mockup file. How to create and organize components in Figma is a topic for another article.

However, there are a few requirements for content components:

  • Components should stretch easily both vertically and horizontally to fit inside a cell;
  • The minimum size of the component should be less than the default cell size (especially height, keep in mind possible cell paddings);
  • Avoid any margins, so the components can align properly inside a cell;
  • Avoid unnecessary backgrounds because a cell itself has it already.

Content components examples

Examples of cell content in components. This is not a complete list; you can use most of the components of your design system inside a table. (Large preview)

Content components can be created gradually: start with the basic ones like text components and add new ones as the project grows in size.

The reason we want the content to be in components is the same as with other elements — it saves uptime. To change the cell’s content, we just need to switch it in the component.

Changing the component inside the cell
Editing the table using cells components (Large preview)

Creating A Cell Component

We created all the atoms we need: background, border, content. It’s time to create a cell component, i.e. the molecule made from atoms. Let’s gather all the components in a cell.

The cell component

The cell component (the ‘molecule’) (Large preview)

Set the background component as the bottom layer and stretch it to the whole cell size (set constraints to “Left & Right” and “Top & Bottom”).

Add the border component with the same constraints as the background component.

Now to the most complicated part — the content content.

The cell has paddings, so you need to make a frame with the component’s content. That frame should be stretched to the whole cell size except for the paddings. The content component should also be stretched to the whole frame size. The content itself needs to be deprived of any margins, so all paddings will be set by the cell.

At the end of the day, cell paddings are the only property in a component that we will set only once without an opportunity to change it later. In the example above, I made it 4px for all sides.

Note: As a fix, you can create columns with empty cells (with no content and width of 16px for example) left and right to the column where extra margin is needed. Or if your table’s design allows, you can add horizontal paddings inside the cell component. For example, cells in Google Material Design have 16px paddings by default.

Don’t forget to remove the “Clip content” option for the cell and frame (this can be done at the right-hand panel in the Properties section). The cell’s content can go out of its borders; for example, when a dropdown is inside your cell and you want to show its state with a popup.

Note: We’ll be using this cell style as the main one. Don’t worry if your table has additional styles — we’ll cover that in the Table States and Components, Not Overrides sections.

Cell Options For A Standard Table

This step could be optional but if your table needs states then you can’t go without it. And even more so if there is more than one border style in the table.

So let’s create additional cell components from which it’d be easier to build up a table. When working with a table, we will select the appropriate component depending on its position in the table (e.g. depending on the type of borders).

In order to do that, let’s take our cell component and create eight more masters from it. We also need to disable the appropriate layers responsible for borders. The result should look like the image below.

Cell options

The cell options we need to build a table. Note that there could be a few extra depending on your table borders styles. (Large preview)

The top row is for the cells on top and in the middle of the table. The bottom row is only for the cells at the bottom. This way we’ll be able to put the cells one after another with no gaps and keep the same stroke width.

A few examples:

The First example

If each cell in the table has a border, we’d only need cells 1, 4, 5 and 8. (Large preview)

The Second example

If there are merged cells or border absence, we must apply the rest 2 and 3 cells as well as 6 and 7 to the bottom row. (Large preview)

The Third example

If the table design considers the absence of vertical borders, cells 2 and 6 would be enough. (Large preview)

Note: For each border style created above, it’d be good to add master components like the ones described earlier.

So we have excluded the necessity of overriding cell’s instances (disabling the appropriate layers, to be precise). Instead of that, we use various components. Now if, for example, a column uses a different style from the default (the fill color or border), you can choose this column and simply change the relative component. And everything will be alright. On the opposite side, changing a border of each cell manually (disabling the appropriate borders) is a pain you don’t want to bother with.

Now we are ready to create tables (in terms of Atomic Design — organisms) from the various cell components (molecules) we made.

Customizing The Table

Changing the row’s height in the whole table is relatively easy: highlight the table, change the element height (in this case, the cell’s height, H in the right-hand panel in the Properties section), and then change the vertical margin from the element to 0. That’s it: changing the line height took two clicks!

Changing the row height
Changing the row height for the whole table (Large preview)

Changing the column width: highlight the column and change the width size. After moving the rest of the table close up, select the whole table by using the Tide Up option in the Alignment panel as well as the first item in the dropdown list under the rightmost icon.

Changing the column width
Changing the column width. (Large preview)

Note: I wouldn’t recommend grouping rows and columns. If you change the column size extending the elements, you’ll get fractional values for width and height. If you don’t group them and snap to the pixel grid, the cell size will remain an integer number.

The background color, stroke type, and content data can be changed in the appropriate component or in one of the eight cells master components (cells that had different stroke styles). The only parameter that can’t be changed right away is the cell margins, e.g. content paddings. The rest are easily customizable.

Components, Not Overrides

Looking at what we got in the end, it might seem like overkill. And it is if there is only one table in your project. In this case, you can simply create one cell component and leave the background and stroke components off. Simply include them in the cell component, create the table and do the necessary customization for each separate cell.

But if components are included in a library that is used by a number of other files, here comes the most interesting stuff.

Note: *I do not recommend changing the background color and stroke in components’ instances. Change them only in the master. By doing so, those instances with overrides won’t get updated. This means you would have to do that manually and that’s what we’re trying to avoid. So let’s stick to the master components.*

If we need to create an additional type of table cells (e.g. the table header), we add the necessary set of master components for cells with the appropriate styles (just like we did above with the eight cells that had different stroke styles), and use it. Yes, it takes longer than overriding components’ instances but this way you will avoid the case when changing the masters will apply those changes to all layouts.

Table States

Let’s talk about the states of the table’s elements. A cell can have three states: default, hover, and selected. Same for columns and rows.

If your project is relatively small, all states can be set by overrides inside instances of your table components. But if it’s a big one, and you’d want to be able to change the look of the states in the future, you’ll have to create separate components for everything.

You’ll need to add all eight cells with different stroke variants for each of the states (maybe less, depends on the stroke style). And yes, we’ll need separate components for the background color and the stroke for the states as well.

In the end, it’ll look similar to this:

Hover and Selected

The cells’ states (hover and selected) (Large preview)

Here’s where a bit of trouble comes in. Unfortunately, if we do everything as described above (when changing the component’s state from one to another), there is a risk of losing the cell’s content. We’ll have to update it apart from the case when the content type is the same as in the master cell. At this point, we can’t do anything about it.

Table with rows’ states

Table with various rows’ states. (Large preview)

I added tables in the mockup file that were made in a few different ways:

  • Using this tutorial (separate components for cells’ styles);
  • Using the cell component (components for borders, background, and content);
  • Using the cell component that unites everything (with only content components in addition).

Try to play around and change the cell’s styles.

Changing the state
Changing the state of the row. (Large preview)

Conclusion

If you’re using the same components library in several projects and you’ve got a reasonable number of tables in each of them, you can create a local copy of components (cells components with stroke styles and, if needed, cells components with different states), customize them, and use them in the project. The cell content can be set based on local components.

Also, if you’re using the table for one large project with different kinds of tables, all the above-mentioned components are easily scaled. The table components can be improved to infinity and beyond, like creating the cell states when hovering and other kinds of interactions.

Questions, feedback, thoughts? Leave a comment below, and I’ll do my best to help you!

Figma Table Mockup Download

As promised, I created a complete version of the Figma table mockup that you’re welcome to use for learning purposes or anything else you like. Enjoy!

Tables in Figma mockup design

Here’s a Figma table mockup that you can use for learning purposes — let the creativity begin!

Useful Resources

  • Figma YouTube Channel
    The official Figma channel on YouTube — it’s the first thing to watch if you are new to Figma.
  • Google Sheets Sync
    A Figma plugin that helps you get data from Google Sheets into your Figma file. This should work fine with the techniques from this tutoria, but you’ll need to invest some time into renaming all the text layers for this to work properly.
Smashing Editorial
(mb, yk, il)

Source: Smashing Magazine, Creating Tables In Figma

Designing Complex Responsive Tables In WordPress

dreamt up by webguru in Uncategorized | Comments Off on Designing Complex Responsive Tables In WordPress

Designing Complex Responsive Tables In WordPress

Designing Complex Responsive Tables In WordPress

Suzanne Scacca



(This is a sponsored article.) Mobile devices can be problematic for displaying complex tables and charts that would otherwise stretch the entire width of a laptop or desktop screen. This may leave some of you wondering whether it’s even worth showing tables to mobile and tablet visitors of your website.

But that doesn’t make sense. In many cases, a table isn’t some stylistic choice for displaying content on a website. Tables are critical elements for gathering, organizing and sharing large quantities of complex and valuable data. Without them, your mobile visitors’ experience will be compromised.

You can’t afford to leave out the data. So, what do you do about it?

This requires a more strategic solution. This means understanding what purpose the data serves and then designing the complex web table in a way that makes sense for mobile consumption.

A WordPress table plugin called wpDataTables has made light work of designing both desktop and mobile compatible tables, so I’ve included examples of these complex tables throughout this post. Keep reading to explore the possibilities.

The Most Common Use Cases For Tables On The Web

There’s a lot of value in presenting data in a table format on a website.

Your writers could probably find a way to tackle each data point one-by-one or to provide a high-level summary of the data as a whole. However, when data is handled this way, your visitors are left with too much work to do, which will only hinder the decision-making process.

On the other hand, tables are great for organizing large quantities of data while also giving visitors an easier way to sift through the data on their own.

As such, your visitors would greatly benefit from having complex data sets presented as tables — across a wide variety of use cases, too.

Feature Lists

There are a couple of ways to use tables to show off product features.

For e-commerce sites, the product inventory is broken up by its most pertinent features, allowing visitors to filter their results based on what’s most important to them:

e-commerce product tables

e-Commerce sites can use product tables to quickly list out all products and their key features. (Image source: wpDataTables) (Large preview)

This would be great for any large vendor that has dozens or hundreds of similar-looking products they want customers to be able to filter and sort through.

You could also use a table to compare your product’s features directly against the competition’s. This would be better for a third-party marketplace where vendors sell their goods.

Amazon includes these kinds of tables:

Side-by-side competitor tables

Marketplace sites use side-by-side competitor tables to simplify decision-making. (Image source: Amazon) (Large preview)

By displaying the data in this format, customers can quickly do a side-by-side comparison of similar products to find the one that checks off all their requirements.

Pricing Tables

If you’re designing a website where services or memberships are sold instead of products, you can still use tables to display the information.

You’ll find a good example of this on the BuzzSumo website:

Service-based companies list prices in tables

Companies that sell services, like BuzzSumo, use tables to display pricing and features. (Image source: BuzzSumo) (Large preview)

Even though there’s less data to compile, you can see how the structure of the table and the stacking of the services side-by-side really help visitors make a more well-informed and easier buying decision.

Catalogs

A catalog is useful for providing visitors with an alphabetized or numerically ordered list. You might use one to organize a physical or digital inventory as this example demonstrates:

Catalog tables

Catalog tables make it easier for users to find what they’re looking for. (Image source: wpDataTables) (Large preview)

This would be good for bookstores, libraries and websites that have their own repository of reference material or content.

You might also use a catalog to help customers improve the accuracy of their orders:

Catalogs for order accuracy

Catalog tables can be used to aid shoppers with order accuracy. (Image source: wpDataTables) (Large preview)

This type of table provides customers with key specifications of available products to ensure they’re ordering the right kinds of parts or equipment.

Best Of Lists

There are tons of resources online that provide rundowns of the “Top” winners or “Best Of” lists. Tables are a useful way to summarize the findings of the article or report before readers scroll down to learn more.

This is something that websites like PC Mag (and, really, any tech or product review site) do really well:

Best-of reviews table

PC Mag organizes a summary of best-of reviews in a table format. (Image source: PC Mag) (Large preview)

This helps readers get a sense for what’s to come. It also allows those who are short on time to make a faster decision.

Directory Tables

Directory websites have ever-growing and regularly updated lists of data. These are your real estate listing sites, travel sites, professional directories and other sites containing high volumes of complex data that really shouldn’t be consumed without a filterable table.

Case in point: this list of available apartments:

Directory website table

Directory websites that change often need tables to keep listings organized. (Image source: wpDataTables) (Large preview)

This makes it much easier for visitors to see all options in a single glance, rather than have to go one-by-one through individual entries that matched a search query.

General Data

There are other data lists that are just too complex to handle as loose text. Sports data, for instance, should always be presented in this format:

Sports statistics table

Basic statistics, like for sports teams, should never be presented as loose data. (Image source: wpDataTables) (Large preview)

You can see how this keeps all data in one place and in a searchable list. Whether visitors are looking for their home team’s stats, or want to compare the performance of different teams from their fantasy sports league, it’s all right there.

How To Design Complex Responsive Tables

Regardless of what type of data you’re tasked with presenting on a website, the goal is to do so in a clear fashion so visitors can take quicker action.

Now, it’s time to figure out how to best format this data for mobile visitors.

Delete, Delete, Delete

If your client has pulled their data from an automated report, they may not have taken time to clean up the results. So, before you start any design work on the table, I would suggest reviewing the data they’ve given you.

First, ask yourself: Is there enough data that it warrants a table?

If it’s a simple and small enough list, it might make more sense to ditch the table.

Then, go over each column: Is each of these useful?

You may find that some of the columns included aren’t necessary and can be stripped out altogether.

You may also find that some columns, while an essential part of each item’s individual specifications list, won’t help visitors make a decision within the table. This would be the case if the column contains an identical data point for every item.

Finally, talk to your writer or data manager: Is there any way to shorten the columns?

The table’s labels and data may have been written in full, but your writer may have a way to simplify the responses without compromising on comprehension.

When possible, have them work their magic to shrink up the text so that columns don’t take up as much space and more can be revealed on mobile. Don’t just do this for mobile users either. Even on desktop and tablet screens where more screen real estate is available, the shortening of labels can help conserve space.

It may be as simple as changing the word “Rank” to the number symbol (#) and abbreviating “Points” as “Pts”.

Make data smaller

Designers and writers need to work together to create smaller tables. (Image source: wpDataTables) (Large preview)

While it might not seem like one word will make much of a difference, it adds up the more complex and lengthier your tables are.

Start With Two Columns

By default, mobile tables should always start with two columns. It’s about all the screen’s width will allow for without compromising the readability of the data within, so it’s best to start with the basics.

When you contrast a full-screen table on desktop against its counterpart on mobile, you can see how easy it is to identify the two columns to include. For example, a mobile statistics table includes a column for item type and one for the profits earned from each:

Mobile table with two columns

It’s a good idea to design responsive tables with two columns to start. (Image source: wpDataTables) (Large preview)

This doesn’t mean that all other data is lost on mobile. You just need to let visitors know how they can expand the table’s view.

In this example, when visitors select the eyeball icon above the table, they have the option to add more columns to the table:

Column view options

If visitors want to scroll right, give them column view options. (Image source: wpDataTables) (Large preview)

In allowing for this option on mobile, your visitors can control how they consume data while also selecting only the data points that are most important to them.

The result will then look like this:

Mobile table with more than two columns

An example of a mobile table with additional columns. (Image source: wpDataTables) (Large preview)

While users will have to scroll right to see the rest of the table, the control they wield over column views helps keep this a reasonable task. With just one scroll right, they’ll see the rest of the table:

Horizontal scrolling on mobile

Even with more columns on mobile, horizontal scrolling is kept to a minimum. (Image source: wpDataTables) (Large preview)

This is a good option to have for lists of products where the side-by-side comparison is useful in expediting the decision-making process.

Use An Accordion For Standalone Entries

There’s another option you can include which will give visitors more control over how they view table content.

For this example, we’ll look at a list of available cryptocurrencies:

Expandable accordions for mobile tables

Data lists (as opposed to product comparison) lists can use expandable accordions. (Image source: wpDataTables) (Large preview)

As you can see, the default here is still to only show two columns. In this case, though, a click of the plus-sign (+) will reveal a new way to view the table:

Expanded row on mobile

An example of what an expanded row looks like on mobile tables. (Image source: wpDataTables) (Large preview)

When open, all of the data that would otherwise force visitors to scroll right is now visible within a single screenful.

While you can certainly include an expandable accordion in any responsive table you create, it would be best suited to ones where a direct side-by-side comparison between products or services isn’t necessary.

Keep Vertical Scrolling To A Minimum

Just as you want to prevent your visitors from having to scroll past the horizontal boundaries of the mobile website’s pages, you should limit how much vertical scrolling they have to do as well.

Data consumption, in general, isn’t always an easy task, so the more you can minimize the work they have to do to get to it, the better.

One way to limit how much vertical scrolling your visitors do is by breaking a table with dozens or hundreds of rows into pages.

A table of annual temperatures on desktop and mobile

An example of how to shrink an extra-large table down to a couple columns and multiple pages. (Image source: wpDataTables) (Large preview)

Just remember to make it easy for visitors to scroll through the pages. A well-designed set of pagination controls either at the top or bottom of the table would be useful:

Responsive table pagination

Use pagination at the bottom of tables to decrease vertical scrolling. (Image source: wpDataTables) (Large preview)

This would be especially useful for a handful of pages. Anything more than that and the pagination process may become tedious.

You can also include a table search function directly above it:

Mobile table search function

Above-the-table search helps reduce the work of scrolling on mobile. (Image source: wpDataTables) (Large preview)

This allows for a quick shortcut when your users have a good idea of what they’re looking for and want to jump straight to it.

Include Both Filtering And Sorting For Larger Data Sets

So, let’s say that you have a very extensive list of data. You don’t want to force users to scroll through dozens of table pages, but you also can’t afford to remove any of the data sets. It’s all pertinent.

In that case, you’re going to hand some of the control back to your visitors. This way, their choices will determine how much of the table they end up seeing.

Let’s use this list of mutual funds as an example:

Complex table example

An example of a complex table on mobile. (Image source: wpDataTables) (Large preview)

The image above is the default view visitors would see if they scrolled immediately to the table. However, they might find it to be intimidating and decide that filtering out bad results will improve the view:

Table filters

Filtering allows users to greatly narrow down how many rows are displayed on mobile. (Image source: wpDataTables) (Large preview)

What’s nice about including filters on mobile tables is that they function the same way your mobile contact forms do. So, visitors should have an easy time filling in and moving between fields, which will get them quicker to the results they want to see.

Another way to improve how their results are displayed is by using the sorting feature. When they click on the top label of any column, it will automatically sort the column in descending order. Another click will reverse it.

Table sorting

Sorting allows users to see results in descending/ascending order. (Image source: wpDataTables) (Large preview)

These two features are a must-have for any table you build, though they’re especially important for mobile visitors that don’t have as much time or attention to give to your tables.

Wrapping Up

You’re here because you want a better way to present complex tables to your mobile visitors.

The key to doing this right is by first familiarizing yourself with the kinds of tables you can create. Even if mobile devices limit how much can be seen at first glance, that doesn’t make it impossible to share that kind of data with them.

Next, you need to build user control into your tables, so that visitors can decide what they see and how they see it.

And, finally, you’d do well to find a tool built specifically for this complex task. For those of you building websites with WordPress, wpDataTables is a WordPress table plugin that’s able to create responsive tables and charts. It doesn’t matter how large your data set, or what use case it’s for, it will enable you to quickly and effectively organize and display responsive tables on your WordPress website.

Smashing Editorial
(ms, yk, il)

Source: Smashing Magazine, Designing Complex Responsive Tables In WordPress

Collective #551

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





C551_json

jsonbox.io

A HTTP based JSON storage that lets you store, read and modify JSON data over HTTP APIs.

Check it out








Screen-Shot-2019-09-23-at-14.17.55

CopyMonkey

CopyMonkey is an online app that uses machine learning to mimic your handwriting style like a monkey.

Check it out



C551_navi

navi

An interactive cheatsheet tool for the command-line that allows you to browse through cheatsheets and execute commands, prompting for argument values.

Check it out



C551_overscroll

overscroll-behavior: contain

A great CSS tip by Aaron Iker: disable parent scrolling when the child scroll container reaches the edge of the scrollport using overscroll-behavior: contain.

Check it out





C551_cascadia

Cascadia Code

A fun new monospaced font that includes programming ligatures and is designed to enhance the modern look and feel of the Windows Terminal.

Check it out






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


Source: Codrops, Collective #551

Is There Such A Thing As Too Much Social Proof?

dreamt up by webguru in Uncategorized | Comments Off on Is There Such A Thing As Too Much Social Proof?

Is There Such A Thing As Too Much Social Proof?

Is There Such A Thing As Too Much Social Proof?

Suzanne Scacca



It’s very easy to start a business these days. But succeeding in that business is another story. There are just too many people who want to escape the 9-to-5, do something with their big idea and make a better life for themselves in the process. I totally applaud that.

However, it’s not practical to think that the idea will sell itself. Consumers need to be given some reason to trust that their money (or time) will be well spent. And when a business or product is new, the best way to gain this trust is by getting clients, customers and others to vouch for you.

That said, is it possible to go overboard with testimonials, reviews, case studies, client logos and other forms of social proof? And is there a wrong way to build social proof into a mobile website or PWA?

Yes and yes!

When Too Much Social Proof Is A Bad Thing

I was working on the copy for a new website earlier this year. My client told me that the design team had prepared a wireframe for the home page and wanted me to use that as a framework for the copy. Normally, I would be stoked. When I work as a writer, I want to stay in writer mode and not have to worry about layout and design suggestions.

The only problem was that the home page they wanted was littered with social proof and trust marks. It would’ve looked like this (note: the purple boxes contain social proof):

Sample wireframe with social proof

A sample wireframe of a home page with too much social proof. (Source: Canva) (Large preview)

In reviewing the wireframe, I had a number of gripes. For starters, it was way too long, especially for mobile visitors.


There was no way people were going to scroll seven times to find the section that finally invites them to take action.

Secondly, there was too much social proof. I know that seems counterintuitive. After all, isn’t it better to have more customer validation? I think in some cases that’s correct. Like with product reviews.

In BrightLocal’s 2018 Local Consumer Review Survey, respondents said they want to see at least 40 product reviews, on average, before believing a star rating.

BrightLocal number of reviews to believe start rating

BrightLocal’s consumer review survey says that consumers want to see 40 review before believing a business’s start rating. (Source: BrightLocal) (Large preview)

Even then, consumers aren’t looking for a perfect score. As you can see here, only 9% of respondents need a business to have a perfect rating or review in order to buy something from them:

BrightLocal star rating preference

BrightLocal survey respondents prefer to see a minimum of 3- or 4-star ratings instead of 5. (Source: BrightLocal) (Large preview)

And I can tell you why that’s the case.

I used to write product reviews. One of the things I’d do when assessing the quality of a product (before making my own judgments) was to look at what online reviewers — professional reviewers and customers — had to say about it. And let me tell you… there are tons of fake reviews out there.

They’re not always easy to spot on their own. However, if you look at enough reviews at once, you’ll start to notice that they all use the same verbiage. That usually means the company paid them to leave the review or gave family, friends and employees pre-written reviews to drop.

I’m not the only one who’s noticed this trend either. BrightLocal’s respondents have as well:

BrightLocal fake reviews

33% of BrightLocal respondents have seen lots of fake reviews while 42% have seen at least one. (Source: BrightLocal) (Large preview)

Only 26% of respondents said they hadn’t come across a fake review while 42% had seen at least one in the last year and 33% had seen a lot.

When it comes to things like testimonials and case studies, I think consumers are growing just as weary about the truthfulness of the praise.

TrustRadius surveyed B2B buyers on the subject of online reviews vs. case studies. This is what it found:

TrustRadius customer reviews vs. case studies

TrustRadius asked respondents to assess their feelings on customer reviews vs. case studies (Source: TrustRadius) (Large preview)

It makes sense why consumers don’t feel as though case studies are all that authentic, trustworthy or balanced. Case studies are written by the companies themselves, so of course they’re only going to share a flattering portrait of the business or product.

Having worked in the digital marketing space for a number of years, I can tell you that many customer testimonials aren’t always genuine either. That’s why businesses need need to stop worrying about how much social proof they have and start paying more attention to the truthfulness and quality of what they’re sharing with visitors.

The point I’m trying to make isn’t that we should ditch social proof. It’s an important part of the decision-making process for consumers. But just because it can affect their decision, it doesn’t mean that repeatedly bashing them over the head with it will work either. If your website and its messaging can’t seal the deal, a bunch of logos and quotes meant to convince them to buy won’t either.

What you need to focus on when building social proof into a mobile site or PWA is quality over quantity. Sure, you might want to highlight the sheer quantity of reviews that have been gathered on a product, but in terms of space on your website? With social proof, less is more.

Tips For Building Social Proof Into A Mobile Website Or PWA

You don’t have a lot of room to spare on mobile and you don’t want to make your visitors dig and dig to find the important details. So, while you do need social proof to help sell the business and its product, you need to do so wisely.

That means giving your content room to shine and strategically enhancing it with social proof when it makes the most sense to do so.

Consolidate Social Proof on the Home Page

I know how hard it can be to convince people to work with you or buy from you when your business is new. That’s especially the case when you’re entering a field that’s already dominated by well-known and well-reviewed companies.

However, rather than make your home page longer than it needs to be — for desktop or mobile visitors — why not consolidate the strongest social proof you have and put it in one section?

What’s neat about this option is that you can get creative with how you mix and match your social proof.

Customer Reviews + Trust Seals

Two Men and a Truck is the kind of company that needs customer testimonials. It’s the only way they’re going to effectively convince new customers to trust them to enter their home and carefully transport their belongings from one location to another.

Two Men and a Truck social proof

Local movers Two Men and a Truck stack a testimonial on top of trust seals on the home page. (Source: Two Men and a Truck) (Large preview)

Rather than bog down their home page with testimonials, Two Men and a Truck use one especially positive review and a number of professional trust seals to close the deal in one fell swoop.

Google Reviews + Facebook Reviews

Another way to consolidate social proof on the home page is by aggregating reviews from other platforms as the website of Drs. Rubinstein and Ducoff does:

Drs. Rubinstein and Ducoff home page with Google and Facebook reviews

The home page of Drs. Rubinstein and Ducoff shows off the latest reviews from Google and Facebook along with an average star rating across all platforms. (Source: Drs. Rubinstein and Ducoff) (Large preview)

This is a tiny section — it doesn’t even fill the entire screen — and yet it packs a lot of punch.

First, you have the total number of reviews and average star rating shown at the top. Remember that survey from BrightLocal? This is the kind of thing that would go a long way in convincing new patients to sign up. There’s a good amount of reviews to go on and the average rating seems realistic.

Also, because these reviews come from Google and Facebook, they’re connected to real people’s profiles. Plus, the date is included in the Google review.

Unlike testimonials which are just a quote and a person’s name (if we’re lucky), this is a quote, a star rating and the date it was published. This way, prospective patients don’t have to wonder how long ago it was that Drs. Rubinstein and Ducoff received these reviews.

Twitter + App Store Reviews + Awards

You’ll find another creative example of consolidated social proof on the Pocket website.

Pocket aggregates social proof from a number of sources

Pocket uses Twitter, the Google App Store, the Google Play Store Webby Awards as trust marks. (Source: Pocket) (Large preview)

Even though Pocket is free to use, that’s not necessarily enough to convince someone to try a new piece of software — especially if you want them to download it as a mobile app.

Rather than rely on faceless testimonials, though, Pocket has chosen to show off some convincing and verifiable social proof:

  • A quote from a Twitter user with a healthy follower base,
  • The actual rating of its app on both apps stores,
  • The number of times it’s won a Webby award.

It’s a unique patchwork of social proof which is sure to stand out from the traditional quote block many websites use to promote their products.

Make It Sticky

One of the great things about making the move to a PWA is you can use app-like elements like a sticky bar to show off important information to visitors. If it makes sense to do so, you could even put some social proof there.

Google Reviews Widget

There’s been a big surge in independent mattress companies in recent years. Tuft & Needle. Loom & Leaf. Saatva. They all seem to promise the same thing — a better quality memory foam mattress at a steal of a price — so it’s got to be hard for consumers to choose between them.

One way to make this differentiation is with Google Reviews.

On the desktop website for Lull, the home page reviews callout is tucked into the bottom-left corner.

Lull Google customer reviews on desktop

Lull shares Google customer reviews in a widget on its desktop website. (Source: Lull) (Large preview)

It’s almost too small to notice the reviews with so much more to take in on the home page. That’s a good thing though. The social proof is always present without being overwhelming.

What’s interesting to note, though, is that the mobile counterpart doesn’t show any Google reviews on the home page. It’s not until someone gets to the Mattress page where they’re able to see what other customers have said.

Lull Google customer reviews on mobile

Lull shares Google customer reviews in a sticky bar on its PWA. (Source: Lull) (Large preview)

In this particular screenshot, you can see that the Mattress page on the PWA has a section promoting the product’s reviews. However, even when visitors scroll past that section, the sticky bar continues to remind them about the quantity and quality of reviews the mattress has received on Google.

CTA Banner

Another type of website this sticky social proof would be useful for would be one in hospitality. For example, this website for the Hyatt Regency San Antonio:

Hyatt Regency San Antonio Suites page

An example of one of the Suites pages on the Hyatt Regency San Antonio website. (Source: Hyatt Regency San Antonio) (Large preview)

Just like the Lull example above, the Hyatt Regency tucks its social proof into a sticky bar on its internal sales pages.

Hyatt Regency sticky bar with social proof

The Hyatt Regency places TripAdvisor reviews next to its conversion elements in a sticky bar. (Source: Hyatt Regency San Antonio) (Large preview)

Visitors see the number of TripAdvisor reviews and star ratings when they first enter the Suites page. When they scroll downwards, the sticky bar stays in place just long enough (about one full scroll) for visitors to realize, “Cool. It’ll be there if or when I’m ready to do more research.”

What’s nice about how this particular sticky bar is designed is that the reviews are part of the conversion bar. It’s kind of like saying, “Want to book your trip, but feeling nervous about it? Here’s one last thing to look at before you make up your mind!”

Create a Dedicated Page for Social Proof

If you’re not building a PWA or you have too much social proof to show off in a small space, create a dedicated page for it. This is a great option, too, if you plan to share something other than just testimonials or reviews.

Testimonials/Reviews

Winkworth is an estate agency in the UK. Testimonials are a useful way to convince other sellers and lessors to work with the agency. Yet, the home page doesn’t have any. Instead, the company has chosen to place them on a Testimonials page.

Winkworth testimonials page

The Winkworth estate agency keeps its home page free of testimonials and instead places them on a dedicated page. (Source: Winkworth) (Large preview)

It’s not as though this page is just a throwaway of every positive thing people have said. The testimonials look like they’ve been hand-picked by Winkworth, especially the longer ones that contain more details about the experience and the people they worked with.

Winkworth testimonials

An example of some of the hand-picked testimonials Winkworth has gathered for its Testimonials page. (Source: Winkworth) (Large preview)

Each testimonial includes the person’s name as well as which Winkworth location they’re referring to. This way, visitors can learn more about the experience at specific locations instead of just hearing how great Winkworth is as a whole.

Case Studies

It’s not just testimonials that could use their own page. Case studies shouldn’t clutter up the home page either.

While Bang Marketing promotes its case studies with a promotional banner on the home page, that’s all you hear of it there. They save their customers’ stories for individual pages like this one:

Bang Marketing case studies

Bang Marketing includes a video testimonial with every case study. (Source: Bang Marketing) (Large preview)

Each case study page is minimally designed, but captures all of the information needed to tell the story.

First, there’s a video from the client explaining what Bang Marketing was able to do for them. Then, there’s a brief description of what the team worked on. Finally, high-quality images provide visitors with a look at the resulting product.

This is a much more effective way to share case studies than placing a barrage of portfolio images all over the home page.

Press

There are two ways to handle the Press section of a website. The company could publish its own press releases or it can share information about where it’s been featured in the press.

While the former is useful for sharing company news and wins with visitors, it’s just too self-promotional and won’t help much with conversion. The latter option could really make a big impact though.

This, for instance, is what visitors will find on the About & Press page for The Dean Hotel:

The Dean Hotel Boston magazine cover

The Dean Hotel includes magazine covers and article screenshots as social proof on its website. (Source: The Dean Hotel) (Large preview)

After a short intro of the hotel, the rest of the page is covered in magazine covers and article screenshots that go back as far as 2013. Visitors can click through to read each of the articles, too.

Dean Hotel social proof

The Dean Hotel uses articles as social proof on its website. (Source: The Dean Hotel) (Large preview)

This is a unique way for a website of any type to share social proof with visitors.

If your client happens to have a bunch of positive press and never-ending hype surrounding its brand, try to leverage that on the site. Plus, by including screenshots from the articles themselves, you get another opportunity to show off the product (or, in this case, the hotel and its rooms).

Wrapping Up

Consumers have become very savvy when it comes to marketing and sales online. That’s not to say that they don’t fall for it — usually, when it’s done genuinely and with transparency. However, we’re at a point where a brand saying, “We’re the best! Trust us! Buy from us!”, doesn’t usually cut it. They need more validation than that.

At the end of the day, your mobile website or PWA needs social proof to convince visitors to convert.

That said, be careful with how you build social proof into the site, especially on the home page. You don’t have time or space to waste, so don’t create something unnecessarily bulky just so you can show off how many testimonials, reviews, case studies, client logos high-profile partnerships you have. This is about quality over quantity, so make it count.

Smashing Editorial
(ra, yk, il)

Source: Smashing Magazine, Is There Such A Thing As Too Much Social Proof?

15 Questions To Ask Your Next Potential Employer

dreamt up by webguru in Uncategorized | Comments Off on 15 Questions To Ask Your Next Potential Employer

15 Questions To Ask Your Next Potential Employer

15 Questions To Ask Your Next Potential Employer

Robert Hoekman Jr



In my book “Experience Required”, I encourage in-house UX professionals to leave companies who refuse to advance their UX intelligence and capability. There are far too many companies these days who understand the value of UX to waste your time being a martyr for one who will only frustrate you. Your best chance of doing a good job is to avoid a bad position.

Smartly, during a recent Q&A about the book, an audience member asked how we can avoid taking these jobs in the first place. What kinds of questions, he wondered, can you ask during an interview to spot red flags before the company stabs the whole flagpole into your sacred UX heart?

Know What You Want To Know

There’s the usual stuff, sure, such as asking why the position you’re applying for is currently open. What the company’s turnover rate is like. Why that turnover rate is so low or high. A little Googling will easily enough net you a decent list of broad questions you can ask any employer.

But what you really want is to get UX-specific. You want to hone in on precisely what your life might be like should you take the position.


Your best chance of doing a good job is to avoid a bad position.

Sadly, I lacked a great answer at the time to the question about interview questions, so I let it eat at me until I woke up at three a.m two days later and started writing notes. That morning, I emailed my reply to the moderator.

Ask A Great Question, Then Shut Up

To devise the list below, I considered what kinds of things I’d wish a company knew and understood about UX prior to working with them. I can operate in all kinds of situations—as a UX and process innovation consultant, this has been my job, and pleasure, for nearly 13 years now—but I want to know from the start, every time, that the effort will be set up for success. These questions aim to uncover the dirty details that will tell me what I’m walking into.

Much like a good validation session or user interview, these questions are open-ended and designed to draw out thoughtful, long-winded responses. (One-word answers are useless.) I strongly recommend that when and if you ask them, you follow each question with a long, stealthy vow of silence. People will tell you all about who they are if you just shut up long enough to hear them do it. Stay quiet for at least ten seconds longer than you think is reasonable and you’ll get the world.


People will tell you all about who they are if you just shut up long enough to hear them do it.

I’d ask these questions of as many individuals as possible. Given that tech interviews are often hours-long and involve many interviewers, you should be able to grab yourself a wealth of good answers before you head out the door to process and sleep.

If, on the contrary, you are given too little time to ask all these questions, prioritize the ones you’re personally most concerned about, and then consider that insufficient interview time might be a red flag.

Important: The key to the answers you receive is to read between the lines. Listen to what is said, note what is not said, and decide how to interpret the answers you get. I’ve included some red flags to watch out for along with each question below.

The Questions

Let’s get right to it.

1. How does this company define UX? As in, what do you believe is the purpose, scope, and result of good UX work?

Intent

Literally every person on Earth who is asked this question will give a slightly, or wildly, different answer than you expect or hope for. At the very least, the person interviewing you should have an opinion. They should have a sense of how the company views UX, what the various UX roles have to offer, and what effect they should have.

Red Flag(s)

The UX team has a very limited role, has no real influence, and the team, for the most part, is stretched so thin you could put them on a cracker.

2. How do the non-UX people on your product team currently participate in UX decisions?

Follow-ups: Describe a recent example of this kind of participation. What was the UX objective? How was that objective vetted as a real need? What did you do to achieve the objective, step-by-step? How did it turn out? What did you learn?

Intent

Find out how the entire product team approaches UX and how collaborative and supportive they might be in acquiring and acting on good research insights.

Red Flag(s)

They don’t participate in UX decisions.

3. What UX roles exist in the organization, and what do they do?

Intent

Determine where you’ll fit in, and how difficult it might be for you to gain influence, experience, or mentorship (depending on what you’re after). Also, build on the previous question about who does what and how.

Red Flag(s)

UX people at the company are heavily skilled in graphic design, and not so skilled in strategy. The current team members have limited influence. Your role will be similar. Strategy is handled by someone else, and it trickles down to the UX team for execution.

4. Who is your most experienced UX person and in what ways does that experience separate them from others?

Intent

Determine the range of UX intelligence on the team from highest to lowest. Is the person at the top whip-smart and a fantastic leader? Does that person mentor the others and make them better?

Red Flag(s)

The interviewer cannot articulate what makes that person better or more compelling than others. If they can’t answer this question, you’re speaking to someone who has no business making a UX hiring decision. Ask to speak to someone with more inside knowledge.

Noteworthy, but not necessarily a red flag: If you learn that the most experienced person on the team is actually someone with a very sleight skill set, this can mean either there’s room for you to become an influencer, or the company puts so little value on UX that they’ve selected only employees with a small view of UX. The latter could mean you’ll spend all your time trying to prove the value of bigger UX involvement and more strategic work. You may like that sort of thing. I do. This would not be a red flag for me. It might be for you.

5. What are the company’s plans for UX long-term? (Expand it? Reduce it? How so, and why? Is there a budget for its expansion? Who controls it and how is it determined?)

Intent

Map out your road for the next couple of years. Can you rise into the role you want? Or will you be stuck in a cul-de-sac with zero chance of professional growth?

Red Flag(s)

We plan to keep doing exactly what we do now, and what we do now is pretty boring or weak. Also, we have no budget—like, ever—so if you want to bring in a consultant, attend a seminar, hire another person, or run a comprehensive usability study with outside customers, well, good luck with that.

6. How do UX professionals here communicate their recommendations?

Follow-up: How could they improve?

Intent

Learn how they do it now, and more importantly, whether or not it works.

Red Flag(s)

The interviewer has no answer, or—far worse—has an anti-answer that involves lots of arm-waving and ideas falling on deaf ears. The former can, again, mean the interviewer has no business interviewing a UX candidate. The latter can mean the UX team is terrible at communicating and selling its ideas. While this can be overcome with your much better communication skills, it will almost certainly mean the company has some baggage to wade through. Poor experiences in the past will put other product team members on defense. You’ll have to play some politics and work extra heard on building rapport to get anywhere.

7. Who tends to offer the most resistance to UX recommendations and methods and why?

Follow-up: And how much power does that person have?

Intent

This person will either give you the most grief or will give you the great opportunity to improve your communication skills (remember: design is communication!). Knowing who it is up front and how that person operates can tell you what the experience will be like.

Red Flag(s)

Executives, because they distrust UX. If you lack support at the top, it will be a daily struggle to achieve anything substantive.

8. What do UX practitioners here do to advance their values and methods beyond project work? Please be specific.

Intent

See how motivated the UX team is to perpetuate UX values to the rest of the company and improve how the team works.

Red Flag(s)

They don’t.

9. What do you think they should do differently? Why?

Intent

Discover how your interviewer feels about UX. This is, after all, a person who has a say in hiring you. Presumably, this person will be a big factor in your success.

Red Flag(s)

Keep their noses out of product development, stop telling the engineers what to do (speaks to perception of pushy UX people).

10. Describe a typical project process. (How does it start? What happens first? Next? And then?)

Intent

Find out if there is a process, what it looks like, and how well it aligns with your beliefs as a UX professional.

Red Flag(s)

You’ll be assigned projects from the top. You’ll research them, design a bunch of stuff in a vacuum with no way to validate and without any iteration method, and then you’ll hand all your work to the Engineering team, who will then have a thousand questions because you never spoke to each other until just now.

Bonus Question

How and when does the team try to improve on its process? (If it doesn’t, let’s call that a potential red flag as well.)

11. How has your company learned from its past decisions, and what have you done with those learnings?

Intent

UX is an everlasting experiment. Find out if this company understands it’s supposed to learn from the work and become smarter as a result.

Red Flag(s)

No examples, no thoughts.

12. If this is an agency who produces work for clients: What kind of support or backup does this agency provide for its UX recommendations, and how much power does the UX group have to push back against wrongheaded client ideas?

Follow-ups: How does the team go about challenging those ideas? Provide a recent example.

Intent

Find out how often you’ll be thrown under the proverbial bus when a client pushes back against what you know to be the right approach to a given problem. Your job will be to make intelligence-based recommendations; don’t torture yourself by working with people who refuse to hear them.

Red Flag(s)

The interviewer says the agency does whatever the clients demand. You will be a glorified wireframe monkey with no real power to change the world for the better.

13. How does the company support the UX group’s work and methods?

Intent

Determine how the company as a whole thinks about UX, both as a team and a practice. Is UX the strange alien in the corner of the room, or is it embraced and participated in by every product team member?

Red Flag(s)

UX is a strange alien. Good luck getting anyone to listen to you.

14. What design tools (software) does your team use and why?

Follow-ups: How receptive are people to trying new tools? How does evolution happen?

Intent

Know what software you should be familiar with, why the team uses it, and how you might go about introducing new tools that could be better in some situations.

Red Flag(s)

Gain insight into how the team thinks about the UI portion of the design process. Does it start with loose ideas drawn on napkins and gradually move toward higher-quality? Or does it attempt to start with perfection and end up throwing out a lot of work? (See the next question for more on this.)

15. Does a digital design start low-fi or high-fi, and what is the thinking behind this approach?

Follow-up: If you start lo-if, how does a design progress?

Intent

You can waste a lot of hours on pixel-perfect work you end up throwing out. A company who burns through money like that is also going to be the first one to cut staff when things get tight. No idea should be carried through to its pixel-perfect end until it’s been collaborated on and vetted somehow, so you want to know that the company is smart enough to start lo-fidelity and move gradually to hi-fidelity. Hi-fi work should be the result of validation and iteration, not the start of it. A lo-fi > hi-fi process mitigates risk.

Red Flag(s)

All design work starts and ends in Photoshop or Sketch, and is expected to be 100% flawless and final before anyone sees what you’ve produced.

Running The Interview

In an unrelated Q&A years ago, a hiring manager asked how to spot a good UX professional during an interview. I answered that he should look for the person asking all the questions. I repeated this advice in Experience Required.

Now you can be the one asking all the questions.

And in doing so, not only will you increase your odds of being offered the gig, you’ll know long before the offer shows up whether to accept it.

If you, dear reader, have more ideas on how to scavenger-hunt a company’s red flags, we’re all ears. Tell us about it in the comments below.

Smashing Editorial
(cc, il)

Source: Smashing Magazine, 15 Questions To Ask Your Next Potential Employer