Skip to main content

Tạo trang Accordion giống Wordpress

Docusaurus hỗ trợ tích hợp các component React vào nội dung MDX, vì vậy bạn có thể tạo một "accordion shortcode"
tương tự như trong WordPress bằng cách tự xây dựng một React component.
Dưới đây là các bước cụ thể và ví dụ mã để thực hiện.

Thực tế ta cần làm 3 bước tuần tự dưới đây:

1)Tạo Component Accordion Tạo một file mới (ví dụ: src/components/Accordion.js) với nội dung sau:

import React, { useState } from 'react';
import styles from './Accordion.module.css';

const Accordion = ({ title, children }) => {
  const [isOpen, setIsOpen] = useState(false);

  const toggleAccordion = () => {
    setIsOpen(prev => !prev);
  };

  return (
    <div className={styles.accordion}>
      <button className={styles.accordionButton} onClick={toggleAccordion}>
        {title}
        <span className={styles.icon}>{isOpen ? '-' : '+'}</span>
      </button>
      {isOpen && (
        <div className={styles.accordionContent}>
          {children}
        </div>
      )}
    </div>
  );
};

export default Accordion;

Giải thích:

Dùng hook useState để quản lý trạng thái mở/đóng của accordion. Khi nhấn button (có chứa tiêu đề), trạng thái
sẽ chuyển đổi và hiển thị hoặc ẩn phần nội dung.

2)Tạo File CSS Module Cho Accordion
Tạo file CSS module (ví dụ: src/components/Accordion.module.scss) với nội dung ví dụ sau:

/* Accordion.module.scss */

/* --- Light Mode --- */
.accordion {
    margin-bottom: 1rem;
    border: 1px solid #333;           /* Sử dụng đường viền tối cho độ tương phản tốt */
    border-radius: 8px;
    overflow: hidden;
    background-color: #ffffff;        /* Nền trắng */
    color: #333333;                   /* Màu chữ đậm */
  }
  
  .accordionButton {
    width: 100%;
    padding: 16px;
    background-color: #f7f7f7;          /* Nền button sáng */
    border: none;
    cursor: pointer;
    text-align: left;
    font-size: 1.1rem;
    display: flex;
    justify-content: space-between;
    align-items: center;
  }
  
  .icon {
    font-size: 1.5rem;
  }
  
  .accordionContent {
    padding: 16px;
    border-top: 1px solid #333;       /* Đường viền trên cho nội dung */
    background-color: #ffffff;
  }
  
  /* --- Dark Mode --- */
  [data-theme="dark"] .accordion {
    border: 1px solid #444;           /* Đường viền dành cho Dark mode */
    background-color: #212121;        /* Nền rất tối */
    color: #ffffff;                   /* Chữ sáng để tăng độ tương phản */
  }
  
  [data-theme="dark"] .accordionButton {
    background-color: #2a2a2a;       /* Nền button tối, nhưng khác với nền container */
    color: #CCFFCC;
  }
  
  [data-theme="dark"] .accordionContent {
    border-top: 1px solid #444;
    background-color: #212121;
    
  }
  

Giải thích:

File CSS này định nghĩa các style cho toàn bộ accordion, cho button và nội dung bên trong. Bạn có thể chỉnh sửa
các giá trị (màu sắc, khoảng cách, font-size) cho phù hợp với giao diện dự án của mình.

3)Sử Dụng Component Accordion trong MDX
Tạo hoặc chỉnh sửa một tệp MDX (ví dụ: docs/accordion-example.mdx) và import component vừa tạo:

---
title: Ví dụ Accordion Shortcode
---

import Accordion from '@site/src/components/Accordion';

# Ví dụ sử dụng Accordion trong Docusaurus

<Accordion title="Tiêu đề Accordion 1">
  Nội dung chi tiết cho Accordion 1. Bạn có thể viết Markdown, HTML hoặc thậm chí là
    nhúng các component khác bên trong.
</Accordion>

<Accordion title="Tiêu đề Accordion 2">
  Nội dung chi tiết cho Accordion 2.
  
  - Mục con 1
  - Mục con 2
</Accordion>

Giải thích:

Trong MDX, bạn import component React bằng cú pháp import Accordion from '@site/src/components/Accordion';
Sau đó, sử dụng component như một "shortcode" để nhúng accordion vào nội dung bài viết.
File "blognote/TIPSENG/bai-01.mdx" điển hình được xây dựng, phát triển từ code trong bài viết này có code như sau:

---
title: Bài 01-4000 Essential English
image: https://res.cloudinary.com/dc9lnec0s/image/upload/v1738299817/artwork-digital-art-trees-nature-path-forest-2236778-wallhere.com_oh3qv1.jpg
authors: [DucTran]

---

Giáo trình 4000 Essential English Words của giáo sư Paul Alen.<br />
Đây là 4000 từ vựng thông dụng nhất, sẽ giúp ích cho bạn trong tất cả các chương trình tiếng Anh dù là trên trường học, hay giao tiếp hàng ngày.
  
<!-- truncate -->
Mỗi từ vựng trong bộ giáo trình này là một từ có tần số xuất hiện cao. Điều này có nghĩa rằng những nỗ lực trong việc học các từ vựng này cũng được đáp lại bởi số lần người học có cơ hội để gặp hoặc sử dụng chúng

## Bài 01

<u><b>VOCABULARY:</b></u><br /><br />
<center><div style={{ width: "100%", maxWidth: "1100px" }}><iframe id="8972FE3F" loading="lazy" src='https://azvocab.ai/embed/SL?params=U2FsdGVkX1%2BQy4hEmwPFWw3YuWLOFtCIpa1IFHLJ7aKsI1c%2BDbxlX8%2FmpwfGlQYN98KII3oP6QsfqOxliPR9ipAD0Hdussz%2FUmTYVs9D3dD0yf8mSoQz8nBniaLGTOg47QzuYXIJzLF8nUjpGkGHRe049HG6ZrzgGKoX5p6GfeUanasTWmMjVgZyNz95O2L08Ko42Oso93larUQnqF3dK34%2F%2Bgpf0RlvcGeESdLIXZfHAN6aOM9tDpH4iB%2FwMX8sYjgSqIA9cg9OAhRKFCSmBi0%2FzguQ742CxjaPrH8BqID9AFSfD3M5YMerBG07ZhXX60IxYdlkGsXn0UnV%2F8%2BMN%2F04EKItvnZzPXZLUKqDpC65RrMqE1oZKM2%2Fxr8DNsCRpBKrOWZAwRDWpdNLCbCn37Qq6mlZEFJFbiw%2FMdU7W%2BWym2XRwjJPXxZTd%2FXAWgf24SWXE5vPrPfIH%2FwhHlrzXnedayz7AYPQ9zk6%2FYMquftAGq2MIBHZFHz3mYHQy5cU%2F%2BN70ItQuqMkdHlYVkwgbRaxF16REFUv1fGv37k2PEDcQVBczTpSoPfwtvCo32ClS67UZHQr32RZM6dz8Ky3EoBaLmusduhAbdhDxrdlauiYpkqYMR96xz5dxN2kxqQkY61cJFQUWQ97VRl1DGw36htYF3xhOMrZ%2FdG7KjjoS7bwOXjlpCkAe3xRQW7oQZDB5JcM0o9FrvH1kx2A%2FNlCy%2FEE9qeHaLb5qPViUsLHRDImv369diCo2UIOm09oLMagHukdpUeS9VxTvMKIbCu6VZ9XbFXeLGtWB7%2F4JtBXm%2BI%3D' width="100%" height="450" frameborder='0'></iframe></div></center><br /><br />
<u><b>BÀI NGHE 01:</b></u><br />
<center><audio controls>
  <source src="/bai01.mp3" type="audio/mpeg" />
  Trình duyệt của bạn không hỗ trợ thẻ audio.
</audio></center><br />


<h3>THE LION AND THE RABBIT</h3>

import Accordion from '@site/src/components/Accordion';

<Accordion title="A cruel lion lived in the forest. Every day, he killed and ate a lot of animals. The other animals were afraid the lion would kill them all.

The animals told the lion, “Let’s make a deal. If you promise to eat only one animal each day, then one of us will come to you every day. Then you don’t have to hunt and kill us.”">
  Có một con sư tử độc ác sống trong rừng. Mỗi ngày, nó giết và ăn thịt rất nhiều động vật khác. Những con vật khác sợ sư tử sẽ giết tất cả chúng.
Chúng nói với sư tử, "Hãy làm một thỏa thuận. Nếu ông hứa chỉ ăn một con vật mỗi ngày, thì mỗi ngày một trong chúng tôi sẽ đến để ông ăn thịt. Lúc đó, ông không phải săn bắt và giết chúng tôi nữa."
</Accordion>

<Accordion title="The plan sounded well thought-out to the lion, so he agreed, but he also said, “ If you don’t come every day, I promise to kill all of you the next day!”

Each day after that, one animal went to the lion so that the lion could eat it. Then, all the other animals were safe.">
Kế hoạch nghe có vẻ có lợi cho sư tử, vì vậy nó đồng ý, nhưng nó cũng nói, "Nếu có một ngày mà không có ai đến, ta hứa sẽ ăn thịt hết tất cả vào ngày hôm sau!"
Thế là mỗi ngày sau đó, lần lượt một con vật đến để sư tử ăn thịt. Rồi tất cả những con khác được an toàn.
</Accordion>

<Accordion title="Finally, it was the rabbit’s turn to go to the lion. The rabbit went very slowly that day, so the lion was angry when the rabbit finally arrived. The lion angrily asked the rabbit, “Why are you late?”

“ I was hiding from another lion in the forest. That lion said he was the king, so I was afraid.”">
Cuối cùng, đến lượt thỏ nạp mạng cho sư tử. Thỏ đã đi rất chậm vào ngày hôm đó, vì vậy sư tử rất giận dữ khi thấy thỏ. Sư tử gầm lên hỏi thỏ, "Sao ngươi lại đến trễ?"
"Tôi đã trốn khỏi một con sư tử khác trong rừng. Hắn nói hắn là vua, vì vậy tôi sợ."
</Accordion>

<Accordion title="The lion told the rabbit, “ I am the only king here! Take me to that other lion, and I will kill him.”

The rabbit replied, “ I will be happy to show you where he lives.” The rabbit led the lion to an old well in the middle of the forest. The well was very deep with water at the bottom. The rabbit told the lion, “Look in there. The lion lives at the bottom.”">
Sư tử nói với thỏ, "Ta là vị vua duy nhất ở đây! Hãy đưa ta đến gặp con sư tử kia, ta sẽ giết nó."
Thỏ đáp, "Tôi sẵn lòng chỉ cho ông hắn sống ở đâu. Thỏ dẫn sư tử đến cái giếng cũ ở giữa rừng. Đáy giếng rất sâu. Thỏ nói với sư tử, "Hãy nhìn vào đó. Hắn sống dưới đáy giếng đấy."
</Accordion>

<Accordion title="When the lion looked in the well, he could see his own face in the water. He thought that was the other lion. Without waiting another moment, the lion jumped into the well to attack the other lion. He never came out.

All of the other animals in the forest were very pleased with the rabbit’s clever trick.">

Khi sư tử nhìn vào giếng, nó nhìn thấy khuôn mặt của mình trong nước. Nó nghĩ đó là con sư tử kia. Không một phút do dự, sư tử nhảy vào giếng để tấn công con sư tử kia. Và nó không bao giờ ngoi lên được nữa.
Tất cả các loài động vật khác trong rừng đều rất vui mừng với trí thông minh của chú thỏ.
</Accordion><br />

<div class="two-column-layout">
  <div class="left-column">
    <h3>THE LION AND THE RABBIT</h3>
    A cruel lion lived in the forest. Every day, he killed and ate a lot of animals. The other animals were afraid the lion would kill them all.

The animals told the lion, “Let’s make a deal. If you promise to eat only one animal each day, then one of us will come to you every day. Then you don’t have to hunt and kill us.”

The plan sounded well thought-out to the lion, so he agreed, but he also said, “ If you don’t come every day, I promise to kill all of you the next day!”

Each day after that, one animal went to the lion so that the lion could eat it. Then, all the other animals were safe.

Finally, it was the rabbit’s turn to go to the lion. The rabbit went very slowly that day, so the lion was angry when the rabbit finally arrived. The lion angrily asked the rabbit, “Why are you late?”

“ I was hiding from another lion in the forest. That lion said he was the king, so I was afraid.”

The lion told the rabbit, “ I am the only king here! Take me to that other lion, and I will kill him.”

The rabbit replied, “ I will be happy to show you where he lives.”

The rabbit led the lion to an old well in the middle of the forest. The well was very deep with water at the bottom. The rabbit told the lion, “Look in there. The lion lives at the bottom.”

When the lion looked in the well, he could see his own face in the water. He thought that was the other lion. Without waiting another moment, the lion jumped into the well to attack the other lion. He never came out.

All of the other animals in the forest were very pleased with the rabbit’s clever trick.
    
  </div>

  <div class="right-column">
    <h3>SƯ TỬ VÀ THỎ</h3>
    Có một con sư tử độc ác sống trong rừng. Mỗi ngày, nó giết và ăn thịt rất nhiều động vật khác. Những con vật khác sợ sư tử sẽ giết tất cả chúng.

Chúng nói với sư tử, "Hãy làm một thỏa thuận. Nếu ông hứa chỉ ăn một con vật mỗi ngày, thì mỗi ngày một trong chúng tôi sẽ đến để ông ăn thịt. Lúc đó, ông không phải săn bắt và giết chúng tôi nữa."

Kế hoạch nghe có vẻ có lợi cho sư tử, vì vậy nó đồng ý, nhưng nó cũng nói, "Nếu có một ngày mà không có ai đến, ta hứa sẽ ăn thịt hết tất cả vào ngày hôm sau!"

Thế là mỗi ngày sau đó, lần lượt một con vật đến để sư tử ăn thịt. Rồi tất cả những con khác được an toàn.

Cuối cùng, đến lượt thỏ nạp mạng cho sư tử. Thỏ đã đi rất chậm vào ngày hôm đó, vì vậy sư tử rất giận dữ khi thấy thỏ. Sư tử gầm lên hỏi thỏ, "Sao ngươi lại đến trễ?"

"Tôi đã trốn khỏi một con sư tử khác trong rừng. Hắn nói hắn là vua, vì vậy tôi sợ."

Sư tử nói với thỏ, "Ta là vị vua duy nhất ở đây! Hãy đưa ta đến gặp con sư tử kia, ta sẽ giết nó."

Thỏ đáp, "Tôi sẵn lòng chỉ cho ông hắn sống ở đâu."

Thỏ dẫn sư tử đến cái giếng cũ ở giữa rừng. Đáy giếng rất sâu. Thỏ nói với sư tử, "Hãy nhìn vào đó. Hắn sống dưới đáy giếng đấy."

Khi sư tử nhìn vào giếng, nó nhìn thấy khuôn mặt của mình trong nước. Nó nghĩ đó là con sư tử kia. Không một phút do dự, sư tử nhảy vào giếng để tấn công con sư tử kia. Và nó không bao giờ ngoi lên được nữa.

Tất cả các loài động vật khác trong rừng đều rất vui mừng với trí thông minh của chú thỏ.
</div>
</div>

Tùy Chỉnh và Nâng Cao Nâng cao: Nếu bạn sử dụng Material UI hoặc các thư viện UI khác, bạn có thể kết hợp hoặc thay thế giao diện của Accordion bằng component Accordion của thư viện đó. Multiple Accordion Items: Bạn có thể tạo nhiều accordion khác nhau trên cùng một trang theo cách trên. Shortcode Style: Nếu bạn muốn tạo cú pháp giống shortcode (như [accordion title="..."] Nội dung [/accordion]), bạn có thể tích hợp remark/MDX plugin hoặc xử lý custom remark plugin, nhưng cách import component trong MDX đã là giải pháp đơn giản và mạnh mẽ. Kiểm tra và Build Chạy npm run start để khởi động trang Docusaurus trên localhost và kiểm tra xem accordion hoạt động đúng như mong đợi. Nếu mọi thứ ổn, build và deploy theo quy trình bạn đã thiết lập. Với các bước và mã ví dụ trên, bạn có thể tạo một accordion shortcode tương tự như WordPress trong trang Docusaurus của mình

Thành quả như trong bài viết này:

ACCORDION