Skip to content

Maz-UI v4.0.0 Migration Guide

Maz-UI v4.0.0 isn’t just an update — it’s a complete rebuild designed to give developers more flexibility and simplicity.

The library is now split into independent packages, allowing you to install and use only what you need.
The theme system has been redesigned to make customizing and managing multiple themes easier, while the internationalization system offers full control over translations.
Performance has also been significantly improved thanks to optimal tree-shaking, more efficient minification, and a modernized architecture.

Connected to Maz-UI MCP

Follow the MCP guide to connect your AI assistant to Maz-UI's documentation for a smooth migration process.

Why Migrate to v4.0.0?

Architectural Revolution

v4.0.0 isn't just an update, it's a complete rebuild that transforms Maz-UI into a modern and performant library:

Optimized Tree-Shaking

  • Dramatic bundle reduction: 60-90% size reduction
  • Granular imports: Every component, composables, plugins, directive, and utility is individually importable
  • Modern bundlers: Perfect compatibility with Vite, Webpack 5, Rollup

Modular Architecture

  • Restructured monorepo: Separation into specialized packages
  • New export structure: Modular exports for better DX
  • Maximum flexibility: Choose exactly what you need

Advanced Theme System

  • Predefined presets: mazUi, obsidian, ocean, pristine
  • Dynamic CSS Variables: Automatic CSS variable generation
  • Intelligent dark mode: Configurable strategies for dark mode based on system preferences and user choice stored in cookies

Complete Internationalization

  • 9 supported languages by default: EN, FR, DE, ES, IT, PT, JA, ZH-CN
  • Add your own languages: Easy integration of custom translations
  • Translation system: Vue plugin and dedicated composables
  • Automatic fallback: Smart handling of missing translations

New Components or refactored

  • MazLink: Modern link component replacing MazBtn variant="link"
  • MazExpandAnimation: CSS Grid expansion animation (replaces MazTransitionExpand)
  • MazDropzone: Complete rewrite without external dependency
  • MazPopover: Versatile overlay component with smart positioning
  • MazSelectCountry: Country/language selector with i18n support

New Packages

v4.0.0 separates functionality into specialized packages for better modularity:

Main Packages

PackageDescriptionStatus
maz-uiVue components, composables, pluginsRefactored
@maz-ui/themesTheme system and presetsNew
@maz-ui/translationsi18n translationsNew
@maz-ui/utilsJavaScript/TypeScript utilitiesNew
@maz-ui/iconsSVG icons and flags (840+ icons)New
@maz-ui/cliCLI for theme generationRenamed
@maz-ui/nuxtNuxt moduleNew
@maz-ui/mcpMCP server for IA agentNew

Migration Checklist

Step 1: Update Dependencies

bash
# Uninstall old version
npm uninstall maz-ui

# Install new version
npm install maz-ui@4.0.0

# Optional: Install specialized packages
npm install @maz-ui/themes @maz-ui/translations @maz-ui/utils @maz-ui/icons

# Remove external dependency no longer needed
npm uninstall dropzone

Updated peer dependencies:

  • Vue: ^3.5.0 (was ^3.0.0)
  • unplugin-vue-components: >=28.0.0
  • unplugin-auto-import: >=19.0.0

Vue users - Plugin configuration

NEW: v4.0.0 introduces a mandatory Vue plugin for configuration.

Before (v3.x)

typescript
// main.ts
import { createApp } from 'vue'
import 'maz-ui/css/main.css'
import App from './App.vue'

createApp(App).mount('#app')

After (v4.0.0)

typescript
// main.ts
import { createApp } from 'vue'
import { MazUi } from 'maz-ui/plugins/maz-ui'
import { mazUi } from '@maz-ui/themes/presets'
import { fr } from '@maz-ui/translations'

// Import styles before your CSS
import 'maz-ui/styles'
import './style.css'

import App from './App.vue'

const app = createApp(App)

// NEW: MazUi plugin required
app.use(MazUi, {
  // Theme configuration (optional)
  theme: {
    preset: mazUi, // or 'ocean' | 'pristine' | 'obsidian'
  },
  // Translation configuration (optional)
  translations: {
    locale: 'fr',
    fallbackLocale: 'en',
    messages: {
      fr,
    },
  },
})

app.mount('#app')

Nuxt users - Module Configuration

NEW: Dedicated Nuxt module with simplified API.

Before (v3.x)

typescript
// nuxt.config.ts
export default defineNuxtConfig({
  modules: ['maz-ui/nuxt'],
  mazUi: {
    // v3 configuration
  }
})

After (v4.0.0)

typescript
// nuxt.config.ts
export default defineNuxtConfig({
  modules: ['@maz-ui/nuxt'], // New package
  mazUi: {
    // New configuration API
    theme: {
      preset: 'maz-ui',
      strategy: 'hybrid',
      darkModeStrategy: 'class',
    },
    translations: {
      locale: 'fr',
      fallbackLocale: 'en',
    },
    plugins: {
      aos: true,
      dialog: true,
      toast: true,
      wait: true,
    },
    directives: {
      vTooltip: true,
      vLazyImg: true,
      vClickOutside: true,
    },
  }
})

Import Migration

MAJOR CHANGE: New modular import structure.

Components

NOTE: Component imports haven't changed - they work the same way as in v3.x.

typescript
// ✅ SAME AS v3.x - Still works
import MazBtn from 'maz-ui/components/MazBtn'
import MazInput from 'maz-ui/components/MazInput'

// ✅ NEW - Batch imports for convenience
import { MazBtn, MazInput } from 'maz-ui/components'

Plugins

typescript
// ❌ BEFORE (v3.x)
import { installToaster, ToastHandler } from 'maz-ui'

// ✅ AFTER (v4.0.0)
import { ToastPlugin, ToastHandler } from 'maz-ui/plugins'
// or for maximum tree-shaking
import { ToastPlugin, ToastHandler } from 'maz-ui/plugins/toast'

Directives

typescript
// ❌ BEFORE (v3.x)
import { vClickOutside, vTooltip } from 'maz-ui'

// ✅ AFTER (v4.0.0)
import { vClickOutside, vTooltip } from 'maz-ui/directives'
// or for maximum tree-shaking
import { vClickOutside } from 'maz-ui/directives/vClickOutside'
import { vTooltip } from 'maz-ui/directives/vTooltip'

Composables

typescript
// ❌ BEFORE (v3.x)
import { useTimer, useToast } from 'maz-ui'

// ✅ AFTER (v4.0.0)
import { useTimer, useToast } from 'maz-ui/composables'
// or for maximum tree-shaking
import { useTimer } from 'maz-ui/composables/useTimer'
import { useToast } from 'maz-ui/composables/useToast'

Utilities

typescript
// ❌ BEFORE (v3.x)
import { currency, date } from 'maz-ui'

// ✅ AFTER (v4.0.0)
import { formatCurrency, formatDate } from 'maz-ui'
// or for better performance
import { formatCurrency, formatDate } from '@maz-ui/utils'

Component Changes

MazBtn - Major Changes

html
<!-- ❌ BEFORE (v3.x) -->
<MazBtn variant="link" href="/path">
  Link
</MazBtn>

<!-- ✅ AFTER (v4.0.0) - Use MazLink -->
<MazLink href="/path">
  Link
</MazLink>

<!-- Action with click -->
<MazLink @click="handleClick">
  Action
</MazLink>

Prop Changes

html
<!-- CHANGED PROPS -->
<MazBtn
  outlined            <!-- NEW: was 'outline' -->
  justify="space-between"  <!-- 🆕 NEW: Content alignment -->
  :padding="false"         <!-- 🆕 NEW: Padding control -->
  rounded-size="full"      <!-- 🆕 NEW: Border radius size -->
>
  Button
</MazBtn>

Replaces MazBtn variant="link" with a richer API:

html
<!-- ✅ NEW COMPONENT -->
<MazLink
  href="/path"
  :auto-external="true"           <!-- 🆕 NEW: Automatic external icon -->
  :underline-hover="true"         <!-- 🆕 NEW: Underline on hover -->
  left-icon="home"                <!-- 🆕 NEW: Left icon -->
  right-icon="arrow-right"        <!-- 🆕 NEW: Right icon -->
  color="primary"                 <!-- 🆕 NEW: Custom color -->
  as="router-link"               <!-- 🆕 NEW: Custom component -->
>
  Link with icons
</MazLink>

MazPicker --> MazDatePicker

MazPicker has been renamed to MazDatePicker.

Props have been changed:

  • no-header --> hide-header
  • input-date-style --> input-date-format

New Props:

  • min-max-auto: Control behavior when the date is in the range of min and max.
html
<MazDatePicker />

MazPopover - New Component

Versatile overlay component with smart positioning:

html
<!-- NEW COMPONENT -->
<MazPopover
  trigger="click"                 <!-- 🆕 NEW: Trigger mode -->
  position="bottom-start"         <!-- 🆕 NEW: Smart positioning -->
  :persistent="true"              <!-- 🆕 NEW: Keep open for interactions -->
  role="dialog"                   <!-- 🆕 NEW: Accessibility role -->
>
  <template #trigger>
    <MazBtn>Open Popover</MazBtn>
  </template>

  <template #default>
    <div class="p-4">
      Popover content
    </div>
  </template>
</MazPopover>

MazSelectCountry - New Component

Country/language selector with i18n support:

html
<!-- ✅ NEW COMPONENT -->
<MazSelectCountry
  v-model="selectedCountry"
  :preferred-codes="['US', 'FR']"  <!-- 🆕 NEW: Preferred countries -->
  :locale="'fr'"                   <!-- 🆕 NEW: Localization -->
  :hide-flags="false"              <!-- 🆕 NEW: Flag display -->
  :display-code="false"            <!-- 🆕 NEW: Show codes -->
/>

MazInputPhoneNumber - Renamed

html
<!-- ❌ BEFORE (v3.x) -->
<MazPhoneNumberInput
  v-model="phone"
  v-model:country-code="country"
  :preferred-countries="['FR', 'US']"
  @update="handleUpdate"
/>

<!-- ✅ AFTER (v4.0.0) -->
<MazInputPhoneNumber
  v-model="phone"
  v-model:country-code="country"
  :preferred-countries="['FR', 'US']"
  @data="handleData"            <!-- 🔄 CHANGED: @update @data -->
/>

MazExpandAnimation - Replaces MazTransitionExpand

html
<!-- ❌ BEFORE (v3.x) -->
<MazTransitionExpand animation-duration="500ms">
  <div v-show="isOpen">Content</div>
</MazTransitionExpand>

<!-- ✅ AFTER (v4.0.0) -->
<MazExpandAnimation
  v-model="isOpen"                <!-- 🆕 NEW: v-model for state control -->
  duration="500ms"               <!-- 🔄 CHANGED: duration instead of animation-duration -->
  timing-function="ease-in-out"  <!-- 🆕 NEW: Timing function -->
>
  <div>Content</div>
</MazExpandAnimation>

MazDropzone - Complete Rewrite

External dependency removed:

bash
# ❌ BEFORE (v3.x) - External dependency required
npm install dropzone

# ✅ AFTER (v4.0.0) - No external dependency
npm uninstall dropzone

New Features:

html
<!-- ✅ NEW FEATURES -->
<MazDropzone
  v-model="files"
  :auto-upload="'single'"          <!-- 🆕 NEW: Automatic upload -->
  url="/api/upload"                <!-- 🆕 NEW: Upload URL -->
  :request-options="{ ... }"       <!-- 🆕 NEW: Request options -->
  :transform-body="transformFn"    <!-- 🆕 NEW: Body transformation -->
  :min-file-size="0.1"            <!-- 🆕 NEW: Min size in MB -->
  @upload-success="onSuccess"      <!-- 🆕 NEW: Success event -->
  @upload-error="onError"          <!-- 🆕 NEW: Error event -->
/>

MazDropdown & MazSelect - Position API

html
<!-- ❌ BEFORE (v3.x) -->
<MazDropdown position="bottom right" />
<MazSelect position="bottom right" />

<!-- ✅ AFTER (v4.0.0) -->
<MazDropdown position="bottom-end" />
<MazSelect position="bottom-end" />

New position type:

typescript
type MazPopoverPosition = 'auto' | 'top' | 'bottom' | 'left' | 'right' |
  'top-start' | 'top-end' | 'bottom-start' | 'bottom-end' |
  'left-start' | 'left-end' | 'right-start' | 'right-end'

MazDialogConfirm - Renamed

typescript
// ❌ BEFORE (v3.x)
import { MazDialogPromise } from 'maz-ui'

// ✅ AFTER (v4.0.0)
import { MazDialogConfirm } from 'maz-ui'

Composable Changes

useDialog - API Changes

No longer Promise-based to avoid JS console errors:

typescript
// ❌ BEFORE (v3.x)
const dialog = useDialog()

try {
  const result = await dialog.confirm({
    title: 'Confirm',
    message: 'Are you sure?',
    confirmText: 'Yes',
    cancelText: 'No'
  })
  // Handle confirm
} catch (error) {
  // Handle cancel
}
typescript
// ✅ AFTER (v4.0.0)
const dialog = useDialog()

dialog.confirm({
  title: 'Confirm',
  message: 'Are you sure?',
  buttons: {                      // 🔄 CHANGED: buttons instead of confirmText/cancelText
    confirm: 'Yes',
    cancel: 'No'
  },
  onAccept: () => {              // 🆕 NEW: Accept callback
    // Handle confirm
  },
  onReject: () => {              // 🆕 NEW: Reject callback
    // Handle cancel
  },
  onClose: () => {               // 🆕 NEW: Close callback (finally)
    // Handle close
  }
})

useDisplayNames - Renamed

typescript
// ❌ BEFORE (v3.x)
import { useLanguageDisplayNames } from 'maz-ui'

const { getDisplayName } = useLanguageDisplayNames()

// ✅ AFTER (v4.0.0)
import { useDisplayNames } from 'maz-ui/composables'

const { getDisplayName } = useDisplayNames()

📖 Complete documentation: useDisplayNames Guide

Helpers to Composables

🔄 MAJOR CHANGE: Several helpers are now Vue composables and must be used within Vue context.

useIdleTimeout

typescript
// ❌ BEFORE (v3.x)
import { idleTimeout } from 'maz-ui'

const controller = idleTimeout({
  timeout: 5000,
  onTimeout: () => console.log('timeout'),
  onActivity: () => console.log('activity')
})

// ✅ AFTER (v4.0.0)
import { useIdleTimeout } from 'maz-ui/composables'

// In a Vue component
const { isIdle } = useIdleTimeout({
  timeout: 5000,
  onTimeout: () => console.log('timeout'),
  onActivity: () => console.log('activity')
})

Color System Changes

Color Removals and Replacements

typescript
// ❌ REMOVED COLORS
color="theme"     // ✅ REPLACED BY: color="contrast"
color="white"     // ❌ REMOVED
color="black"     // ❌ REMOVED
color="danger"    // ✅ REPLACED BY: color="destructive"

🆕 New Color System

Available colors in v4.0.0:

typescript
type MazColor = 'primary' | 'secondary' | 'accent' | 'info' | 'success' |
  'warning' | 'destructive' | 'contrast' | 'transparent'

Migration examples:

html
<!-- ❌ BEFORE (v3.x) -->
<MazBtn color="theme">Theme Button</MazBtn>
<MazBtn color="danger">Danger Button</MazBtn>

<!-- ✅ AFTER (v4.0.0) -->
<MazBtn color="contrast">Contrast Button</MazBtn>
<MazBtn color="destructive">Destructive Button</MazBtn>

Removed Features

Removed Directive

html
<!-- ❌ REMOVED - v-closable directive -->
<div v-closable="handler">Content</div>

<!-- ✅ ALTERNATIVE - Use v-click-outside -->
<div v-click-outside="handler">Content</div>

Removed Utility Names

typescript
// ❌ BEFORE (v3.x)
import { currency, date } from 'maz-ui'

// ✅ AFTER (v4.0.0)
import { formatCurrency, formatDate } from 'maz-ui'

TypeScript Changes

Type Prefixing

All component types are now prefixed with Maz:

typescript
// ❌ BEFORE (v3.x)
import type { Props } from 'maz-ui/components/MazBtn'
import type { ButtonsRadioOption, Row, Color, Size } from 'maz-ui'

// ✅ AFTER (v4.0.0)
import type { MazBtnProps } from 'maz-ui/components/MazBtn'
import type { MazRadioButtonsOption, MazTableRow, MazColor, MazSize } from 'maz-ui'

Type Import Changes

typescript
// ❌ BEFORE (v3.x)
import type { Color, Size } from 'maz-ui'

// ✅ AFTER (v4.0.0)
import type { MazColor, MazSize } from 'maz-ui'

Theme System

Basic Configuration

typescript
// main.ts
import { MazUi } from 'maz-ui/plugins/maz-ui'
import { mazUi } from '@maz-ui/themes/presets'

app.use(MazUi, {
  theme: {
    preset: mazUi, // or 'ocean' | 'pristine' | 'obsidian'
  },
})

Custom Theme

typescript
import { definePreset } from '@maz-ui/themes'
import { mazUi } from '@maz-ui/themes/presets'

const customTheme = definePreset({
  base: mazUi,
  name: 'custom-theme',
  colors: {
    light: {
      primary: '220 100% 50%',
      secondary: '220 14% 96%',
    },
    dark: {
      primary: '220 100% 70%',
      secondary: '220 14% 4%',
    }
  }
})

app.use(MazUi, {
  theme: {
    preset: customTheme,
  },
})

useTheme Composable

vue
<script setup>
import { useTheme } from 'maz-ui/composables'

const { isDark, toggleDarkMode, setTheme } = useTheme()

// Change theme
setTheme('ocean')

// Toggle dark mode
toggleDarkMode()
</script>

<template>
  <button @click="toggleDarkMode">
    {{ isDark ? '☀️' : '🌙' }}
  </button>
</template>

📖 Complete documentation: Theme Guide

Translation System

Configuration

typescript
// main.ts
import { MazUi } from 'maz-ui/plugins/maz-ui'
import { fr, en } from '@maz-ui/translations'

app.use(MazUi, {
  translations: {
    locale: 'fr',
    fallbackLocale: 'en',
    messages: {
      fr,
      en,
    },
  },
})

useTranslations Composable

vue
<script setup>
import { useTranslations } from 'maz-ui/composables'

const { t, locale, setLocale } = useTranslations()

// Change language
setLocale('fr')
</script>

<template>
  <p>{{ t('button.cancel') }}</p>
</template>

📖 Complete documentation: Translation Guide

Common Errors and Solutions

"idleTimeout is not a function"

typescript
// ❌ Old way
import { idleTimeout } from 'maz-ui'

// ✅ New way
import { useIdleTimeout } from 'maz-ui/composables'

// In a Vue component
const { isIdle } = useIdleTimeout({ timeout: 5000 })

❌ "MazTransitionExpand is not exported"

vue
<!-- ❌ Removed component -->
<MazTransitionExpand>
  <div v-show="isOpen">Content</div>
</MazTransitionExpand>

<!-- ✅ New component -->
<MazExpandAnimation v-model="isOpen">
  <div>Content</div>
</MazExpandAnimation>

❌ "Module not found: Can't resolve 'dropzone'"

bash
# ❌ Remove old dependency
npm uninstall dropzone

# ✅ MazDropzone has no external dependency

❌ "useTheme must be used within MazUi plugin"

typescript
// ❌ Missing plugin
import { createApp } from 'vue'

// ✅ Add MazUi plugin
import { MazUi } from 'maz-ui/plugins/maz-ui'

app.use(MazUi)

❌ "Property 'outline' does not exist"

html
<!-- ❌ Old prop name -->
<MazBtn outline>Button</MazBtn>

<!-- ✅ New prop name -->
<MazBtn outlined>Button</MazBtn>

Migration Benefits

Performance

Metricv3.xv4.0.0Improvement
Bundle Size~500KB~50-200KB60-90%
Tree-shaking❌ Limited✅ OptimalPerfect
Lazy Loading❌ Basic✅ AdvancedIntelligent
TypeScript✅ Good✅ ExcellentStrict

Developer Experience

  • Auto-imports: Resolvers for unplugin-vue-components
  • TypeScript: Strict types and perfect auto-completion
  • DevTools: Nuxt DevTools integration
  • Documentation: Interactive guides and examples

Maintenance

  • Modularity: Separate packages for better maintenance
  • Versioning: Semantic versioning for each package
  • Stability: Mature and tested architecture

Complete Migration Checklist

Dependencies

Configuration

Imports

Components

API Changes

Helpers to Composables

TypeScript

Testing and Validation

Additional Resources

Need Help?

Migration seems complex? We're here to help:


🎉 Congratulations! You now have all the tools to migrate to Maz-UI v4.0.0 and enjoy an exceptional developer experience with optimized performance!