Color Admin

“Vue 3 + Vite JS Version” Documentation by “Sean Ngu” v5.4.1

CLI

Updated on: 27/July/2024
By: Sean Ngu

If you have any inquiries or require further assistance beyond what is covered in this help file, please do not hesitate to send us a message through Wrapbootstrap. We are more than happy to help.

Thank you very much!

Follow the following step to install the vue cli in your localhost
You may refer to their official documentation for how to setup the development environment.
Setup Guide

<!-- run the following command -->
cd /your-path-url/template_vue3
npm install
npm run serve

<!-- browse the url -->
http://localhost:8081/

Verify that you are running at least node 20.x.x or later and npm 10.x.x by running node -v and npm -v in a terminal/console window. Older versions produce errors, but newer versions are fine.


Copy over the required image from global assets folder

<!-- copy the following folder-->
/admin/template/assets/img
 
<!-- paste it into vue3 folder -->
/admin/template/template_vue3/public/assets/img

File structure overview for Vue JS Version

template_vue/
├── .eslintrc.cjs
├── .gitignore
├── .vscode/
├── cypress/
├── cypress.json
├── env.d.ts
├── index.html
├── package.json
├── public/
├── README.md
├── src/
│   ├── App.vue
│   ├── assets/
│   ├── components/
│   ├── composables/
│   ├── main.ts
│   ├── router/
│   ├── scss/
│   ├── stores/
│   └── views/
├── tsconfig.app.json
├── tsconfig.json
├── tsconfig-vite-config.json
└── tsconfig.vitest.json
    └── vite.config.ts

Below is the code from App.vue which include the header, sidebar, right sidebar, top menu, page content and footer. You may remove the component if you are not using it.

<template>
  <div class="app" v-bind:class="{ 
    'app-header-menu-search-toggled': appOption.appHeaderSearchToggled,
    'app-header-fixed': appOption.appHeaderFixed,
    'app-sidebar-fixed': appOption.appSidebarFixed,
    'app-sidebar-grid': appOption.appSidebarGrid,
    'app-sidebar-toggled': appOption.appSidebarToggled,
    'app-sidebar-collapsed': appOption.appSidebarCollapsed,
    'app-sidebar-mobile-toggled': appOption.appSidebarMobileToggled,
    'app-sidebar-mobile-closed': appOption.appSidebarMobileClosed,
    'app-sidebar-end-toggled': appOption.appSidebarEndToggled,
    'app-sidebar-end-mobile-toggled': appOption.appSidebarEndMobileToggled,
    'app-content-full-height': appOption.appContentFullHeight,
    'app-content-full-width': appOption.appSidebarHide,
    'app-without-sidebar': appOption.appSidebarHide,
    'app-with-end-sidebar': appOption.appSidebarEnd,
    'app-with-wide-sidebar': appOption.appSidebarWide,
    'app-with-hover-sidebar': appOption.appSidebarHover,
    'app-with-top-menu': appOption.appTopMenu,
    'app-with-two-sidebar': appOption.appSidebarTwo,
    'pt-0': appOption.appHeaderHide,
    'app-boxed-layout': appOption.appBoxedLayout,
    'app-footer-fixed': appOption.appFooterFixed,
    'app-sidebar-minified': appOption.appSidebarMinified,
    'app-gradient-enabled': appOption.appGradientEnabled
  }">
    <vue3-progress-bar />
    <app-header v-if="!appOption.appHeaderHide" />
    <app-sidebar v-if="!appOption.appSidebarHide" />
    <app-sidebar-right v-if="appOption.appSidebarTwo" />
    <app-top-menu v-if="appOption.appTopMenu" />
    <div class="app-content" v-bind:class="appOption.appContentClass">
      <router-view></router-view>
    </div>
    <app-footer v-if="appOption.appFooter" />
    <app-theme-panel />
  </div>
</template>

List of components inside the components folder

/src/components/
├── app/
│   ├── AnimateNumber.vue
│   ├── Footer.vue
│   ├── Header.vue
│   ├── HeaderMegaMenu.vue
│   ├── NavScrollTo.vue
│   ├── Sidebar.vue
│   ├── SidebarNav.vue
│   ├── SidebarRight.vue
│   ├── ThemePanel.vue
│   ├── TopMenu.vue
│   └── TopMenuNav.vue
├── bootstrap/
│   ├── Panel.vue
│   ├── PanelBody.vue
│   ├── PanelFooter.vue
│   ├── PanelGroup.vue
│   ├── PanelHeader.vue
│   ├── PanelTitle.vue
│   └── PanelToolbar.vue
└── plugins/
    ├── Apexcharts.vue
    ├── Chartjs.vue
    ├── Datepicker.vue
    ├── Highlightjs.vue
    ├── QuillEditor.vue
    ├── TagsInput.vue
    ├── Typeahead.vue
    ├── VueSelect.vue
    └── VueTable.vue

This template used mitt as event bus to emit events between component. Emitter files can be found via /composables/useEmitter.ts

import useEmitter from '@/composables/useEmitter';

const emitter = useEmitter();

// emit event
emitter.emit('my-event', true);

// event listener
this.emitter.on('my-event', (evt) => {
  // do something
});

This template used pinia to create the store and share the states variable between the components. Store files can be found via /src/stores/

/src/stores/
├─ app-option.ts            // global app option states
├─ app-sidebar-menu.ts      // global app sidebar menu list
└─ app-variable.ts          // global app variable (fetched from css / font variables)

You can use the global app option from /stores/app-option.ts

import { useAppOptionStore } from '@/stores/app-option';

const appOption = useAppOptionStore();

export default {
  mounted() {
    // available app option
    appOption.appThemeClass: '',
    appOption.appDarkMode: '',
    
    appOption.appHeaderHide: false,
    appOption.appHeaderFixed: true,
    appOption.appHeaderInverse: false,
    appOption.appHeaderSearchToggled: false,
    appOption.appHeaderLanguageBar: false,
    appOption.appHeaderMegaMenu: false,
    
    appOption.appSidebarTwo: false,
    appOption.appSidebarHide: false,
    appOption.appSidebarEnd: false,
    appOption.appSidebarWide: false,
    appOption.appSidebarLight: false,
    appOption.appSidebarFixed: true,
    appOption.appSidebarCollapsed: false,
    appOption.appSidebarMobileToggled: false,
    appOption.appSidebarMobileClosed: false,
    appOption.appSidebarMinified: false,
    appOption.appSidebarHover: false,
    appOption.appSidebarSearch: false,
    appOption.appSidebarEndToggled: false,
    appOption.appSidebarEndMobileToggled: false,
    appOption.appSidebarTransparent: false,
    
    appOption.appTopMenu: false,
    
    appOption.appContentFullHeight: false,
    appOption.appContentClass: '',
    
    appOption.appFooter: false,
    appOption.appFooterFixed: false,
    
    appOption.appThemePanelToggled: false
  },
  beforeUnmount() {
    // set to default before leave the page
    appOption.appTopMenu = false;
  }
}

You can use the global app variables (css color / font family) from /stores/app-variable.ts

import { useAppVariableStore } from '@/stores/app-variable';

const appVariable = useAppVariableStore();

export default {
  data() {
    return {
      variableName: appVariable.color.theme
      
      // font variable
      appVariable.font.family;
      appVariable.font.size;
      appVariable.font.weight;
      
      // color variable
      appVariable.color.componentColor;
      appVariable.color.componentBg;
      appVariable.color.theme;
      appVariable.color.blue;
      appVariable.color.green;
      appVariable.color.orange
      appVariable.color.red;
      appVariable.color.cyan;
      appVariable.color.purple;
      appVariable.color.yellow;
      appVariable.color.indigo;
      appVariable.color.pink;
      appVariable.color.black;
      appVariable.color.white;
      appVariable.color.gray;
      appVariable.color.dark;
      appVariable.color.gray100;
      appVariable.color.gray200;
      appVariable.color.gray300;
      appVariable.color.gray400;
      appVariable.color.gray500;
      appVariable.color.gray600;
      appVariable.color.gray700;
      appVariable.color.gray800;
      appVariable.color.gray900;
      
      // color variable (rgba)
      appVariable.color.componentColorRgb;
      appVariable.color.componentBgRgb;
      appVariable.color.themeRgb;
      appVariable.color.blueRgb;
      appVariable.color.greenRgb;
      appVariable.color.orange
      appVariable.color.redRgb;
      appVariable.color.cyanRgb;
      appVariable.color.purpleRgb;
      appVariable.color.yellowRgb;
      appVariable.color.indigoRgb;
      appVariable.color.pinkRgb;
      appVariable.color.blackRgb;
      appVariable.color.whiteRgb;
      appVariable.color.grayRgb;
      appVariable.color.darkRgb;
      appVariable.color.gray100Rgb;
      appVariable.color.gray200Rgb;
      appVariable.color.gray300Rgb;
      appVariable.color.gray400Rgb;
      appVariable.color.gray500Rgb;
      appVariable.color.gray600Rgb;
      appVariable.color.gray700Rgb;
      appVariable.color.gray800Rgb;
      appVariable.color.gray900Rgb;
    }
  }
}

Set the app sidebar menu list from from /stores/app-sidebar-menu.ts

// single level structure
{
  'url': '/',
  'icon': 'fa fa-sitemap',
  'text': 'Dashboard'
},

// multi level structure 
{
  'icon': 'fa fa-envelope',
  'text': 'Email',
  'children': [{
    'url': '/email/inbox',
    'action': 'Inbox',
    'text': 'Inbox'
  }, {
    'url': '/email/compose',
    'action': 'Compose',
    'text': 'Compose'
  }, {
    'url': '/email/detail',
    'action': 'Detail',
    'text': 'Detail'
  }]
}

Enable the dark mode from template_vue/stores/app-variable.ts

...
appDarkMode: true
...

Apple Design

  1. Change the variable from template_vue/src/scss/vue.scss.
    @import 'apple/styles';
    
  2. Add the following css link to template_vue/public/index.html.
    <link href="https://cdnjs.cloudflare.com/ajax/libs/ionicons/2.0.1/css/ionicons.min.css" rel="stylesheet" />
    
  3. Change the sidebar icon from Fontawesome to Ionicons and background color class is needed as well.
    <div class="menu-icon">
      <i class="ion-ios-pulse bg-gradient-blue"></i>
    </div>
    

Facebook Design

  1. Change the variable from template_vue/src/scss/vue.scss.
    @import 'facebook/styles';
    
  2. Enable the app header inverse from template_vue/stores/app-option.ts.
    ...
    appHeaderInverse: true
    ...
    

Transparent Design

  1. Change the variable from template_vue/src/scss/vue.scss.
    @import 'transparent/styles';
    
  2. Add the .app-cover next to the <body> tag in template_vue/public/index.html.
    <body>
      <!-- BEGIN page-cover -->
      <div class="app-cover"></div>
      <!-- END page-cover -->
      
      ...
    </body>
    

Google Design

  1. Change the variable from template_vue/src/scss/vue.scss.
    @import 'google/styles';
    
  2. Change the sidebar icon from Fontawesome to Material Icons.
    <div class="menu-icon">
      <i class="material-icons">home</i>
    </div>
    
  3. Enable the app sidebar light & wide option from template_vue/stores/app-option.ts.
    ...
    appSidebarWide: true,
    appSidebarLight: true,
    ...
    
  4. Add the navbar desktop toggler to the .app-header in template_vue/src/components/app/Header.vue.
    <!-- BEGIN #header -->
    <div id="header" class="app-header">
      <!-- BEGIN navbar-header -->
      <div class="navbar-header">
        <button type="button" class="navbar-desktop-toggler">
          <span class="icon-bar"></span>
          <span class="icon-bar"></span>
          <span class="icon-bar"></span>
        </button>
        <button type="button" class="navbar-mobile-toggler">
          ...
        </button>
        <a class="navbar-brand">
          Color Admin
        </a>
      </div>
      <!-- END navbar-header -->
      ...
    </div>
    

Material Design

  1. Change the variable from template_vue/src/scss/vue.scss.
    @import 'material/styles';
    
  2. Change the sidebar icon from Fontawesome to Material Icons.
    <div class="menu-icon">
      <i class="material-icons">home</i>
    </div>
    
  3. Enable the app sidebar wide option from template_vue/stores/app-option.ts.
    ...
    appSidebarWide: true,
    ...
    
  4. Add the navbar desktop toggler to the .app-header in template_vue/src/components/app/Header.vue.
    <!-- BEGIN #header -->
    <div id="header" class="app-header">
      <!-- BEGIN navbar-header -->
      <div class="navbar-header">
        <button type="button" class="navbar-desktop-toggler">
          <span class="icon-bar"></span>
          <span class="icon-bar"></span>
          <span class="icon-bar"></span>
        </button>
        <button type="button" class="navbar-mobile-toggler">
          ...
        </button>
        <a class="navbar-brand">
          Color Admin Material
        </a>
      </div>
      <!-- END navbar-header -->
      ...
    </div>
    
  5. Add the floating navbar form to the .app-header in template_vue/src/components/app/Header.vue AND REMOVE the default .navbar-form.
    <!-- BEGIN #header -->
    <div id="header" class="app-header">
      <!-- BEGIN header-nav -->
      <div class="navbar-nav">
        <div class="navbar-item">
          <a href="#" class="navbar-link icon">
            <i class="material-icons">search</i>
          </a>
          
          <!-- REMOVE IT -->
          <div class="navbar-item navbar-form">
            ...
          </div>
        </div>
        ...
      </div>
      <!-- END header-nav -->
      
      <div class="navbar-floating-form">
        <button class="search-btn" type="submit"><i class="material-icons">search</i></button>
        <input type="text" class="form-control" placeholder="Search Something..." />
        <a href="#" class="close">
          <i class="material-icons">close</i>
        </a>
      </div>
    </div>
    
  6. Change the .app-loader in template_vue/public/index.html.
    <!-- BEGIN #loader -->
    <div id="loader" class="app-loader">
      <div class="material-loader">
        <svg class="circular" viewBox="25 25 50 50">
          <circle class="path" cx="50" cy="50" r="20" fill="none" stroke-width="2" stroke-miterlimit="10"></circle>
        </svg>
        <div class="message">Loading...</div>
      </div>
    </div>
    <!-- END #loader -->
    

Now Vue.js version is fully scss configured. You may switch the Color Admin theme by changing the file /template_vue3/src/scss/vue.scss.

@import 'default/styles';
 
<!-- other themes -->
@import 'apple/styles';
@import 'facebook/styles';
@import 'google/styles';
@import 'material/styles';
@import 'transparent/styles';

Below is the list of package that has been installed in this project. You may use the following example to find the package from their official website. https://www.npmjs.com/package/bootstrap-vue

{
  "name": "color-admin",
  "version": "5.4.1",
  "scripts": {
    "dev": "vite",
    "build": "vue-tsc --noEmit && vite build",
    "preview": "vite preview --port 5050",
    "test:unit": "vitest --environment jsdom",
    "test:e2e": "start-server-and-test preview http://127.0.0.1:5050/ 'cypress open'",
    "test:e2e:ci": "start-server-and-test preview http://127.0.0.1:5050/ 'cypress run'",
    "typecheck": "vue-tsc --noEmit -p tsconfig.vitest.json --composite false",
    "lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore"
  },
  "dependencies": {
    "@caohenghu/vue-colorpicker": "^1.2.4",
    "@chenfengyuan/vue-countdown": "^2.1.2",
    "@fortawesome/fontawesome-free": "^6.6.0",
    "@fortawesome/fontawesome-svg-core": "^6.6.0",
    "@fortawesome/free-solid-svg-icons": "^6.6.0",
    "@fortawesome/vue-fontawesome": "^3.0.8",
    "@fullcalendar/bootstrap": "^6.1.15",
    "@fullcalendar/common": "^5.11.5",
    "@fullcalendar/core": "^6.1.15",
    "@fullcalendar/daygrid": "^6.1.15",
    "@fullcalendar/interaction": "^6.1.15",
    "@fullcalendar/list": "^6.1.15",
    "@fullcalendar/timegrid": "^6.1.15",
    "@fullcalendar/vue3": "^6.1.15",
    "@highlightjs/vue-plugin": "github:highlightjs/vue-plugin",
    "@marcoschulte/vue3-progress": "^0.0.7",
    "@sipec/vue3-tags-input": "^3.0.4",
    "@vuepic/vue-datepicker": "^9.0.1",
    "@vueup/vue-quill": "^1.2.0",
    "apexcharts": "3.51",
    "axios": "^1.7.2",
    "bootstrap": "^5.3.3",
    "bootstrap-icons": "^1.11.3",
    "bootstrap-social": "^5.1.1",
    "chart.js": "^4.4.3",
    "date-fns": "^3.6.0",
    "flag-icons": "^7.2.3",
    "highlight.js": "^11.10.0",
    "jsvectormap": "^1.6.0",
    "lity": "^2.4.1",
    "maska": "^3.0.0",
    "masonry-layout": "^4.2.2",
    "mitt": "^3.0.1",
    "moment": "^2.30.1",
    "photoswipe": "^5.4.4",
    "pinia": "^2.1.7",
    "simple-line-icons": "^2.5.5",
    "v-calendar": "^3.0.0-alpha.8",
    "vue": "^3.4.33",
    "vue-axios": "^3.5.2",
    "vue-router": "^4.4.0",
    "vue-select": "^4.0.0-beta.3",
    "vue3-apexcharts": "^1.5.3",
    "vue3-datepicker": "^0.4.0",
    "vue3-google-map": "^0.20.0",
    "vue3-perfect-scrollbar": "^2.0.0",
    "vue3-simple-typeahead": "^1.0.11",
    "vue3-table-lite": "^1.4.0"
  },
  "devDependencies": {
    "@iconify/vue": "^4.1.2",
    "@rushstack/eslint-patch": "^1.10.3",
    "@types/jsdom": "^21.1.7",
    "@types/node": "^20.14.11",
    "@vitejs/plugin-vue": "^5.0.5",
    "@vitejs/plugin-vue-jsx": "^4.0.0",
    "@vue/eslint-config-prettier": "^9.0.0",
    "@vue/eslint-config-typescript": "^13.0.0",
    "@vue/test-utils": "^2.4.6",
    "@vue/tsconfig": "^0.5.1",
    "cypress": "^13.13.1",
    "eslint": "^8.56.0",
    "eslint-plugin-cypress": "^3.3.0",
    "eslint-plugin-vue": "^9.27.0",
    "jsdom": "^24.1.1",
    "prettier": "^3.3.3",
    "sass": "1.75.0",
    "sass-loader": "^14.2.1",
    "start-server-and-test": "^2.0.4",
    "typescript": "~5.5.4",
    "vite": "^5.3.4",
    "vitest": "^2.0.4",
    "vue-tsc": "^2.0.28"
  }
}