Vue Core
Basic UI components for Vue 3.
✨ Features
- Tree-shaking: Only import what you use. Importing a single component won't bundle the rest of the library.
- Easy overrides: Default styles use zero specificity (
:where()), so your own CSS always wins.
📦 Installation
npm install @digitalwalletcorp/vue-core @digitalwalletcorp/vue-svg-icons
# or
yarn add @digitalwalletcorp/vue-core @digitalwalletcorp/vue-svg-icons
⚠️ Requirements
- Vue 3.5.29+: Props are typed with Vue's
ClassValue, which is exported since Vue 3.5.29.- @digitalwalletcorp/vue-svg-icons 1.15.3+: Used for the icons in components.
📖 Usage
There are three ways to use the components.
| When to use | Bundled components | |
|---|---|---|
| Import individually | When you want to minimize bundle size or prefer explicit imports | Only the components you import |
| Register all components globally (Vue) | When you want to use components without importing them in each file | All components |
| Register components globally (Nuxt) | When you want to use components globally in a Nuxt project | Only the components you use |
1. Import components individually
<script setup lang="ts">
import { CopyButton } from '@digitalwalletcorp/vue-core';
</script>
<template>
<CopyButton value="Order #12345" />
</template>
2. Register all components globally (Vue)
// main.ts
import { createApp } from 'vue';
import { registerComponents } from '@digitalwalletcorp/vue-core/register';
import App from './App.vue';
const app = createApp(App);
registerComponents(app);
app.mount('#app');
3. Register components globally (Nuxt)
// nuxt.config.ts
export default defineNuxtConfig({
modules: ['@digitalwalletcorp/vue-core/nuxt']
});
🔤 Types
The props, events and slots of each component are exported as types named <Component>Props, <Component>Emits and <Component>Slots, such as ModalDialogProps and ModalDialogEmits.
Use them when you wrap a component in your own component.
<script setup lang="ts">
import { ModalDialog } from '@digitalwalletcorp/vue-core';
import type { ModalDialogProps } from '@digitalwalletcorp/vue-core';
const props = defineProps<ModalDialogProps>();
</script>
<template>
<ModalDialog v-bind="props" class="app-dialog" />
</template>
📐 Stylesheet
Import the stylesheets to ensure default alignment and icon styles.
- Vue: Import in your entry file.
// main.ts
import '@digitalwalletcorp/vue-core/style.css';
import '@digitalwalletcorp/vue-svg-icons/style.css'; // Required for components using icons from vue-svg-icons
- Nuxt: Add to your config array.
// nuxt.config.ts
export default defineNuxtConfig({
css: [
'@digitalwalletcorp/vue-core/style.css',
'@digitalwalletcorp/vue-svg-icons/style.css' // Required for components using icons from vue-svg-icons
]
});
💡 Icon Styles
Components such as
AccordionFieldsetrely on @digitalwalletcorp/vue-svg-icons. Importing its stylesheet ensures icons align properly with text.
📏 Sizes
The spaces around the texts, such as paddings, gaps, and margins, are set in em, so that they follow the font size of your application.
The defaults are the em values that give the pixel sizes below at a font size of 12px.
Line elements (borders, outlines, shadows) and non-text component sizes are set in px.
| px | em |
|---|---|
| 2 | 0.17 |
| 3 | 0.25 |
| 4 | 0.33 |
| 5 | 0.4 |
| 6 | 0.5 |
| 8 | 0.67 |
| 10 | 0.83 |
| 12 | 1 |
| 14 | 1.17 |
| 16 | 1.33 |
| 18 | 1.5 |
| 20 | 1.67 |
| 22 | 1.83 |
| 28 | 2.33 |
| 30 | 2.5 |
⚙️ Adapting to your application
🎨 Dark Mode & Theme Support
Components automatically adapt to your application's color-scheme (supporting both light and dark modes natively).
- Follow OS Setting: Add
:root { color-scheme: light dark; }to your global CSS. - Custom Theme Switching: Change the CSS
color-schemeproperty on:rootor a parent container (e.g.,color-scheme: dark). The components will switch automatically. - No Theme Switching: Add
:root { color-scheme: light; }to your global CSS, and the components are displayed in light mode.
⚠️ Declare
color-schemeeven if you don't switch themes This library uses the CSSlight-dark()function for theming. Some build tools, when optimizing for older browsers, require acolor-schemedeclaration to correctly process these styles. Without it, default styles (like backgrounds and borders) may be missing in the production build, even if they appear correctly on the development server. To prevent this, please declarecolor-schemein your global CSS.
🛠️ Customizing Styles (--dwui-* Variables)
Default styles use CSS variables (--dwui-*) and zero-specificity selectors (:where()), making them easy to override. The variables of each component are listed in its document. docs/dwui-variables.css lists all of them with their default values, grouped by the component they apply to. Copy the lines you want to change into your own dwui-variables.css.
The following default styles do not use :where(). To override them, use a CSS rule with higher specificity.
| Component | Style | Reason |
|---|---|---|
ScreenLoading | outline on focus | The loading does not accept user interaction, so it does not show a focus ring. |
We recommend creating a dwui-variables.css file to map your application's design tokens to the library's --dwui-* variables, and importing it after the library stylesheet. If you use both vue-forms and vue-core, you can use a single dwui-variables.css file for both libraries, as they share common variables like those for focus rings.
/* dwui-variables.css */
:root {
--dwui-background-tab-header: var(--app-tab-header-background);
--dwui-color-text-tab-header: var(--app-tab-header-text);
--dwui-background-tab-header-selected: var(--app-tab-header-selected-background);
--dwui-color-text-tab-header-selected: var(--app-tab-header-selected-text);
}
// nuxt.config.ts
export default defineNuxtConfig({
css: [
'@digitalwalletcorp/vue-core/style.css',
'@digitalwalletcorp/vue-svg-icons/style.css',
'@/assets/css/default.css', // your global CSS
'@/assets/css/dwui-variables.css'
]
});
🧭 Application-wide Options (VueCore)
Settings that are the same on every page, such as the texts of DataTable or the timezone of the time on snackbars, can be set once for the whole application instead of being passed to each component.
Install the VueCore plugin with app.use and pass the options to it.
A prop wins over the application-wide value, and without either, the default of the library is used.
// Vue: main.ts
import { VueCore } from '@digitalwalletcorp/vue-core';
app.use(VueCore, {
dataTable: {
labels: { totalCount: 'Total', totalUnit: 'records', noData: 'No data' },
sortMode: 'page'
}
});
// Nuxt: plugins/vue-core.ts
import { VueCore } from '@digitalwalletcorp/vue-core';
export default defineNuxtPlugin((nuxtApp) => {
nuxtApp.vueApp.use(VueCore, {
dataTable: {
labels: { totalCount: 'Total', totalUnit: 'records', noData: 'No data' },
sortMode: 'page'
},
snackbar: {
// The timezone the user selected. A ref or a function is read each time a snackbar is shown.
timezone: () => userSession.timezone
}
});
});
| Property | Type | Description |
|---|---|---|
dataTable | DataTableOptions | Sets default props for DataTable components across the application. For example, you can configure default labels or sort behavior. |
snackbar | SnackbarOptions | Sets the default timezone of the time shown on snackbars, as a string, a ref, or a function that returns it. It applies to the snackbars shown with useSnackbar() and to CopyButton. |
csv | CsvOptions | Sets the defaults of the CSV download of DataTable, such as the delimiter, the encoding and the text of the confirmation dialog. It applies to the functions returned by useDataTableDownload(). |
Installing VueCore also connects the dialogs, windows and snackbars shown from code to your app, so plugins and provided values such as i18n or a store work inside them.
Install it without options if you only need this.
To set the options for only a part of the application, provide them with vueCoreOptionsKey in a component above the components.
🛠️ Helper Functions
Dialogs, snackbars and floating windows are shown from code, so you can call them from a click handler or a store action without placing a component in the template.
import { showConfirmationDialog, showSnackbar } from '@digitalwalletcorp/vue-core';
const onClickDelete = async () => {
const result = await showConfirmationDialog('Do you want to delete this item?', { title: 'Delete item' });
if (result === 'yes') {
await deleteItem();
showSnackbar('The item has been deleted.', { duration: 5000 });
}
};
| Function | Description |
|---|---|
showInformationDialog() / showConfirmationDialog() / showWarningDialog() / showErrorDialog() / showModalDialog() | Shows a modal dialog with a message and returns the button the user chose. |
showSnackbar() / closeAllSnackbars() / useSnackbar() | Shows a short message at an edge of the screen. |
showOverlayBox() / closeAllOverlayBoxes() / useOverlayBox() | Shows a component in an OverlayBox and returns a handle to close it. |
showFloatingComponent() / showFloatingMessage() / closeAllFloatingComponents() / useFloatingComponent() | Shows a component or a message in a window that floats over the page without a backdrop. |
showScreenLoading() | Covers the whole screen with a spinner until the returned handle is closed. |
downloadDataTablePage() / downloadDataTableAll() / dataTableToCsv() / useDataTableDownload() | Saves the rows of a DataTable as a CSV file. |
headersToCsvColumns() / rowToCsvColumns() | Converts DataTable headers and rows into CSV columns. |
saveFile() | Saves a Blob, an ArrayBuffer or a data URL as a file through the download of the browser. |
resolveLabel() | Returns the text of a LabelText, a string or a function that returns a string. |
Functions that help you implement components, such as waiting for an element to appear or finding the first field to focus, are listed in Component Helpers.
Many components and helper functions accept text labels as LabelText, which is a string or a function () => string.
Passing a function allows for dynamic text that updates with your application's locale, for example when using an i18n library.
See Label Helpers for more details.
🧰 Components
| Component | Description |
|---|---|
AccordionFieldset | A fieldset whose contents can be collapsed and expanded from the legend. |
AccordionSection | An area whose contents can be collapsed and expanded with a toggle button below them. |
CopyButton | A button that copies a value to the clipboard. |
DarkModeSelector | A switch that toggles between light and dark mode and remembers the choice. |
DataTable | A table for a list of records, with sortable and resizable headers, row selection, and paging controls. |
DiffText | Compares two strings character by character and shows the added, removed and unchanged characters in different colors. |
HelpButton | A question-mark button that shows its contents in a popover next to the button. |
HelpPopper | A question-mark icon that shows its contents in a tooltip while hovered or focused. |
HighlightText | Shows a text with every part that matches a word highlighted. |
HourglassLoading | Shows an hourglass in place of a value while it is loading. |
IntersectionLazyComponent | Renders its contents only once it scrolls into view. |
LabelIcon | Displays an icon and a text label side by side. |
LabelButton | Renders a button containing an icon and a text label. |
ModalDialog | A dialog that shows a message and asks the user to answer with its buttons. |
OverlayBox | A window shown over a dimmed backdrop that covers the whole page, with a title and a close button. |
PageSection | A section of a page with a heading. |
PageTitle | The title bar of a page, with the contents of the default slot on its right side. |
ScreenLoading | Covers the whole screen with a dimmed backdrop and shows a spinner. |
TabGroup / TabContent | Switches between contents with tab headers. |
WarningPopper | A warning icon that shows its contents in a tooltip while hovered or focused. |
📜 License
This project is licensed under the MIT License. See the LICENSE file for details.