Keyboard Shortcuts on Browser: A Hot Mess

Published on 8 Oct

Too many footguns, not enough discussions.

Here be dragons.

  1. People are most familiar with Cmd + Shift + * shortcuts but since browser is an app itself it reserves many shortcuts like Cmd + P, Cmd + Shift + N, Cmd + Shift + P.

  2. Some keyboard shortcuts are not overridable like

    Cmd + W, Cmd + Shift + T

  3. User might have some apps installed which run on Cmd + Shift + C, Cmd + Option + D so during testing things might be fine but for real users some popular apps might be taking over and there's no way to know.

  4. The reserved kbd shortcuts may vary on browsers and operating systems. Like Firefox open incognito with Cmd + Shift + P whereas Chrome open on Cmd + Shift + N.

  5. For Mac use Cmd, for Windows need to use Control. Similarly other kbd shortcuts have to be dynamically mapped.

  6. Browser extensions can also potentially bind keyboard shortcuts.

  7. Alternative APIs without Cmd means that we don't know if user is pressing keys to type or if they actually want to run a keyboard shortcut. For eg- Shift + P. Maybe user pressed it to type uppercase P.

  8. If non modifier based shortcuts need to be supported then we have to disable shortcuts on all fields where user can type. May not be very trivial depending on the app.

  9. Non modifier based shortcuts can be accidentally triggered by heavy keyboard and speech input users so they have to be disabled or need alternate shortcuts to pass Accessibility Success Criterion 2.1.4: Character Key Shortcuts

  10. If we have many complementary shortcuts like * + X

    opens Create X Modal and * + * + X navigates to List X page then to give a consistent experience is even more hard since Cmd + P might be available but Cmd + Shift + P may not.

  11. Option is not a modifier like Cmd or Shift. Option's main purpose is to provide alternative letters on standard keys like typing Option + o would lead to ø. So it runs into same issues as Shift + P.

  12. If we need to support variants shortcuts like Cmd + P opens Create Payout but Cmd + Option + P opens bulk payouts then again very few shortcuts are possible. Another example of variants is of that in Mac. Cmd + V duplicates a copied file to current location whereas Cmd + Option + V moves the original copied file to current location.

  13. Having an intuitive system for complementary and variant shortcuts is very important if user is supposed to remember the shortcuts. If shortcuts are made ad-hoc without consistency then they won't stick in people's head and they're just going to use the mouse instead of digging the shortcut.

  14. Sequence shortcuts give the most flexibility. But they have a problem that it's hard to explain in text how to use them. Like press g then release it then press p. People are more used to pressing 2 or 3 keys together.

  15. Even with sequence type shortcuts if the first key is not modifier then they run into same issue of non modifier type shortcuts.

  16. Sequence shortcuts like Cmd + G , p may look like a good solution but problem is that browsers already have a shortcut on Cmd + G. It is overridable but since there is some time gap in pressing p our custom version will not take over instead browser one will be immediately triggered.

  17. Cmd + * , * have even more flexibility than just letter sequences but they are even more hard to explain to user textually and the most unusual too.

This talk from a Figma engineer reveals even more footguns.

URL shortcuts for developers

Published on 12 Apr 2021

All the cool URLs you can type in the address bar to increase productivity

Here are some URLs you'll find useful everyday-

1. GitHub box

If you have a repo (even branch) you can open it in CodeSandbox immediately by changing github to githubbox.

Try- https://githubbox.com/itaditya/redux-hooks-for-food-delivery

2. GitHub1s

Explore any GitHub repo in a VS Code web version. Simply change github to github1s.

Try- https://github1s.com/pmndrs/zustand/blob/HEAD/src/index.ts

3. GHub

If you know a npm package name and quickly want to go to its GitHub repo, add the package name at the end of ghub.io.

Try- https://ghub.io/birla

4. Check package files with unpkg

Many times you'd want to check what files were actually published to npm. unpkg provides a file explorer for npm packages.

Try- https://unpkg.com/birla/ (the trailing slash is important)

What's cool is that you can check files of old versions as well. That makes it possible to host your html docs for each package version on unpkg for free! I haven't tried this myself but according to Michael it should be possible.

5. csb.new

Quickly create CodeSandbox with your framework of choice

For React- react.new

Others- vue.new ts.new csb.new

6. Other .new goodies

New CodePen - pen.new

New GitHub repo- repo.new

Making a Google Doc / Sheet / Meeting with- docs.new sheets.new meet.new

New story on Medium- story.new

Shortlink with Bit.ly- link.new

Node.js workspace with RunKit- api.new

Frontend Jargon de-mystified

Published on 27 Sep 2020

In discussions, developers often blurt out words that you've never heard before and you feel like Joey from FRIENDS, nodding along

Joey Nods Along GIF

Here are some of the common ones you'll hear frequently and from now on you'll know what they mean.

1. TDD

TDD is an acronym for Test Driven Development ihfi. which is a practise where first we write the tests for a module and then write the actual code for it. The tests resemble the specification of how your software will work. As you add code, one by one tests start passing and when they are all green, it means you have completed the desired specs.

This technique is not that popular in frontend but people often use the term to mean "writing tests". That is actually not what TDD means.

2. Above the Fold

This term comes from newspaper printing. When you open a folded newspaper, you see a crease. As we read from top to bottom, its a good idea to keep the most important content which grabs the readers attention above the fold and other news items below the fold.

In web, above the fold mean the initial section of the site that user sees without scrolling. You might do optimizations to render Above the Fold content as fast as possible and then load other content. Some techniques are extracting critical css or setting content visibility as auto to below the fold content.

3. Flag

When a value is used to determine the next step of the program, its called a flag. You might find a isUserLoggedIn boolean flag where we will show the user's name if the flag's value is true otherwise show a login link. A Flag doesn't need to be a boolean though.

4. Feature Flags

Modern Software uses Feature Flags to turn on/off various features for users on the fly. If you put a new feature behind a feature flag then you can deploy to production without users noticing the new feature. Then from some dashboard you can choose a segment of users who see this new feature or the users could themselves opt in to beta features.

This article goes into advanced patterns for using Feature Flags.

5. Graceful Degredation

One major goal of web is to run anywhere. Old IE versions are still used by banks and even their device is not that fast. When you open Gmail they show a link to Load Basic (HTML) view in the corner. That way they offer a degraded experience to users but ensure that the core functionality is still usable.

6. Progressive Enhancement

In this approach, we establish a basic level of user experience. Then if the client has support for a new feature then we use that feature. For eg- our app works fine on major devices but if the device has service worker support we cache all the images client side so that next time the page opens much faster.

7. Hot Reload

A couple of years back when we used to change some code we would refresh the browser and see the changes and repeat this process. Then came live-reloading tools which would watch your code and automatically reload your page on change.

But when we start building modular applications using bundlers, we got a new technique called Hot Module Reloading (HMR). In this technique, the bundler figures out exactly which modules need to update and in browser only those modules are updated without refreshing the page. This way if you had typed something in the search box that text would stay if you made changes in a Heading component.

8. Brownfield Project

When you join a company, they would have a working software where some parts would be legacy. In these kind of projects you can't just adapt whatever new tech you want. We need to consider how it will fit in our existing application.

9. Greenfield Project

Whenever you create a new project its a greenfield project. You don't have to fight with somebody else's bad judgment. Instead, you'll be the person who'll be making the bad judgments for the future you. You can adapt whatever new tech you want without any baggage.

10. Coupling

If two modules are tightly coupled that means if you change something in one module then you will also need to ensure that the other module didn't break.

Let's say you get a Button component from a library. Since CSS is global you could alter that Button component styles by doing something like ".custom-button > span.icon-wrapper". Now you have tightly coupled your CSS with the Button component's internal HTML structure. When you update the library version it might have changed Button's internal structure and you would need to update your CSS too.

In short, tight coupling forces your hand when making changes so it should be minimized.

11. Cohesion

A module has high cohesion if all its internal elements focus on doing one thing and doing it well. Traditionally we used to keep our JavaScript (behavior) separate from the HTML and CSS (presentation). That means when you add a new feature you would touch a lot of files to implement it. The traditional approach lacked cohesion and that was a problem for the modern apps we build.

With the Component model (React, Vue, Svelte) we keep all relevant elements of a feature in one component. The component owns its presentation and behavior. If you want to add an icon in a Button component then you just open the Button component file, add the icon's HTML and change its CSS (assuming you use something like Emotion.js, Tailwind, Linaria). High cohesion boosts developer productivity.

Other examples of increasing cohesion-

  1. Keeping all Redux artifacts for a feature in one file using redux-toolkit.

  2. Project Structure by features rather than keeping models and views folders.

Fast deploy pipeline for Unpolished posts

Published on 19 Apr 2020

I needed a fast way to collect my unpolished thoughts into a post and share them. The normal Git flow would be a hindrance. Here's how I built a faster pipeline.

I really like SSG. The build does take more time as your content grows but it's still worth it considering the performance benefits you get. That's why my blog uses MDX + Next.js to pre-render all the blog posts whenever I add a new commit to master. But when I built this new section for my site called Unpolished I had to tweak it a little. This new section is meant to house my unpolished thoughts which I'll keep updating till they become worthy of being a blog post.

Why I didn't use the Git flow.

As I said my blog works like a normal SSG app. I add a new MDX file and push to a branch. Netlify pre-renders all blog posts using getStaticProps from Next.js. Then I open the Netlify preview url, see if its working there and then merge to master. This is great for content which is expected to not change frequently.

But for my unpolished thoughts I can't use such a long process. What I want is a text editor where I make changes and see the updated draft on my site instantly. When I'm happy with the draft, I click Publish and my site gets deployed with new posts. The process should be optimized for frequent updates.

The new process of working with Unpolished Posts.

To make a new post or update an existing one, I open the Contentful Rich Text editor. I make my changes and open the draft page. The draft page component has a useEffect hook which fetches the data for all drafts from Contentful using their Preview API. Because the drafts are only meant to be seen by me, I can trade the performance degrade with the increased speed of previewing content.

When I Publish the draft, Contentful uses a webhook to tell Netlify to deploy again. During the build Next.js pre-renders the unpolished posts using getStaticProps and that way for people who opens the /unpolished page the performance is still great.

Benefits of this process

In this process, I don't have open my Code Editor, start dev server and create a commit. My git history is also not getting clogged up with commits for typo fixes.

P.S.- During the 1 hour period of me publishing this post it has went through 4 edits.

Why I prefer Tailwind for design systems

Published on 19 Apr 2020

Design Systems are meant to unite all the products of a company. That's why they should follow the Rule of Least Power. Here are my thoughts on why I consider TailwindCSS to be a great solution for Design Systems.

Tailwind in a nutshell is generating CSS utility classes from a tailwind.config.js file. The only thing you need to setup TailwindCSS in an app is include the generated CSS file in your html. And this property of Tailiwind makes it very useful to build design systems.

What does design system include?

A design system is not just a themed component library. It is a collection of all the best practices your company follows that are aimed to give users a consistent and usable interface while minimizing the effort that has to be done by designers, developers, product managers and all other people who help in crafting the UI. That means design systems cover a lot of territory.

  • Web apps built for users- Depending on the company size they can have only one app or multiple apps built by different teams using different libraries. Say your company provides a software which has two parts. The user facing part is built by one team using React. The customer facing legacy app was built using PHP templates. If your design system is built on top of JS then you can't use it for the legacy app.

  • Email Templates- Many companies rely on emails to promote their product to users. So you'd want to ensure that the emails also look consistent with the app UI your users remember you by. Email clients supports CSS but doesn't support JS currently and once again we realize that our design system should be built with the Rule of Least power.

  • Wordpress Landing Page- Many companies use Wordpress to make their landing pages. I haven't used Wordpress myself but I assume that since it is built on top of PHP, the UI code ends up in PHP templates. So there also we need a css based design system.

For all these requirements, a design system built on top of static CSS makes more sense. And TailwindCSS fits the bill perfectly.

How TailwindCSS fits all the requirements

  1. TailwindCSS is just utility classes so you can use it anywhere which supports adding CSS classes to an HTML element. That means it can work in any SPA framework like React, Vue, Svelte.

  2. It can also work in any backend templating system like PHP or Django. And I'm assuming it'll also work in Wordpress.

  3. TailwindCSS can be made to work with emails with just a few steps. Write the mail template in an HTML file and style it by adding tailwind classes. A CSS file containing class declarations can be made in advance for all templates or generated for each template (to decrease CSS file size). This CSS file can then be included in the mail template.

  4. Since Tailwind generates classes using tailwind.config.js, the design tokens can be kept in a js file and imported in the config file. That way the js files containing the tokens can be used to generate design tokens for other platforms like Android apps as well.

  5. One more reason I prefer tailwind for design systems is that it frees you from writing component classes. Component classes are like .btn, .navbar. When using component classes inside a React component you make it easy for your component consumers (other teams using the design system) to override the internal designs of a component. Although your components become more flexible they also make your component a leaky abstraction. If you just use atomic classes then consumers can't override internal markup of a component. Now if you refactor the internals of a component it will not break somebody's app visually. Read this blog for more details.

That's all the benefits I can think of right now but I'll keep updating this post if I get new ideas. This post is meant to start discussion related to our current best practices. We can discuss this on twtter coz I love getting more thoughts on my posts.

Also I just want to add that TailwindCSS is not a silver bullet. For your usecase it might not be the best solution. Take whatever I say with a grain of salt.