Vue Amazing UI
A Vue 3 Component Library
Theme Customizable, Fully using TypeScript and SFC, Supports tree shaking.
Kinda Interesting
English | 中文
Documentation
Features
- The component library is implemented with
Vue@3.5.44+TypeScript@5.9.3+Vite@7.3.7+Less@4.9.1. - Currently, it includes
73basic UI components and16utility functions, with continuous exploration and updates ongoing... - Theme Customizable, all you need is to provide a theme color, then all the stuffs will be done by me.
- By the way, they are all treeshakable.
- All the stuff in Vue Amazing UI is written in TypeScript. It can work with your typescript project seamlessly.
- All components are built in single file component
SFCand can be used independently. - Ready to use out of the box, no fuss.
Installation
pnpm add vue-amazing-ui
# or
npm install vue-amazing-ui
# or
yarn add vue-amazing-ui
# or
bun add vue-amazing-ui
Use Components
Global Registration All Components (Not Recommended)
No tree-shaking. Bundle will have redundant codes.
import { createApp } from 'vue'
import App from './App.vue'
import VueAmazingUI from 'vue-amazing-ui'
import 'vue-amazing-ui/css'
const app = createApp(App)
app.use(VueAmazingUI)
app.mount('#app')
Global Partial Registration
In this form, only the imported components will be bundled.
import { createApp } from 'vue'
import App from './App.vue'
import { Button, Tag } from 'vue-amazing-ui'
// One style entry per component (recommended form): global default styles + the component's own styles + its dependency components' styles
import 'vue-amazing-ui/es/button/style'
import 'vue-amazing-ui/es/tag/style'
const app = createApp(App)
app.use(Button).use(Tag)
app.mount('#app')
Local Registration
In this form, only the imported components will be bundled as well.
<script setup lang="ts">
import { Button, Tag } from 'vue-amazing-ui'
// One style entry per component (recommended form): global default styles + the component's own styles + its dependency components' styles
import 'vue-amazing-ui/es/button/style'
import 'vue-amazing-ui/es/tag/style'
</script>
<template>
<Button>button</Button>
<Tag>tag</Tag>
</template>
The style entry also supports the more explicit file form
import 'vue-amazing-ui/es/button/style/index.js'.
Automatic On-Demand Import (Strongly Recommended)
Use the unplugin-vue-components plugin to automatically import components on demand. The plugin will automatically parse the components used in the template and import the components and styles.
pnpm add unplugin-vue-components -D
# or
npm install unplugin-vue-components -D
# or
yarn add unplugin-vue-components -D
# or
bun add unplugin-vue-components -D
// vite.config.ts
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import Components from 'unplugin-vue-components/vite'
// vue-amazing-ui on-demand import
import { VueAmazingUIResolver } from 'vue-amazing-ui'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [
vue(),
Components({
resolvers: [
// auto import components from VueAmazingUI
VueAmazingUIResolver({
cjs: false // whether use commonjs build, default false
})
]
})
]
})
Then, you can directly use all components from vue-amazing-ui in your code.
<template>
<Button>button</Button>
<Tag>tag</Tag>
</template>
Use Types
All types can be directly imported and used from vue-amazing-ui without any additional installation.
<script setup lang="ts">
import { ref } from 'vue'
import type { ButtonProps } from 'vue-amazing-ui'
const shape = ref<ButtonProps['shape']>('default')
</script>
<template>
<Button :shape="shape">button</Button>
</template>
Use Functions
<script setup lang="ts">
import {
dateFormat,
formatNumber,
throttle,
debounce,
add,
downloadFile,
useEventListener,
useMutationObserver,
useScroll,
useFps,
useMediaQuery,
useResizeObserver,
useSlotsExist,
useOptionsSupported,
getScrollParent,
useScrollParent
} from 'vue-amazing-ui'
</script>
Project
- Get the project code
git clone https://github.com/themusecatcher/vue-amazing-ui.git
- Install dependencies
cd vue-amazing-ui
pnpm i
- Run project
pnpm dev
- Run docs
pnpm docs:dev
Contributing
Vue Amazing UI grows together with its community. Whether you are adding a component, fixing a bug, or improving the docs and examples, your contribution is always welcome.
Before submitting code, please read the Contributing Guide.
Blogs
Sponsorship
Vue Amazing UI is an open-source project licensed under the MIT license, and it is completely free to use. All work on the component library and documentation is completed by the author alone, and the development and iteration process has been challenging. For the healthy and sustainable development of the component library, your support and sponsorship are greatly appreciated.
Become a Sponsor
Sponsors
All sponsors will be listed here, thank you very much for your support and sponsorship
Components
| Name | Description | Name | Description | Name | Description |
|---|---|---|---|---|---|
| Alert | Alert | AutoComplete | Auto Complete | Avatar | Avatar |
| BackTop | Back to Top | Badge | Badge | Breadcrumb | Breadcrumb |
| Button | Button | Calendar | Calendar | Card | Card |
| Carousel | Carousel | Cascader | Cascader | Checkbox | Checkbox |
| Collapse | Collapse | ColorPicker | Color Picker | Comment | Comment |
| ConfigProvider | Global Config | Countdown | Countdown | DatePicker | Date Picker |
| Descriptions | Descriptions | Dialog | Dialog | Divider | Divider |
| Drawer | Drawer | Dropdown | Dropdown | Ellipsis | Text Ellipsis |
| Empty | Empty State | Flex | Flex Layout | FloatButton | Float Button |
| GradientText | Gradient Text | Grid | Grid | Highlight | Highlight Text |
| Image | Image | Input | Input | InputNumber | Number Input |
| InputSearch | Search Input | Layout | Layout | List | List |
| LoadingBar | Loading Bar | Menu | Menu | Message | Global Message |
| Modal | Modal | Notification | Notification | NumberAnimation | Number Animation |
| Pagination | Pagination | Popconfirm | Popconfirm | Popover | Popover |
| Progress | Progress | QRCode | QR Code | Radio | Radio |
| Rate | Rating | Result | Result | Scrollbar | Scrollbar |
| Segmented | Segmented | Select | Select | Skeleton | Skeleton |
| Slider | Slider | Space | Spacing | Spin | Loading |
| Statistic | Statistic | Steps | Steps | Swiper | Swiper |
| Switch | Switch | Table | Table | Tabs | Tabs |
| Tag | Tag | Textarea | Textarea | TextScroll | Text Scroll |
| Timeline | Timeline | TimePicker | Time Picker | Tooltip | Tooltip |
| Upload | Upload | Video | Video Player | Waterfall | Waterfall |
| Watermark | Watermark |
Functions
| Name | Description | Type |
|---|---|---|
| dateFormat | Format date-time string function | (value: number | string | Date = Date.now(), format: string = 'YYYY-MM-DD HHss') => string |
| formatNumber | Number formatting function | (value: number | string, precision: number = 2, separator: string = ',', decimal: string = '.', prefix?: string, suffix?: string) => string |
| throttle | Throttle function | (fn: Function, delay: number = 300) => Function |
| debounce | Debounce function | (fn: Function, delay: number = 300) => Function |
| add | Addition function that eliminates precision issues in JavaScript arithmetic | (num1: number, num2: number) => number |
| downloadFile | Function to download a file with a custom filename, with built-in dual download strategies for same-origin anchor and cross-origin iframe; if no filename is provided, it extracts the filename from the URL |
(url: string, fileName?: string, options?: { target?: '_self' | '_blank'; strategy?: 'auto' | 'anchor' | 'iframe' }) => Promise<void> |
| useEventListener | Function to add and remove event listeners using Vue lifecycle hooks | (target: HTMLElement | Window | Document, event: string, callback: Function) => void |
| useMutationObserver | Function to observe changes in DOM elements using MutationObserver |
(target: Ref | Ref[] | HTMLElement | HTMLElement[], callback: MutationCallback, options: object = {}) => { start: () => void, stop: () => void } |
| useScroll | Function to monitor the scroll position, direction and edges of a target in real time | (target?: MaybeRefOrGetter<HTMLElement | Window | Document | null>, options?: UseScrollOptions) => { x: Ref<number>, y: Ref<number>, maxX: Ref<number>, maxY: Ref<number>, isScrolling: Ref<boolean>, direction: Ref<'left' | 'right' | 'top' | 'bottom' | null>, atLeft: Ref<boolean>, atRight: Ref<boolean>, atTop: Ref<boolean>, atBottom: Ref<boolean>, refresh: () => void, start: () => void, stop: () => void } |
| useFps | Function to monitor the browser's refresh rate (FPS) in real time | () => { fps: Ref<number> } |
| useMediaQuery | Function to determine if the current environment matches a specified media query condition | (mediaQuery: string) => { match: Ref<boolean> } |
| useResizeObserver | Function to observe changes in the dimensions of DOM elements using ResizeObserver |
(target: Ref | Ref[] | HTMLElement | HTMLElement[], callback: ResizeObserverCallback, options: object = {}) => { start: () => void, stop: () => void } |
| useSlotsExist | Function to watch for the existence of slots with given names, supporting single slots or an array of slots | <T extends string | string[] = 'default'>(slotsName: T) => T extends string ? ComputedRef<boolean> : Reactive<Record<string, ComputedRef<boolean>>> |
| useOptionsSupported | Checks if the browser supports the given event listener options | (option: 'capture' | 'once' | 'passive' | 'signal') => { isSupported: Ref<boolean> } |
| getScrollParent | Function to find the nearest scrollable parent element upward | (el: HTMLElement | null) => HTMLElement | null |
| useScrollParent | Composable to query and watch the nearest scrollable parent element and respond to viewport resize |
(contentRef: Ref<HTMLElement | null>, onScroll: () => void, options: ScrollParentOptions = {}) => { scrollTarget: Ref<HTMLElement | null>, viewportWidth: Ref<number>, viewportHeight: Ref<number>, observeScroll: () => void, cleanup: () => void } |