tsc-ui-library

TSC UI Components Library - Reusable Vue 3 components
2,770
Install
npm install tsc-ui-library
Latest Version:1.0.15
Vue:3
License:MIT
Last Updated:Aug 17, 2026
Links: npm
Maintainer: nknguyen2810

TSC Design System

A comprehensive Vue 3 component library built with TypeScript, PrimeVue, and SCSS.

📚 Documentation

  • GETTING_STARTED.md - Bắt đầu sử dụng (Chọn file phù hợp)
  • USAGE_GUIDE.md - Hướng dẫn sử dụng chi tiết (Tiếng Việt)
  • COMPONENTS_INDEX.md - Danh mục tìm kiếm components
  • QUICK_START.md - Hướng dẫn nhanh 5 phút
  • PUBLISH.md - Hướng dẫn publish và sử dụng
  • CHANGELOG.md - Lịch sử thay đổi

📦 Installation

System Requirements

  • Node.js: 16.0.0+
  • Vue: 3.4.0+
  • TypeScript: 5.0.0+ (optional)
  • Vite: 5.0.0+ (recommended)
npm install tsc-ui-library --legacy-peer-deps

Lưu ý: Sử dụng --legacy-peer-deps để tránh lỗi peer dependency

🚀 Quick Start

1. Install Dependencies

npm install vue@^3.4.0 primevue@^3.46.0 primeicons primeflex@^3.3.1 --legacy-peer-deps

2. Import and Use

// main.ts
import { createApp } from 'vue'
import App from './App.vue'
import TscUI from 'tsc-ui-library'
import 'primevue/resources/themes/saga-blue/theme.css'
import 'primevue/resources/primevue.min.css'
import 'primeicons/primeicons.css'
import 'primeflex/primeflex.css'
import 'tsc-ui-library/dist/styles/index.css'

const app = createApp(App)
app.use(TscUI)
app.mount('#app')

3. Use Components

<template>
  <div>
    <!-- Basic Components -->
    <DaButton label="Click me" />
    <DaInputText v-model="text" placeholder="Enter text" />
    
    <!-- Layout Components -->
    <MainLayout
      :menu-items="menuItems"
      :app-name="'My App'"
      :user-info="userInfo"
    >
      <div>Your content here</div>
    </MainLayout>
  </div>
</template>

<script setup>
import { ref } from 'vue'

const text = ref('')
const menuItems = ref([
  { id: 'home', label: 'Home', icon: 'dashboard-icon', href: '/home' },
  { id: 'about', label: 'About', icon: 'info', href: '/about' }
])

const userInfo = ref({
  name: 'John Doe',
  role: 'Admin',
  avatar: 'JD'
})
</script>

📘 Component Usage & CSS Customization

Dưới đây là hướng dẫn chi tiết cách sử dụng và custom CSS cho tất cả 62 components. Ghi đè CSS variables bằng cách đặt trong :root hoặc selector bao ngoài.

:root {
  /* Ví dụ: override màu toàn cục */
  --tsc-btn-bg: #2563eb;
}

🎯 Basic Components

DaButton

Props: label, type, loading, disabled, icon, severity Events: @click

<DaButton label="Primary" type="button" @click="onClick" />
<DaButton label="Loading" :loading="true" />
<DaButton label="Disabled" :disabled="true" />
<DaButton icon="pi pi-check" label="With Icon" />
:root {
  --tsc-btn-bg: #2563eb;
  --tsc-btn-color: #ffffff;
  --tsc-btn-hover-bg: #1d4ed8;
  --tsc-btn-border-radius: 6px;
  --tsc-btn-padding: 0.5rem 1rem;
  --tsc-btn-font-weight: 500;
}
DaModal

Props: v-model:visible, title, modal, closable, dismissableMask Slots: #default, #header, #footer

<DaModal v-model:visible="open" title="Settings" :closable="true">
  <template #default>
    Nội dung modal
  </template>
  <template #footer>
    <DaButton label="Close" @click="open=false" />
  </template>
</DaModal>
:root {
  --tsc-modal-title-weight: 600;
  --tsc-modal-title-size: 1.25rem;
  --tsc-modal-title-color: #0f172a;
  --tsc-modal-color: #334155;
  --tsc-modal-bg: #ffffff;
  --tsc-modal-border-radius: 4px;
}
DaInputText

Props: v-model, placeholder, disabled, invalid, readonly Events: @input, @change, @focus, @blur

<DaInputText v-model="value" placeholder="Search..." :invalid="hasError" />
<DaInputText v-model="text" :disabled="true" />
:root {
  --tsc-input-text-placeholder-color: #94a3b8;
  --tsc-input-text-invalid-border: #ef4444;
  --tsc-input-text-disabled-bg: #e5e7eb;
  --tsc-input-text-border: #d1d5db;
  --tsc-input-text-focus-border: #3b82f6;
  --tsc-input-text-padding: 0.5rem 0.75rem;
}
DaCheckbox

Props: v-model, binary, disabled, readonly Events: @change

<DaCheckbox v-model="checked" />
<DaCheckbox v-model="value" :binary="true" />
:root {
  --tsc-checkbox-border: #d1d5db;
  --tsc-checkbox-bg: #ffffff;
  --tsc-checkbox-hover-border: #3b82f6;
  --tsc-checkbox-checked-bg: #3b82f6;
  --tsc-checkbox-checked-border: #3b82f6;
  --tsc-checkbox-icon-color: #ffffff;
}
DaTriStateCheckBox

Props: v-model, disabled, readonly Events: @change

<DaTriStateCheckBox v-model="state" />
<!-- state: true, false, null -->
:root {
  --tsc-tristate-checkbox-border: #cbd5e1;
  --tsc-tristate-checkbox-bg: #ffffff;
  --tsc-tristate-checkbox-hover-border: #3b82f6;
  --tsc-tristate-checkbox-active-bg: #3b82f6;
  --tsc-tristate-checkbox-active-border: #3b82f6;
  --tsc-tristate-checkbox-active-hover-bg: #60a5fa;
  --tsc-tristate-checkbox-icon-color: #ffffff;
}
DaTabs

Props: tabs, v-model:activeIndex, scrollable Events: @tab-change

<DaTabs :tabs="tabs" v-model:activeIndex="active" />
:root {
  --tsc-tabs-skeleton-bg: #e5e7eb;
  --tsc-tabs-active-color: #00a7cf;
  --tsc-tabs-active-border: #00a7cf;
  --tsc-tabs-tab-padding: 0.75rem 1rem;
  --tsc-tabs-tab-font-weight: 500;
}
DaChips

Props: v-model, addOnBlur, allowDuplicate, max Events: @add, @remove

<DaChips v-model="chips" placeholder="Add tags" />
:root {
  --tsc-chips-bg: #f3f4f6;
  --tsc-chips-color: #374151;
  --tsc-chips-border: #d1d5db;
  --tsc-chips-remove-bg: #ef4444;
  --tsc-chips-remove-color: #ffffff;
}
DaMessage

Props: severity, closable, sticky Events: @close

<DaMessage severity="success" :closable="true">Success message</DaMessage>
<DaMessage severity="error">Error message</DaMessage>
:root {
  --tsc-message-success-bg: #d1fae5;
  --tsc-message-success-border: #10b981;
  --tsc-message-success-color: #065f46;
  --tsc-message-error-bg: #fee2e2;
  --tsc-message-error-border: #ef4444;
  --tsc-message-error-color: #991b1b;
}
DaImg

Props: src, alt, width, height, preview Events: @error, @load

<DaImg src="/image.jpg" alt="Description" :preview="true" />
<DaImg src="data:image/svg+xml;base64,..." width="24" height="24" />
:root {
  --tsc-img-tooltip-bg: #ffffff;
  --tsc-img-tooltip-color: #002550;
  --tsc-img-border-radius: 4px;
}
DaError

Props: message, showRefresh Events: @refresh

<DaError message="Something went wrong" :showRefresh="true" @refresh="retry" />
:root {
  --tsc-error-color: #ef4444;
  --tsc-error-bg: #fef2f2;
  --tsc-error-border: #fecaca;
}

📝 Form Components

DaTextarea

Props: v-model, placeholder, rows, cols, autoResize Events: @input, @change

<DaTextarea v-model="text" placeholder="Enter description" :rows="4" />
<DaTextarea v-model="content" :autoResize="true" />
:root {
  --tsc-textarea-placeholder-color: #94a3b8;
  --tsc-textarea-border: #d1d5db;
  --tsc-textarea-focus-border: #3b82f6;
  --tsc-textarea-padding: 0.5rem 0.75rem;
  --tsc-textarea-resize: vertical;
}
DaInputNumber

Props: v-model, min, max, step, currency, locale Events: @input, @change

<DaInputNumber v-model="value" :min="0" :max="100" :step="1" />
<DaInputNumber v-model="price" currency="USD" />
:root {
  --tsc-input-number-border: #d1d5db;
  --tsc-input-number-focus-border: #3b82f6;
  --tsc-input-number-button-bg: #f9fafb;
  --tsc-input-number-button-hover-bg: #f3f4f6;
}
DaSelectButton

Props: v-model, options, multiple, disabled Events: @change

<DaSelectButton v-model="value" :options="options" />
<DaSelectButton v-model="values" :options="options" :multiple="true" />
:root {
  --tsc-select-button-bg: #ffffff;
  --tsc-select-button-border: #d1d5db;
  --tsc-select-button-selected-bg: #3b82f6;
  --tsc-select-button-selected-color: #ffffff;
  --tsc-select-button-hover-bg: #f3f4f6;
}
DaDropdown

Props: v-model, options, optionLabel, optionValue, placeholder Events: @change, @filter

<DaDropdown v-model="selected" :options="options" optionLabel="name" />
<DaDropdown v-model="city" :options="cities" placeholder="Select city" />
:root {
  --tsc-dropdown-border: #d1d5db;
  --tsc-dropdown-focus-border: #3b82f6;
  --tsc-dropdown-panel-bg: #ffffff;
  --tsc-dropdown-option-hover-bg: #f3f4f6;
  --tsc-dropdown-option-selected-bg: #dbeafe;
}
DaInputSwitch

Props: v-model, disabled, readonly Events: @change

<DaInputSwitch v-model="checked" />
<DaInputSwitch v-model="enabled" :disabled="true" />
:root {
  --tsc-input-switch-bg: #d1d5db;
  --tsc-input-switch-checked-bg: #3b82f6;
  --tsc-input-switch-handle-bg: #ffffff;
  --tsc-input-switch-handle-checked-bg: #ffffff;
}
DaPassword

Props: v-model, placeholder, feedback, toggleMask Events: @input, @change

<DaPassword v-model="password" :feedback="true" />
<DaPassword v-model="pwd" placeholder="Enter password" />
:root {
  --tsc-password-border: #d1d5db;
  --tsc-password-focus-border: #3b82f6;
  --tsc-password-toggle-color: #6b7280;
  --tsc-password-feedback-bg: #f9fafb;
}
DaPagination

Props: totalRecords, rows, v-model:first, pageLinkSize Events: @page-change

<DaPagination :totalRecords="200" :rows="20" v-model:first="first" />
<DaPagination :totalRecords="1000" :rows="10" :pageLinkSize="5" />
:root {
  --tsc-pagination-btn-bg: #ffffff;
  --tsc-pagination-btn-color: #0f172a;
  --tsc-pagination-btn-active-bg: #e0f2fe;
  --tsc-pagination-btn-active-color: #0284c7;
  --tsc-pagination-btn-hover-bg: #f3f4f6;
  --tsc-pagination-btn-border: #d1d5db;
}
DaMultiSelect

Props: v-model, options, optionLabel, optionValue, placeholder Events: @change, @filter

<DaMultiSelect v-model="selected" :options="options" optionLabel="name" />
<DaMultiSelect v-model="tags" :options="tags" placeholder="Select tags" />
:root {
  --tsc-multiselect-border: #d1d5db;
  --tsc-multiselect-focus-border: #3b82f6;
  --tsc-multiselect-panel-bg: #ffffff;
  --tsc-multiselect-option-hover-bg: #f3f4f6;
  --tsc-multiselect-chip-bg: #e0f2fe;
  --tsc-multiselect-chip-color: #0284c7;
}
DaTreeSelect

Props: v-model, options, optionLabel, optionValue, placeholder Events: @change, @node-select, @node-unselect

<DaTreeSelect v-model="selected" :options="treeData" optionLabel="label" />
:root {
  --tsc-tree-select-border: #d1d5db;
  --tsc-tree-select-focus-border: #3b82f6;
  --tsc-tree-select-panel-bg: #ffffff;
  --tsc-tree-select-node-hover-bg: #f3f4f6;
  --tsc-tree-select-node-selected-bg: #dbeafe;
}

📊 Data Components

DaDataTable

Props: value, paginator, rows, totalRecords, lazy, sortField, sortOrder Events: @page, @sort, @row-select, @row-unselect

<DaDataTable :value="products" :paginator="true" :rows="10">
  <template #header>
    <div>Product List</div>
  </template>
  <Column field="name" header="Name" :sortable="true"></Column>
  <Column field="price" header="Price" :sortable="true"></Column>
</DaDataTable>
:root {
  --tsc-datatable-header-bg: #f8fafc;
  --tsc-datatable-header-color: #1e293b;
  --tsc-datatable-row-hover-bg: #f1f5f9;
  --tsc-datatable-row-selected-bg: #dbeafe;
  --tsc-datatable-border: #e2e8f0;
  --tsc-datatable-paginator-bg: #ffffff;
}
DaFormModal

Props: v-model:visible, title, formData, fields, submitLabel Events: @submit, @cancel

<DaFormModal 
  v-model:visible="showModal" 
  title="Add User" 
  :formData="userForm"
  :fields="formFields"
  @submit="handleSubmit"
/>
:root {
  --tsc-form-modal-bg: #ffffff;
  --tsc-form-modal-border-radius: 8px;
  --tsc-form-modal-shadow: 0 10px 25px rgba(0,0,0,0.1);
  --tsc-form-modal-header-bg: #f8fafc;
  --tsc-form-modal-footer-bg: #f8fafc;
}
DaListboxWithCheckbox

Props: v-model, options, optionLabel, optionValue, multiple Events: @change

<DaListboxWithCheckbox 
  v-model="selected" 
  :options="options" 
  optionLabel="name"
  :multiple="true"
/>
:root {
  --tsc-listbox-header-bg: #d1d5db;
  --tsc-listbox-header-weight: 500;
  --tsc-listbox-header-color: #374151;
  --tsc-listbox-error-color: #ef4444;
  --tsc-listbox-option-hover-bg: #f3f4f6;
  --tsc-listbox-option-selected-bg: #dbeafe;
}
DaInputNumberWithUnit

Props: v-model, unit, units, placeholder, min, max Events: @change, @unit-change

<DaInputNumberWithUnit 
  v-model="value" 
  :units="['px', 'em', 'rem']" 
  placeholder="Enter value"
/>
:root {
  --tsc-input-number-unit-color: #374151;
  --tsc-input-number-dropdown-border: #d1d5db;
  --tsc-input-number-invalid-border: #ef4444;
  --tsc-input-number-placeholder-color: #9ca3af;
  --tsc-input-number-label-weight: 400;
  --tsc-input-number-label-size: 14px;
  --tsc-input-number-label-color: #374151;
  --tsc-input-number-error-color: #ef4444;
  --tsc-input-number-disabled-bg: #f3f4f6;
  --tsc-input-number-disabled-border: #d1d5db;
  --tsc-input-number-disabled-color: #9ca3af;
}
DaCalendar

Props: v-model, showTime, timeOnly, minDate, maxDate Events: @date-select, @change

<DaCalendar v-model="date" :showTime="true" />
<DaCalendar v-model="time" :timeOnly="true" />
:root {
  --tsc-calendar-label-weight: 400;
  --tsc-calendar-label-size: 14px;
  --tsc-calendar-label-color: #374151;
  --tsc-calendar-error-color: #ef4444;
  --tsc-calendar-invalid-border: #ef4444;
  --tsc-calendar-time-input-color: #374151;
  --tsc-calendar-panel-bg: #ffffff;
  --tsc-calendar-today-bg: #3b82f6;
  --tsc-calendar-today-color: #ffffff;
}
DaPieChart

Props: option, height, width Events: @chart-click, @chart-ready

<DaPieChart :option="pieChartOption" height="300px" />
DaBarChart

Props: option, height, width Events: @chart-click, @chart-ready

<DaBarChart :option="barChartOption" height="400px" />
DaLineChart

Props: series, xAxis, option, height, width Events: @chart-click, @chart-ready

<DaLineChart 
  :series="lineChartSeries" 
  :x-axis="lineChartXAxis" 
  :option="lineChartOption"
  height="350px"
/>
:root {
  --tsc-chart-tooltip-bg: #002249;
  --tsc-chart-tooltip-text-color: #002249;
  --tsc-chart-tooltip-label-color: #335173;
  --tsc-chart-tooltip-date-color: #616161;
  --tsc-chart-legend-color: #374151;
  --tsc-chart-axis-color: #6b7280;
}
DaDropdownPageSize

Props: v-model, options, placeholder Events: @change

<DaDropdownPageSize v-model="pageSize" :options="[10, 20, 50, 100]" />
:root {
  --tsc-dropdown-page-size-border: #d1d5db;
  --tsc-dropdown-page-size-focus-border: #3b82f6;
  --tsc-dropdown-page-size-panel-bg: #ffffff;
  --tsc-dropdown-page-size-option-hover-bg: #f3f4f6;
}
DaTableSkeleton

Props: rows, columns Events: None

<DaTableSkeleton :rows="5" :columns="4" />
:root {
  --tsc-table-skeleton-bg: #f3f4f6;
  --tsc-table-skeleton-animation: pulse 2s infinite;
  --tsc-table-skeleton-border-radius: 4px;
}

🛠️ Utility Components

DaLabel

Props: for, required Events: None

<DaLabel for="input1" :required="true">Username</DaLabel>
:root {
  --tsc-label-weight: 400;
  --tsc-label-size: 14px;
  --tsc-label-color: #374151;
  --tsc-label-required-color: #ef4444;
}
DaDotColor

Props: color, size Events: None

<DaDotColor color="#3b82f6" :size="12" />
<DaDotColor color="red" :size="8" />
:root {
  --tsc-dot-color-size: 12px;
  --tsc-dot-color-border-radius: 50%;
  --tsc-dot-color-border: 1px solid #ffffff;
}
DaEllipsis

Props: text, maxLength, placement Events: None

<DaEllipsis :text="longText" :maxLength="50" placement="top" />
:root {
  --tsc-ellipsis-tooltip-shadow: 0px 0px 4px rgba(0, 0, 0, 0.15);
  --tsc-ellipsis-tooltip-color: #1e293b;
  --tsc-ellipsis-tooltip-bg: #ffffff;
  --tsc-ellipsis-tooltip-border-radius: 4px;
}
DaInputGroup

Props: label, required Events: None

<DaInputGroup label="Email Address" :required="true">
  <DaInputText v-model="email" placeholder="Enter email" />
</DaInputGroup>
:root {
  --tsc-input-group-label-color: #1e293b;
  --tsc-input-group-label-size: 12px;
  --tsc-input-group-label-weight: 500;
  --tsc-input-group-label-margin-bottom: 0.5rem;
}
DaInputMask

Props: v-model, mask, placeholder Events: @input, @change

<DaInputMask v-model="phone" mask="(999) 999-9999" placeholder="(123) 456-7890" />
<DaInputMask v-model="date" mask="99/99/9999" placeholder="MM/DD/YYYY" />
:root {
  --tsc-input-mask-border: #d1d5db;
  --tsc-input-mask-focus-border: #3b82f6;
  --tsc-input-mask-placeholder-color: #9ca3af;
  --tsc-input-mask-padding: 0.5rem 0.75rem;
}
IconHelp

Props: tooltip, placement Events: None

<IconHelp tooltip="This field is required" placement="top" />
:root {
  --tsc-icon-help-color: #6b7280;
  --tsc-icon-help-hover-color: #374151;
  --tsc-icon-help-tooltip-bg: #1f2937;
  --tsc-icon-help-tooltip-color: #ffffff;
}
RowDetails

Props: expanded, data Events: @toggle

<RowDetails :expanded="isExpanded" :data="rowData" @toggle="toggleRow" />
:root {
  --tsc-row-details-bg: #f8fafc;
  --tsc-row-details-border: #e2e8f0;
  --tsc-row-details-padding: 1rem;
  --tsc-row-details-toggle-color: #6b7280;
}

🏗️ Layout Components

MainLayout

Props: menuItems, appName, appSubtitle, userInfo, version, copyright, defaultExpanded, backgroundColor, contentPadding Events: @menu-click, @logo-click

<MainLayout
  :menu-items="menuItems"
  :app-name="'My App'"
  :app-subtitle="'Dashboard'"
  :user-info="userInfo"
  :version="'2.0.0'"
  :copyright="'© 2024 My Company'"
  :default-expanded="true"
  :backgroundColor="'#f8f9fa'"
  :contentPadding="'20px'"
  @menu-click="handleMenuClick"
  @logo-click="handleLogoClick"
>
  <div>Your content</div>
</MainLayout>
:root {
  --tsc-main-layout-bg: #f8f9fa;
  --tsc-main-layout-sidebar-bg: #ffffff;
  --tsc-main-layout-sidebar-border: #e5e7eb;
  --tsc-main-layout-topbar-bg: #ffffff;
  --tsc-main-layout-topbar-border: #e5e7eb;
  --tsc-main-layout-content-bg: #f8f9fa;
  --tsc-main-layout-content-padding: 20px;
}
Topbar

Props: userInfo, showNotifications, showUserMenu Events: @notification-click, @user-menu-click

<Topbar 
  :user-info="userInfo" 
  :showNotifications="true" 
  :showUserMenu="true"
  @notification-click="handleNotification"
  @user-menu-click="handleUserMenu"
/>
:root {
  --tsc-topbar-bg: #ffffff;
  --tsc-topbar-border: #e5e7eb;
  --tsc-topbar-height: 60px;
  --tsc-topbar-padding: 0 1rem;
  --tsc-topbar-user-info-color: #374151;
  --tsc-topbar-notification-color: #6b7280;
}
Sidebar

Props: menuItems, expanded, showLogo Events: @menu-click, @toggle

<Sidebar 
  :menu-items="menuItems" 
  :expanded="isExpanded" 
  :showLogo="true"
  @menu-click="handleMenuClick"
  @toggle="toggleSidebar"
/>
:root {
  --tsc-sidebar-bg: #ffffff;
  --tsc-sidebar-border: #e5e7eb;
  --tsc-sidebar-width: 250px;
  --tsc-sidebar-collapsed-width: 60px;
  --tsc-sidebar-menu-item-color: #374151;
  --tsc-sidebar-menu-item-hover-bg: #f3f4f6;
  --tsc-sidebar-menu-item-active-bg: #dbeafe;
  --tsc-sidebar-menu-item-active-color: #2563eb;
}

🔔 Toast Components

ToastMessage

Props: None Events: None

<ToastMessage />
// Gọi toast
window.triggerToast?.({
  severity: 'success',
  detail: 'Operation completed successfully!',
  life: 3000,
  closable: true,
  position: 'top'
})
:root {
  --tsc-toast-success-bg: #e6f5f0;
  --tsc-toast-success-border: #4caf50;
  --tsc-toast-success-color: #4caf50;
  --tsc-toast-success-icon-color: #4caf50;
  --tsc-toast-success-text-color: #002550;
  --tsc-toast-error-bg: #f5e7e6;
  --tsc-toast-error-border: #f44336;
  --tsc-toast-error-color: #f44336;
  --tsc-toast-error-icon-color: #f44336;
  --tsc-toast-error-text-color: #f44336;
}

🎨 Advanced Components

DaTieredMenu

Props: model, popup, appendTo Events: @show, @hide

<DaTieredMenu :model="menuItems" />
<DaTieredMenu :model="menuItems" :popup="true" />
:root {
  --tsc-tiered-menu-bg: #ffffff;
  --tsc-tiered-menu-border: #e5e7eb;
  --tsc-tiered-menu-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
  --tsc-tiered-menu-item-hover-bg: #f3f4f6;
  --tsc-tiered-menu-item-active-bg: #dbeafe;
}

⚡ Specialized Components

DaPopover

Props: v-model:visible, target, placement, arrow, hover Events: @show, @hide

<DaPopover v-model:visible="showPopover" target="button" placement="top" :arrow="true">
  <template #target>
    <DaButton label="Hover me" />
  </template>
  <template #content>
    <div>Popover content</div>
  </template>
</DaPopover>
:root {
  --tsc-popover-bg: #ffffff;
  --tsc-popover-border: #e5e7eb;
  --tsc-popover-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
  --tsc-popover-arrow-color: #ffffff;
  --tsc-popover-padding: 0.75rem;
}
ErrorWithRefreshButton

Props: errorMessage, showRefresh Events: @refresh

<ErrorWithRefreshButton 
  errorMessage="Something went wrong" 
  :showRefresh="true" 
  @refresh="retry"
/>
:root {
  --tsc-error-refresh-message-color: #dc3545;
  --tsc-error-refresh-btn-bg: #007bff;
  --tsc-error-refresh-btn-color: white;
  --tsc-error-refresh-btn-hover-bg: #0056b3;
  --tsc-error-refresh-padding: 1rem;
}
ActionMenu

Props: items, placement Events: @item-click

<ActionMenu :items="menuItems" placement="bottom" @item-click="handleAction" />
:root {
  --tsc-actionmenu-item-color: #6b7280;
  --tsc-actionmenu-item-hover-bg: #f3f4f6;
  --tsc-actionmenu-green-color: #10b981;
  --tsc-actionmenu-red-color: #ef4444;
  --tsc-actionmenu-disabled-opacity: 0.5;
}
DaDropdownButton

Props: label, items, split Events: @click, @item-click

<DaDropdownButton label="Actions" :items="menuItems" />
<DaDropdownButton label="Split" :items="menuItems" :split="true" />
:root {
  --tsc-dropdown-button-bg: #3b82f6;
  --tsc-dropdown-button-color: #ffffff;
  --tsc-dropdown-button-hover-bg: #2563eb;
  --tsc-dropdown-button-border: #3b82f6;
  --tsc-dropdown-button-split-border: #2563eb;
}
DaNavbarItems

Props: items, activeItem Events: @item-click

<DaNavbarItems :items="navItems" :activeItem="activeNav" @item-click="handleNav" />
:root {
  --tsc-navbar-item-color: #374151;
  --tsc-navbar-item-hover-bg: #f3f4f6;
  --tsc-navbar-item-active-bg: #dbeafe;
  --tsc-navbar-item-active-color: #2563eb;
  --tsc-navbar-item-active-weight: 500;
  --tsc-navbar-item-active-border: #1e293b;
  --tsc-navbar-item-icon-color: #6b7280;
  --tsc-navbar-item-active-icon-color: #2563eb;
}
DaTableToolBar

Props: title, showSearch, showFilter, showExport Events: @search, @filter, @export

<DaTableToolBar 
  title="Products" 
  :showSearch="true" 
  :showFilter="true" 
  :showExport="true"
  @search="handleSearch"
  @filter="handleFilter"
  @export="handleExport"
/>
:root {
  --tsc-table-toolbar-bg: #f8fafc;
  --tsc-table-toolbar-border: #e2e8f0;
  --tsc-table-toolbar-padding: 1rem;
  --tsc-table-toolbar-title-color: #1e293b;
  --tsc-table-toolbar-title-weight: 600;
}
DaTableFilter

Props: filters, showClear Events: @filter-change, @clear

<DaTableFilter :filters="filterOptions" :showClear="true" @filter-change="handleFilter" />
:root {
  --tsc-table-filter-bg: #ffffff;
  --tsc-table-filter-border: #d1d5db;
  --tsc-table-filter-padding: 0.75rem;
  --tsc-table-filter-input-border: #d1d5db;
  --tsc-table-filter-input-focus-border: #3b82f6;
}
DaTableContent

Props: loading, emptyMessage Events: None

<DaTableContent :loading="isLoading" emptyMessage="No data available" />
:root {
  --tsc-table-content-loading-bg: #f8fafc;
  --tsc-table-content-empty-color: #6b7280;
  --tsc-table-content-empty-bg: #f8fafc;
  --tsc-table-content-padding: 2rem;
}

🎨 Icon Components

BroadcastStationIcon

Props: size, color Events: None

<BroadcastStationIcon :size="24" color="#3b82f6" />
CaretIcon

Props: direction, size, color Events: None

<CaretIcon direction="down" :size="16" color="#6b7280" />
<CaretIcon direction="up" :size="16" color="#6b7280" />
GroupIcon

Props: size, color Events: None

<GroupIcon :size="20" color="#10b981" />
NotificationIcon

Props: size, color, badge Events: @click

<NotificationIcon :size="24" color="#6b7280" :badge="5" @click="showNotifications" />
PeopleCommunityIcon

Props: size, color Events: None

<PeopleCommunityIcon :size="20" color="#8b5cf6" />
PersonIcon

Props: size, color Events: None

<PersonIcon :size="20" color="#f59e0b" />
RadioDeviceIcon

Props: size, color Events: None

<RadioDeviceIcon :size="24" color="#ef4444" />
RadioUnitIcon

Props: size, color Events: None

<RadioUnitIcon :size="24" color="#06b6d4" />
StopIcon

Props: size, color Events: None

<StopIcon :size="20" color="#ef4444" />
TalkgroupIcon

Props: size, color Events: None

<TalkgroupIcon :size="20" color="#84cc16" />
TrashBinIcon

Props: size, color Events: None

<TrashBinIcon :size="20" color="#ef4444" />

🎯 Misc Components

DaNotification

Props: count, maxCount, showZero Events: @click

<DaNotification :count="5" :maxCount="99" @click="showNotifications" />
:root {
  --tsc-notification-icon-color: #6b7280;
  --tsc-notification-badge-bg: #ef4444;
  --tsc-notification-badge-color: white;
  --tsc-notification-badge-size: 18px;
  --tsc-notification-badge-border-radius: 50%;
}

Gợi ý: Để xem đầy đủ CSS variables cho tất cả components, tham khảo file src/styles/variables.scss trong thư viện hoặc USAGE_GUIDE.md để biết chi tiết props, events, slots của từng component.

📚 Component Categories

🎯 Basic Components (10)

  • TheLoader - Loading spinner
  • DaColorChip - Color display chip
  • DaError - Error message display
  • DaMessage - Message component
  • DaTabs - Tab navigation
  • DaChips - Chip components
  • DaButton - Button component
  • DaModal - Modal dialog
  • DaImg - Image component with icons
  • DaCheckbox - Checkbox input

📝 Form Components (10)

  • DaTextarea - Textarea input
  • DaInputNumber - Number input
  • DaSelectButton - Select button group
  • DaInputText - Text input
  • DaDropdown - Dropdown select
  • DaInputSwitch - Toggle switch
  • DaPassword - Password input
  • DaPagination - Pagination controls
  • DaMultiSelect - Multi-select dropdown
  • DaTreeSelect - Tree select component

📊 Data Components (10)

  • DaFormModal - Form modal
  • DaDataTable - Data table
  • DaListboxWithCheckbox - Listbox with checkboxes
  • DaInputNumberWithUnit - Number input with unit
  • DaCalendar - Calendar with time picker
  • DaPieChart - Pie chart
  • DaBarChart - Bar chart
  • DaLineChart - Line chart
  • DaDropdownPageSize - Page size selector
  • DaTableSkeleton - Table skeleton loader

🛠️ Utility Components (7)

  • DaLabel - Label component
  • DaDotColor - Color dot indicator
  • DaTriStateCheckBox - Three-state checkbox
  • DaEllipsis - Text ellipsis with tooltip
  • DaInputGroup - Input group wrapper
  • DaInputMask - Input with mask
  • IconHelp - Help icon with popover
  • RowDetails - Expandable row details

🎨 Advanced Components (1)

  • DaTieredMenu - Multi-level menu

⚡ Specialized Components (7)

  • DaPopover - Popover component
  • ErrorWithRefreshButton - Error with refresh
  • ActionMenu - Action menu
  • DaDropdownButton - Dropdown button
  • DaNavbarItems - Navbar items
  • DaTableToolBar - Table toolbar
  • DaTableFilter - Table filter
  • DaTableContent - Table content

🏗️ Layout Components (3)

  • MainLayout - Main layout wrapper
  • Topbar - Top navigation bar
  • Sidebar - Sidebar navigation

🎨 Icon Components (11)

  • BroadcastStationIcon - Broadcast station icon
  • CaretIcon - Caret icon
  • GroupIcon - Group icon
  • NotificationIcon - Notification icon
  • PeopleCommunityIcon - People community icon
  • PersonIcon - Person icon
  • RadioDeviceIcon - Radio device icon
  • RadioUnitIcon - Radio unit icon
  • StopIcon - Stop icon
  • TalkgroupIcon - Talkgroup icon
  • TrashBinIcon - Trash bin icon

🔔 Toast Components (1)

  • ToastMessage - Toast notification

🎯 Misc Components (2)

  • DaPopover - Popover component
  • ErrorWithRefreshButton - Error with refresh button

🎨 Styling

The library uses SCSS modules for styling. You can override styles by:

  1. CSS Variables: Override CSS custom properties
  2. SCSS Variables: Import and override SCSS variables
  3. Component Classes: Use component-specific classes
// Override main layout background
.main-layout {
  --background-color: #ffffff;
}

// Override button styles
.da-button {
  --button-primary-color: #007bff;
  --button-border-radius: 8px;
}

🔧 Configuration

Vue Router Integration

// router/index.ts
import { createRouter, createWebHistory } from 'vue-router'

const router = createRouter({
  history: createWebHistory(),
  routes: [
    { path: '/', component: Home },
    { path: '/dashboard', component: Dashboard },
    { path: '/users', component: Users }
  ]
})

export default router

Event Handling

<template>
  <div>
    <!-- Error with refresh -->
    <ErrorWithRefreshButton 
      error-message="Something went wrong"
      @refresh="handleRefresh"
    />
    
    <!-- Popover -->
    <DaPopover hover arrow placement="top">
      <DaButton label="Hover me" />
      <template #content>
        <div>Popover content</div>
      </template>
    </DaPopover>
  </div>
</template>

<script setup>
const handleRefresh = () => {
  // Retry the failed operation
  console.log('Refreshing...')
}
</script>

📱 Responsive Design

All components are responsive and work on:

  • Desktop (1200px+)
  • Tablet (768px - 1199px)
  • Mobile (320px - 767px)

🎯 Browser Support

  • Chrome 90+
  • Firefox 88+
  • Safari 14+
  • Edge 90+

📄 License

Copyright (c) 2024 TSC Communications. All rights reserved.

🤝 Contributing

  1. Fork the repository
  2. Create a feature branch
  3. Make your changes
  4. Add tests
  5. Submit a pull request

📞 Support

For support and questions:


Total Components: 62 Categories: 9 Built with: Vue 3, TypeScript, PrimeVue, SCSS


📘 Component Reference & Custom CSS Guide

Ghi chú chung:

  • Tất cả components hỗ trợ customClass?: string để nhận CSS tùy biến.
  • Mỗi component có fixed class name (bắt đầu với da-...) để target CSS toàn cục khi cần.
  • Ví dụ chỉ mang tính minh họa, có thể thay đổi theo nhu cầu UI.

Basic

  • DaButton (fixed: da-button): label, severity, size, disabled, loading, customClass
    • Dùng: <DaButton label="Save" severity="success" customClass="my-btn" />
    • CSS: .da-button.my-btn{border-radius:12px;background:#2563eb!important;color:#fff!important;}
  • DaModal (fixed: da-modal): header, visible, customClass
  • DaMessage (fixed: da-message): message, severity, customClass
  • DaError (fixed: da-error): message, htmlMessage, retryButton, customClass
  • DaImg (fixed: da-img): name, type, tooltip, customClass
  • DaTabs (fixed: da-tabs): items, activeIndex, loading, customClass

Form

  • DaInputText (fixed: da-input-text): v-model, label, icon, helpText, disabled, validator, customClass
  • DaTextarea (fixed: da-textarea): v-model, label, disabled, validator, customClass
  • DaInputNumber (fixed: da-input-number): v-model, label, min, max, disabled, customClass
  • DaDropdown (fixed: da-dropdown): v-model, options, optionLabel, optionValue, label, placeholder, customClass
  • DaSelectButton (fixed: da-select-button): v-model, options (nhận optionLabel/optionValue qua $attrs), customClass
  • DaInputSwitch (fixed: da-input-switch): v-model:boolean, label, customClass
  • DaPassword (fixed: da-password): v-model, toggleMask?, feedback?, customClass
  • DaPagination (fixed: da-pagination): v-model(page), total, rows, customClass
  • DaMultiSelect (fixed: da-multi-select): v-model[], options, optionLabel, optionValue, customClass
  • DaTreeSelect (fixed: da-tree-select): v-model, options(Tree), customClass
  • DaInputMask (fixed: da-input-mask): v-model, mask, customClass

Data

  • DaDataTable (fixed: da-data-table): value, columns, loading, paginator, customClass
  • DaFormModal, DaListboxWithCheckbox, DaInputNumberWithUnit, DaCalendar, DaDropdownPageSize, DaTableSkeleton

Utility

  • DaLabel (da-label), DaDotColor (da-dot-color), DaEllipsis (da-ellipsis), DaInputGroup (da-input-group), IconHelp (icon-help), RowDetails (da-row-details), TheLoader (the-loader), ErrorWithRefreshButton (error-with-refresh-button), DaTriStateCheckBox

Advanced & Specialized

  • DaTieredMenu, DaPopover, ActionMenu, DaDropdownButton, DaNavbarItems, DaTableToolBar, DaTableFilter, DaTableContent

Layout

  • MainLayout (main-layout), Topbar (topbar), Sidebar (sidebar)

Charts

  • DaPieChart (da-pie-chart), DaBarChart (da-bar-chart), DaLineChart (da-line-chart)

Toast & Notifications

  • ToastMessage (da-toast-message): dùng window.triggerToast({ severity, detail, life, position })
  • DaNotification (da-notification): icon chuông + badge, canh vị trí bằng customClass

Mẫu CSS nhanh

.da-button.my-btn { border-radius: 12px; background:#2563eb !important; color:#fff !important; }
.da-input-text.rounded { border-radius: 12px !important; padding: 10px 14px !important; }
.da-dropdown.flat :global(.p-dropdown) { border-radius: 10px; border: 2px solid #e5e7eb; }
.da-modal.card { border-radius: 16px; box-shadow: 0 20px 40px rgba(0,0,0,.2); }

Related Packages

seeroad-ui

seeroad project ui library

3,733
ui
smart-ui

High Quality Mobile UI Componets by Vue.js 2.

1,883 11
ui
hea-ui

hea-ui is a h5 ui component for vue

1,520 14
ui
canna-ui-vue

shims-vue.d.ts declare module 'canna-ui-vue'

674
ui

Version History

Version Released Vue License
1.0.15 ^3.4.0 MIT
1.0.14 ^3.4.0 MIT
1.0.13 ^3.4.0 MIT
1.0.12 ^3.4.0 MIT
1.0.11 ^3.4.0 MIT