Skip to content

codemonster-ru/vueforge

Repository files navigation

VueForge

npm downloads license

Open source component-level UI library for Vue.js.

Install

npm i @codemonster-ru/vueforge

Peer dependencies:

  • vue (v3)
  • vue-router (v4)
  • @codemonster-ru/vueiconify

Usage

import { createApp } from 'vue';
import {
    VueForge,
    DefaultTheme,
    Button,
    Input,
    NumberInput,
    FormField,
    Textarea,
    FileUpload,
    Breadcrumbs,
    Select,
    Autocomplete,
    MultiSelect,
    DatePicker,
    DateRangePicker,
    TimePicker,
    Pagination,
    DataTable,
    Checkbox,
    Switch,
    Alert,
    Skeleton,
    Progress,
    Badge,
    Chip,
    Accordion,
    AccordionItem,
    Slider,
    Stepper,
    Rating,
    Drawer,
    Dropdown,
} from '@codemonster-ru/vueforge';
import '@codemonster-ru/vueforge/dist/index.css';

const app = createApp(App);

app.use(VueForge, {
    theme: {
        preset: DefaultTheme,
    },
});
<Button label="Hello" severity="primary" />
<FormField label="Name" hint="Required field">
    <Input v-model="name" placeholder="Your name" />
</FormField>
<NumberInput v-model="age" :min="0" :max="120" :step="1" />
<Textarea v-model="bio" placeholder="Tell us about yourself" />
<FileUpload v-model="resume" accept=".pdf,.doc,.docx" />
<Breadcrumbs :items="breadcrumbItems" />
<Select v-model="role" :options="roles" placeholder="Choose role" />
<Autocomplete v-model="country" :options="countries" placeholder="Find country" />
<MultiSelect v-model="countries" :options="countryOptions" placeholder="Select countries" clearable />
<DatePicker v-model="birthday" placeholder="Pick birthday" />
<DateRangePicker v-model="range" placeholder="Pick range" />
<TimePicker v-model="meetingTime" placeholder="Pick time" />
<Pagination v-model="page" :total-items="240" :page-size="20" />
<DataTable :columns="columns" :rows="rows" sortable striped />
<Checkbox v-model="agreed" label="I agree" />
<Switch v-model="darkMode" label="Dark mode" />
<Alert severity="info" title="Heads up" message="Project settings were updated." />
<Skeleton height="12px" width="140px" />
<Progress :value="64" />
<Badge label="Beta" />
<Chip label="New" />
<Slider v-model="volume" :min="0" :max="100" :step="5" show-value />
<Stepper v-model="step" :steps="steps" clickable />
<Rating v-model="rating" allow-half />
<Accordion v-model="faq">
    <AccordionItem value="shipping" title="Shipping">
        Shipping details
    </AccordionItem>
    <AccordionItem value="returns" title="Returns">
        Returns policy
    </AccordionItem>
</Accordion>
<Drawer v-model="drawerOpen" title="Filters" position="right">
    <template #body>
        Drawer content
    </template>
</Drawer>
<Dropdown :items="menuItems">
    <template #trigger>
        <Button label="Actions" />
    </template>
</Dropdown>

Components

  • Button
  • Card
  • Checkbox
  • RadioGroup
  • RadioButton
  • Tabs
  • Tab
  • TabPanel
  • Accordion
  • AccordionItem
  • Toast
  • ToastContainer
  • Alert
  • Input
  • NumberInput
  • FormField
  • Textarea
  • FileUpload
  • Link
  • Breadcrumbs
  • Menu
  • Modal
  • Drawer
  • Dropdown
  • Popover
  • Select
  • Autocomplete
  • MultiSelect
  • DatePicker
  • DateRangePicker
  • TimePicker
  • Pagination
  • DataTable
  • Switch
  • Tooltip
  • Skeleton
  • Progress
  • Badge
  • Chip
  • Avatar
  • Slider
  • Stepper
  • Rating

Input / Textarea (quick API):

  • Input: single-line control, supports v-model, size, variant, disabled, readonly.
  • NumberInput: numeric control, supports v-model, min, max, step, precision, controls, size, variant.
  • Textarea: multi-line control, same as Input plus rows.
  • Checkbox, Select, Autocomplete, MultiSelect, DatePicker, DateRangePicker, Pagination, and DataTable also support variant: 'filled' | 'outlined'.

FormField

Props:

  • id?: string (used in label for and slot props)
  • label?: string
  • hint?: string
  • error?: string
  • required?: boolean
  • disabled?: boolean
  • size?: 'small' | 'normal' | 'large' (default normal)

Slots:

  • default - form control wrapper slot props: { id, describedBy, invalid, required }
  • label (optional)
  • hint (optional)
  • error (optional)

Example:

<FormField label="Email" hint="We never share it" :error="emailError">
    <template #default="{ id, describedBy }">
        <Input :id="id" v-model="email" :aria-describedby="describedBy" placeholder="name@example.com" />
    </template>
</FormField>

Note: default filled backgrounds for Input/Select/Textarea use controls.backgroundColor (defaults to bgSoftColor). Set it to bgColor to disable soft backgrounds.

Autocomplete

Props:

  • modelValue?: string | number (v-model)
  • options?: Array<{ label: string; value: string | number; disabled?: boolean }>
  • optionLabel?: string (default label)
  • optionValue?: string (default value)
  • placeholder?: string
  • disabled?: boolean
  • readonly?: boolean
  • loading?: boolean
  • loadingText?: string (default Loading...)
  • emptyText?: string (default No results)
  • filter?: boolean (default true)
  • size?: 'small' | 'normal' | 'large' (default normal)
  • variant?: 'filled' | 'outlined' (default filled)

Events:

  • update:modelValue
  • change
  • search
  • focus
  • blur

Example:

<Autocomplete v-model="country" :options="countries" placeholder="Find country" />

MultiSelect

Props:

  • modelValue?: Array<string | number> (v-model)
  • options?: Array<{ label: string; value: string | number; disabled?: boolean }>
  • optionLabel?: string (default label)
  • optionValue?: string (default value)
  • placeholder?: string
  • searchPlaceholder?: string (default Search...)
  • disabled?: boolean
  • readonly?: boolean
  • loading?: boolean
  • loadingText?: string (default Loading...)
  • emptyText?: string (default No results)
  • filter?: boolean (default true)
  • clearable?: boolean (default false)
  • size?: 'small' | 'normal' | 'large' (default normal)
  • variant?: 'filled' | 'outlined' (default filled)

Events:

  • update:modelValue
  • change
  • search
  • focus
  • blur

Example:

<MultiSelect v-model="countries" :options="countryOptions" placeholder="Select countries" clearable />

MultiSelect tokens

Component tokens (override via theme.overrides.components.multiselect):

  • minWidth, fontSize, controlGap, chevronSize
  • padding, borderRadius, borderColor
  • backgroundColor, textColor, placeholderColor
  • focusBorderColor, focusRingShadow, hoverBorderColor
  • disabledOpacity
  • panelBackgroundColor, panelBorderColor, panelPadding, panelMaxHeight, panelRadiusOffset, panelShadow
  • searchPadding, searchBorderColor, searchBorderRadius
  • optionPadding, optionBorderRadius
  • optionHoverBackgroundColor, optionActiveBackgroundColor, optionActiveTextColor, optionHighlightedBackgroundColor
  • emptyPadding, emptyColor
  • loadingPadding, loadingColor
  • clearSize, clearRadius, clearHoverBackgroundColor
  • small.fontSize, small.padding
  • large.fontSize, large.padding

DatePicker

Props:

  • modelValue?: string (v-model, ISO date YYYY-MM-DD)
  • placeholder?: string
  • disabled?: boolean
  • readonly?: boolean
  • min?: string (ISO date YYYY-MM-DD)
  • max?: string (ISO date YYYY-MM-DD)
  • locale?: string (default en-US)
  • firstDayOfWeek?: number (default 0, Sunday)
  • size?: 'small' | 'normal' | 'large' (default normal)
  • variant?: 'filled' | 'outlined' (default filled)

Events:

  • update:modelValue
  • change
  • focus
  • blur

Example:

<DatePicker v-model="startDate" placeholder="Pick date" min="2026-01-01" max="2026-12-31" />

DateRangePicker

Props:

  • modelValue?: [string | null, string | null] | null (v-model, ISO date YYYY-MM-DD)
  • placeholder?: string
  • startPlaceholder?: string (default Start)
  • endPlaceholder?: string (default End)
  • separator?: string (default -)
  • disabled?: boolean
  • readonly?: boolean
  • min?: string (ISO date YYYY-MM-DD)
  • max?: string (ISO date YYYY-MM-DD)
  • locale?: string (default en-US)
  • firstDayOfWeek?: number (default 0, Sunday)
  • size?: 'small' | 'normal' | 'large' (default normal)
  • variant?: 'filled' | 'outlined' (default filled)

Events:

  • update:modelValue
  • change
  • focus
  • blur

Example:

<DateRangePicker v-model="dateRange" placeholder="Pick date range" min="2026-01-01" max="2026-12-31" />

TimePicker

Props:

  • modelValue?: string (v-model, time HH:mm)
  • placeholder?: string
  • disabled?: boolean
  • readonly?: boolean
  • min?: string (time HH:mm)
  • max?: string (time HH:mm)
  • step?: number (minutes, default 30)
  • format?: '24h' | '12h' (default 24h)
  • size?: 'small' | 'normal' | 'large' (default normal)
  • variant?: 'filled' | 'outlined' (default filled)

Events:

  • update:modelValue
  • change
  • focus
  • blur

Example:

<TimePicker v-model="meetingTime" placeholder="Pick time" min="09:00" max="18:00" :step="15" />

TimePicker tokens

Component tokens (override via theme.overrides.components.timepicker):

  • minWidth, fontSize, controlGap, chevronSize
  • padding, borderRadius, borderColor
  • backgroundColor, textColor, placeholderColor
  • focusBorderColor, focusRingShadow, hoverBorderColor
  • disabledOpacity
  • panelBackgroundColor, panelBorderColor, panelPadding, panelMaxHeight, panelRadiusOffset, panelShadow
  • optionPadding, optionBorderRadius
  • optionHoverBackgroundColor, optionActiveBackgroundColor, optionActiveTextColor
  • small.fontSize, small.padding
  • large.fontSize, large.padding

Pagination

Props:

  • modelValue?: number (v-model, default 1)
  • totalItems?: number (default 0)
  • pageSize?: number (default 10)
  • totalPages?: number (optional override instead of totalItems/pageSize)
  • siblingCount?: number (default 1)
  • boundaryCount?: number (default 1)
  • disabled?: boolean
  • size?: 'small' | 'normal' | 'large' (default normal)
  • variant?: 'filled' | 'outlined' (default filled)
  • prevLabel?: string (default Prev)
  • nextLabel?: string (default Next)
  • ellipsisLabel?: string (default ...)

Events:

  • update:modelValue
  • change

Slots:

  • indicator - slot props: { step, index, status, active, completed, upcoming, error }
  • step - slot props: { step, index, status, active, completed, upcoming, error }

Example:

<Pagination v-model="page" :total-items="240" :page-size="20" />

Pagination tokens

Component tokens (override via theme.overrides.components.pagination):

  • gap, itemMinWidth, fontSize, padding
  • borderRadius, borderColor
  • backgroundColor, textColor
  • hoverBackgroundColor
  • activeBorderColor, activeBackgroundColor, activeTextColor
  • focusBorderColor, focusRingShadow
  • disabledOpacity, ellipsisPadding
  • small.fontSize, small.padding
  • large.fontSize, large.padding

DataTable

Props:

  • rows?: Array<Record<string, unknown>>
  • columns?: Array<{ field: string; header?: string; sortable?: boolean; align?: 'left' | 'center' | 'right'; width?: string; minWidth?: string; formatter?: (row, value, column) => string | number }>
  • rowKey?: string | ((row, index) => string | number)
  • sortable?: boolean
  • sortField?: string | null
  • sortOrder?: 'asc' | 'desc' | null
  • loading?: boolean
  • loadingText?: string (default Loading...)
  • emptyText?: string (default No data)
  • striped?: boolean (default false)
  • hover?: boolean (default true)
  • size?: 'small' | 'normal' | 'large' (default normal)
  • variant?: 'filled' | 'outlined' (default filled)
  • showHeader?: boolean (default true)
  • ariaLabel?: string (default Data table)

Events:

  • update:sortField
  • update:sortOrder
  • sort
  • rowClick

Slots:

  • header-{field}
  • cell-{field}
  • empty
  • loading

Example:

<DataTable
    :columns="[
        { field: 'name', header: 'Name', sortable: true },
        { field: 'role', header: 'Role' },
        { field: 'age', header: 'Age', align: 'right', sortable: true },
    ]"
    :rows="[
        { id: 1, name: 'Alice', role: 'Developer', age: 29 },
        { id: 2, name: 'Bob', role: 'Designer', age: 34 },
    ]"
    row-key="id"
    sortable
    striped
/>

DataTable tokens

Component tokens (override via theme.overrides.components.datatable):

  • borderColor, borderRadius, backgroundColor
  • fontSize, textColor
  • headerBackgroundColor, headerTextColor, headerFontSize, headerFontWeight, headerBorderColor, headerGap
  • rowBackgroundColor, rowTextColor, rowBorderColor
  • cellPadding
  • stripedBackgroundColor, hoverBackgroundColor
  • sortIconColor, sortIconActiveColor, sortIconSize
  • statePadding, stateTextColor
  • small.fontSize, small.cellPadding
  • large.fontSize, large.cellPadding

Textarea

Props:

  • modelValue?: string (v-model)
  • placeholder?: string
  • disabled?: boolean
  • readonly?: boolean
  • size?: 'small' | 'normal' | 'large' (default normal)
  • variant?: 'filled' | 'outlined' (default filled)
  • rows?: number (default 3)

Events:

  • update:modelValue
  • input
  • change
  • focus
  • blur

Example:

<Textarea v-model="bio" placeholder="Tell us about yourself" rows="4" />

FileUpload

Props:

  • modelValue?: File | File[] | null (v-model)
  • multiple?: boolean
  • accept?: string
  • disabled?: boolean
  • readonly?: boolean
  • maxSize?: number (bytes)
  • maxFiles?: number
  • placeholder?: string
  • buttonLabel?: string (default Browse)
  • size?: 'small' | 'normal' | 'large' (default normal)
  • variant?: 'filled' | 'outlined' (default filled)

Events:

  • update:modelValue
  • change
  • reject (payload: Array<{ file: File; reason: 'maxSize' | 'maxFiles'; maxSize?: number; maxFiles?: number }> )
  • focus
  • blur

Example:

<FileUpload v-model="attachments" multiple :max-files="5" :max-size="10_000_000" />

FileUpload tokens

Component tokens (override via theme.overrides.components.fileUpload):

  • minHeight, fontSize, gap, padding
  • borderRadius, borderColor
  • backgroundColor, textColor, placeholderColor
  • focusBorderColor, focusRingShadow, hoverBorderColor
  • disabledOpacity, dragBackgroundColor
  • listGap, itemPadding, itemBorderColor, itemBackgroundColor, itemRadius, itemTextColor, sizeTextColor
  • buttonPadding, buttonRadius, buttonBorderColor, buttonBackgroundColor, buttonTextColor, buttonHoverBackgroundColor
  • removeSize, removeRadius, removeHoverBackgroundColor
  • small.fontSize, small.padding, small.buttonPadding
  • large.fontSize, large.padding, large.buttonPadding

NumberInput

Props:

  • modelValue?: number | null (v-model)
  • min?: number
  • max?: number
  • step?: number (default 1)
  • precision?: number
  • placeholder?: string
  • disabled?: boolean
  • readonly?: boolean
  • controls?: boolean (default true)
  • size?: 'small' | 'normal' | 'large' (default normal)
  • variant?: 'filled' | 'outlined' (default filled)
  • ariaLabel?: string (default Number input)

Events:

  • update:modelValue
  • input
  • change
  • focus
  • blur

Example:

<NumberInput v-model="quantity" :min="0" :max="10" :step="1" />

RadioGroup / RadioButton

Props (RadioGroup):

  • modelValue?: string | number | boolean (v-model)
  • name?: string
  • disabled?: boolean
  • variant?: 'filled' | 'outlined' (default filled)
  • direction?: 'vertical' | 'horizontal' (default vertical)

Props (RadioButton):

  • value?: string | number | boolean
  • label?: string
  • disabled?: boolean
  • name?: string
  • variant?: 'filled' | 'outlined' (default filled)

Example:

<RadioGroup v-model="plan" direction="horizontal">
    <RadioButton value="basic">Basic</RadioButton>
    <RadioButton value="pro">Pro</RadioButton>
</RadioGroup>

Breadcrumbs

Props:

  • items?: Array<{ label?: string; to?: string; href?: string; url?: string; active?: boolean; disabled?: boolean }>
  • separator?: string (default /)
  • ariaLabel?: string (default Breadcrumbs)

Slots:

  • item - slot props: { item, index, isLast, active }
  • separator (optional) - slot props: { separator }

Example:

<Breadcrumbs
    :items="[
        { label: 'Home', to: '/' },
        { label: 'Settings', to: '/settings' },
        { label: 'Profile', active: true },
    ]"
/>

Breadcrumbs tokens

Component tokens (override via theme.overrides.components.breadcrumbs):

  • gap, fontSize, textColor, hoverColor, activeColor
  • separatorColor, disabledOpacity

Tabs / Tab / TabPanel

Props (Tabs):

  • modelValue?: string | number (v-model)
  • disabled?: boolean
  • orientation?: 'horizontal' | 'vertical' (default horizontal)

Props (Tab):

  • value: string | number
  • label?: string
  • disabled?: boolean

Props (TabPanel):

  • value: string | number

Example:

<Tabs v-model="tab">
    <template #tabs>
        <Tab value="overview">Overview</Tab>
        <Tab value="settings">Settings</Tab>
    </template>
    <template #panels>
        <TabPanel value="overview">Overview content</TabPanel>
        <TabPanel value="settings">Settings content</TabPanel>
    </template>
</Tabs>

Tabs tokens

Component tokens (override via theme.overrides.components.tabs):

  • gap, listGap, listBorderWidth, listBorderColor, listVerticalPadding
  • tabPadding, tabFontSize, tabBorderRadius
  • tabTextColor, tabBackgroundColor, tabHoverBackgroundColor
  • tabActiveTextColor, tabActiveBackgroundColor, tabActiveBorderColor, tabActiveBorderWidth
  • panelPadding, panelBorderRadius, panelBackgroundColor, panelTextColor
  • disabledOpacity

Accordion / AccordionItem

Props (Accordion):

  • modelValue?: string | number | Array<string | number> (v-model)
  • multiple?: boolean (default false)
  • disabled?: boolean
  • variant?: 'filled' | 'outlined' (default filled)
  • size?: 'small' | 'normal' | 'large' (default normal)
  • ariaLabel?: string
  • ariaLabelledby?: string

Props (AccordionItem):

  • value: string | number
  • title?: string
  • disabled?: boolean
  • unmount?: boolean (default false)

Events:

  • update:modelValue
  • change

Example:

<Accordion v-model="faq">
    <AccordionItem value="shipping" title="Shipping">
        Shipping details
    </AccordionItem>
    <AccordionItem value="returns" title="Returns">
        Returns policy
    </AccordionItem>
</Accordion>

Accordion tokens

Component tokens (override via theme.overrides.components.accordion):

  • gap, borderRadius, borderColor, backgroundColor
  • headerGap, headerPadding, headerFontSize, headerFontWeight
  • headerTextColor, headerBackgroundColor, headerHoverBackgroundColor, headerActiveBackgroundColor
  • contentPadding, contentTextColor, contentBackgroundColor
  • iconSize, iconColor, dividerColor
  • focusRingShadow, disabledOpacity
  • small.headerPadding, small.headerFontSize, small.contentPadding
  • large.headerPadding, large.headerFontSize, large.contentPadding

Toast / ToastContainer

Props (Toast):

  • modelValue?: boolean (v-model)
  • title?: string
  • message?: string
  • severity?: 'neutral' | 'info' | 'success' | 'warn' | 'danger' (default neutral)
  • closable?: boolean (default true)
  • duration?: number (ms, default 0, no auto-close)

Props (ToastContainer):

  • position?: 'top-right' | 'top-left' | 'bottom-right' | 'bottom-left' (default top-right)

Example:

<ToastContainer position="top-right">
    <Toast v-model="toastOpen" title="Saved" message="Changes are saved." severity="success" :duration="2500" />
</ToastContainer>

Toast tokens

Component tokens (override via theme.overrides.components.toast):

  • gap, padding, borderRadius, borderColor
  • backgroundColor, textColor, shadow, minWidth
  • fontSize, lineHeight, bodyGap
  • titleFontSize, titleFontWeight, closeSize
  • containerGap, containerPadding, containerMaxWidth, zIndex
  • info.*, success.*, warn.*, danger.* (backgroundColor/borderColor/textColor)

Alert

Props:

  • modelValue?: boolean (optional v-model)
  • title?: string
  • message?: string
  • severity?: 'neutral' | 'info' | 'success' | 'warn' | 'danger' (default neutral)
  • closable?: boolean (default false)
  • icon?: string

Slots:

  • default - message content (fallbacks to message)
  • title (optional)
  • icon (optional)
  • actions (optional)
  • close (optional)

Events:

  • update:modelValue
  • close

Example:

<Alert v-model="alertOpen" severity="warn" title="Unsaved changes" closable>
    You have unsaved form changes.
    <template #actions>
        <Button label="Save" size="small" />
    </template>
</Alert>

Alert tokens

Component tokens (override via theme.overrides.components.alert):

  • gap, padding, borderRadius, borderColor
  • backgroundColor, textColor, iconColor
  • fontSize, lineHeight, bodyGap
  • titleFontSize, titleFontWeight
  • actionsGap, closeSize, closeRadius, closeFontSize, closeHoverBackgroundColor
  • info.*, success.*, warn.*, danger.* (backgroundColor/borderColor/textColor)

Textarea tokens

Component tokens (override via theme.overrides.components.textarea):

  • gap, fontSize, padding
  • borderRadius, borderColor
  • backgroundColor, textColor, placeholderColor
  • focusBorderColor, focusRingShadow, hoverBorderColor
  • disabledOpacity
  • minHeight, resize
  • small.fontSize, small.padding
  • large.fontSize, large.padding

Modal

Props:

  • modelValue?: boolean (v-model)
  • title?: string
  • size?: 'sm' | 'md' | 'lg'
  • closeOnOverlay?: boolean (default true)
  • closeOnEsc?: boolean (default true)
  • showClose?: boolean (default true)
  • lockScroll?: boolean (default true)

Slots:

  • header (optional) - replaces the title area
  • body (optional) - modal content (defaults to default slot if not provided)
  • default (optional) - modal content if body slot is not used
  • footer (optional)
  • close (optional) - custom close button; slot props: { close }

Events:

  • update:modelValue
  • open
  • close

Example:

<Modal v-model="open" title="Confirm action" size="sm">
    <template #body>
        <p>Are you sure?</p>
    </template>
    <template #footer>
        <Button label="Cancel" severity="secondary" @click="open = false" />
        <Button label="Confirm" @click="open = false" />
    </template>
</Modal>

Modal tokens

Component tokens (override via theme.overrides.components.modal):

  • width, maxWidth, maxHeight
  • widthSm, maxWidthSm
  • widthLg, maxWidthLg
  • padding, borderRadius
  • backgroundColor, textColor
  • overlayBackgroundColor
  • shadow
  • zIndex
  • headerGap, bodyGap, footerGap
  • titleFontSize, titleLineHeight, titleFontWeight
  • closeSize, closeRadius, closeOffset
  • closeColor, closeFontSize, closeHoverBackgroundColor

Drawer

Props:

  • modelValue?: boolean (v-model)
  • title?: string
  • position?: 'left' | 'right' | 'top' | 'bottom' (default right)
  • size?: 'sm' | 'md' | 'lg'
  • overlay?: boolean (default true)
  • closeOnOverlay?: boolean (default true)
  • closeOnEsc?: boolean (default true)
  • showClose?: boolean (default true)
  • lockScroll?: boolean (default true)

Slots:

  • header (optional) - replaces the title area
  • body (optional) - drawer content (defaults to default slot if not provided)
  • default (optional) - drawer content if body slot is not used
  • footer (optional)
  • close (optional) - custom close button; slot props: { close }

Events:

  • update:modelValue
  • open
  • close

Example:

<Drawer v-model="open" title="Filters" position="right">
    <template #body>
        <p>Drawer content</p>
    </template>
    <template #footer>
        <Button label="Reset" severity="secondary" size="small" />
        <Button label="Apply" size="small" @click="open = false" />
    </template>
</Drawer>

Drawer tokens

Component tokens (override via theme.overrides.components.drawer):

  • width, widthSm, widthLg
  • height, heightSm, heightLg
  • padding, borderRadius
  • backgroundColor, textColor
  • overlayBackgroundColor
  • shadow
  • zIndex
  • headerGap, bodyGap, footerGap
  • titleFontSize, titleLineHeight, titleFontWeight
  • closeSize, closeRadius, closeOffset
  • closeColor, closeFontSize, closeHoverBackgroundColor

Dropdown

Props:

  • modelValue?: boolean (v-model)
  • items?: Array<{ label?: string; to?: string; href?: string; url?: string; icon?: string; disabled?: boolean; separator?: boolean; command?: () => void }>
  • placement?: 'bottom-start' | 'bottom-end' | 'top-start' | 'top-end' | 'bottom' | 'top' (default bottom-start)
  • offset?: number (default 6)
  • disabled?: boolean
  • closeOnSelect?: boolean (default true)
  • closeOnEsc?: boolean (default true)
  • matchTriggerWidth?: boolean (default true)

Slots:

  • trigger
  • default (optional) - dropdown content (defaults to items list if provided)

Note: For custom dropdown content, add data-dropdown-close to clickable elements to auto-close on click.

Events:

  • update:modelValue
  • open
  • close
  • select

Example:

<Dropdown :items="menuItems">
    <template #trigger>
        <Button label="Actions" />
    </template>
</Dropdown>

Dropdown tokens

Component tokens (override via theme.overrides.components.dropdown):

  • panelPadding, panelBorderRadius, panelBorderColor
  • panelBackgroundColor, panelShadow, zIndex
  • disabledOpacity, itemPadding

Tooltip

Props:

  • text?: string
  • placement?: 'top' | 'bottom' | 'left' | 'right' (default top)
  • disabled?: boolean
  • arrow?: boolean (default false)

Slots:

  • default - trigger content
  • content (optional) - tooltip content (fallbacks to text)

Example:

<Tooltip text="Helpful hint" arrow>
    <Button label="Hover me" />
</Tooltip>

Skeleton

Props:

  • width?: string | number
  • height?: string | number
  • variant?: 'text' | 'rect' | 'circle' (default text)
  • animated?: boolean (default true)

Example:

<Skeleton width="240px" height="14px" />
<Skeleton width="180px" height="14px" />
<Skeleton variant="circle" width="48" />

Badge

Props:

  • label?: string
  • size?: 'small' | 'normal' | 'large' (default normal)
  • variant?: 'solid' | 'soft' | 'outline' (default soft)
  • severity?: 'neutral' | 'info' | 'success' | 'warn' | 'danger' (default neutral)
  • ariaLabel?: string

Slots:

  • default - badge content (fallbacks to label)

Example:

<Badge label="Beta" />
<Badge severity="success" variant="outline">Active</Badge>

Badge tokens

Component tokens (override via theme.overrides.components.badge):

  • fontSize, lineHeight, paddingX, paddingY, borderRadius, gap
  • backgroundColor, textColor, borderColor
  • softBackgroundColor, softTextColor, softBorderColor
  • outlineTextColor, outlineBorderColor
  • info.*, success.*, warn.*, danger.* (backgroundColor/textColor/borderColor/soft*/outline*)
  • small.fontSize, small.paddingX, small.paddingY
  • large.fontSize, large.paddingX, large.paddingY

Chip

Props:

  • label?: string
  • size?: 'small' | 'normal' | 'large' (default normal)
  • variant?: 'solid' | 'soft' | 'outline' (default soft)
  • severity?: 'neutral' | 'info' | 'success' | 'warn' | 'danger' (default neutral)
  • disabled?: boolean
  • closable?: boolean (default false)
  • icon?: string
  • ariaLabel?: string
  • closeLabel?: string (default Remove)

Slots:

  • default - chip content (fallbacks to label)
  • icon (optional)
  • close (optional)

Events:

  • close

Example:

<Chip label="New" />
<Chip severity="info" closable>Info</Chip>

Chip tokens

Component tokens (override via theme.overrides.components.chip):

  • fontSize, lineHeight, paddingX, paddingY, borderRadius, gap
  • backgroundColor, textColor, borderColor
  • softBackgroundColor, softTextColor, softBorderColor
  • outlineTextColor, outlineBorderColor
  • iconSize, closeSize, closeFontSize, closeRadius, closeColor, closeHoverBackgroundColor, disabledOpacity
  • info.*, success.*, warn.*, danger.* (backgroundColor/textColor/borderColor/soft*/outline*)
  • small.fontSize, small.paddingX, small.paddingY
  • large.fontSize, large.paddingX, large.paddingY

Avatar

Props:

  • src?: string
  • alt?: string
  • name?: string
  • size?: 'small' | 'normal' | 'large' (default normal)
  • shape?: 'circle' | 'rounded' (default circle)
  • status?: 'online' | 'offline' | 'busy' | 'away'

Slots:

  • default - custom avatar content

Example:

<Avatar name="Ada Lovelace" />
<Avatar src="/img/ada.png" alt="Ada Lovelace" size="large" />
<Avatar name="Ada Lovelace" status="online" />

Avatar tokens

Component tokens (override via theme.overrides.components.avatar):

  • size, fontSize, fontWeight
  • backgroundColor, textColor, borderColor, borderWidth, borderRadius
  • statusSize, statusBorderWidth, statusBorderColor
  • statusOnlineColor, statusOfflineColor, statusBusyColor, statusAwayColor
  • small.size, small.fontSize, small.statusSize
  • large.size, large.fontSize, large.statusSize

Progress

Props:

  • value?: number (0-100; omit for indeterminate)
  • variant?: 'linear' | 'circular' (default linear)
  • size?: 'small' | 'normal' | 'large' (default normal)
  • label?: string
  • showValue?: boolean (default false)
  • severity?: 'neutral' | 'info' | 'success' | 'warn' | 'danger' (default neutral)
  • ariaLabel?: string

Example:

<Progress :value="64" />
<Progress variant="circular" :value="42" size="small" />
<Progress variant="linear" severity="success" showValue :value="85" />
<Progress variant="linear" />

Progress tokens

Component tokens (override via theme.overrides.components.progress):

  • width, height, borderRadius
  • backgroundColor, barColor
  • labelColor, labelFontSize, gap
  • circularSize, circularThickness
  • animationDuration
  • info.barColor, success.barColor, warn.barColor, danger.barColor
  • small.height, small.labelFontSize, small.circularSize, small.circularThickness
  • large.height, large.labelFontSize, large.circularSize, large.circularThickness

Slider

Props:

  • modelValue?: number | [number, number] (v-model)
  • min?: number (default 0)
  • max?: number (default 100)
  • step?: number (default 1)
  • range?: boolean (default false)
  • disabled?: boolean
  • size?: 'small' | 'normal' | 'large' (default normal)
  • variant?: 'filled' | 'outlined' (default filled)
  • showValue?: boolean (default false)
  • marks?: Array<{ value: number; label?: string }>

Events:

  • update:modelValue
  • input
  • change
  • focus
  • blur

Example:

<Slider v-model="volume" :min="0" :max="100" :step="5" show-value />
<Slider v-model="priceRange" :min="0" :max="1000" :step="10" range />

Slider tokens

Component tokens (override via theme.overrides.components.slider):

  • width, gap
  • textColor
  • trackHeight, trackBackgroundColor, trackRadius, fillBackgroundColor
  • thumbSize, thumbColor, thumbBorderColor, thumbBorderWidth, thumbShadow
  • focusRingShadow, disabledOpacity
  • markSize, markColor, markLabelFontSize, markLabelColor, marksHeight
  • valueFontSize, valueColor
  • small.trackHeight, small.thumbSize, small.valueFontSize
  • large.trackHeight, large.thumbSize, large.valueFontSize

Stepper

Props:

  • modelValue?: string | number (v-model)
  • steps?: Array<{ label?: string; description?: string; value?: string | number; disabled?: boolean; status?: 'completed' | 'active' | 'upcoming' | 'error' }>
  • orientation?: 'horizontal' | 'vertical' (default horizontal)
  • size?: 'small' | 'normal' | 'large' (default normal)
  • clickable?: boolean (default false)
  • ariaLabel?: string
  • ariaLabelledby?: string

Events:

  • update:modelValue
  • change

Example:

<Stepper v-model="step" :steps="steps" clickable />
<Stepper v-model="step" :steps="steps" orientation="vertical" size="small" />

Stepper tokens

Component tokens (override via theme.overrides.components.stepper):

  • gap, itemGap, lineThickness, lineLength, lineColor
  • indicatorSize, indicatorBorderRadius, indicatorBorderWidth, indicatorFontSize
  • indicatorBackgroundColor, indicatorTextColor, indicatorBorderColor
  • activeIndicatorBackgroundColor, activeIndicatorTextColor, activeIndicatorBorderColor
  • completedIndicatorBackgroundColor, completedIndicatorTextColor, completedIndicatorBorderColor
  • errorIndicatorBackgroundColor, errorIndicatorTextColor, errorIndicatorBorderColor
  • labelFontSize, labelColor, descriptionFontSize, descriptionColor
  • disabledOpacity
  • small.indicatorSize, small.indicatorFontSize, small.labelFontSize, small.descriptionFontSize, small.lineLength, small.itemGap
  • large.indicatorSize, large.indicatorFontSize, large.labelFontSize, large.descriptionFontSize, large.lineLength, large.itemGap

Rating

Props:

  • modelValue?: number (v-model)
  • max?: number (default 5)
  • allowHalf?: boolean (default false)
  • readonly?: boolean
  • disabled?: boolean
  • size?: 'small' | 'normal' | 'large' (default normal)
  • ariaLabel?: string

Events:

  • update:modelValue
  • change
  • focus
  • blur

Example:

<Rating v-model="score" />
<Rating v-model="score" allow-half size="large" />

Rating tokens

Component tokens (override via theme.overrides.components.rating):

  • gap, size, color, activeColor, hoverColor
  • focusRingShadow, focusRadius, disabledOpacity
  • small.size
  • large.size

Tokens

VueForge exposes design tokens as CSS variables generated from the theme preset. Core groups:

  • colors.*--vf-{color} + shades (--vf-{color}-100..900)
  • radii.* → corner radii
  • typography.* → base font size & line height
  • states.* → focus ring, disabled opacity
  • controls.* → base control sizing (height, padding)
  • sizes.sm/lg → shared small/large sizing for Button/Input/Select

Typed tokens:

  • ThemeTokens/ThemeOptions/ThemePreset are exported for type-safe theming in TS.
  • components.* accepts component-specific tokens (typed keys: button/card/checkbox/radio/tabs/accordion/toast/alert/input/numberInput/formField/textarea/link/breadcrumbs/menu/modal/drawer/popover/dropdown/select/autocomplete/multiselect/datepicker/daterangepicker/timepicker/pagination/switch/tooltip/skeleton/progress/badge/chip/avatar/datatable/slider/stepper/rating).

Default core values (from DefaultTheme):

Token Value
borderWidth 1px
controls.height 2rem
controls.paddingY 0.25rem
controls.paddingX 0.6rem
radii.sm 4px
radii.md 6px
radii.lg 10px
typography.fontSize 1rem
typography.lineHeight 1.4
states.disabledOpacity 0.6
states.focusRingShadow 0 0 0 3px rgba(var(--vf-blue-600-rgb), 0.12)
sizes.sm.fontSize 0.875rem
sizes.sm.paddingY 0.2rem
sizes.sm.paddingX 0.5rem
sizes.lg.fontSize 1.125rem
sizes.lg.paddingY 0.5rem
sizes.lg.paddingX 1rem

Example override:

setTheme({
    preset: DefaultTheme,
    overrides: {
        typography: {
            fontSize: '0.9375rem',
            lineHeight: '1.4',
        },
        controls: {
            height: '2rem',
            paddingY: '0.25rem',
            paddingX: '0.6rem',
        },
        sizes: {
            sm: { fontSize: '0.8125rem', paddingY: '0.2rem', paddingX: '0.45rem' },
            lg: { fontSize: '1.125rem', paddingY: '0.5rem', paddingX: '1rem' },
        },
    },
});

Examples

The example app lives in src/example and showcases all components.

npm run dev

Theming

VueForge maps the theme preset to CSS variables. You can override parts of the preset and it will recompute shades for color tokens.

app.use(VueForge, {
    theme: {
        preset: DefaultTheme,
        strict: false,
        overrides: {
            colors: {
                green: '#18a66a',
            },
        },
        selector: ':root',
        darkSelector: ':root[data-theme=dark]',
    },
});

You can also update the theme at runtime:

import { setTheme, updateTheme } from '@codemonster-ru/vueforge';

setTheme({ preset: DefaultTheme });
updateTheme({
    overrides: {
        colors: { blue: '#2b6cb0' },
    },
});

Notes:

  • Non-hex colors (e.g. rgb(...), hsl(...), var(--brand)) are allowed, but shade variables (--vf-*-100..900) will not be generated.
  • Set theme.strict: true to throw on invalid token values (non-string / non-plain object) during theme application.

Theme API

Core methods:

  • setTheme(options) — apply a theme preset (with optional overrides).
  • updateTheme(partial) — update only parts of the current theme.
  • getTheme() — get the last applied theme options.

Key options:

  • preset: base theme object (e.g. DefaultTheme)
  • overrides: partial overrides merged into preset
  • selector: CSS selector for base variables (default :root)
  • darkSelector: selector for dark scheme (default :root[data-theme=dark])
  • strict: throw on invalid token values (otherwise warnings)

Example:

setTheme({
    preset: DefaultTheme,
    overrides: {
        colors: { blue: '#2b6cb0' },
        typography: { fontSize: '0.95rem' },
    },
    strict: true,
});

License

MIT

Author

@KolesnikovKirill