oruga-ui / oruga

🐛 Oruga is a lightweight library of UI components without any CSS framework dependency
https://oruga-ui.com
MIT License
1.12k stars 169 forks source link

Add Dialog Component #225

Closed mouadTaoussi closed 2 years ago

mouadTaoussi commented 3 years ago

Description

Adding Dialog Component .

Why Oruga need this feature

Easiest way to propmt or alert the user

Note:I Might take time becuase I have a Display issue in my Laptop that needs to be fixed first, then work on the feature!

Thaurin commented 2 years ago

Yes, I need this before I can finish migrating to Oruga!

Thaurin commented 2 years ago

This is literally keeping me from migrating a Vue 2 web application that is in production to Vue 3 with Oruga with Bulma plugin, then Vue 3!

jtommy commented 2 years ago

I got it, in the next release will be available the carousel. There is a PR but incomplete and I need time to add Oruga features

As workaround you can use modal component

urkle commented 2 years ago

@jtommy @mouadTaoussi so I took a look some at the PR #254 and it currently doesn't really work.
I have a local branch where I have done some rework on it and have it doing the basic alert dialog now (including working with theme-bulma, but only Vue2 right now)

@jtommy A few questions I have though on how you envision this component working in Oruga.

1) the dialog currently uses them-bulma-specific inner contents (modal-card-head, modal-card, etc..). Q: how do you envision exposing this to configuration to allow the best customization by the CSS framework layer? 2) the dialog currently "extends" off of Modal and re-implements a lot of properties and code. Q: right now my version just has an o-modal in the body that I am using. Is that acceptable? or would you still rather have it extend OModal? What is the "official" set of properties it should expose to the $dialog.* methods?

jtommy commented 2 years ago

The PR was born as Buefy porting but without any Oruga features.

  1. It needs the class props in order to customize each element
  2. It extends modal to get all data and methods but the template is different. If we decide to use o-modal probably doesn't make sense the dialog component, it's only a quick way to show alert but it always works as programmatic modal
urkle commented 2 years ago

@jtommy

1) the dialog contents, my concern there is that to make it "right" for the CSS agnostic functionality the theme configuration should realistically allow the entire template contents to be customized. But I am not quite sure how to cleanly do that in a way that 1) won't require the vue template compiler in final builds, and 2) will work cleanly between 2& 3 (though I 2.6+ now has the same slot syntaxes as v3 right?)

  1. So I can investigate reworking the dialog "JS" code (in DialogProgrammatic) to instead trigger the programatic modal.. but we just need to find the clean answer to 1 as to how we should expose the "template".

right now have something that looks like this (note I do NOT have all the functionality in-place at all)

          <o-modal ref="modal" :active="isActive">
            <div class="modal-card">
                <header class="modal-card-head" v-if="title">
                    <p class="modal-card-title">{{ title }}</p>
                </header>
                <section class="modal-card-body">
                    <div class="media">
                        <div
                            class="media-left"
                            v-if="hasIcon && (icon || iconByType)">
                            <o-icon
                                :icon="icon ? icon : iconByType"
                                :pack="iconPack"
                                :type="type"
                                :both="!icon"
                                size="is-large"/>
                        </div>
                        <div class="media-content">
                            <p>
                                <template v-if="$slots.default">
                                    <slot />
                                </template>
                                <template v-else>
                                    <span v-html="message" />
                                </template>
                            </p>

                            <div v-if="hasInput" class="field">
                                <div class="control">
                                    <input
                                        v-model="prompt"
                                        class="input"
                                        ref="input"
                                        :class="{ 'is-danger': validationMessage }"
                                        v-bind="inputAttrs"
                                        @compositionstart="isCompositing = true"
                                        @compositionend="isCompositing = false"
                                        @keydown.enter="confirm">
                                </div>
                                <p class="help is-danger">{{ validationMessage }}</p>
                            </div>
                        </div>
                    </div>
                </section>
                <footer class="modal-card-foot">
                    <o-button
                        v-if="showCancel"
                        ref="cancelButton"
                        @click="cancel">{{ cancelText }}</o-button>
                    <o-button
                        :class="type"
                        ref="confirmButton"
                        @click="confirm">{{ confirmText }}</o-button>
                </footer>
            </div>
        </o-modal>
jtommy commented 2 years ago
  1. As i told you in this PR there is nothing about Oruga idea. For example there isn't bodyClass prop or no modal class are applied to it. Does it make sense?

About template I don't know.. dialog might be different by modal but usually is only a built-in modal with a template for alert, confirm and prompt. For this reason I'm asking if it make sense to add the dialog component.

urkle commented 2 years ago

I understand that PR was about a quick and dirty port.. I'm trying to make a PR that is more close to the final "oruga style" idea. Hence all the questions.. I'd rather build up something useful that can easily be included in the next release vs something that'd have to be redone again to fit more with the Oruga style.

As for why add a dialog component? Because there is some nicety in having a built-in alert, confirm, and prompt style dialogs in the system. AND especially if those work in a promise/async+await style manner to make coding easy.

Or find a way to "easily" provide that kind of thing using the programatic modal? and include some nice examples on how to utilize that? (e.g. like the "tost" examples for notifications)

In the end I am wanting something like this.

const result = await this.$oruga.dialog.confirm({
   message: 'Really delete this record?',
   type: 'variant',
});

// Or whatever is decided the return value to be
if (result === true) {
   // do stuff to trigger the deletion.
}

VS doing lots of callbacks.

In another project (vue 2-based) where I spent this week switching it from "basic html" to Oruga I found the lack of this construct in Oruga (hence why I am looking at this issue so I can help contribute). And had to stick with using another library (vue-modal-dialogs) All for a simple confirm dialog.

jtommy commented 2 years ago

I understand that promise way is great and helpful for prompt and confirm. In other hand dialog UI is only a modal and the good examples could be enough at the moment

urkle commented 2 years ago

@jtommy What about a "dialog" promise interface with no component but injects props into a user-provided component to represent their UI and provides a clean way to send back the "response"? This could (maybe) even be an adjustment of the programatic Modal interface?

jtommy commented 2 years ago

Can you make an example to understand better?

urkle commented 2 years ago

@jtommy I created PR #314 that has a proposal for handling a "promise/async" modal.open method.

I've tested this in both Vue2 and Vue3 and it works great.

I did change the return contract for modal.open, but it was already inconsistent before.. (Vue2 returned the component instance, Vue3 returned void)

We could extend this promise concept to the notifications.open and loading.open as well.

jtommy commented 2 years ago

I want to fix Vue 3, because it has to return the component instance instead of void as https://github.com/oruga-ui/oruga/issues/313

urkle commented 2 years ago

@jtommy Ok. Let me see if I can figure how to do that and extend this to support returning the instance in Vue 3 ( I recall seeing where that was exposed ). and move the promise handling to a different location.

I'll submit a different PR that just fixes the instance return separate from the promise PR.

jtommy commented 2 years ago

@urkle https://github.com/oruga-ui/oruga/blob/dff0a04fde4d2477bc18510d5fbcfd8c880d3850/packages/oruga-next/src/components/modal/index.ts#L35 I think we haven't to return the result of render but only vnode variable.

urkle commented 2 years ago

@jtommy to return the component it is actually vnode.component.proxy (that is the same as "this" inside any component method).

I have a PR going up shortly.

urkle commented 2 years ago

@jtommy PR #315