Files
KanbanGit/tests/Fixtures/FeedbackPreview.vue
T
Twyco 7edd8daf49
CI/CD / test_and_check_app (push) Successful in 4m48s
CI/CD / Publish immutable image (push) Skipped
CI/CD / Publish immutable image (pull_request) Canceled after 0s
CI/CD / test_and_check_app (pull_request) Canceled after 5s
feat(KAN-20): unify dialogs feedback and protect ticket drafts
2026-09-10 09:26:12 +02:00

155 lines
5.9 KiB
Vue

<script setup>
import { Link, useForm } from '@inertiajs/vue3';
import { ref } from 'vue';
import ProjectTicketController from '@/actions/App/Http/Controllers/ProjectTicketController';
import AppearanceTabs from '@/components/AppearanceTabs.vue';
import FeedbackState from '@/components/FeedbackState.vue';
import FormFeedback from '@/components/FormFeedback.vue';
import InputError from '@/components/InputError.vue';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import {
Dialog,
DialogContent,
DialogDescription,
DialogHeader,
DialogTitle,
DialogTrigger,
DialogClose,
DialogScrollContent,
} from '@/components/ui/dialog';
import {
Sheet,
SheetContent,
SheetTitle,
SheetDescription,
SheetTrigger,
} from '@/components/ui/sheet';
import {
DropdownMenu,
DropdownMenuTrigger,
DropdownMenuContent,
DropdownMenuItem,
} from '@/components/ui/dropdown-menu';
import { useFormProtection } from '@/composables/useFormProtection';
import { index as projectsIndex } from '@/routes/projects/index';
const form = useForm('feedback-preview', { title: '' });
const protection = useFormProtection(form);
const dialogOpen = ref(false);
const menuSelection = ref('');
const submit = () =>
protection.submit(ProjectTicketController.store({ project: 7 }));
</script>
<template>
<main class="gap-column p-page mx-auto grid max-w-3xl">
<div class="gap-stack flex flex-wrap items-center justify-between">
<h1 class="text-headline">Dialogs and feedback</h1>
<AppearanceTabs />
</div>
<FeedbackState
state="empty"
description="New tickets will appear here."
/>
<FeedbackState state="loading" />
<form
class="gap-card bg-card p-card grid rounded-md border"
@submit.prevent="submit"
>
<label for="title">Title</label>
<Input
id="title"
v-model="form.title"
:invalid="Boolean(form.errors.title)"
aria-describedby="title-error"
/>
<InputError id="title-error" :message="form.errors.title" />
<FormFeedback :state="protection.state.value" @retry="submit" />
<Button type="submit" :loading="form.processing">Save draft</Button>
<Button type="button" variant="outline" @click="form.cancel()"
>Cancel request</Button
>
</form>
<Link :href="projectsIndex()">Leave page</Link>
<div class="gap-stack flex flex-wrap">
<Dialog v-model:open="dialogOpen">
<Button id="programmatic-trigger" @click="dialogOpen = true"
>Open dialog</Button
>
<DialogContent>
<DialogHeader
><DialogTitle>Edit details</DialogTitle
><DialogDescription
>Keyboard and focus preview.</DialogDescription
></DialogHeader
>
<Input aria-label="Dialog title" />
<Dialog>
<DialogTrigger as-child
><Button>Open nested dialog</Button></DialogTrigger
>
<DialogContent>
<DialogHeader
><DialogTitle>Nested details</DialogTitle
><DialogDescription
>Returns focus to the parent
dialog.</DialogDescription
></DialogHeader
>
<DialogClose as-child
><Button>Done</Button></DialogClose
>
</DialogContent>
</Dialog>
<DialogClose as-child
><Button variant="outline">Cancel</Button></DialogClose
>
</DialogContent>
</Dialog>
<Dialog>
<DialogTrigger as-child
><Button>Open long dialog</Button></DialogTrigger
>
<DialogScrollContent>
<DialogHeader
><DialogTitle>Long details</DialogTitle
><DialogDescription
>Scrollable content on small
screens.</DialogDescription
></DialogHeader
>
<p v-for="item in 30" :key="item">Detail {{ item }}</p>
<DialogClose as-child
><Button>Finish reading</Button></DialogClose
>
</DialogScrollContent>
</Dialog>
<Sheet>
<SheetTrigger as-child
><Button>Open sheet</Button></SheetTrigger
>
<SheetContent class="p-page">
<SheetTitle>Sheet details</SheetTitle
><SheetDescription
>Focus returns to the trigger.</SheetDescription
>
<Input aria-label="Sheet title" />
</SheetContent>
</Sheet>
<DropdownMenu>
<DropdownMenuTrigger as-child
><Button>Open actions</Button></DropdownMenuTrigger
>
<DropdownMenuContent>
<DropdownMenuItem disabled>Unavailable</DropdownMenuItem>
<DropdownMenuItem @select="menuSelection = 'selected'"
>Select action</DropdownMenuItem
>
</DropdownMenuContent>
</DropdownMenu>
<span role="status">{{ menuSelection }}</span>
</div>
</main>
</template>