Skip to content

UI — @tasco/ui

Bộ component design system của Tasco, xây trên Ant Design Vue và bám design token (@tasco/theme). Không import trực tiếp ant-design-vue — ESLint sẽ chặn; dùng qua @tasco/ui (hoặc các component C* đã đăng ký global).

Tham khảo trực quan: chạy playground (pnpm --filter playground dev) → trang /ui-kit, hoặc Storybook (pnpm --filter @tasco/ui storybook).

Component thương hiệu (có style riêng)

Đăng ký global qua app.use(TascoUI) (layer đã làm) → dùng thẳng trong template, không cần import.

ComponentMô tảProps chính
CButtonNút đa biến thể, gradient thương hiệuvariant (primary/secondary/outline/ghost/danger/link/text), size (sm/md/lg), block
CCardThẻ nội dung, có chế độ thu gọntitle, collapsible, defaultOpen, borderless; slot #title, #actions
CTableBảng (header nền primary, ô gọn)forward toàn bộ props a-table
CFormForm (mặc định layout="vertical")forward props a-form
CPageHeaderTiêu đề trang + breadcrumbtitle, subTitle, breadcrumb[]; event @navigate; slot #extra
CStatisticThẻ chỉ số KPIlabel, value, trend, accent; slot #icon, #suffix
CTagNhãn pill semanticcolor (default/primary/accent/success/warning/error/info), dot
CStatusChỉ báo active/inactivestatus, activeValue, activeText, inactiveText, showText
CEmptyTrạng thái rỗngdescription, bordered; slot #image, default (actions)
CInputCurrencyÔ nhập tiền tệ (1.234.567,89 ↔ số)v-model:value (number)
CInputPercentÔ nhập phần trăm, kẹp min/maxv-model:value, min, max, precision
vue
<template>
  <CPageHeader title="Đơn hàng" :breadcrumb="[{ title: 'Trang chủ', to: '/' }, { title: 'Đơn hàng' }]">
    <template #extra>
      <CButton variant="outline" size="sm">Xuất Excel</CButton>
      <CButton variant="primary" size="sm">Tạo đơn</CButton>
    </template>
  </CPageHeader>

  <CCard title="Bộ lọc" collapsible>
    <CForm>
      <a-form-item label="Số tiền"><CInputCurrency v-model:value="amount" /></a-form-item>
    </CForm>
  </CCard>

  <CTag color="success" dot>Hoàn thành</CTag>
  <CStatus :status="1" show-text />
</template>

Re-export có kiểm soát (primitive antdv)

Các primitive không cần wrap được re-export (đặt bí danh C*) để có một điểm import duy nhất và thoả ESLint:

ts
// Layout
import { Row, Col, Space, Flex, Divider, Typography, Layout } from '@tasco/ui'
// Nhập liệu
import { CInput, CTextarea, CInputNumber, CSelect, CSelectOption, CCheckbox, CSwitch, CDatePicker, CRangePicker, CFormItem, CUpload } from '@tasco/ui'
// Hiển thị dữ liệu
import { CDescriptions, CBadge, CAvatar, CTabs, CTabPane, CCollapse, CTooltip, CPopover, CPagination, CSteps, CTree } from '@tasco/ui'
// Phản hồi
import { CModal, CDrawer, CPopconfirm, CResult, CSpin, CSkeleton, CAlert, CProgress } from '@tasco/ui'
// Điều hướng
import { CDropdown, CMenu, CMenuItem, CBreadcrumb, CBreadcrumbItem } from '@tasco/ui'
// Imperative
import { message, notification } from '@tasco/ui'

Layout shell (kế thừa sẵn)

Framework cung cấp layout mặc định (default.vue trong layer): khung sider (gradient navy + brand) + header (toggle thu gọn + account/logout) + vùng nội dung cuộn + footer. Dự án extends @tasco/nuxt-layer-base không cần dựng lại — chỉ khai báo trong app/app.config.ts:

Bố cục giống OneAuto: dải logo navy góc trên-trái + menu module ngang (topNav) trên header, sidebar có icon + item active pill cam, chuông + account bên phải.

ts
import { h } from 'vue'
import { IconHome, IconShoppingCart } from '@tabler/icons-vue'
import type { NavItem } from '@tasco/ui'

export default defineAppConfig({
  tasco: {
    appTitle: 'Sản phẩm A',
    footerText: '© Tập đoàn Tasco',
    // Menu module ngang trên header (bỏ trống nếu không dùng).
    topNav: [
      { label: 'Tổng quan', path: '/' },
      { label: 'Bán hàng', path: '/orders' },
    ] satisfies NavItem[],
    // Menu sidebar — icon là component (vd @tabler/icons-vue).
    nav: [
      { label: 'Trang chủ', path: '/', icon: () => h(IconHome, { size: 18 }) },
      {
        label: 'Bán hàng',
        icon: () => h(IconShoppingCart, { size: 18 }),
        children: [{ label: 'Đơn hàng', path: '/orders' }],
      },
    ] satisfies NavItem[],
  },
})
  • CSideNav/CTopNav tự tô sáng item theo route.path (khớp tiền tố dài nhất); sidebar mở sẵn submenu cha.
  • Điều hướng router-agnostic: click item phát @navigate(path) → layer gọi navigateTo.
  • icon là render function của component icon (khuyến nghị @tabler/icons-vue như OneAuto); giúp chế độ thu gọn hiển thị đẹp.
  • Đổi khung hoàn toàn: tạo app/layouts/default.vue trong dự án (Nuxt ưu tiên layer gần nhất).
  • Dựng layout thủ công từ component thô: CAppLayout (slot #logo/#nav/#header/#actions/#footer) + CSideNav + CTopNav.
ComponentMô tảProps/Slots chính
CAppLayoutKhung shell: dải logo + header + sider + content + footerv-model:collapsed, appTitle, footerText, siderWidth; slot #logo/#nav/#header/#actions/#footer
CSideNavMenu sidebar từ config (icon + submenu, active pill cam)items: NavItem[], activePath, collapsed; event @navigate
CTopNavMenu module ngang trên headeritems: NavItem[], activePath; event @navigate

Theme & style

  • Màu/biến thể bám CSS variables --tasco-* (sinh từ @tasco/theme).
  • Layer nạp sẵn @tasco/theme/base.css (reset, scrollbar, header bảng navy, menu active accent) và @tasco/ui/style.css (scoped style component). App không cần import thủ công.
  • Đổi nhận diện: sửa token trong @tasco/theme → lan toả toàn bộ component.

Storybook

bash
pnpm --filter @tasco/ui storybook        # dev
pnpm --filter @tasco/ui build-storybook  # build tĩnh