WeTeach Design System
Comprehensive guide for buttons, layout patterns, cards, badges, empty states, and more.
Table of Contents
Buttons
Layout Patterns
Part 1: Buttons
Primary Buttons
Use for: Main call-to-action, primary user actions, form submissions, create/add actions
Examples: "Tạo yêu cầu", "Đăng ký", "Lưu", "Gửi đơn", "Xác nhận"
Standard Primary
Primary Sizes
Primary with Icons
Code Example
<button type="button" class="btn btn-primary">Tạo yêu cầu dạy học</button>
<!-- Rounded pill CTA -->
<a href="#" class="btn btn-success btn-sm rounded-pill px-3">
<i class="bi bi-plus-lg me-1"></i>Tạo Lớp Học Mới
</a>
Success Buttons
Use for: Confirmation actions, approve/accept actions, positive outcomes, create actions
Examples: "Chấp nhận", "Phê duyệt", "Tạo Lớp Học Mới", "Hoàn thành"
Danger Buttons
Use for: Destructive actions, delete/remove, reject/decline
Secondary / Warning / Info Buttons
Secondary (Cancel, Back)
Warning (Caution, Pause)
Info (View, Learn more)
Light (Filter reset, subtle actions)
Outline Buttons
Use for: Secondary actions, less visual weight, mobile filter toggles
Soft Buttons
Use for: Subtle actions, tags, filters, badges with interaction, header nav
<button class="btn btn-primary-soft">Primary Soft</button>
Icon-Only Buttons
Use for: Space-constrained areas. Always add aria-label.
Link Buttons
Use for: Text actions, inline actions, minimal visual weight
Button Groups, Blocks & Disabled State
Button Group
Block Buttons
Disabled State
Part 2: Layout Patterns
Hero Section
Use for: Top of listing pages. Contains badge, title, subtitle, and search bar.
Gradient: linear-gradient(135deg, #2888d2 0%, #f3c935 100%)
Decorative elements: ::before and ::after pseudo-elements with large semi-transparent circles.
Trang Mẫu
Mô tả ngắn gọn về nội dung trang hiển thị tại đây
Code Structure
<section class="hero-classes py-5">
<div class="container position-relative" style="z-index: 1;">
<div class="row justify-content-center">
<div class="col-lg-8 text-center">
<span class="badge bg-white bg-opacity-25 text-white px-3 py-2 rounded-pill mb-3">
<i class="bi bi-mortarboard me-1"></i> Badge Text
</span>
<h1 class="text-white display-5 fw-bold mb-3">Page Title</h1>
<p class="text-white text-opacity-90 fs-5 mb-4">Subtitle</p>
<!-- Search bar -->
<form class="d-flex justify-content-center">
<div class="input-group" style="max-width: 560px;">
<input class="form-control form-control-lg border-0 shadow" type="search" placeholder="...">
<button type="submit" class="btn btn-dark btn-lg px-4">
<i class="bi bi-search"></i>
</button>
</div>
</form>
</div>
</div>
</div>
</section>
Required CSS
.hero-classes {
background: linear-gradient(135deg, #2888d2 0%, #f3c935 100%);
position: relative;
overflow: hidden;
}
.hero-classes::before {
content: '';
position: absolute;
top: -50%; right: -20%;
width: 600px; height: 600px;
border-radius: 50%;
background: rgba(255,255,255,0.05);
}
.hero-classes::after {
content: '';
position: absolute;
bottom: -30%; left: -10%;
width: 400px; height: 400px;
border-radius: 50%;
background: rgba(255,255,255,0.05);
}
Main + Sidebar Layout
Use for: All listing pages (classes, posts, teachers). Main content area with filter sidebar that collapses to offcanvas on mobile.
col-lg-8 col-xl-9Toolbar, Card Grid, Pagination
col-lg-4 col-xl-3Filter Cards (offcanvas on mobile)
<section class="pt-4 pb-5">
<div class="container">
<div class="row">
<div class="col-lg-8 col-xl-9">
<!-- Toolbar, Grid, Pagination -->
</div>
<div class="col-lg-4 col-xl-3">
<div class="offcanvas-lg offcanvas-end" id="offcanvasSidebar">
<div class="offcanvas-header bg-light">...</div>
<div class="offcanvas-body p-3 p-lg-0">
<form method="GET">
<!-- Filter cards here -->
</form>
</div>
</div>
</div>
</div>
</div>
</section>
Toolbar Pattern
Use for: Sort dropdown + result count + mobile filter toggle. Always appears above the card grid.
Hiển thị 1-10 / 50
<div class="d-flex flex-wrap justify-content-between align-items-center gap-3 mb-4">
<form method="GET" class="d-inline-flex align-items-center">
<label class="me-2 small fw-semibold text-nowrap">
<i class="bi bi-sort-down me-1"></i>Sắp xếp:
</label>
<select class="form-select form-select-sm" name="sort" style="width: auto;" onchange="this.form.submit()">
<option value="newest">Mới nhất</option>
...
</select>
</form>
<div class="d-flex align-items-center gap-3">
<button class="btn btn-outline-primary btn-sm d-lg-none" data-bs-toggle="offcanvas" data-bs-target="#offcanvasSidebar">
<i class="bi bi-funnel me-1"></i>Bộ lọc
</button>
<p class="mb-0 text-body-secondary small">
Hiển thị <strong>1-10</strong> / <strong>50</strong>
</p>
</div>
</div>
CTA Gradient Section
Use for: Bottom of listing pages. Encourages user action (signup, create, etc.).
Buttons: btn-white (primary) and btn-hero-secondary (glass effect).
Bạn là giáo viên? Tạo lớp học ngay!
Chia sẻ kiến thức của bạn với hàng ngàn học viên. Đăng ký miễn phí!
Required CSS
.cta-gradient {
background: linear-gradient(135deg, #2888d2 0%, #f3c935 100%);
position: relative; overflow: hidden; border-radius: 8px;
}
.cta-gradient::before {
content: '';
position: absolute; top: -40%; right: -15%;
width: 400px; height: 400px; border-radius: 50%;
background: rgba(255,255,255,0.06);
}
.btn-hero-secondary {
background: rgba(255,255,255, 0.15);
color: #fff;
border: 2px solid rgba(255,255,255, 0.5);
backdrop-filter: blur(4px);
}
.btn-hero-secondary:hover {
background: rgba(255,255,255, 0.3);
border-color: rgba(255,255,255, 0.8);
}
Part 3: Components
Item Cards
Use for: Class cards, course cards, post cards in listing grids.
Grid: col-sm-6 col-xl-4 (3 columns on XL, 2 on SM)
Key CSS: border-radius: 16px, hover translateY(-4px), shadow-sm
Tên khóa học / lớp học hiển thị tại đây
Mô tả ngắn gọn về nội dung khóa học hiển thị ở đây...
Tên khóa học trung tâm
Mô tả ngắn gọn khóa học trung tâm...
Required CSS
.class-item-card { /* or any item card class */
border: none;
border-radius: 8px;
transition: transform 0.3s ease, box-shadow 0.3s ease;
cursor: pointer;
}
.class-item-card:hover {
transform: translateY(-4px);
box-shadow: 0 0.5rem 1.5rem rgba(0,0,0,0.1) !important;
}
.type-badge {
padding: 6px 14px;
border-radius: 0 0 8px 0;
font-size: 0.78rem;
font-weight: 600;
}
.text-truncate-2 {
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
}
Filter Sidebar Cards
Use for: Each filter group in the sidebar (subjects, location, fee, etc.).
Structure: Icon + label header, then filter control.
Action Buttons (bottom of filter form)
.filter-sidebar-card {
border: none;
border-radius: 8px;
transition: box-shadow 0.3s ease;
}
.filter-sidebar-card:hover {
box-shadow: 0 0.5rem 1.5rem rgba(0,0,0,0.08) !important;
}
Badges & Tags
Type Badges (card image overlay, top-left)
Use: Identify card type. Uses .type-badge class.
Subject Badges (card body)
Use: Show subjects using bg-{color} bg-opacity-10 text-{color}
Fee Badges (card image overlay, bottom-right)
550.000₫ Miễn phíStatus Badges
Online Chờ duyệt Hoạt độngHero / Page Badge
Nền tảng học tập WeTeachEmpty States
Use for: When search/filter returns no results. Centered icon + message + action buttons.
Không tìm thấy kết quả
Chúng tôi không thể tìm thấy lớp học hoặc khóa học nào phù hợp với tiêu chí của bạn. Hãy thử thay đổi bộ lọc hoặc từ khóa tìm kiếm.
<div class="card border-0 shadow-sm rounded-4 p-5 text-center">
<div class="mx-auto mb-3 empty-state-icon bg-warning bg-opacity-10 text-warning">
<i class="bi bi-journal-x"></i>
</div>
<h5 class="fw-semibold mb-2">Không tìm thấy kết quả</h5>
<p class="text-body-secondary mb-3">Message here...</p>
<div class="d-flex justify-content-center gap-2">
<a href="#" class="btn btn-primary">Action 1</a>
<a href="#" class="btn btn-success">Action 2</a>
</div>
</div>
/* Required CSS */
.empty-state-icon {
width: 80px; height: 80px;
display: flex; align-items: center; justify-content: center;
border-radius: 50%; font-size: 2rem;
}
Pagination
Use for: Navigating paginated lists. Uses pagination-primary-soft with chevron icons.
<nav class="mt-5 d-flex justify-content-center" aria-label="điều hướng">
<ul class="pagination pagination-primary-soft d-inline-block d-md-flex rounded mb-0">
<li class="page-item mb-0">
<a class="page-link" href="..."><i class="bi bi-chevron-double-left"></i></a>
</li>
<li class="page-item mb-0 active"><a class="page-link" href="#">2</a></li>
<li class="page-item mb-0">
<a class="page-link" href="..."><i class="bi bi-chevron-double-right"></i></a>
</li>
</ul>
</nav>
Radio Pill Filters
Use for: Mutually exclusive filter options (location type: all/online/offline).
<input type="radio" class="btn-check" name="location" value="" id="location-all" checked>
<label class="btn btn-outline-primary btn-sm rounded-pill" for="location-all">Tất cả</label>
<input type="radio" class="btn-check" name="location" value="online" id="location-online">
<label class="btn btn-outline-primary btn-sm rounded-pill" for="location-online">
<i class="bi bi-wifi me-1"></i>Online
</label>
Part 4: Guidelines & Best Practices
Usage Guidelines
Do's
- Use clear, action-oriented labels (e.g., "Tạo yêu cầu" not "OK")
- Limit to one primary action per screen/section
- Use
rounded-pillfor create/CTA buttons - Use
border-radius: 16pxfor all cards - Use the Hero + Main/Sidebar + CTA layout for listing pages
- Use
shadow-smfor cards,shadowfor modals - Use Bootstrap Icons (
bi-*) everywhere — NOT FontAwesome - Use
text-body-secondary— NOTtext-muted - Preserve all filter params when submitting sort/search/pagination
- Use offcanvas sidebar for mobile filter UI
- Show loading states for async actions
Don'ts
- Don't use FontAwesome icons (
fas fa-*) - Don't use
text-muted— usetext-body-secondary - Don't use
bg-darkfor hero banners — use the gradient - Don't use multiple primary buttons in the same context
- Don't use red/danger buttons for non-destructive actions
- Don't use vague labels like "Click here" or "Submit"
- Don't use inline styles for border-radius on cards (use CSS class)
- Don't put search in both hero AND filter sidebar (hero only)
- Don't use
btn-success-softfor create CTAs — usebtn-success rounded-pill - Don't forget to show empty states when no results
Action Priority Hierarchy
| Priority | Button Style | Usage | Example |
|---|---|---|---|
| Critical | Destructive, irreversible actions | Delete account, Remove post | |
| High | Main call-to-action | Create, Submit, Save, Apply Filter | |
| Medium-High | Create/add CTAs, confirmations | Tạo Lớp Học Mới, Chấp nhận | |
| Medium | Secondary actions | Edit, View, Download, Filter toggle | |
| Low | / | Tertiary, reset actions | Clear filters, Learn more, Terms |
Standard Page Structure
| Section | Purpose | Key Classes |
|---|---|---|
| Hero | Page title, subtitle, search | .hero-{page} py-5, gradient, decorative circles |
| Toolbar | Sort, result count, mobile filter toggle | d-flex flex-wrap justify-content-between |
| Create CTA | Role-aware create button | btn btn-success btn-sm rounded-pill px-3 |
| Card Grid | Item listing | row g-4, col-sm-6 col-xl-4 |
| Empty State | No results message | card border-0 shadow-sm rounded-4 p-5 text-center |
| Pagination | Page navigation | pagination pagination-primary-soft |
| Sidebar | Filter cards | offcanvas-lg offcanvas-end, .filter-sidebar-card |
| CTA Section | Bottom call-to-action | .cta-gradient, btn-white, btn-hero-secondary |
Accessibility Considerations
- Semantic HTML: Use
<button>for actions,<a>for navigation - aria-label for icon-only buttons:
<button class="btn btn-primary btn-icon" aria-label="Chỉnh sửa"><i class="bi bi-pencil"></i></button> - aria-label for pagination:
<nav aria-label="điều hướng"> - Disabled state: Use both
disabledattribute andaria-disabled="true" - Focus indicators: Ensure visible focus states for keyboard navigation
- Color contrast: Text meets WCAG AA standards (4.5:1)
- Touch targets: Minimum 44x44px for mobile