Strapi Series, Part 6: Coming Soon QA

An illustration of a mysterious book of spells with a glowing, arcane symbol on the cover, surrounded by flickering candles and an ominous mist, in the style of dark fantasy art, photorealistic, viewed from a top-down perspective --v 5 --ar 3:2

First things first, I want to swap over to TypeScript. Well, want is a bit strong but I will. One cool thing that I learned from some ChatGPT prompts is that it will essentially document a component for you. I’m not going to paste the whole output here, but I recommend trying something like this, followed by pasting the code:

here is JSX code for a component

I followed up by asking it to convert the component to TypeScript and got what I would expect:

interface ComingSoonProps {
  buttonText?: string;
  inputLabel?: string;
  text?: string;
  title: string;
}

const ComingSoon: FunctionComponent<ComingSoonProps> = ({
  buttonText = 'Notify Me',
  inputLabel = 'Enter your email',
  text,
  title,
}) => {
  ...

I made some small changes, using FC instead of FunctionComponent just for reducing characters. I then installe TypeScript, renamed the file with the .tsx extension, and ran a build to make sure all is well. The styles were missing, so I realized that I needed to add ts, tsx to the tailwind.config.js.

Story Time

The styles were missing in Storybook by default, too. A quick Google search led me to an article with a fix.

Screenshot of a Strapi's UI for content and the code output in the API

Storybook does not work with Tailwind CSS by default. As a result, if we create a React component using Tailwind utility classes and then create a story based on this component, the Tailwind CSS changes will not be reflected in the Storybook environment.

Elijah Asaolu on LogRocket's blog

I wanted to share that article since it gave me the answer to what I’m looking for, but I went to the Storybook docs for adding Tailwind, since I knew it was written before version 7.

I know writing docs are hard, especially for a tool with so many possible implementations. However, this part on what to do with PostCSS is confusing. It has you add @storybook/addon-styling with postCSS set to true, but then there’s a note below. At that point, I wasn’t sure if I even need @storybook/addon-styling, but it seems to work without it.

Note: Using Vite, @storybook/nextjs, or @storybook/preset-create-react-app with react-scripts@2.0.0 and up? You don't need to set postCss to true.

Storybook docs

So Close and Yet…

I’m not sure you’ll be able to see it in the screenshots, but there’s a small difference in the weight of the font. It’s the ever-controversial font-smoothing property, but there are some other classes that could lead to unexpected differences. (This is one of my challenges with Storybook or pure component development. I defer to wanting to replicate the environment in the preview.)

Screenshot of a Strapi's UI for content and the code output in the API

The problem is that the html element doesn’t get the classes that a page in the Next app does.

<html
  class="h-full scroll-smooth bg-white antialiased [font-feature-settings:'ss01'] js-focus-visible"
  lang="en"
  data-js-focus-visible=""
></html>

Most of that is set in the _document.jsx file, the exception being the js-focus-visible which is dynamic. This is the HTML in the Storybook iframe.

<html lang="en"></html>

I didn’t ask the right question for ChatGPT to help here, it wanted to add classes within the component. Google searches won on this one, but again I don’t really understand what they’re saying here.

Unfortunately, the docs are a little weird here again. They say “You can accomplish this by creating a file called preview-body.html inside your .storybook directory and adding tags like this:”

<!--  .storybook/preview-body.html -->

<div id="custom-root"></div>

That outputs a div before the contents of the time and closes it, but I found this workaround.

// preview.js
import React from "react";

export const decorators = [
  (Story) => (
    <div className="new">
      <Story />
    </div>
  ),
];

Boom! We now get a div that wraps the content with the classes that are on the html element in the app.

<div id="story--marketing-comingsoon--base--primary-inner" data-name="Base">
  <div
    class="h-full scroll-smooth bg-white antialiased [font-feature-settings:'ss01']"
  >
    ...
  </div>
</div>

We Can Finally Test The Component!

This felt like another round for ChatGPT, so I asked it to give me 5 versions of each with different lengths. It works really well for these examples, but it feels like overkill to paste them in here.

This is a great example of how challenging creating components that allow for content from a CMS can be. This one is highly restrictive, but character counts provide a wildly different experience, especially when they’re in the title. I think this would be solved with a combination of some styling tweaks and some suggestions in Strapi itself.

Screenshot of a Strapi's UI for content and the code output in the API

My only beef with how this particular one is built is that there is sizable padding by default. It’s especially noticeable in landscape views on small screens. What was built was perfect for the character counts that exist in the original version, but I want some more flexibility. I fixed it up with a minimum of 1 rem padding, using a flex column with a min-height of the screen, and then resetting that when it goes horizontal for the height to adjust by the text at larger screens.

Screenshot of a Strapi's UI for content and the code output in the API

Learning In Two Ways

There’s the learnings of how to work around all of the tooling and the component thinking itself, but this also shows how challenging it is to share this part in a blog post. The screenshots are gonna be lame on mobile unless I divide them all up, but that feels like overkill. I think I will start recording a video for future components, especially for the testing part.

That’ll do it for now, here’s the PR for the changes in this post. Next up, I’ll do a little review of the page to try to plan out some components and see what global changes we’ll want to make before I go component-by-component.

Check out
Front-end conf
we're bringing the conf back in April 2024!
10 speakers across two days, with plenty
of time for conversations