Building and Operating a Design System Using Chakra UI, ShadCN, and Material UI
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
- Example:
- Custom naming conventions (
Tailwind CSS,CSS Modules,Emotion, etc.)- Tailwind:
btn-primary,input-label - CSS Modules:
styles.primaryButton
- Tailwind:
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.
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
sxprop - Component-based UI with accessibility in mind
- Easy theme customization for styles
- Rich official components that speed up development
- Intuitive style definition using the
- Advantages
- Installing
@chakra-ui/reactprovides basic components out of the box - Responsive design is considered by default
- Easy to maintain design consistency through theme customization
- Installing
- Disadvantages
- Component styles are unique to
Chakra, so freedom is somewhat limited - Not suited to utility-first design like Tailwind
- Component styles are unique to
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/systemforCSS-in-JSstyling - Using MUI X gives access to advanced table and data grid features
- Faithfully reproduces Google’s
- 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-heightandletter-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
- Use tools such as
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/Arrowkeys - Set
tabindexappropriately 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
labelwithforandid -
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
altattribute appropriately -
Attach appropriate
labels to form elements -
Improve visibility of
focusandhover
Improve Visibility of focus and hover
- Provide visual feedback on focus
- Clarify styles with
:focus-visibleand: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.
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 ofimports (standard modules, external libraries, internal modules)import/no-unresolved: Prevents unresolvedimportsimport/no-duplicates: Detects duplicateimports
② 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 validhrefsjsx-a11y/no-noninteractive-element-interactions: Whether non-interactive elements such asdivhave event handlersjsx-a11y/alt-text: Whether images have appropriatealtattributes
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 CSStailwindcss/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
80automatically 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
{
"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.
- Run from the command line
npx prettier --write .
- With
--write, target files are formatted and overwritten.
- 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: trueautomatically 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
- BEM (e.g.,
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
-
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.
-
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.
Questions about this article 📝
If you have any questions or feedback about the content, please feel free to contact us.Go to inquiry form
Related Articles
Chat App (with Image/PDF Sending and Video Call Features)
2024/07/15Practical Component Design Guide with React × Tailwind CSS × Emotion: The Optimal Approach to Design Systems, State Management, and Reusability
2024/11/22Management Dashboard Features (Graph Display, Data Import)
2024/06/02ESLint / Prettier Introduction Guide: Thorough Explanation from Husky, CI/CD Integration, to Visualizing Code Quality
2024/02/12Tutorial for Implementing Authentication with Next.js and Auth.js
2024/09/13Implementation guide for building an account registration screen with Tailwind CSS and shadcn (Next.js compatible)
2024/01/20How to Create a Top Page in Next.js 14 and Implement Navigation to Login and Account Registration Screens
2024/01/11Frontend Test Automation Strategy: Optimizing Unit, E2E, and API Tests with Jest, Playwright, and MSW
2024/01/21