Migrating from ghl-ui Modal to HighRise Modal
This guide provides a comprehensive overview of migrating from the ghl-ui Modal component to the new HighRise Modal component.
Component Implementation Changes
Import Changes
diff
- import { UIModal, UIModalHeader, UIModalContent, UIModalFooter } from '@gohighlevel/ghl-ui'
+ import { HLModal, HLModalFooter } from '@platform-ui/highrise'
Basic Usage Changes
diff
- <UIModal v-model="showModal">
- <UIModalHeader
- id="modal-header"
- title="Modal Title"
- description="Modal description"
- :icon="InfoIcon"
- @close="showModal = false" <!-- This event moves to HLModal -->
- @update:show="showModal = $event"
- />
- <UIModalContent>
- Modal content goes here
- </UIModalContent>
- <UIModalFooter
- id="modal-footer"
- positiveText="Confirm"
- negativeText="Cancel"
- @positive-click="handleConfirm"
- @negative-click="showModal = false"
- />
- </UIModal>
+ <HLModal
+ id="my-modal"
+ v-model:show="showModal"
+ type="info"
+ :show-header-icon="false"
+ :closable="false"
+ @close="showModal = false" <!-- Event moved here from UIModalHeader -->
<!---Removed update:show event as it is replaced with v-model:show-->
+ >
+ <template #header>
+ <h3>Modal Title</h3>
+ <p>Modal description</p>
+ </template>
+ <div>
+ Modal content goes here
+ </div>
+ <template #footer>
+ <HLModalFooter>
+ <HLButton @click="handleConfirm">Confirm</HLButton>
+ </HLModalFooter>
+ </template>
+ </HLModal>
+ <!-- Note: The close event is now handled on the HLModal component itself instead of the header -->
Modal Type Examples
Default Modal
vue
<template>
<HLModal
id="default-modal"
v-model:show="showModal"
type="default"
showBack
@back="handleBack"
:show-header-icon="false"
:closable="false"
>
<template #header>Default Modal</template>
<p>This modal has back, cancel, and continue buttons.</p>
</HLModal>
</template>
Modal Header Migration
The UIModalHeader
component has been replaced with either a simple header text or a more customizable header using the HLHeaderLite
component:
diff
- <UIModalHeader
- id="modal-header"
- title="Modal Title"
- description="Modal description"
- :icon="InfoIcon"
- @close="showModal = false" <!-- @close event should be moved to HLModal component -->
- />
+ <!-- Simple header text -->
+ <template #header>
+ Modal Title
+ </template>
+ <!-- OR: Custom header with HLHeaderLite -->
+ <template #header>
+ <HLHeaderLite
+ title="Modal Title"
+ subtitle="Last updated 2m ago"
+ :closable="false"
+ >
+ <template #header-icons>
+ <HLIcon size="lg" color="black">
+ <TrendUp01Icon />
+ </HLIcon>
+ </template>
+ <template #header-content>
+ <HLHeaderLiteItem justify="end" size="sm">
+ <HLButton variant="ghost" size="xs" color="gray">
+ Action
+ </HLButton>
+ </HLHeaderLiteItem>
+ </template>
+ </HLHeaderLite>
+ </template>
TIP
When using HLHeaderLite
in a modal:
- Set
:closable="false"
since the modal handles its own close button - Use the
header-icons
slot for custom icons - Use the
header-content
slot for additional actions - The close event is handled by the modal component itself
Here's a complete example with a custom header:
vue
<template>
<HLModal id="modal-custom-header" v-model:show="showModal" type="default" :showHeaderIcon="false" @close="showModal = false">
<template #header>
<HLHeaderLite title="Modal Title" subtitle="Last updated 2m ago" :closable="false">
<template #header-icons>
<HLIcon size="lg" color="black">
<TrendUp01Icon />
</HLIcon>
</template>
<template #header-content>
<HLHeaderLiteItem justify="end" size="sm">
<HLButton variant="ghost" size="xs" color="gray"> Action </HLButton>
</HLHeaderLiteItem>
</template>
</HLHeaderLite>
</template>
<div class="p-4">Modal content goes here</div>
</HLModal>
</template>
<script setup>
import { ref } from 'vue'
import { TrendUp01Icon } from '@gohighlevel/ghl-icons/24/outline'
const showModal = ref(false)
</script>
Modal with Custom Header
diff
- <UIModalHeader
- id="modal-header"
- title="Modal Title"
- description="Modal description"
- :icon="InfoIcon"
- @close="showModal = false" <!-- @close event should be moved to HLModal component -->
- >
- <template #customHeader>
- <div class="flex items-center justify-between w-full bg-white">
- <div class="flex items-center gap-3">
- <div
- class="w-12 h-12 bg-blue-100 rounded-full flex items-center justify-center"
- >
- </div>
- <div>
- <UITextMdMedium class="text-xl font-semibold text-gray-900">
- This is a title
- </UITextMdMedium>
- <UITextSmRegular class="text-sm text-gray-600">
- This is a description
- </UITextSmRegular>
- </div>
- </div>
- <XCloseIcon
- class="h-5 w-5 cursor-pointer text-gray-500 absolute right-6 top-6 rounded-lg hover:bg-gray-100"
- @click="close"
- /> <!-- Remove the close icon as it is already handled in the HLModal component -->
- </div>
- </template>
- >
+ <template #header>
+ <div class="flex items-center justify-between w-full bg-white">
+ <div class="flex items-center gap-3">
+ <div
+ class="w-12 h-12 bg-blue-100 rounded-full flex items-center justify-center"
+ >
+ <div>
+ <HLText size="2xl" weight="medium" color="gray-900" class="leading-6">
+ This is a title
+ </HLText>
+ <HLText size="lg" color="gray-500" weight="regular" class="leading-5">
+ This is a description
+ </HLText>
+ <!-- Remove the close icon as it is already handled in the HLModal component -->
+ </div>
+ </div>
+ </div>
+ </template>
Modal Footer Migration
- UIModalFooter component has been replaced with the #footer slot in HLModal component
diff
- <UIModalFooter
- id="modal-footer"
- positiveText="Confirm"
- negativeText="Cancel"
- @positive-click="handleConfirm"
- @negative-click="showModal = false"
- />
+ <template #footer>
+ <div class="flex justify-end gap-2">
+ <HLButton @click="showModal = false">Cancel</HLButton>
+ <HLButton color="blue" variant="primary" @click="handleConfirm"> Confirm </HLButton>
+ </div>
+ </template>
Info Modal
vue
<template>
<HLModal id="info-modal" v-model:show="showModal" type="info" :show-header-icon="false" :closable="false">
<template #header>Information</template>
<p>This modal has cancel and continue buttons.</p>
</HLModal>
</template>
Success Modal
vue
<template>
<HLModal id="success-modal" v-model:show="showModal" type="success" :show-header-icon="false" :closable="false">
<template #header>Success</template>
<p>This modal has only a continue button.</p>
</HLModal>
</template>
Warning Modal
vue
<template>
<HLModal
id="warning-modal"
v-model:show="showModal"
type="warning"
@close="showModal = false"
:show-header-icon="false"
:closable="false"
>
<template #header>Warning</template>
<p>This modal has discard, cancel, and save changes buttons.</p>
</HLModal>
</template>
Error Modal
vue
<template>
<HLModal id="error-modal" v-model:show="showModal" type="error" :show-header-icon="false" :closable="false">
<template #header>Error</template>
<p>This modal has discard, cancel, and delete buttons.</p>
</HLModal>
</template>
Modal Padding
The modal component does not have any default padding. You must add padding to your content manually:
- Header: No default padding - you must add padding using Tailwind classes
- Content: No default padding - you must add padding using Tailwind classes
- Footer: Default padding is coming from the
HLSectionFooter
component. You can override the padding by passing:top-padding="false"
and:bottom-padding="false"
to theHLSectionFooter
component.
vue
<template>
<HLModal id="modal-with-padding" v-model:show="showModal" type="default" :show-header-icon="false"
:closable="false">
<template #header>
<!-- Padding is coming from the HLText component -->
<HLText size="3xl" weight="medium" color="gray-900" class="leading-7">Modal Title</HLText>
</template>
<div class="pl-4 pr-4 pb-4">
<p>Modal content</p>
</div>
<template #footer>
<HLSectionFooter :bottom-padding="false">
<HLSectionFooterItem>
<HLButton @click="handleCancel">Cancel</HLButton>
<HLButton color="blue" variant="primary" @click="handleSubmit"> Submit </HLButton>
</HLSectionFooterItem>
</HLSectionFooter>
</HLModal>
</template>
Props Changes
Core Props
ghl-ui Prop | HighRise Prop | Notes |
---|---|---|
- | id | Required string for accessibility |
modelValue | show | Controls modal visibility |
width | width | Modal width (default: 483px) |
zIndex | zIndex | Custom z-index |
maskClosable | maskClosable | Close on mask click (default: true) |
closeOnEsc | closeOnEsc | Close on ESC key (default: true) |
autoFocus | autoFocus | Auto focus on open (default: false) |
- | type | 'default', 'info', 'success', 'warning', 'error' |
- | showBack | Show back button (default: false) |
- | showClose | Show close button (default: true) |
- | showHeader | Show header section (default: true) |
- | showFooter | Show footer section (default: true) |
- | showHeaderIcon | Show type icon in header (default: true) |
Event Changes
ghl-ui Event | HighRise Event | Notes |
---|---|---|
update:modelValue | update:show | Model binding update |
close | close | Modal close event |
positive-click | right-primary-click | Primary action click |
negative-click | right-secondary-click | Secondary action click |
- | left-click | Left action click |
- | back | Back button click |
- | after-enter | After modal opens |
- | after-leave | After modal closes |
- | before-leave | Before modal closes |
- | esc | ESC key pressed |
- | mask-click | Mask clicked |
Slot Changes
ghl-ui Component | HighRise Slot | Notes |
---|---|---|
UIModalHeader | header | Header content with title and description |
UIModalContent | default | Main content |
UIModalFooter | footer | Footer content (optional) |
Advanced Examples
Form Modal with Custom Footer
vue
<template>
<HLModal id="form-modal" v-model:show="showModal" type="default" :show-footer="true">
<template #header>User Information</template>
<form @submit.prevent="handleSubmit">
<div class="space-y-4">
<input v-model="form.name" placeholder="Name" />
<input v-model="form.email" placeholder="Email" />
</div>
</form>
<template #footer>
<div class="p-4">
<HLSectionFooter :top-padding="false" :bottom-padding="false">
<HLSectionFooterItem>
<HLButton @click="handleCancel">Cancel</HLButton>
<HLButton color="blue" variant="primary" @click="handleSubmit"> Submit </HLButton>
</HLSectionFooterItem>
</HLSectionFooter>
</div>
</template>
</HLModal>
</template>
<script setup>
import { ref } from 'vue'
const showModal = ref(false)
const form = ref({ name: '', email: '' })
const handleSubmit = () => {
// Handle form submission
showModal.value = false
}
const handleCancel = () => {
form.value = { name: '', email: '' }
showModal.value = false
}
</script>
Breaking Changes
- Required ID Prop: The
id
prop is now required for accessibility purposes - Component Structure: Simplified from multiple components (UIModal, UIModalHeader, UIModalContent, UIModalFooter) to a single HLModal component
- Slot System: Changed from component-based to slot-based structure
- Model Binding: Changed from
v-model
tov-model:show
- Type System: Standardized modal types with predefined styles and behaviors
- Footer Actions: Changed from custom buttons to predefined action patterns
- Event Names: Standardized event naming and added new lifecycle events
- Header Icons: Integrated icon system with type-based defaults
- Theme Integration: New color system integrated with HighRise theme variables
- Accessibility: Enhanced ARIA support and keyboard navigation
Best Practices
- Always provide a unique
id
prop for accessibility - Use appropriate modal types based on context:
default
: For general confirmations and formsinfo
: For information messagessuccess
: For success confirmationswarning
: For warning messageserror
: For destructive actions
- Keep modal content concise and clear
- Use appropriate event handlers for actions
- Consider mobile responsiveness
- Follow accessibility guidelines
- Use consistent styling across your application
- Handle ESC and mask clicks appropriately
- Provide clear action labels
- Use appropriate modal width for content
Additional Features
- Enhanced Styling: Built-in support for theme variables
- Type System: Predefined styles and behaviors for different types
- Back Navigation: Built-in support for back button
- Action Patterns: Standardized footer action patterns
- Accessibility: Improved ARIA attributes and keyboard navigation
- Animations: Smooth enter/leave transitions
- Event System: Comprehensive lifecycle events
- Theme Integration: Consistent styling with HighRise components
- Icon System: Type-based icons with customization options
- Responsive Design: Flexible sizing options