Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
180 changes: 180 additions & 0 deletions adminforth/documentation/docs/tutorial/03-Customization/14-afcl.md
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,186 @@ const enable = ref(false)
</div>
</div>

## Dialog (Pop-up)

<div class="split-screen" >
<div>

```ts
import { Dialog } from '@/afcl';
import { Button } from '@/afcl';
```

```html
<Dialog class="w-96">
<template #trigger>
<Button>Dialog Toggle</Button>
</template>

<div class="space-y-4">
<p>This is the first paragraph of dialog content.</p>
<p>And this is the second paragraph.</p>
</div>
</Dialog>
```
</div>
<div>
![AFCL Dialog](image-87.png)
</div>
</div>

### Header
You can add header to the dialog by using header prop.

<div class="split-screen" >
<div>

```html
//diff-remove
<Dialog class="w-96">
//diff-add
<Dialog
//diff-add
class="w-96"
//diff-add
header="Dialog Header"
//diff-add
>
<template #trigger>
<Button>Dialog Toggle</Button>
</template>

<div class="space-y-4">
<p>This is the first paragraph of dialog content.</p>
<p>And this is the second paragraph.</p>
</div>
</Dialog>
```
</div>
<div>
![AFCL Dialog](image-88.png)
</div>
</div>

If you want to remove close button in header, you can add `:header-close-button="false"` prop to `<Dialog>`.

### Buttons
By default dialog will have just one "Close" button. If you want to change that, you can set `buttons` to a desirable array.

<div class="split-screen" >
<div>

```html
<Dialog
class="w-96"
header="Dialog Header"
//diff-add
:buttons="[
//diff-add
{ label: 'Save', onclick: (dialog) => { doSave(); dialog.hide(); } },
//diff-add
{ label: 'Close', onclick: (dialog) => dialog.hide() },
//diff-add
]"
>
<template #trigger>
<Button>Dialog Toggle</Button>
</template>

<div class="space-y-4">
<p>This is the first paragraph of dialog content.</p>
<p>And this is the second paragraph.</p>
</div>
</Dialog>
```
</div>
<div>
![AFCL Dialog](image-89.png)
</div>
</div>

Dialog component will render each button using afcl `Button` component. You can pass any props to those buttons by adding `options` field to a button item.

<div class="split-screen" >
<div>

```html
<Dialog
class="w-96"
header="Dialog Header"
:buttons="[
//diff-remove
{ label: 'Save', onclick: (dialog) => { doSave(); dialog.hide(); } },
//diff-add
{
//diff-add
label: 'Save',
//diff-add
options: {
//diff-add
disabled: savingIsAllowed,
//diff-add
},
//diff-add
onclick: (dialog) => { doSave(); dialog.hide(); },
//diff-add
},
{ label: 'Close', onclick: (dialog) => dialog.hide() },
]"
>
<template #trigger>
<Button>Dialog Toggle</Button>
</template>

<div class="space-y-4">
<p>This is the first paragraph of dialog content.</p>
<p>And this is the second paragraph.</p>
</div>
</Dialog>
```
</div>
<div>
![AFCL Dialog](image-90.png)
</div>
</div>

### Dialog persistence
Default behavior of the Dialog component will allow user to close it by just clicking outside. You can prevent that by setting `clickToCloseOutside` to `false`.

<div class="split-screen" >
<div>

```html
<Dialog
class="w-96"
header="Dialog Header"
:buttons="[
{
label: 'Save',
options: {
disabled: savingIsAllowed,
},
onclick: (dialog) => { doSave(); dialog.hide(); },
},
{ label: 'Close', onclick: (dialog) => dialog.hide() },
]"
//diff-add
:click-to-close-outside="false"
>
<template #trigger>
<Button>Dialog Toggle</Button>
</template>

<div class="space-y-4">
<p>This is the first paragraph of dialog content.</p>
<p>And this is the second paragraph.</p>
</div>
</Dialog>
```
</div>
<div>
</div>
</div>

## Dropzone

Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
91 changes: 47 additions & 44 deletions adminforth/spa/src/afcl/Dialog.vue
Original file line number Diff line number Diff line change
@@ -1,51 +1,54 @@
<template>
<div @click="modal?.show()" class="inline-flex items-center cursor-pointer">
<slot></slot>
<div
v-if="$slots.trigger"
@click="modal?.show()" class="inline-flex items-center cursor-pointer"
>
<slot name="trigger"></slot>
</div>
<div ref="modalEl" tabindex="-1" aria-hidden="true" class="hidden overflow-y-auto overflow-x-hidden fixed top-0 right-0 left-0 z-50 justify-center items-center w-full md:inset-0 h-[calc(100%-1rem)] max-h-full">
<div class="relative p-4 w-full max-w-2xl max-h-full">
<!-- Modal content -->
<div class="relative bg-white rounded-lg shadow-sm dark:bg-gray-700">
<!-- Modal header -->
<div
v-if="header"
class="flex items-center justify-between p-4 md:p-5 border-b rounded-t dark:border-gray-600 border-gray-200"
>
<h3 class="text-xl font-semibold text-gray-900 dark:text-white">
{{ header }}
</h3>
<button
v-if="headerCloseButton"
type="button"
class="text-gray-400 bg-transparent hover:bg-gray-200 hover:text-gray-900 rounded-lg text-sm w-8 h-8 ms-auto inline-flex justify-center items-center dark:hover:bg-gray-600 dark:hover:text-white"
@click="modal?.hide()"
>
<svg class="w-3 h-3" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 14 14">
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="m1 1 6 6m0 0 6 6M7 7l6-6M7 7l-6 6"/>
</svg>
<span class="sr-only">Close modal</span>
</button>
</div>
<!-- Modal body -->
<div class="p-4 md:p-5 space-y-4">
<slot name="content"></slot>
</div>
<!-- Modal footer -->
<div
v-if="buttons.length"
class="flex items-center p-4 md:p-5 border-t border-gray-200 rounded-b dark:border-gray-600"
>
<Button
v-for="(button, buttonIndex) in buttons"
:key="buttonIndex"
v-bind="button.options"
:class="{ 'ms-3': buttonIndex > 0 }"
@click="button.onclick(modal)"
>
{{ button.label }}
</Button>
</div>
<div v-bind="$attrs" class="relative p-4 max-w-2xl max-h-full" :class="$attrs.class?.includes('w-') ? '' : 'w-full'">
<!-- Modal content -->
<div class="relative bg-white rounded-lg shadow-sm dark:bg-gray-700">
<!-- Modal header -->
<div
v-if="header"
class="flex items-center justify-between p-4 md:p-5 border-b rounded-t dark:border-gray-600 border-gray-200"
>
<h3 class="text-xl font-semibold text-gray-900 dark:text-white">
{{ header }}
</h3>
<button
v-if="headerCloseButton"
type="button"
class="text-gray-400 bg-transparent hover:bg-gray-200 hover:text-gray-900 rounded-lg text-sm w-8 h-8 ms-auto inline-flex justify-center items-center dark:hover:bg-gray-600 dark:hover:text-white"
@click="modal?.hide()"
>
<svg class="w-3 h-3" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 14 14">
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="m1 1 6 6m0 0 6 6M7 7l6-6M7 7l-6 6"/>
</svg>
<span class="sr-only">Close modal</span>
</button>
</div>
<!-- Modal body -->
<div class="p-4 md:p-5 space-y-4 text-gray-700 dark:text-gray-400">
<slot></slot>
</div>
<!-- Modal footer -->
<div
v-if="buttons.length"
class="flex items-center p-4 md:p-5 border-t border-gray-200 rounded-b dark:border-gray-600"
>
<Button
v-for="(button, buttonIndex) in buttons"
:key="buttonIndex"
v-bind="button.options"
:class="{ 'ms-3': buttonIndex > 0 }"
@click="button.onclick(modal)"
>
{{ button.label }}
</Button>
</div>
</div>
</div>
</div>
</template>
Expand Down
1 change: 1 addition & 0 deletions adminforth/spa/src/afcl/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,6 @@ export { default as Table } from './Table.vue';
export { default as ProgressBar } from './ProgressBar.vue';
export { default as Spinner } from './Spinner.vue';
export { default as Skeleton } from './Skeleton.vue';
export { default as Dialog } from './Dialog.vue';