Skip to content

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 -->

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>

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:

  1. Set :closable="false" since the modal handles its own close button
  2. Use the header-icons slot for custom icons
  3. Use the header-content slot for additional actions
  4. 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>
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>
  • 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>

The modal component does not have any default padding. You must add padding to your content manually:

  1. Header: No default padding - you must add padding using Tailwind classes
  2. Content: No default padding - you must add padding using Tailwind classes
  3. Footer: Default padding is coming from the HLSectionFooter component. You can override the padding by passing :top-padding="false" and :bottom-padding="false" to the HLSectionFooter 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 PropHighRise PropNotes
-idRequired string for accessibility
modelValueshowControls modal visibility
widthwidthModal width (default: 483px)
zIndexzIndexCustom z-index
maskClosablemaskClosableClose on mask click (default: true)
closeOnEsccloseOnEscClose on ESC key (default: true)
autoFocusautoFocusAuto focus on open (default: false)
-type'default', 'info', 'success', 'warning', 'error'
-showBackShow back button (default: false)
-showCloseShow close button (default: true)
-showHeaderShow header section (default: true)
-showFooterShow footer section (default: true)
-showHeaderIconShow type icon in header (default: true)

Event Changes

ghl-ui EventHighRise EventNotes
update:modelValueupdate:showModel binding update
closecloseModal close event
positive-clickright-primary-clickPrimary action click
negative-clickright-secondary-clickSecondary action click
-left-clickLeft action click
-backBack button click
-after-enterAfter modal opens
-after-leaveAfter modal closes
-before-leaveBefore modal closes
-escESC key pressed
-mask-clickMask clicked

Slot Changes

ghl-ui ComponentHighRise SlotNotes
UIModalHeaderheaderHeader content with title and description
UIModalContentdefaultMain content
UIModalFooterfooterFooter content (optional)

Advanced Examples

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

  1. Required ID Prop: The id prop is now required for accessibility purposes
  2. Component Structure: Simplified from multiple components (UIModal, UIModalHeader, UIModalContent, UIModalFooter) to a single HLModal component
  3. Slot System: Changed from component-based to slot-based structure
  4. Model Binding: Changed from v-model to v-model:show
  5. Type System: Standardized modal types with predefined styles and behaviors
  6. Footer Actions: Changed from custom buttons to predefined action patterns
  7. Event Names: Standardized event naming and added new lifecycle events
  8. Header Icons: Integrated icon system with type-based defaults
  9. Theme Integration: New color system integrated with HighRise theme variables
  10. Accessibility: Enhanced ARIA support and keyboard navigation

Best Practices

  1. Always provide a unique id prop for accessibility
  2. Use appropriate modal types based on context:
    • default: For general confirmations and forms
    • info: For information messages
    • success: For success confirmations
    • warning: For warning messages
    • error: For destructive actions
  3. Keep modal content concise and clear
  4. Use appropriate event handlers for actions
  5. Consider mobile responsiveness
  6. Follow accessibility guidelines
  7. Use consistent styling across your application
  8. Handle ESC and mask clicks appropriately
  9. Provide clear action labels
  10. Use appropriate modal width for content

Additional Features

  1. Enhanced Styling: Built-in support for theme variables
  2. Type System: Predefined styles and behaviors for different types
  3. Back Navigation: Built-in support for back button
  4. Action Patterns: Standardized footer action patterns
  5. Accessibility: Improved ARIA attributes and keyboard navigation
  6. Animations: Smooth enter/leave transitions
  7. Event System: Comprehensive lifecycle events
  8. Theme Integration: Consistent styling with HighRise components
  9. Icon System: Type-based icons with customization options
  10. Responsive Design: Flexible sizing options