Building and Operating a Design System Using Chakra UI, ShadCN, and Material UI

  • shadcn
    shadcn
  • materialui
    materialui
  • prettier
    prettier
  • tailwindcss
    tailwindcss
  • storybook
    storybook
  • css
    css
Published on 2024/03/12

Introduction

In recent years, the importance of design systems has increased, and many companies and projects have begun adopting them. To maintain consistency between design and development and realize a scalable UI, appropriate design and operation are essential.

This article explains concrete methods for building and operating a design system. In particular, while leveraging UI frameworks such as Chakra UI, ShadCN, and Material UI, it introduces practical approaches that are useful in real-world projects. The goal is to provide valuable information for those who are considering introducing a design system and for those who want to further refine an existing system.

Defining Design System Requirements and Creating Application Guidelines

A design system is a framework that provides a unified UI/UX and facilitates smooth collaboration between designers and engineers. By defining requirements and formulating application guidelines, you can ensure the system’s consistency and extensibility.

What is a Design System?

A design system is a mechanism for unifying a product’s UI (user interface) and UX (user experience) and improving the efficiency of development and design.
In general, it includes the following elements:

  • UI component library
    Buttons, forms, cards, modals, and other shared components
  • Style guide
    Rules for using colors, typography, spacing, and icons
  • Pattern library
    UX patterns such as navigation, search, and form validation
  • Brand guidelines
    Logo, tone & manner, and accessibility standards
  • Documentation
    Application rules that designers and engineers can reference

Purpose of a Design System

“Providing a unified UI/UX” means solving the following issues:

  • Consistent design
    • Prevents appearance and behavior from becoming inconsistent within a product
    • For example, prevents the same button from having different designs on different pages
  • More efficient development and design
    • Reusing predefined components prevents duplicated work
    • Communication between designers and engineers becomes smoother (reduces discussions like “How should we design this button?”)
  • Improved UX
    • Provides a unified experience so users can operate without confusion
    • For example, if form error messages differ from screen to screen, users become confused

Who Uses It?

Because multiple roles are involved in a design system, you need to clarify each role and design it so that it is easy to apply.

  • Designers
    • Maintain consistency in UI design
    • Manage components in design tools such as Figma or Sketch
    • Drive improvements in visuals and UX
  • Frontend engineers
    • Implement components in frameworks such as React, Next.js, and Vue
    • Develop reusable UI components
    • Style design (Tailwind CSS, Emotion, Material-UI, etc.)
  • Product managers
    • Ensure the design system aligns with the overall product vision
    • Support specification definition and rollout planning

Points to consider at design time

  • Introduce according to the team’s skill set (for highly skilled development teams or designed to be easy for beginners to apply)
  • In small teams, avoid overly complex designs and apply simple rules

Which Projects Should It Be Applied To?

Clarifying the scope of application of the design system increases its practicality.

  • Can it be used in small-scale projects?
    • YES: Provide a simple component set to improve development efficiency
    • NO: Specialize for large-scale projects; may become overhead for small ones
  • Can it be shared across multiple platforms (Web, Mobile)?
    • Web: Frontend frameworks such as React and Vue
    • Mobile: Consider whether it can be reused with React Native, Flutter, etc.
  • Points of unification
    • Unify the design language of UI components (Material Design, Fluent UI, etc.)
    • Leverage component libraries that can be used on both mobile and web (MUI, Chakra UI, etc.)

Defining Core Components

Define the components that form the core of the design system and formulate application rules.

  • Buttons

    • Variations such as primary, secondary, and icon buttons
    • Sizes (small, medium, large)
    • Interactions (styles on hover, focus, and click)
  • Input forms (Input, Select, Checkbox, Radio)

    • Unified validation rules (how to display error messages, etc.)
    • Unified design (borders, placeholders, behavior on focus)
  • Modals (Modal, Dialog)

    • Distinguish between full-screen modals and partial modals
    • Background overlay handling and accessibility support (keyboard navigation)
  • Component application rules

    • Clarify usage scenarios for components (e.g., only use primary color for CTA buttons)
    • Unify styles (use Tailwind CSS custom classes and CSS variables)

Organizing Guidelines

To operate a design system properly, you need to manage components and organize documentation.

1. Component Naming Conventions

  • BEM (Block, Element, Modifier)
    • Example: .button--primary, .input__label
  • Custom naming conventions (Tailwind CSS, CSS Modules, Emotion, etc.)
    • Tailwind: btn-primary, input-label
    • CSS Modules: styles.primaryButton

2. Managing Components with Figma / Storybook

  • Figma
    • Turn design components into a library
    • Define component variants (size, color, state)
  • Storybook
    • Component catalog for frontend engineers
    • Document component behavior (explanation of Props, interaction tests)

3. Creating Documentation

  • Share information with tools such as Notion / Confluence
    • Clearly state the basic policy of the design system and the introduction guide
    • Publish FAQs to support smooth adoption
  • README / API documentation
    • List component props and usage examples
    • Describe how to customize and extend components

Designing and Implementing UI Components

By incorporating the concept of Atomic Design into UI component design and implementation, you can improve scalability and maintainability. In addition, by using Next.js + Tailwind CSS + ShadCN, you can efficiently create modern, polished components. Furthermore, using Storybook makes it easy to visualize and manage components and facilitates collaboration between designers and developers.

Using Atomic Design

By incorporating the concept of Atomic Design into component design, you can build components that are easy to manage and highly reusable.

Component Classification

1. Atoms

  • The smallest units of UI (e.g., buttons, input fields, icons)
  • Highly reusable and building blocks for other components
    import { cn } from "@/lib/utils";
    
    export const Button = ({ 
      children,
      className 
    }: { 
      children: React.ReactNode
      className?: string 
    }) => {
      return <button className={cn("px-4 py-2 rounded-md bg-blue-500 text-white", className)}
        >{children}
      </button>;
    };
    

2. Molecules

  • Small UI components composed of atoms (e.g., search bar, form group)
    import { Input } from "@/components/ui/input";
    import { Button } from "@/components/ui/button";
    
    export const SearchBar = () => {
      return (
        <div className="flex space-x-2">
          <Input type="text" placeholder="Search..." />
          <Button>Search</Button>
        </div>
      );
    };
    

3. Organisms

  • Larger UI components within a page composed of molecules and atoms (e.g., header, navigation)
    import { SearchBar } from "@/components/molecules/SearchBar";
    
    export const Header = () => {
      return (
        <header className="flex justify-between items-center p-4 bg-gray-800 text-white">
          <h1 className="text-lg font-bold">Site Name</h1>
          <SearchBar />
        </header>
      );
    };
    

4. Templates

  • Define the basic page layout structure by placing organisms (e.g., two-column layout, dashboard frame)
    import { Header } from "@/components/organisms/Header";
    
    export const MainLayout = ({ 
      children 
    }: { 
      children: React.ReactNode 
    }) => {
      return (
        <div>
          <Header />
          <main className="p-4">{children}</main>
        </div>
      );
    };
    

5. Pages

  • Complete screens by embedding actual data and content into templates
    import { MainLayout } from "@/components/templates/MainLayout";
    
    const HomePage = () => {
      return (
        <MainLayout>
          <h2>Hello!</h2>
          <p>Atomic Design is being utilized.</p>
        </MainLayout>
      );
    };
    
    export default HomePage;
    

Example of Component Implementation with Next.js + Tailwind CSS + ShadCN

Combining Next.js and Tailwind CSS enables flexible UI design, and using ShadCN allows you to easily implement modern designs.

Setting Up ShadCN UI

To introduce ShadCN, run the following command:

npx shadcn-ui@latest init

Then install the components you need. The example below installs the button component.

npx shadcn-ui@latest add button

Implementation Example: Primary Button

import { Button } from "@/components/ui/button";

export const PrimaryButton = () => {
  return <Button variant="primary">click</Button>;
};

By using ShadCN, you can easily create customizable Button components and continue development while maintaining a unified design.

A tutorial is available that shows how to introduce Shadcn and Tailwind CSS into a Next.js project and actually build a screen. Please refer to it together.

https://shinagawa-web.com/en/blogs/nextjs-tailwind-shadcn-homepage

Managing Components with Storybook

Introducing Storybook makes it easy to visualize components, collaborate with designers, and test the UI.
For example, when developing the PrimaryButton component, you can adjust it while checking variations (differences in color and size) in Storybook.

Setting Up Storybook

npx storybook init

Then create a story file for each component in the stories folder.

Implementation Example: Button Storybook

import type { Meta, StoryObj } from "@storybook/react";
import { PrimaryButton } from "@/components/ui/PrimaryButton";

const meta: Meta<typeof PrimaryButton> = {
  title: "Components/Button",
  component: PrimaryButton,
};

export default meta;

export const Default: StoryObj<typeof PrimaryButton> = {
  args: {},
};

With this configuration, you can check the behavior of the PrimaryButton you created in Storybook.


Introducing UI Frameworks (Using Chakra UI / ShadCN / Material UI)

In frontend development, the choice of UI framework greatly affects development speed, maintainability, and design consistency. This section explains in detail the representative UI frameworks Chakra UI, ShadCN, and Material UI, and compares which types of projects they are suitable for.

Features and Comparison of Each Framework

Framework Features Customizability Main Use Cases
Chakra UI Provides a flexible styling system and component library. Accessibility is considered by default. High Small to medium-sized projects
ShadCN Lightweight and based on Tailwind CSS. Can be built with minimal styles while leveraging design tokens. Very high Projects using Next.js
Material UI Implements Google’s Material Design. Suitable for large-scale development such as enterprise SaaS. High Large-scale projects, enterprise use

Chakra UI

  • Features
    • Intuitive style definition using the sx prop
    • Component-based UI with accessibility in mind
    • Easy theme customization for styles
    • Rich official components that speed up development
  • Advantages
    • Installing @chakra-ui/react provides basic components out of the box
    • Responsive design is considered by default
    • Easy to maintain design consistency through theme customization
  • Disadvantages
    • Component styles are unique to Chakra, so freedom is somewhat limited
    • Not suited to utility-first design like Tailwind

ShadCN

  • Features
    • Built on Tailwind CSS, allowing class-based styling
    • Uses a copy-and-paste approach for required components (code is directly incorporated into the project rather than installed as a package)
    • ShadCN UI (shadcn/ui) leverages Radix UI to provide components with accessibility in mind
  • Advantages
    • Extremely high degree of customization (can fully leverage Tailwind CSS)
    • You can delete unnecessary components to keep bundle size small
    • Simple and highly extensible
  • Disadvantages
    • Does not provide a unified design system like other UI frameworks
    • Has a higher learning cost if you are not familiar with Tailwind CSS
    • Component maintenance is your own responsibility

Material UI

  • Features
    • Faithfully reproduces Google’s Material Design
    • Widely adopted in enterprise SaaS development and enterprise applications
    • Can use @mui/system for CSS-in-JS styling
    • Using MUI X gives access to advanced table and data grid features
  • Advantages
    • Clear design guidelines make it easy to create a consistent UI
    • Rich component set greatly reduces development effort
    • MUI X supports advanced UI requirements
  • Disadvantages
    • Default design is heavily dependent on Material Design, so customization is somewhat cumbersome
    • Components tend to be large in bundle size due to their rich functionality

Choosing the Right UI Framework for Your Project

Selection Criteria

Requirement Recommended UI Framework
Prioritize development speed (intuitive styling) Chakra UI
Fully leverage Tailwind CSS ShadCN
Enterprise SaaS / large-scale development Material UI
Want to keep bundle size small ShadCN
Prioritize accessibility Chakra UI / Material UI
Adopt Google’s Material Design Material UI

Concrete Application Scenarios

  • Small to medium-sized apps where the default design is sufficient
    • Choose Chakra UI
    • Example: ToDo apps, personal projects
  • When using Next.js and wanting highly flexible customization
    • Choose ShadCN
    • Example: SaaS for startups, simple dashboards
  • Enterprise SaaS or enterprise systems
    • Choose Material UI
    • Example: Admin systems, business applications

Strengthening Responsive Design Support

With the spread of smartphones and tablets, the importance of responsive design is increasing. Ensuring that users can comfortably view content from any device is an essential element of web development. This section explains key points and practical methods for strengthening responsive design support.

Properly Setting Breakpoints

To achieve responsive design, it is important to set appropriate breakpoints. Below are examples of common breakpoints:

  • 480px and below: Smartphones
  • 768px and below: Tablets
  • 1024px and below: Small desktops
  • 1200px and above: Large desktops

Use the CSS @media rule to apply appropriate styles.

@media (max-width: 768px) {
  .container {
    flex-direction: column; /* Change layout to vertical when screen width is 768px or less */
  }
}

Designing Flexible Layouts

Instead of fixed-width layouts, use flexbox and grid to design flexible layouts that can adapt to various screen sizes.

Responsive Support Using Flexbox

.container {
  display: flex;
  flex-wrap: wrap;
}
.item {
  flex: 1 1 50%;
}
@media (max-width: 768px) {
  .item {
    flex: 1 1 100%;
  }
}
  • Allow child elements to wrap
  • Set each element’s width to 50%
  • Change elements to a single column when screen width is 768px or less

Responsive Support Using CSS Grid

.grid-container {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 16px;
}
  • Create columns of at least 200px and adjust according to width
  • Set 16px spacing between elements

Optimizing Images

If image sizes are fixed, layouts may break on small screens. Use max-width: 100% so images shrink according to content width.

img {
  max-width: 100%;
  height: auto;
}
  • Match image width to the maximum width of the parent element
  • Maintain aspect ratio

You can also use srcset to provide images of appropriate sizes.

<img src="small.jpg" srcset="medium.jpg 768w, large.jpg 1200w" alt="Responsive image">

This code applies medium.jpg or large.jpg depending on screen width to provide optimally sized images.

Adjusting Font Size

Applying appropriate font sizes for each device improves readability. Using rem or vw is recommended.

body {
  font-size: 16px; /* Default font size */
}
@media (max-width: 768px) {
  body {
    font-size: 14px; /* Reduce font size when screen width is 768px or less */
  }
}

5. Optimizing Navigation

On small screens, adopting navigation such as a hamburger menu can improve usability.

<button class="menu-toggle"></button>
<nav class="nav-menu">
  <ul>
    <li><a href="#">Home</a></li>
    <li><a href="#">About</a></li>
    <li><a href="#">Contact</a></li>
  </ul>
</nav>
.nav-menu {
  display: none;
}
.menu-toggle {
  display: block;
}
@media (min-width: 768px) {
  .nav-menu {
    display: block;
  }
  .menu-toggle {
    display: none;
  }
}
  • Hide the menu by default
  • Show the button for mobile
  • Show the menu when screen width is 768px or more
  • Hide the menu button

6. Setting the Viewport Meta Tag

To apply responsive design, set an appropriate viewport meta tag in the HTML <head>.

<meta name="viewport" content="width=device-width, initial-scale=1">

Setting this tag applies scaling according to device width and allows responsive design to function properly.

Unifying Color Palette, Typography, and Spacing to Enhance Design Consistency

In web and app design, consistent visuals improve user experience and strengthen brand recognition. To achieve this, unifying the color palette, typography, and spacing is crucial. This section explains how each element should be designed and implemented.

Unifying the Color Palette

Selecting Base Colors

The color palette is a key element that determines the impression of a brand or service. First, decide on the following basic colors:

  • Primary color (main brand color)
  • Secondary color (supporting color)
  • Accent color (used for emphasis)
  • Neutral colors (for backgrounds and text)

Color Variations

To unify color variations, prepare versions with adjusted brightness and saturation and use them for the following purposes:

  • Light versions (for backgrounds)
  • Medium versions (for buttons and UI elements)
  • Dark versions (for text and shadows)

Consider Color Contrast

To ensure visibility, be mindful of contrast ratios that meet WCAG (Web Content Accessibility Guidelines) standards.

  • Normal text: 4.5:1 or higher
  • Large text (18px or larger): 3:1 or higher

Defining Color Styles

Use design tools (Figma, Adobe XD, etc.), CSS variables, or Tailwind CSS custom themes to manage unified color styles.

:root {
  --primary-color: #1E90FF;
  --secondary-color: #FFD700;
  --neutral-color: #F5F5F5;
}

Unifying Typography

Choosing Fonts

Fonts are an important element that expresses brand personality. Key points when choosing fonts:

  • Heading font (bold and highly legible)
  • Body font (high readability and easy to read)
  • Monospace font (used when handling code or numbers)

Example:

body {
  font-family: 'Inter', sans-serif;
}
h1, h2, h3 {
  font-family: 'Poppins', sans-serif;
}

Setting Font Sizes and Hierarchy

Set a scale to determine consistent text sizes.

h1 { font-size: 2.5rem; }
h2 { font-size: 2rem; }
h3 { font-size: 1.75rem; }
p { font-size: 1rem; }

Modular Scale

A modular scale is a method for unifying ratios of font sizes and spacing in design. Instead of simple “multiples,” it uses mathematical ratios (e.g., 1.25, 1.414, 1.618) as a basis for determining sizes, creating a well-balanced visual hierarchy.

For example, using a ratio of 1.414 (the silver ratio) and a base size of 16px, you get:

16px × 1.414 ≈ 22.6px
22.6px × 1.414 ≈ 32px
32px × 1.414 ≈ 45px

In CSS, it looks like this:

:root {
  --base-font-size: 16px;
  --scale-ratio: 1.414;
  --h1-size: calc(var(--base-font-size) * var(--scale-ratio) * var(--scale-ratio));
  --h2-size: calc(var(--base-font-size) * var(--scale-ratio));
  --p-size: var(--base-font-size);
}

h1 {
  font-size: var(--h1-size);
}

h2 {
  font-size: var(--h2-size);
}

p {
  font-size: var(--p-size);
}

Using this method creates consistency in font size selection and naturally results in an easy-to-read design.

Main modular scale ratios

  • 1.25 (4:5) - Small size differences, suitable for subtle designs
  • 1.414 (√2) - Also used in print design (A4, A3)
  • 1.618 (golden ratio) - Tends to produce beautiful balance

Adjusting Line Height and Letter Spacing

  • Line height: 1.5–1.75 times is ideal
  • Letter spacing: slightly wider for titles, standard for body text
p {
  line-height: 1.6;
  letter-spacing: 0.02em;
}

Unifying Spacing

Designing Margins and Padding

Setting consistent spacing creates a unified layout.

:root {
  --spacing-xs: 4px;
  --spacing-sm: 8px;
  --spacing-md: 16px;
  --spacing-lg: 24px;
  --spacing-xl: 32px;
}

Unifying padding for buttons and cards maintains overall consistency.

button {
  padding: var(--spacing-md) var(--spacing-lg);
}

Spacing in Responsive Design

  • Mobile: Compact
  • Tablet: Medium spacing
  • Desktop: Generous spacing
.container {
  padding: 16px;
}
@media (min-width: 768px) {
  .container {
    padding: 24px;
  }
}

Design Principles from Material Design / Apple HIG

  • Color palette: Balance between primary and accent colors
  • Typography: Unified line-height and letter-spacing
  • Spacing: Adopt a 4px, 8px, 16px grid system

Implementation Support for Improving Accessibility

Web accessibility is the effort to ensure that all users, regardless of disability, can comfortably use websites and applications. It is especially important to ensure appropriate information delivery and operability for users with limitations in vision, hearing, motor function, or cognitive ability.

Accessibility Checklist

By addressing the following items, you can build an environment that is easier for more users to use.

Appropriate Contrast Ratio (Compliant with WCAG Standards)

  • WCAG (Web Content Accessibility Guidelines) 2.1 recommends the following minimum contrast ratios:
    • General text: 4.5:1 or higher
    • Large text (18pt or 14pt bold or larger): 3:1 or higher
    • UI components and graphics: 3:1 or higher
  • Implementation examples
    • Use tools such as color-contrast() to check during the design phase
    • Support dark mode and high-contrast mode

Ensure Keyboard Operability

  • Check that you can navigate the page properly using only the Tab key without a mouse
  • Ensure operations can be performed with Enter / Space / Arrow keys
  • Set tabindex appropriately to control focus order
    <button onClick={handleClick} tabIndex="0">click</button>
    

Set ARIA Attributes Appropriately

  • Use aria-label and aria-labelledby to improve navigation with screen readers
  • Specify the role attribute appropriately to clarify the intent of components
  • Implementation example
    <button aria-label="Open menu"></button>
    

Test Operation with Screen Readers

  • Use NVDA (Windows) or VoiceOver (Mac) to check whether information is conveyed properly via speech
  • Use aria-live to notify updates to dynamic content
  • Implementation example
    <div aria-live="polite">You have new messages</div>
    

Implementation Techniques

Set the alt Attribute Appropriately

  • Specify the alt attribute for images and provide an appropriate description
  • For decorative images, specify alt="" so that screen readers do not read them
  • Implementation example
    <img src="logo.png" alt="Company Logo" />
    

Attach Appropriate Labels to Form Elements

  • Associate label with for and id

  • Set clear labels instead of relying only on placeholders

  • Implementation example

    <label for="email">Email Address</label>
    <input type="email" id="email" name="email" required />
    
  • Set the alt attribute appropriately

  • Attach appropriate labels to form elements

  • Improve visibility of focus and hover

Improve Visibility of focus and hover

  • Provide visual feedback on focus
  • Clarify styles with :focus-visible and :hover
  • Implementation example
    button:focus-visible {
      outline: 2px solid #005fcc;
      outline-offset: 2px;
    }
    

Organizing Code Style

Maintaining consistent code style and design is essential for improving development efficiency and readability and for smooth communication in team development. This section delves into concrete methods.

ESLint (Static Code Analysis)

ESLint is a tool that statically analyzes JavaScript and TypeScript code to detect potential errors and style inconsistencies.
It helps developers adhere to coding conventions and prevent bugs in advance.

Main Features

  • Static analysis: Detects problems without executing code
  • Customizable rule sets: Can set styles for each project
  • Plugin extensions: Can add rules for specific purposes such as React, TypeScript, and accessibility
  • Auto-fix (--fix): Automatically fixes simple style issues

How to Configure Rules

Create .eslintrc.js (or .eslintrc.json) in the project root directory and define rules.

.eslintrc.js
module.exports = {
  env: {
    browser: true,
    es2021: true,
  },
  extends: [
    'eslint:recommended',  // Apply ESLint’s recommended rule set
    'plugin:react/recommended',
    'plugin:@typescript-eslint/recommended',
    'prettier'  // Prevent conflicts with Prettier
  ],
  parser: '@typescript-eslint/parser',
  parserOptions: {
    ecmaVersion: 12,
    sourceType: 'module',
  },
  plugins: [
    'react',
    '@typescript-eslint',
    'import',
    'jsx-a11y',
    'tailwindcss',
  ],
  rules: {
    'no-console': 'warn', // Warn when console.log is used
    'no-unused-vars': 'warn', // Warn about unused variables
    'react/prop-types': 'off', // Unnecessary when using TypeScript
    'tailwindcss/no-custom-classname': 'warn', // Check Tailwind CSS naming conventions
  },
};

Representative Customizable Rules

Rule Description Example Setting
no-console Warn or forbid use of console.log "no-console": "warn"
no-unused-vars Warn about unused variables "no-unused-vars": "warn"
eqeqeq Enforce === instead of == "eqeqeq": "error"
max-len Specify maximum characters per line "max-len": ["error", { "code": 100 }]
camelcase Enforce camelCase for variable and function names "camelcase": "error"

Using Plugins

By introducing ESLint plugins, you can apply rules for specific purposes such as React, TypeScript, and accessibility.

① eslint-plugin-import (Unifying import Order)
A plugin for checking and organizing the order of module imports and unused imports.

Install

npm install eslint-plugin-import --save-dev

Configuration Example

module.exports = {
  extends: [
    'eslint:recommended',
    'plugin:import/recommended',
  ],
  rules: {
    'import/order': [
      'error',
      {
        'groups': ['builtin', 'external', 'internal'],
        'alphabetize': { 'order': 'asc', 'caseInsensitive': true }
      }
    ]
  }
};

Items Checked

  • import/order: Order of imports (standard modules, external libraries, internal modules)
  • import/no-unresolved: Prevents unresolved imports
  • import/no-duplicates: Detects duplicate imports

② eslint-plugin-jsx-a11y (Accessibility Checks)

Install

npm install eslint-plugin-jsx-a11y --save-dev

Configuration Example

module.exports = {
  "plugins": ["jsx-a11y"],
  "rules": {
    'jsx-a11y/anchor-is-valid': 'warn', // Warn about invalid `<a>` tags
    'jsx-a11y/no-noninteractive-element-interactions': 'warn' // Warn about event listeners on non-interactive elements
  },
};

Items Checked

  • jsx-a11y/anchor-is-valid: Whether <a> tags have valid hrefs
  • jsx-a11y/no-noninteractive-element-interactions: Whether non-interactive elements such as div have event handlers
  • jsx-a11y/alt-text: Whether images have appropriate alt attributes

You can apply all rules with the following configuration:

{
  "extends": ["plugin:jsx-a11y/recommended"]
}

③ eslint-plugin-tailwindcss (Checking Tailwind CSS Class Order)

Install

npm install eslint-plugin-tailwindcss --save-dev

Configuration Example

module.exports = {
  plugins: ['tailwindcss'],
  rules: {
    'tailwindcss/no-custom-classname': 'warn', // Warn about class names that do not exist in Tailwind CSS
    'tailwindcss/classnames-order': 'warn' // Check class order
  },
};

Items Checked

  • tailwindcss/no-custom-classname: Prevents class names that do not exist in Tailwind CSS
  • tailwindcss/classnames-order: Organizes class order according to official recommendations

Prettier (Unifying Code Formatting)

Prettier is a tool that forcibly unifies code formatting. While ESLint mainly aims at “code quality” and “error checking,” Prettier aims to automatically unify “code style (formatting).”

For example, introducing Prettier unifies differences in formatting as follows:

Before (Inconsistent Code)

function greet(name) {
console.log(  "Hello, " + name  + "!" );
}

After (After Applying Prettier)

function greet(name) {
  console.log("Hello, " + name + "!");
}
  • Unifies indentation (fixes misaligned spaces)
  • Applies double quotes (can be changed by settings)
  • Fixes inappropriate use of spaces

Using Prettier provides the following benefits in team or personal projects:

1. Unifying Indentation and Spaces

  • Prettier unifies code indentation (spaces or tabs) and formats it into a readable form.
  • You can also unify choices such as tab vs space and the number of spaces (e.g., 2 or 4 spaces).

2. Unifying Single vs Double Quotes

  • In JavaScript and TypeScript, both single (') and double (") quotes can be used, but Prettier can unify them across the project.

Before

console.log("Hello, World!"); // Double quotes

After (After Applying Prettier)

console.log('Hello, World!'); // Unified to single quotes

3. Unifying Line Wrapping Rules

  • Automatically breaks long lines at appropriate positions to improve readability.
  • For example, setting printWidth to 80 automatically wraps long lines at 80 characters.

4. Unifying Code Style in Team Development

  • Eliminates review comments such as “spacing is different” or “quotes are inconsistent.”
  • With auto-formatting, developers can focus on logic and design.

Integrating Prettier and ESLint

Prettier unifies code formatting, but ESLint also has some formatting rules. Therefore, ESLint and Prettier rules can conflict.

For example, even if ESLint specifies indent: ["error", 2], if Prettier is set to tabWidth: 4, indentation rules will conflict.

To resolve this conflict, introduce eslint-config-prettier to disable ESLint settings that conflict with Prettier rules.

Install

npm install --save-dev eslint-config-prettier

Configuration Example

{
  "extends": [
    "eslint:recommended",
    "plugin:@typescript-eslint/recommended",
    "prettier"
  ]
}

Configuring Prettier

.prettierrc.json
{
  "printWidth": 100,       // Maximum characters per line
  "tabWidth": 2,           // Number of spaces for indentation
  "useTabs": false,        // Use spaces instead of tabs
  "singleQuote": true,     // Use single quotes
  "semi": false,           // Omit semicolons
  "trailingComma": "all"   // Add trailing commas (unify with ESLint rules)
}

Using Prettier

You can run Prettier from the command line or via an editor plugin.

  1. Run from the command line
npx prettier --write .
  • With --write, target files are formatted and overwritten.
  1. Auto-format in VSCode
    If you enable Prettier in VSCode, files can be auto-formatted on save.
{
  "editor.defaultFormatter": "esbenp.prettier-vscode",
  "editor.formatOnSave": true
}
  • Setting formatOnSave: true automatically runs Prettier when saving files.

Establishing Code Review Rules

In team development, clearly defining code review rules helps maintain consistent quality.

  • Review perspectives

    • Adherence to code style (ESLint/Prettier applied)
    • Consistent component design
    • Reducing redundant code (prevent unnecessary re-renders)
    • Proper use of types (strict typing in TypeScript)
    • Consideration of accessibility (a11y)
  • GitHub pull request operations

    • Prepare a PR description template (what was changed, impact scope, how to verify, etc.)
    • Automatic checks (run ESLint, Prettier, and tests in CI/CD)

Example PR Template

### Changes
- Added xxx feature
- Fixed xxx bug

### How to Verify
1. Run xxx
2. Verify behavior

### Impact Scope
- Affects xxx components
- xxx tests verified

Unifying Component Naming Conventions

Unifying naming conventions improves code readability and searchability.

  • Component naming
    • PascalCase (e.g., UserCard, ProductList)
  • CSS naming
    • BEM (e.g., .card__title, .button--primary)
    • When using Tailwind CSS, write classes directly and keep custom CSS to a minimum

Creating Documentation for Developers and Designers

To enable smooth collaboration between developers and designers and prevent misalignment of understanding, creating appropriate documentation is essential. This section explains the types of necessary documents and key points for creating effective documentation.

Types of Required Documentation

1. Design System Documentation

To maintain design consistency, clearly describe the following information:

  • Color palette
    • Definitions of primary and secondary colors
    • Usage of each color (background, buttons, text, etc.)
    • Color codes (Hex / RGB / HSL)
  • Typography
    • Font families (e.g., Inter, Roboto)
    • Font sizes (headings, body, captions)
    • Line height and letter spacing
  • Component specifications
    • Definitions of components such as buttons, forms, modals, and cards
    • States (hover, active, disabled)
    • Component design examples (managed in Figma or Storybook)

Recommended tools:

  • Figma / Adobe XD: Visualizing designs
  • Storybook: Documenting UI components
  • Zeroheight / Notion: Centralized management of the design system

2. Coding Guidelines

Unify coding practices to improve project readability and maintainability.

  • Formatting
    • Code formatting rules with ESLint / Prettier
    • Indentation (2 spaces or 4 spaces)
  • Directory structure
      /src
        /components   # UI components
        /pages        # Page-level components
        /utils        # Shared functions
        /api          # API communication logic
    
  • Naming conventions
    • Variables: camelCase (userName, fetchData)
    • Components: PascalCase (UserCard, HeaderNav)
    • Functions: camelCase (handleClick, getUserData)
    • Files: kebab-case.tsx (user-card.tsx, fetch-data.ts)

Recommended tools:

  • Notion / Confluence: Sharing coding rules
  • GitHub Wiki: Managing within the repository
  • Husky / lint-staged: Automatically applying code formatting

Key Points for Effective Documentation

  1. Centralized information management

    • If documentation is scattered, it becomes unclear which is the latest and causes confusion.
    • Use tools such as Notion, Confluence, and GitHub Wiki to consolidate information in a place that the team can easily reference.
  2. Regular maintenance

    • Outdated information causes confusion
    • Decide on a review cycle and update regularly (e.g., once a month)
    • Manage change history (use Notion’s version history feature)

Availability Testing and Improving Usability

System availability and usability are important factors that directly affect whether users can use the system smoothly. By properly conducting availability tests and improving usability, you can enhance the system’s reliability and ease of use.

Conducting Availability Testing

Availability testing verifies whether the system continues to operate properly and whether it can recover quickly in the event of a failure. It also includes measures to improve system performance and UX (user experience).

1. Conducting User Tests

Purpose: Observe how actual users use the system and identify issues

Methods:

  • User interviews: Have users use the system and collect feedback
  • Scenario-based testing: Have users execute predefined use cases (e.g., purchasing a product, creating an account) and identify issues
  • Remote testing: Record how users use the system in their actual environment and analyze issues

Points:

  • Collect not only subjective feedback but also behavioral data (where they got stuck)

  • Select appropriate test subjects (users close to the target audience)

  • Record and analyze results and use them for subsequent improvements

  • Conduct user tests to verify actual usage scenarios

  • Use A/B testing to make design and UX improvements based on data

  • Use heatmaps and analytics tools to visualize user behavior

2. Using A/B Testing

Purpose: Compare different designs and features and determine the optimal one for users based on data

Methods:

  • Randomly show two or more versions (A/B) to users and measure which yields better results
  • Compare metrics such as click-through rate, conversion rate, and bounce rate
  • Examples of A/B tests:
    • CTA button color and text (“Purchase” vs “Order Now”)
    • Simplifying form input (reducing steps vs keeping as is)
    • Changing user registration flow (introducing social login vs email-only registration)

Points:

  • Clarify the objective: what you want to improve (e.g., increase conversion rate)
  • Collect sufficient data: secure a statistically significant sample size
  • Change only one element at a time: to clearly identify what caused the effect

3. Using Heatmaps and Analytics Tools

Purpose: Visualize user behavior and identify issues

Tools:

  • Heatmap tools: Visually show where users click and where they stop scrolling (e.g., Hotjar, Crazy Egg)
  • Google Analytics: Analyze page dwell time, bounce rate, and conversion rate
  • Session replay: Record actual user behavior and check how they operate the page

Examples of use:

  • “CTA button is not clicked → Place it in a more prominent position and change its color”
  • “Users drop off midway → Simplify the form”
  • “Low scroll rate → Place important information higher up”

Measures to Improve Usability

Usability refers to whether users can operate intuitively and achieve their goals without stress. Implementing the following measures provides a more comfortable UX.

1. Clear Navigation and Optimized Information Architecture

Purpose: Ensure users can reach their target page without getting lost

Measures:

  • Introduce breadcrumbs: Help users understand their current location
  • Optimize categorization: Group content in a way users can intuitively understand
  • Strengthen search functionality: Add autocomplete and filter features

Points:

  • Too much information causes confusion → Keep the structure simple and easy to understand
  • Make menu labels specific (e.g., “Pricing Plans” instead of “Services”)

2. Feedback for Interactive Elements

Purpose: Provide appropriate feedback for user actions and improve usability

Measures:

  • Change styles on hover: Visually indicate that buttons and links are clickable
  • Loading indicators: Inform users that content is loading (spinner, progress bar)
  • Use animations: Smooth transitions and state changes (e.g., fade-in for modal windows)

Points:

  • Avoid excessive animations (slow behavior causes stress)
  • Visually emphasize clickable elements (use color and shadows)

3. Supporting User Input

Purpose: Reduce the burden of form input and prevent errors

Measures:

  • Use placeholders: e.g., “Example: yourname@example.com”
  • Real-time validation: Show error messages immediately when there is an input mistake
  • Support autofill: Automatic completion of addresses, etc.

Points:

  • Keep forms as short as possible (remove unnecessary fields)
  • Instead of “Input error,” provide specific messages such as “Password must be at least 8 characters”

Conclusion

A design system is not something you create once and finish; it is important to continuously evolve it. By updating and improving it appropriately according to changes in project scale and requirements, it becomes a more valuable system.

By leveraging the methods introduced in this article—using UI frameworks, formulating guidelines, strengthening accessibility, and organizing documentation—try building the optimal design system for your company or project. With continuous improvement and team collaboration, you will be able to provide a more refined UI/UX.

Xでシェア
Facebookでシェア
LinkedInでシェア

Questions about this article 📝

If you have any questions or feedback about the content, please feel free to contact us.
Go to inquiry form