Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: modal and toast improvements #7

Draft
wants to merge 34 commits into
base: main
Choose a base branch
from

Conversation

anwarulislam
Copy link
Member

@anwarulislam anwarulislam commented Mar 4, 2024

Closes HFE-415

Two new components were added. HoppToast and HoppModal.

HoppToast has legacy support for previous Toast integration with vue-toasted.

New Toast (vue-sonner) and Legacy Toast (vue-toasted)

Using Toast

  1. Import toast and Toaster from @hoppscotch/ui.
  2. Include <Toaster /> in your template.
  3. Create a function that calls toast.success with a message and options.
  4. Trigger the function to show the toast.
<template>
  <Toaster />
  <button @click="showToast">Show Toast</button>
</template>

<script lang="ts" setup>
import { toast, Toaster } from '@hoppscotch/ui'

const showToast = () => {
  toast.success('Hello from Hoppscotch!', {
    duration: 5000,
    position: 'bottom-right'
  })
}
</script>

Using Legacy Toast

  1. Import legacyToast from @hoppscotch/ui.
  2. Include <Toaster /> in your template.
  3. Create a function that calls legacyToast.success with a message and options.
  4. Trigger the function to show the legacy toast.
<template>
  <button @click="showLegacyToast">Show Legacy Toast</button>
</template>

<script lang="ts" setup>
import { legacyToast } from '@hoppscotch/ui'

const showLegacyToast = () => {
  legacyToast.success('Hello from Hoppscotch!', {
    duration: 5000,
    action: [
      {
        text: 'Undo',
        onClick: () => {
          alert('Undo clicked')
        }
      },
      {
        text: 'Close',
        onClick: (_, toast) => {
          toast?.goAway(0)
        }
      }
    ]
  })
}
</script>

Using Modal

  1. Import VuePromiseModalsPlugin from @hoppscotch/ui and use it in main.ts as plugin app.use(VuePromiseModalsPlugin).
  2. Import useModals, HoppModal, and DialogHost from @hoppscotch/ui.
  3. Include <DialogHost /> in your template.
  4. Use useModals to get the openModal function.
  5. Create a function that calls openModal with a component that uses HoppModal. (HoppModal is a UI wrapper for modals)
  6. Trigger the function to show the modal.
<template>
  <DialogHost />
  <!-- Include DialogHost once in your app -->
  <button @click="showModal">Show Modal</button>
</template>

<script lang="ts" setup>
import { useModals, HoppModal, DialogHost } from "@hoppscotch/ui";
import { defineComponent, h } from "vue";

const { openModal } = useModals();

const showModal = () => {
  openModal(
    defineComponent({
      render() {
        return h(
          HoppModal,
          {
            title: "Hello from Hoppscotch!",
            onClose: () => {
              this.$emit("modal-reject");
            },
          },
          {
            body: () => "This is a modal",
          }
        );
      },
    })
  );
};
</script>

Open a modal component

Create a new component that uses HoppModal and defineEmits to emit the modal-reject event when the modal is closed.

<template>
  <HoppModal title="Hello from Hoppscotch!" @close="emit('modal-reject')">
    <p>This is a modal</p>
  </HoppModal>
</template>

<script setup lang="ts">
import { HoppModal } from '@hoppscotch/ui'
const emit = defineEmits<{
  (e: 'modal-reject'): void
}>()
</script>

And then pass it to openModal:

<script lang="ts" setup>
import { useModals, HoppModal, DialogHost } from '@hoppscotch/ui'
import GreetingsDialog from './GreetingsDialog.vue'

const { openModal } = useModals()

const showModal = () => {
  openModal(GreetingsDialog)
}
</script>

@anwarulislam anwarulislam marked this pull request as ready for review April 9, 2024 13:30
Copy link
Contributor

@JoelJacobStephen JoelJacobStephen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@anwarulislam I am having a few doubts here:

  1. The new HoppModal doesn't have a proper UI associated with it. I would assume that it should have a UI similar to the old HoppSmartModal.
  2. Why do we need InputDialog as a separate component? Can it be clubbed with HoppModal and toggled using props?

src/helpers/toast.ts Outdated Show resolved Hide resolved
src/components/modal/InputDialog.vue Outdated Show resolved Hide resolved
src/stories/NewModal.story.vue Outdated Show resolved Hide resolved
src/stories/Toast.story.vue Outdated Show resolved Hide resolved
src/helpers/toast.ts Outdated Show resolved Hide resolved
src/helpers/toast.ts Outdated Show resolved Hide resolved
src/stories/Toast.story.vue Outdated Show resolved Hide resolved
Copy link
Contributor

@JoelJacobStephen JoelJacobStephen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@anwarulislam Please look into these comments.
Also, I noticed that we are having really long import statements in most components. I think we can perform an abstraction so that we can have better import hierarchy. We can tackle this in the future though.

src/components/modal/examples/InputDialog.vue Outdated Show resolved Hide resolved
src/components/modal/examples/NestedDialog.vue Outdated Show resolved Hide resolved
src/stories/NewModal.story.vue Outdated Show resolved Hide resolved
src/components/modal/index.vue Outdated Show resolved Hide resolved
src/stories/Modal.story.vue Outdated Show resolved Hide resolved
@JoelJacobStephen JoelJacobStephen self-requested a review May 3, 2024 07:03
Copy link
Contributor

@JoelJacobStephen JoelJacobStephen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

toast.success, toast.error seems to not be working. In the legacy toast story, clicking on the simple legacy toast button does not invoke a toaster.

Copy link
Member

@jamesgeorge007 jamesgeorge007 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • While testing out the HoppModal component behavior from the app, I noticed the modal gets displayed for the first time, but not for further attempts with the following error getting logged to the console.

    image

    Tried it on the CollectionsAdd component, Ref.

    The handler at the page level was updated as below.

    // collections/index.vue
    
    import { useModals } from "@hoppscotch/ui"
    import CollectionsAdd from "./Add.vue"
    
    const { openModal } = useModals()
    
    const displayModalAdd = async (show: boolean) => {
      showModalAdd.value = show
    
      try {
        const { name: collectionName } = await openModal(CollectionsAdd, {
          show: showModalAdd.value,
          loadingState: modalLoadingState.value,
        })
    
        addNewRootCollection(collectionName)
      } catch (_) {
        displayModalAdd(false)
      }
    
      if (!show) resetSelectedData()
    }

    DialogHost component is rendered at the top level App component.

  • Pressing the escape key anytime results in the following exception.

    image

    image

src/components/modal/index.ts Outdated Show resolved Hide resolved
src/helpers/index.ts Outdated Show resolved Hide resolved
src/helpers/toast.ts Outdated Show resolved Hide resolved
src/components/modal/index.vue Show resolved Hide resolved
src/helpers/toast.ts Outdated Show resolved Hide resolved
@jamesgeorge007 jamesgeorge007 changed the title Modal and Toaster Improvements feat: modal and toast improvements May 6, 2024
Copy link
Member

@jamesgeorge007 jamesgeorge007 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The issue mentioned above with the HoppModal component persists.

Create collection flow

  • The actions (save/cancel) don't give any feedback during the first attempt at opening the modal.

  • They start responding during further attempts.

  • Creating a collection and attempting to open the modal again results in the above exception.

    image

hopp-modal-behavior.mov

Comment on lines +29 to +31
setTimeout(() => {
sonner.dismiss(toastId)
}, delay)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We'll need a way to clear the timeout via clearTimeout.

src/components/toast/legacy-toast.ts Show resolved Hide resolved
src/components/toast/Toast.vue Outdated Show resolved Hide resolved
@AndrewBastin AndrewBastin marked this pull request as draft May 30, 2024 15:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants