Tailwind Strategies for themes

🞄
🞄

In this article I will talk about some strategies you can use to create themes on Tailwind, a way to write CSS in utility classes, like if you want to say display: flex, you can just give a classname of flex. Of course this is a very simple example, but you can do so much more and everything is customizable.

Tailwind CSS as the docs says:

A utility-first CSS framework packed with classes like flex, pt-4, text-center and rotate-90 that can be composed to build any design, directly in your markup.

#What is Tailwind CSS

To understand Tailwind CSS is good to know how it was created. Well, the framework was created by Adam Wathan because he wanted to use a Bootstrap kinda syntax with Less processor, as you may know Bootstrap has build in classes for buttons, forms, etc. Tailwind in other hand has just utility classes, like flex, backgrounds, paddings, margins, etc. That's why in the first versions of Tailwind, it has some of the classes like Bootstrap, but from time on Adam switched to more generic classes. He also needed to change the processor to PostCSS, but you can find the whole history at OfferZen Origins's channel.

For me, frameworks that's uses utility classes are the best ones, it can be strange at first but the productivity grows so much using this strategy that I cannot stop using.

#Popularity

For popularity Tailwind is one of the favorite CSS Framework out there. You can see this in State of CSS Survey:

Survey from State of CSS showing the is one of most used technologies for styling
State of CSS. Ref.https://2023.stateofcss.com/en-US/css-frameworks

They have a lot of interesting data. I suggest you to take look and see for yourself.

#How to use

As said before, Tailwind uses utility classes, so you will add them into your html as so:

html<div className="m-4 flex items-center justify-center">
  <span>Item 1</span>
  <span>Item 2</span>
</div>

When I started coding, the company used Angular with kinda of utility classes. We a had a big style sheet containing all the most used classes like padding or margin and them, if we would need some more specific style, we create a class just for it. I grow up and for my experience, don't do that, try to stay just with utility classes, it way more easy to maintain.

You can find the list of utility classes available in the docs.

#What is theme

Theme is a set of characteristics that build an idea. I can be applied to an environment to give the feeling of that characteristics. So you can made a party using a Halloween theme, so everyone and the party probably will have characteristics from Halloween.

In design is the same thing, we can made certain rules that build in a theme, like font sizes, spaces, images and colors. This can be used for accessibility advantages or just to made a design some unique like a special version for christmas.

It became very popular for all designs to have at least a version called dark with more darker colors and a light with, of course, lighter colors. So it is very important to know how you can handle this.

#Strategies for theming in Tailwind

In this tutorial, I will show only themes that change colors, that's because I think changing the font-size or spaces can be tricky and not so great in the final product.

Tailwind already has a theme build in support but I think is not ideal mostly if you want to add more than just dark and light theme. So that's why I gonna show you some strategies you can use to add more themes for Tailwind CSS.

#Using external libraries

There a lot of libs created by the community to solve the problem of multiple themes in Tailwind. Some examples would be:

All have a very similar concept and way to solve this by enable to create themes on Tailwind.config.ts, as an example of configuring three themes dark, light and forest using TW Colors:

typescriptconst { createThemes } = require('tw-colors');
 
module.exports = {
  content: ['./src/**/*.{html,js,jsx,md,mdx,svelte,ts,tsx,vue}'],
  plugins: [
      createThemes({
        light: {
            'primary': 'steelblue',
            'secondary': 'darkblue',
            'brand': '#F3F3F3',
        },
      dark: {
        'primary': 'turquoise',
        'secondary': 'tomato',
        'brand': '#4A4A4A',
      },
      forest: {
        'primary': '#2A9D8F',
        'secondary': '#E9C46A',
        'brand': '#264653',
      },
      })
  ],
};

It is a great improve on my point of view and you can certainly use it, but for me I would like to make my own code in my own way.

#CSS Variables

TW Colors uses CSS variables to make the themes, so I thought I could use too as I already made a theme logic using them when working with Angular 2 years ago.

Then I started thinking what are my needs and how can I solve them. The first thing was that I want as many themes as possible- So I would need to provide to every theme into different files as I wanted a lot of them, staying at the same file would not be very scalable. Second thing I wanted is to control the theme based on a html attribute data-theme as:

html<html data-theme="dark"></html>

With this in mind, I thought on a simple solution: Use CSS variables, and change the value of them using Javascript. To start this I overwrite Tailwind default colors with my colors in Tailwind.config.ts using CSS variables syntax as:

typescriptimport type { Config } from 'tailwindcss'
import defaultTheme from 'tailwindcss/defaultTheme'
 
const config: Config = {
  content: [
    './src/**/**/*.{js,ts,jsx,tsx,mdx}',
  ],
  theme: {
    colors: {
      'primary': 'var(--primary)',
      'secondary': 'var(--secondary)',
      'text': 'var(--text)',
      'title': 'var(--title)',
      'foreground': 'var(--foreground)',
      'background': 'var(--background)',
      'background-card': 'var(--background-card)',
      'text-on-primary': 'var(--text-on-primary)',
      'text-hover': 'var(--text-hover)',
      'primary-hover': 'var(--primary-hover)',
 
      'code-header': 'var(--code-header)',
      'transparent': 'transparent',
      'current': 'currentColor',
    },
  }
}
export default config

A little observation about two colors transparent and current that are been used as constants and not variables values, because I do not want to change them when the theme is changed.

Continuing after colors configuration, I need to declare these variables and default values for them into some place so I went to global.css where Tailwind is init and then declare the variables into a root pseudo-class:

css@tailwind base;
@tailwind components;
@tailwind utilities;
 
:root {
  --primary: #51C28A;
  --secondary: #74DFAA;
  --text: #DDDDDD;
  --title: #EAEAEA;
  --foreground: #282929;
  --background: #131313;
  --background-card: #ffffff0a;
  --text-on-primary: #FFFFFF;
  --text-hover: #888888;
  --primary-hover: #409c6e;
 
  --code-header: #21222C;
}

If you want, you can add a accessible medias prefers color scheme.

That almost it, now you just need to add in some css file the values for each theme like so:

css:root[data-theme='dark'] {
  --primary: #51C28A;
  --secondary: #74DFAA;
  --text: #DDDDDD;
  --title: #EAEAEA;
  --foreground: #282929;
  --background: #131313;
  --background-card: #ffffff0a;
  --text-on-primary: #FFFFFF;
  --text-hover: #888888;
  --primary-hover: #409c6e;
 
  --code-header: #21222C;
}

To make a better organization I like to make one file for each theme and then export all in one file.

Folder structure
Folder structure
css/* themes/variants/dark.css */
:root[data-theme='dark'] {
  --primary: #51C28A;
  --secondary: #74DFAA;
  --text: #DDDDDD;
  --title: #EAEAEA;
  --foreground: #282929;
  --background: #131313;
  --background-card: #131313;
  --text-on-primary: #FFFFFF;
  --text-hover: #888888;
  --primary-hover: #409c6e;
 
  --code-header: #21222C;
}
css/* themes/variants/light.css */
:root[data-theme='light'] {
  --primary: #359967;
  --secondary: #4d9470;
  --text: #090a0a;
  --title: #191b1a;
  --foreground: #dfdfdf;
  --background: #ffffff;
  --background-card: #dfdfdf;
  --text-on-primary: #FFFFFF;
  --text-hover: #888888;
  --primary-hover: #409c6e;
 
  --code-header: #21222C;
}
css/* themes/index.css */
@import './variants/dark.css';
@import './variants/light.css';

This way I can import the index.css file with all the imports already set up.

The last part, we need to make the logic to change themes. To do this first you need to map all your themes into an array.

typescript/* themes/themes.theme.ts */
export const themes = [
  'dark',
  'light',
]

Lastly just change the value of the html attribute data-theme with Javascript and voilà.

javascriptdocument.getElementsByTagName('html')[0].setAttribute('data-theme', 'light')

#SSR Themes preference

If you analyze my blog you would probably noticed that theme preference is storage somewhere and then loaded before even the page. How that's possible? The key word is cookies. These type of data is storage and can be access by the server, not only the browser like local storage, using this, we can load the theme in server and then bring to browser the storage one as default.

There are many ways to manage cookies and I think that every framework has its own way to do that. In this tutorial I will teach you with NextJS 13 using app router because it is what I use and have experience.

First we need to install 1 dependency called cookies-next because with the new API of app router, we can only use cookies at server components but this solves just one part of the equation the load can be at server components, but every time we use interaction, the component need to be client, so how am I supposed to save a cookie of user theme choice? That's why we use cookies-next, to manipulate cookies at client components.

bashnpm install cookies-next

Let's start in the root layout.tsx.

jsxexport default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  const cookieTheme = cookies().get('data-theme')
  const theme = themes.includes(cookieTheme?.value ?? '') ? cookieTheme?.value : 'dark'
 
  return (
    <html lang="en" data-theme={theme}>
      <body>
        <main>
          {children}
        </main>
      </body>
    </html>
  )
}

Using the code above you can load the cookie data-theme and then pass to html. Now to change this just use the code Javascript that I said to you earlier.

jsx 
// Here you can storage these values together with the themes like I showed you earlier.
const themes = [
  'dark',
  'light',
]
 
function handleTheme(theme: string) {
  document.getElementsByTagName('html')[0].setAttribute('data-theme', theme)
}
 
export function ThemeSelector() {
  return (
    <div>
      {
        themes.map((theme) => (
          <button key={theme} onClick={() => handleTheme(theme)}>
            {theme}
          </button>
        ))
      }
    </div>
  )
}

#User preferences - prefers-color-scheme, prefers-reduced-motion, etc

One last thing you can do to make your code even better is to add a default theme based on user preference, it is very common to add a option on theme selector saying default or system, this is a theme based on user's system theme. So that's really import to make our interface looks like the user's on first time accessing our site. To do that is very simple, just add a CSS query prefers-color-scheme.

css/* themes/variants/system.css */
@media (prefers-color-scheme: dark) {
  :root {
    --primary: #51C28A;
      --secondary: #74DFAA;
      --text: #DDDDDD;
      --title: #EAEAEA;
      --foreground: #282929;
      --background: #131313;
      --background-card: #282929;
      --text-on-primary: #FFFFFF;
      --text-hover: #888888;
      --primary-hover: #409c6e;
 
      --code-header: #21222C;
    }
}
 
@media (prefers-color-scheme: light) {
  :root {
    --primary: #359967;
    --secondary: #4d9470;
    --text: #090a0a;
    --title: #191b1a;
    --foreground: #dfdfdf;
    --background: #ffffff;
    --background-card: #dfdfdf;
    --text-on-primary: #FFFFFF;
    --text-hover: #888888;
    --primary-hover: #409c6e;
 
    --code-header: #f3e9de;
    }
}

#Conclusion

In this article I told you a little about the history behind Tailwind CSS creation, with the explain about what are themes and how people use them with Tailwind. For last how I would implement themes by myself using Tailwind and NextJS SSR feature to load theme in the server rendering time.

Thank you for your time. Have a nice day. 😎✨✨✨😎

References

Tailwind doc. Access at

Indie Hackers - Adam Wathan. Access at

OfferZen Origins - Adam Wathan. Access at

Design system theming - UX Pin. Access at

Mozilla Developer. Access at

Help us improve

If you find any mistakes or just want to make the article more complete, consider editing this page in Github.

About the author

Profile of Felipe Scherer
Written by:

Felipe Scherer

- Software Engineer

Hello. I currently working as developer for more than 2 years coding sites, apps and games. In the free time I like to write articles to help people get started in this incredible world of coding. Feel free to explore my Github and use my public code 😊. Don't forget to follow me on my socials. 🌟

You may also like

7 minutes read

How to create good looking custom scrollbars

In my opinion one of the most difficult part in frontend is to make the layout look similar in every browser and that's because we have CSS Resets, but scrollbars can be one of the points we forget but can makes a huge difference to users. ## Introduction At my first year as developer, I always will remember a gaffe committed when introducing some new features I had developed to the CEO's company. Well, I use Mozilla Developer Edition to code, but at that time I forgot users uses Chrome in majority. <Img src="https://github.com/fescherer/blog/assets/62115215/8be10ac9-bb0f-47d5-93b7-bed3144ad9fe" source="https://gs.statcounter.com" name="Browser Market Share Worldwide Dec 2022 - Jan 2024" alt="Statcounter graph showing Chrome are used by 70% of the users" /> So the CEO. Yes, the scrollbar's feature was horrible in Chrome because the scrollbars are not aesthetic as Firefox. In the end, I did not got any in any trouble, the CEO only just pointed out and I did the fix in the next patch. I learnt to never forget scrollbars again, it cannot be neglected. ## Problems The main issue with scrollbars it is different styles in each browser which makes really hard to us track how the final layout is gonna be delivered to the user. And is not only the visuals, some browsers make the scrollbars take a size of the container, which can lead to layout looking weird. We gonna follow the name convention in [this fantastic article by Zach Leatherman - Two Browsers Walked Into a Scrollbar](https://www.filamentgroup.com/lab/scrollbars/): <Blockquote cite="https://www.filamentgroup.com/lab/scrollbars"> - Obtrusive scrollbars: scrollbars that take up screen real estate. These do not overlay on top of the content, but appear next to it. - Unobtrusive scrollbars: scrollbars that sit on top of the content. These don't subtract screen real estate away from the container they belong to. </Blockquote> I personally would prefer that every browser had unobtrusive scrollbars most because we as developer would not need to worry about taking some space in our layout. But I know that's not possible and probably would ruin a lot of layouts out there. Don't get me wrong, I am not saying some browser is better than other, I really think that every browser has some kind of problem when talking about scrollbars. Let's point out: ### Mozilla Firefox Firefox has unobtrusive and really aesthetic scrollbar which is great but I don't like how only "grows" the scrollbar on hover, not the container, but the scrollbar. I think if it has to grow, that should grow on hover the content to be easy accessed and not the scrollbar. Like if I already have reached the scrollbar, it does not need to grow, right? The grow is to make the bar more accessible... <Img src="https://github.com/fescherer/blog/assets/62115215/ad1747c2-699f-492f-9f07-be5b8f2f97aa" name="Mozilla Firefox default scrollbar" alt="Gif showing that Firefox only grows the scrollbar if hovered IN the scrollbar" /> ### Chromium Browsers I love chromium browsers specially Chrome and Opera GX, I use them both in different situations, like coding I like Chrome and Mozilla Firefox Developer, but for daily routines I prefer Opera GX. But most of the scrollbars are not that great. First, they are obtrusive which for sole already brings some problems. Second, it is so wider even if user is not hovering the content, which is really ugly... <Img src="https://github.com/fescherer/blog/assets/62115215/d0c6360e-0546-4999-a296-8c11c2f62947" name="Chrome default scrollbar" alt="Gif showing the default behavior scrollbar in Mozilla Firefox" /> ### Edge One scrollbar I really like is from Edge Browser, yes, the successor of Internet Explorer. I think Edge has a lot of similar stuff with Chrome and the scrollbar is no different. Edge still has a wide scrollbar, but the borders are rounded which gives like a Firefox feeling. I really like, but I think could be better if were a little thinner. <Img src="https://github.com/fescherer/blog/assets/62115215/64badb1a-3fb8-4174-8c73-ba4222560296" name="Edge default scrollbar" alt="Gif showing the default behavior scrollbar in Edge" /> ## Mobile In mobile we have a little different problem. In my opinion mobile, the scrollbar can have the same problems above depending on which mobile browser you are, but with additional that scrollbars are only shown if you are actually scrolling, how I am supposed to know if that container has scroll if does not have a scrollbar? ## Objectives In this article I gonna show you how you can make your scrollbars aesthetic as can be in many different browsers, only using CSS. I am already warning you that is not possible to make like a reset to them, like we have done to `h1`, `p` and so on. CSS has its limitations and to achieve the fully goal probably will you need some Javascript code or maybe create all the logic with it. The method I am gonna show you is relative simple and can works on most browsers like Mozilla Firefox, Google Chrome, Brave, Opera GX, Edge and Safari, there will be an image with properties browser support in the end of the article. I think that's enough of talk, let's code. ## Solution First, please, do not ever style the main scrollbar. This is not standard, this do not need to follow your layout, it's good to look native to users do get lost. I think is good to style your scrollbars inside something you created, because this is "part" of your layout, different from the main scrollbar that is "part" of browser's layout. Did get it? Well, for the solution, I searched a lot and got really frustrated when finding out the perfect solution do not exist, but we can came to a really nice result. Most of the sites uses some kind of Javascript or very difficult CSS approaches, so I filtered out the really necessary styles and merge them in a class `styled-scrollbars` you can use in the overflowing container. Most of these styles were gotten from [Reddit's aside menu](https://www.reddit.com). ## CSS code There is no error, we gonna use two properties for Firefox (`scrollbar-color` and `scrollbar-width`) and some webkit for Chromium's browsers. ``` css /* Firefox Only */ /* Approaches mobile first, because here, the scrollbar-color will be set and always will be that color, but on desktop, that we have hover effect, we can give a transparent color, but how this is mobile first, we give the color here, and treat the desktop in other style */ .styled-scrollbars { scrollbar-color: var(--some-really-nice-color-here); scrollbar-width: thin; } /* Chrome and others Browsers */ .styled-scrollbars::-webkit-scrollbar { width: 4px; height: 4px } /* Chrome and others Browsers */ .styled-scrollbars::-webkit-scrollbar-track { background: transparent; } /* With device has hover (Desktop or TV, etc) give a little effect on hover */ @media (hover: hover) { .styled-scrollbars { scrollbar-color: var(--some-really-nice-color-here-not-hover) transparent ; scrollbar-width: thin; border-radius: 8px; transition: cubic-bezier(0.165, 0.84, 0.44, 1) 500ms all ; } .styled-scrollbars:hover { scrollbar-color: var(--some-really-nice-color-here) transparent } .styled-scrollbars:hover::-webkit-scrollbar-thumb { background: var(--some-really-nice-color-here); border-radius: 8px; -ms-overflow-style: none; scrollbar-width: thin; } } ``` To find the browser's support, please look at: - [webkit-scrollbar](https://developer.mozilla.org/en-US/docs/Web/CSS/::-webkit-scrollbar) - [scrollbar-color](https://developer.mozilla.org/en-US/docs/Web/CSS/scrollbar-color) - [scrollbar-width](https://developer.mozilla.org/en-US/docs/Web/CSS/scrollbar-width) ## Final results <Img src="https://github.com/fescherer/blog/assets/62115215/4af5a2b1-b06a-444d-a135-3b5f85472089" name="Mozilla Firefox" alt="Gif showing the result of aesthetic scrollbar in Firefox" /> <Img src="https://github.com/fescherer/blog/assets/62115215/24d9ca86-69a8-4335-9dea-b68f0278701d" name="Chrome" alt="Gif showing the result of aesthetic scrollbar in Chrome" /> <Img src="https://github.com/fescherer/blog/assets/62115215/9e114c2b-06ca-459b-aa95-aecc4b02e57d" name="Edge" alt="Gif showing the result of aesthetic scrollbar in Edge" /> ## Additional tips One very interesting stuff I found by searching content for this article is a solution for components that has a special css for hovering effects, is to use `media query hover` to only enable this on hover support devices. You can checkout the [full video by the master of CSS Kevin Powell](https://www.youtube.com/watch?v=uuluAyw9AI0). I highly recommend. ## Conclusion In this article we saw a very clean way, consistent and CSS only to style your scrollbars to be aesthetic as possible between many different browsers like Mozilla Firefox, Google Chrome, Brave, Opera GX, Edge and Safari. Of course this approach is not 100% effective in all platforms, but works on most of them. Have a nice day. 😎✨✨✨😎

7 minutes read

12 must have VSCode extensions

VSCode is one of the most popular IDE's for coding everything from Java to Javascript. VSCode is super customizable and for that the community created a lot of custom extensions for VSCode. That's what we will cover in this article. ## Extensions.json This is a file you can add to `.vscode` folder and configure a set of extensions that are recommended by VSCode if the user don't have them. ## 1. VSCode Eslint <Img src="https://github.com/fescherer/blog/assets/62115215/be8bd7f5-b4f1-40c7-9974-290068604da3" name="VSCode Eslint" alt="Print showing VSCode Eslint extension" /> [As the doc says](https://eslint.org/docs/latest/use/getting-started): <Blockquote cite="https://eslint.org/docs/latest/use/getting-started"> Eslint is a tool for identifying and reporting on patterns found in ECMAScript/JavaScript code </Blockquote> This means that its goal is to be a tool to enforce certain patterns that we can consider "Good practices" or just avoid errors and bad syntaxes. This is possible by using a big set of rules that are completely customizable, and with just one line you can turn on or off the rules that you prefer and of course there are a lot of custom rules made by the community that in addition to add more validation to Javascript, also makes an integration to other stuff you may have like [React](https://www.npmjs.com/package/eslint-plugin-React), [TailwindCSS](https://www.npmjs.com/package/eslint-plugin-tailwindcss), [Typescript](https://typescript-eslint.io) and many more. So Eslint is very good but why do I need the extension? Well, you can run `npx eslint .` every time to check if Eslint got any error or warning, but if you want something more fast and easy to do, and trust me, you do, [installing the extension](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint) allows Eslint to run parallel while coding, ensuring that the error will be shown as you code. **Link for download**: [VSCode Eslint](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint) ## 2. Git Lens <Img src="https://github.com/fescherer/blog/assets/62115215/5a918dda-768d-40ae-b1aa-7baf01632f11" name="Git Lens" alt="Print showing Git Lens extension" /> Have you ever code with a partner? A friend, co-worker or relative and found a line with a very serious bug and needed went to Github to found how made that line? Well, with Git Lens solves your problem by adding a little hint of who made the last update to that line and in how much time ago. I can tell you must be thinking. How this is so useful? For me, it can be handy to have, you may forgot the extension installed but at some time I can assure you will use. Not only for to know the person how did change the line, but also to know when was the last time that line was updated. I know Git Lens offers other uses, but for my necessities this is good enough. You can read more about it [here](https://www.gitkraken.com/gitlens). **Link for download**: [Git Lens](https://marketplace.visualstudio.com/items?itemName=eamodio.gitlens) ## 3. Editor Config <Img src="https://github.com/fescherer/blog/assets/62115215/433781d2-df06-44ee-a87c-0399dd640e7e" name="Editor Config" alt="Print showing Editor Config extension" /> [Editor config](https://editorconfig.org) is a set of configurations that can maintain consistent coding across multiple IDEs, the configurations are basically about indentations, file formats, charset, unix style new lines, etc. This extensions enables to overwrite vscode configurations with the ones set on `.editorconfig` file. I always like to config this file instead my vscode because this way I know the code will be more consistent across multiple IDEs. **Link for download**: [Editor Config](https://marketplace.visualstudio.com/items?itemName=EditorConfig.EditorConfig) ## 4. Print showing Code Snapshot extension <Img src="https://github.com/fescherer/blog/assets/62115215/9fe14a53-fdf7-4849-b417-7ad969150b72" name="Code Snapshot" alt="Print showing Code Snapshot extension" /> I confess that Code Snapshot is not a super must have extension, but it is really nice and works really well. It can take screenshots from your code in MacOS style for you to post anywhere you want, like in a social media. **Link for download**: [Code Snapshot](https://marketplace.visualstudio.com/items?itemName=robertz.code-snapshot) ## 5. VSCode Icons <Img src="https://github.com/fescherer/blog/assets/62115215/f310c814-9f83-4752-a1a6-d21c8e9be2e2" name="VSCode Icons" alt="Print showing VSCode Icons extension" /> This one has a lot of my opinion, but I really think you should have an extension to modify your icons. It help so much when finding that specific file, I always go for the icon first instead of the file extension or the name of it. **Link for download**: [VSCode Icons](https://marketplace.visualstudio.com/items?itemName=vscode-icons-team.vscode-icons) ## 6. Import Cost <Img src="https://github.com/fescherer/blog/assets/62115215/80b88259-d63e-4233-b75d-32881818b14b" name="Import Cost" alt="Print showing Import Cost extension" /> One of the most important thing we as developer need to understand is how our site can be found by search engines like Google or Bing, and one thing I see a lot is a very large [First Contentful Paint(FCP)](https://web.dev/fcp). This is basically the time when the first render of page ends and this is [crucial for user experience](https://web.dev/fcp/#what-is-a-good-fcp-score), a bad time may result in user leaving your page. One of the strategies to decrease FCP time is the only first load the necessary and after you can load the small pieces like an api call. And this can be achieved by removing all the big bundles inside your project. The [Import Cost extension](https://marketplace.visualstudio.com/items?itemName=wix.vscode-import-cost) helps you to do that by showing the bundle size of that lib and then you can or remove it or search for a lighter lib. **Link for download**: [Import Cost](https://marketplace.visualstudio.com/items?itemName=wix.vscode-import-cost) ## 7. Markdown All in One and MDX <Img src="https://github.com/fescherer/blog/assets/62115215/53dd13aa-8bef-4898-9604-45bf2d875d79" name="MDX extension" alt="Print showing MDX extension" /> <Img src="https://github.com/fescherer/blog/assets/62115215/61d48f6d-a3bb-419a-bc6b-f0952582bd7d" name="A markdown file" alt="Print showing markdown file" /> In this topic I will put two extensions because I know not everyone is a React developer and uses [MDX](https://marketplace.visualstudio.com/items?itemName=unifiedjs.vscode-mdx) files as I use, so it is more reasonable for these people use [Markdown All in One](https://marketplace.visualstudio.com/items?itemName=yzhang.markdown-all-in-one) that gives all the essential stuff to have a great time writing your files. For React developers I suggest using [MDX](https://mdxjs.com), a superset of Markdown allowing to use React component inside Markdown. It is super handful and as I see, MDX is becoming a popular way to write Markdown in [NextJS](https://nextjs.org/docs/app/building-your-application/configuring/mdx). You can even use [Content layer](https://contentlayer.dev/docs/sources/files/mdx-d747e46d) to type your Markdown, if that's not fantastic I don't know what is. **Link for download**: [Markdown All in One](https://marketplace.visualstudio.com/items?itemName=yzhang.markdown-all-in-one) **Link for download**: [MDX](https://marketplace.visualstudio.com/items?itemName=unifiedjs.vscode-mdx) ## 8. Code Spell Checker <Img src="https://github.com/fescherer/blog/assets/62115215/fd817aa8-e864-4a55-98a9-8844c359cd9e" name="Code Spell Checker" alt="Print showing Code Spell Checker extension" /> Again, if you write files Markdown or anything that will probably be useful to have a grammar corrector and this extension is just like that. **Link for download**: [Code Spell Checker](https://marketplace.visualstudio.com/items?itemName=streetsidesoftware.code-spell-checker) ## 9. Auto Rename Tag <Img src="https://github.com/fescherer/blog/assets/62115215/10594378-40dd-419a-8ff6-9c38c2ec95e0" name="Auto Rename Tag" alt="Print showing Auto Rename Tag extension" /> One of the most useful extension I use is Auto Rename Tag, this as the name says, when change the tag name, the matching one will be changed too. **Link for download**: [Auto Rename Tag](https://marketplace.visualstudio.com/items?itemName=formulahendry.auto-rename-tag) ## 10. Themes <Img src="https://github.com/fescherer/blog/assets/62115215/effc88d1-7a25-40a3-b2b4-2c5f02c1d93f" name="Dracula Theme" alt="Print showing Dracula Theme" /> In number 10 I will put a more vast collection of extensions used to change the VSCode appearance, of course I am talking about [themes](https://vscodethemes.com/). There are a lot and I mean A LOT of available themes that can change the most different aspects, but most likely the colors, you can find a more lighter, darker, greener, yellowish and many more themes. If you want a recommendation, I would certain suggest to use [Dracula Theme](https://marketplace.visualstudio.com/items?itemName=dracula-theme.theme-dracula), it is one of most famous themes out there with more than 5 million installs. The colors are great even for dark environments or bright environments. **Link for download**: [Dracula Theme](https://marketplace.visualstudio.com/items?itemName=dracula-theme.theme-dracula) ## 11. Extra ones Well, for last I would suggest you to install the extension useful for what you are using to code, like if you are using [TailwindCSS](https://tailwindcss.com), please use the [TailwindCSS extension](https://marketplace.visualstudio.com/items?itemName=bradlc.vscode-tailwindcss), and this can be applied to everything in your project, [Styled Components](https://marketplace.visualstudio.com/items?itemName=styled-components.vscode-styled-components) or even other language than Javascript like [Python](https://www.python.org) VSCode has the extension [Python for VSCode](https://marketplace.visualstudio.com/items?itemName=ms-python.python). So have a look what you have installed and search if has an extension that could help you. 😊 ## Conclusion Conclusion reading this article you were introduced to a set of VSCode extensions that can help improve your coding time and quality. All of that are free and can be downloaded from [Microsoft VSCode MarketPlace](https://marketplace.visualstudio.com). Thank you for reading and see you in the next article. Have a nice day. 😎✨✨✨😎

7 minutes read

How to create morse code translator

Did you know what is morse code? It is a method of communication using short and long signals that are common represented as dots and dashes. Developed to transmit human language to math language and as only translate letters it became and international standard. ## Short Answer To create a morse code encrypter and decrypter you have two methods. One can use the [ASCII table](https://www.lookuptables.com/text/ascii-table) as described in this [answer of Stackoverflow](https://stackoverflow.com/a/26059284). But my preferred way is making a dictionary mapping all valid characters, which would be letters A from Z, number 0 to 9 and a blank space to separate words, anything else would be `undefined` and you can handle as you want. 1. Create a dictionary containing all valid characters: ```typescript const dictionary = { 'a': '.-', 'b': '-...', 'c': '-.-.', 'd': '-..', 'e': '.', 'f': '..-.', 'g': '--.', 'h': '....', 'i': '..', 'j': '.---', 'k': '-.-', 'l': '.-..', 'm': '--', 'n': '-.', 'o': '---', 'p': '.--.', 'q': '--.-', 'r': '.-.', 's': '...', 't': '-', 'u': '..-', 'v': '...-', 'w': '.--', 'x': '-..-', 'y': '-.--', 'z': '--..', '1': '.----', '2': '..---', '3': '...--', '4': '....-', '5': '.....', '6': '-....', '7': '--...', '8': '---..', '9': '----.', '0': '-----', ' ': '/' } ``` 2. Add function to transform letters into morse code: ```typescript function transformToMorse(rawText: string) { return rawText.split('').map(letter => dictionary[letter.toLowerCase()]).join(' ') } ``` --- ## Long Answer ### What is morse code? Morse code was created by [Samuel Morse](https://en.wikipedia.org/wiki/Samuel_Morse) and [Alfred Vail](https://en.wikipedia.org/wiki/Alfred_Vail). It is a method to encode human words characters into just short and long sequences that can be anything from lights, sounds, smoke, anything you can make a short or long signal can be used to represent any word or number from *a-z* and *0-9*. It became very popular in telegraph - grandfather of communication that used morse code to transmit messages from short and long bip. They even had a profession to people hearing and translating the messages- [telegraphist](https://en.wikipedia.org/wiki/Telegraphist). Morse code works by using a [sequence of short or long signal](https://en.wikipedia.org/wiki/Morse_code) to represent one letter/number. For example, the letter **t** can be represent by a long signal **-**, but the letter **g** is two long signal and one short signal **--.**. With this you can make a very good system of communication to transform human language into natural language. It's also very popular on pop culture as almost every riddle movie has a part using morse to encrypt or decrypt some kind of message. ### Alphabet |Character | Morse Equivalent| |----|----| | 0 | ----- | | 1 | .---- | | 2 | ..--- | | 3 | ...-- | | 4 | ....- | | 5 | ..... | | 6 | -.... | | 7 | --... | | 8 | ---.. | | 9 | ----. | | a | .- | | b | -... | | c | -.-. | | d | -.. | | e | . | | f | ..-. | | g | --. | | h | .... | | i | .. | | j | .--- | | k | -.- | | l | .-.. | | m | -- | | n | -. | | o | --- | | p | .--. | | q | --.- | | r | .-. | | s | ... | | t | - | | u | ..- | | v | ...- | | w | .-- | | x | -..- | | y | -.-- | | z | --.. | ### Google learn morse If you stay curious to learn more about morse code, I highly recommend you try [Google's morse learn](https://morse.withgoogle.com/learn). They use images to help us remember the letters. <Img src="https://github.com/fescherer/blog/assets/62115215/65e73bb9-c4a8-4316-9391-a001b0d77d2a" source="https://kpronline.com/blog/learn-morse-code-with-the-morse-typing-trainer" name="Code cues used in the Morse Typing Trainer" alt="List of all codes cues used in morse typing trainer" /> ### Javascript/Typescript functions To create a morse code encrypter and decrypter you have two methods. - Using ASCII table You can use the [ASCII table](https://www.lookuptables.com/text/ascii-table) as described in this [answer of Stackoverflow](https://stackoverflow.com/a/26059284). By knowing that ASCII table characters *a - z* goes from *97* to *122* and numbers *0 - 9* goes from *48* to *57* you can do something like this. 1. First create 2 arrays containing the characters and one constant for the space. ```typescript // Characters in order A - Z and 0 - 9 const charactersAZ = ['.-', '-...','-.-.','-..','.','..-.','--.','....','..','.---','-.-','.-..','--','-.','---','.--.','--.-','.-.','...','-','..-','...-','.--','-..-','-.--','--..'] const numbers09 = ['-----', '.----', '..---', '...--', '....-', '.....', '-....', '--...', '---..', '----.'] const characterSpace = '/' ``` 2. Now you need to remove all weird characters that does not have an index on our arrays ```typescript function cleanRawText(rawText: string) { return rawText.toLowerCase().replace(/[^a-z0-9\s]/g, ""); } ``` 3. Finally make a function to return the encrypted character. ```typescript const isNumberRegex = /^\d+$/ function transformToMorse(rawText: string) { const formatText = cleanRawText(rawText); return formatText.split('').map(letter => { if(letter === " ") return characterSpace; asciiCode = letter.charCodeAt(letter); if(isNumberRegex.test(letter)) return numbers09[asciiCode - 48]; else return charactersAZ[asciiCode - 97]; }).join(' '); } ``` 4. Test the functions ```typescript transformToMorse('Hello world') // result .... . .-.. .-.. --- / .-- --- .-. .-.. -.. ``` -Using dictionary My preferred way is making a dictionary mapping all valid characters, which would be letters A from Z, number 0 to 9 and a blank space to separate words, anything else would be `undefined` and you can handle as you want. 1. Create a dictionary containing all valid characters: ```typescript const dictionary = { 'a': '.-', 'b': '-...', 'c': '-.-.', 'd': '-..', 'e': '.', 'f': '..-.', 'g': '--.', 'h': '....', 'i': '..', 'j': '.---', 'k': '-.-', 'l': '.-..', 'm': '--', 'n': '-.', 'o': '---', 'p': '.--.', 'q': '--.-', 'r': '.-.', 's': '...', 't': '-', 'u': '..-', 'v': '...-', 'w': '.--', 'x': '-..-', 'y': '-.--', 'z': '--..', '0': '-----', '1': '.----', '2': '..---', '3': '...--', '4': '....-', '5': '.....', '6': '-....', '7': '--...', '8': '---..', '9': '----.', ' ': '/' } ``` 2. Add function to transform letters into morse code: ```typescript function transformToMorse(rawText: string) { return rawText.split('').map(letter => dictionary[letter.toLowerCase()]).join(' ') } ``` 3. Test it ```typescript transformToMorse('Hello world') // result .... . .-.. .-.. --- / .-- --- .-. .-.. -.. ``` Which one of them should I choose? Well, I think is up to you, personally I will not go to performance side because both has `map` method and the others doesn't make that much difference. I would choose based on readability as the first one the arrays seems a bit confusing and object making a dictionary seems much more readable for me. Okay, but this is only an encrypter, where is the decrypter? For this, just invert the logic, make a dictionary containing morse code as keys, letters with values and the backslash for white space. ### Bonus: UI - NextJS - Tailwind This article only shows how to convert, but not how to create an application with these logics. I'am gonna leave this for you to create a design. I personally recommend to create a [NextJS](https://nextjs.org/docs/getting-started/installation) project with [TailwindCSS](https://tailwindcss.com/docs/installation) for styling and [Vercel](https://vercel.com) as free host. [You can checkout the source code to get inspired](https://github.com/fescherer/morse-secret-scripter) <Img src="https://github.com/fescherer/blog/assets/62115215/e3c04fd3-5140-484a-8063-541abe46f66f" source="https://morse-secret-scripter.felipescherer.com" name="Morse secret scripter home page" alt="Home page of morse secret scripter containing input and output text areas for encrypt and decrypt" /> ### Conclusion In this article you learnt the history of morse code and how to create simple functions to translate/encrypt/decrypt morse code using Javascript/Typescript. Feel free to leave any suggestions, corrections and tips. Thank you for reading and see you in the next article. Have a nice day. 😎✨✨✨😎