# Modal

Modals serve as overlays to concentrate user attention on a specific task without navigating away from the current context. They are typically used to elicit a response from the user.

To utilize Modals, your application needs to first set up the overlay plugin. This facilitates the necessary context and layering for Modals within your app. For a detailed guide on setup, refer to the Overlay docs (opens new window).

# Opening a Modal

Modals are opened using the show method of the overlay object, accessible through this.$overlay.show(). The method requires three arguments: the Modal component to be opened, any options for the component, and any callbacks for the view.

this.$overlay.show(
  MyModalComponent,
  { title: this.myModalTitle },
  { onSubmit: this.doSomething }
)

# Title Prop/Slot

The title prop is used to set the title of the modal. It is a string that gets displayed at the top of the modal. The title prop is required for the ci-modal component. It provides context to the user and typically indicates the purpose of the modal.

# Action Slot

The action slot is available for use with various components, for example, ci-button components can be passed into this slot, and they are automatically stacked vertically. The button with the highest priority should be placed at the top. At a minimum, Modals should have a brand button and a brand-text button, following UX best practices.

<template>
  <div>
    <ci-button @click="openModal">Open Modal</ci-button>
  </div>
</template>

<script>
import ModalDemoModal from './ModalDemoModal.vue'

export default {
  methods: {
    openModal() {
      this.$overlay.show(ModalDemoModal, { title: 'Modal with Actions', dismissible: true })
    },
  },
}
</script>
// ModalDemoModal.vue
<template>
  <ci-modal :title="title" :dismissible="dismissible">
    Content goes here.
    <template #actions>
      <ci-button @click="handleAction">Action</ci-button>
      <ci-button variant="brand-text" @click="handleClose">Close</ci-button>
    </template>
  </ci-modal>
</template>

<script>
export default {
  props: {
    title: {
      type: String,
      default: 'Modal'
    },
    dismissible: {
      type: Boolean,
      default: false
    }
  },
  methods: {
    handleAction() {
      alert('Action');
    },
    handleClose() {
      this.$emit('close');
    },
  },
}
</script>

# Variants

The variant prop allows you to modify the title size of the Modal. The compact variant is meant for sidebar applications.

<template>
  <DemoGrid>
    <ci-button @click="openModal('compact')">Open Compact Modal</ci-button>
    <ci-button @click="openModal('normal')">Open Normal Modal</ci-button>
    <ci-button @click="openModal('large')">Open Large Modal</ci-button>
    <ci-button @click="openModal('extra-large')">Open Extra Large Modal</ci-button>
  </DemoGrid>
</template>

<script>
import ModalVariantsDemoModal from './ModalVariantsDemoModal.vue'

export default {
  methods: {
    openModal(variant) {
      this.$overlay.show(ModalVariantsDemoModal, { title: `This is a ${variant} modal`, variant, dismissible: true })
    },
  }
}
</script>

// ModalVariantsDemoModal.vue
<template>
  <ci-modal :title="title" :variant="variant" :dismissible="dismissible">
    Content goes here.
    <template #actions>
      <ci-button @click="handleAction">Action</ci-button>
      <ci-button variant="brand-text" @click="handleClose">Close</ci-button>
    </template>
  </ci-modal>
</template>

<script>
export default {
  props: {
    title: {
      type: String,
      default: 'Modal'
    },
    variant: {
      type: String,
      default: 'standard'
    },
    dismissible: {
      type: Boolean,
      default: false
    }
  },
  methods: {
    handleAction() {
      alert('Action');
    },
    handleClose() {
      this.$emit('close');
    },
  },
}
</script>

# Padding

Use the padding prop to adjust the padding on the Modal.

<template>
  <DemoGrid>
    <ci-button
      v-for="option in paddingOptions"
      :key="option"
    >
      {{ option }} padding
    </ci-button>
  </DemoGrid>
</template>
<script>
import ModalPaddingDemoModal from './ModalPaddingDemoModal.vue'

export default {
  data() {
    return {
      paddingOptions: ['flush', '2xs', 'xs', 'sm', 'md']
    }
  },
  methods: {
    openModal(padding) {
      this.$overlay.show(ModalPaddingDemoModal, { title: `This is a ${padding} modal`, padding, dismissible: true })
    }
  }
}
</script>
// ModalPaddingDemoModal.vue
<template>
  <ci-modal 
    :title="title" 
    :padding="padding" 
    :dismissible="dismissible"
  >
    Content goes here.
    <template #actions>
      <ci-button @click="handleAction">
        Action
      </ci-button>
      <ci-button 
        variant="brand-text" 
        @click="handleClose"
      >
        Close
      </ci-button>
    </template>
  </ci-modal>
</template>

<script>
export default {
  props: {
    title: {
      type: String,
      default: 'Modal'
    },
    padding: {
      type: String,
      default: 'xs'
    },
    dismissible: {
      type: Boolean,
      default: false
    }
  },
  methods: {
    handleAction() {
      alert('Action');
    },
    handleClose() {
      this.$emit('close');
    },
  },
}
</script>

# Dismissible Modals

Modals can be made dismissible by setting the dismissible prop to true. A dismissible modal can be closed by clicking the X or the overlay background.

<template>
  <div>
    <ci-button @click="openModal">Open Dismissible Modal</ci-button>
  </div>
</template>

<script>
import ModalDismissibleDemoModal from './ModalDismissibleDemoModal.vue'

export default {
  methods: {
    openModal() {
      this.$overlay.show(ModalDismissibleDemoModal, { title: 'Dismissible Modal', dismissible: true })
    },
  },
}
</script>
// ModalDismissibleDemoModal.vue
<template>
  <ci-modal :title="title" :dismissible="dismissible">
    Content goes here.
    <template #actions>
      <ci-button @click="handleAction">Action</ci-button>
      <ci-button variant="brand-text" @click="handleClose">Close</ci-button>
    </template>
  </ci-modal>
</template>

<script>
export default {
  props: {
    title: {
      type: String,
      default: 'Modal'
    },
    dismissible: {
      type: Boolean,
      default: false
    }
  },
  methods: {
    handleAction() {
      alert('Action');
    },
    handleClose() {
      this.$emit('close');
    },
  },
}
</script>

# Events

Event Description Payload
close This event is emitted when the dynamic component inside the overlay emits a close event None

# Methods

Method Description Parameters
show Displays the overlay with a specified component and its attributes and listeners component: VueConstructor, componentsAttrs: any = {}, componentListeners: any = {}
Last Updated: 11/27/2023, 3:18:44 PM