From 4a5e2e44450070c868b8e96d7e16f45b9a366373 Mon Sep 17 00:00:00 2001 From: andrzej Date: Wed, 19 Jun 2024 23:21:51 +0200 Subject: [PATCH] add delete dialog --- src/@/components/ui/badge.tsx | 4 +- src/@/components/ui/dialog.tsx | 122 +++++++++++++++++++++++++++++ src/app/story/columns.tsx | 33 +++++++- src/app/tailwind.css | 135 +++++++++++++++++++++++++++++++++ 4 files changed, 288 insertions(+), 6 deletions(-) create mode 100644 src/@/components/ui/dialog.tsx diff --git a/src/@/components/ui/badge.tsx b/src/@/components/ui/badge.tsx index f000e3e..0cae797 100644 --- a/src/@/components/ui/badge.tsx +++ b/src/@/components/ui/badge.tsx @@ -9,7 +9,7 @@ const badgeVariants = cva( variants: { variant: { default: - "border-transparent bg-primary text-primary-foreground hover:bg-primary/80", + "border-transparent bg-primary text-primary-foreground", secondary: "border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80", destructive: @@ -25,7 +25,7 @@ const badgeVariants = cva( export interface BadgeProps extends React.HTMLAttributes, - VariantProps {} + VariantProps { } function Badge({ className, variant, ...props }: BadgeProps) { return ( diff --git a/src/@/components/ui/dialog.tsx b/src/@/components/ui/dialog.tsx new file mode 100644 index 0000000..01ff19c --- /dev/null +++ b/src/@/components/ui/dialog.tsx @@ -0,0 +1,122 @@ +"use client" + +import * as React from "react" +import * as DialogPrimitive from "@radix-ui/react-dialog" +import { X } from "lucide-react" + +import { cn } from "@/lib/utils" + +const Dialog = DialogPrimitive.Root + +const DialogTrigger = DialogPrimitive.Trigger + +const DialogPortal = DialogPrimitive.Portal + +const DialogClose = DialogPrimitive.Close + +const DialogOverlay = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +DialogOverlay.displayName = DialogPrimitive.Overlay.displayName + +const DialogContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, ...props }, ref) => ( + + + + {children} + + + Close + + + +)) +DialogContent.displayName = DialogPrimitive.Content.displayName + +const DialogHeader = ({ + className, + ...props +}: React.HTMLAttributes) => ( +
+) +DialogHeader.displayName = "DialogHeader" + +const DialogFooter = ({ + className, + ...props +}: React.HTMLAttributes) => ( +
+) +DialogFooter.displayName = "DialogFooter" + +const DialogTitle = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +DialogTitle.displayName = DialogPrimitive.Title.displayName + +const DialogDescription = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +DialogDescription.displayName = DialogPrimitive.Description.displayName + +export { + Dialog, + DialogPortal, + DialogOverlay, + DialogClose, + DialogTrigger, + DialogContent, + DialogHeader, + DialogFooter, + DialogTitle, + DialogDescription, +} diff --git a/src/app/story/columns.tsx b/src/app/story/columns.tsx index f5b1f6e..31c5580 100644 --- a/src/app/story/columns.tsx +++ b/src/app/story/columns.tsx @@ -5,13 +5,21 @@ import { ArrowUpDown, MoreHorizontal } from "lucide-react" import { Button } from "@/components/ui/button" import { Badge } from "@/components/ui/badge" import { Trash2, Search } from "lucide-react" +import { + Dialog, + DialogContent, + DialogDescription, + DialogFooter, + DialogHeader, + DialogTitle, + DialogTrigger, +} from "@/components/ui/dialog" import { deleteStory } from "app/lib/del" import Link from "next/link" const columnHelper = createColumnHelper() - export const columns: ColumnDef[] = [ { accessorKey: "title", @@ -56,9 +64,26 @@ export const columns: ColumnDef[] = [ cell: ({ row }) => { return
- + + + + + + + Are you sure? + + Deleting a story cannot be undone! + + + + + + +
} } diff --git a/src/app/tailwind.css b/src/app/tailwind.css index 2b4a9bf..76868f7 100644 --- a/src/app/tailwind.css +++ b/src/app/tailwind.css @@ -600,6 +600,18 @@ body { } } +.sr-only { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); + white-space: nowrap; + border-width: 0; +} + .pointer-events-auto { pointer-events: auto; } @@ -620,6 +632,10 @@ body { position: relative; } +.inset-0 { + inset: 0px; +} + .left-1 { left: 0.25rem; } @@ -644,6 +660,22 @@ body { top: 0.5rem; } +.left-\[50\%\] { + left: 50%; +} + +.right-4 { + right: 1rem; +} + +.top-4 { + top: 1rem; +} + +.top-\[50\%\] { + top: 50%; +} + .z-50 { z-index: 50; } @@ -845,6 +877,10 @@ body { max-width: 24rem; } +.max-w-lg { + max-width: 32rem; +} + .shrink-0 { flex-shrink: 0; } @@ -857,6 +893,16 @@ body { border-collapse: collapse; } +.translate-x-\[-50\%\] { + --tw-translate-x: -50%; + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); +} + +.translate-y-\[-50\%\] { + --tw-translate-y: -50%; + transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); +} + .transform { transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y)); } @@ -911,6 +957,10 @@ body { justify-content: space-around; } +.justify-items-center { + justify-items: center; +} + .gap-1 { gap: 0.25rem; } @@ -919,6 +969,10 @@ body { gap: 0.5rem; } +.gap-4 { + gap: 1rem; +} + .space-x-1 > :not([hidden]) ~ :not([hidden]) { --tw-space-x-reverse: 0; margin-right: calc(0.25rem * var(--tw-space-x-reverse)); @@ -979,6 +1033,12 @@ body { margin-bottom: calc(2rem * var(--tw-space-y-reverse)); } +.space-y-1\.5 > :not([hidden]) ~ :not([hidden]) { + --tw-space-y-reverse: 0; + margin-top: calc(0.375rem * calc(1 - var(--tw-space-y-reverse))); + margin-bottom: calc(0.375rem * var(--tw-space-y-reverse)); +} + .justify-self-start { justify-self: start; } @@ -1084,6 +1144,10 @@ body { background-color: transparent; } +.bg-black\/80 { + background-color: rgb(0 0 0 / 0.8); +} + .fill-current { fill: currentColor; } @@ -1224,6 +1288,11 @@ body { line-height: 1rem; } +.text-lg { + font-size: 1.125rem; + line-height: 1.75rem; +} + .font-black { font-weight: 900; } @@ -1248,10 +1317,22 @@ body { line-height: 1; } +.leading-normal { + line-height: 1.5; +} + +.leading-tight { + line-height: 1.25; +} + .tracking-widest { letter-spacing: 0.1em; } +.tracking-tight { + letter-spacing: -0.025em; +} + .text-accent-foreground { color: hsl(var(--accent-foreground)); } @@ -1325,6 +1406,10 @@ body { opacity: 0.9; } +.opacity-70 { + opacity: 0.7; +} + .shadow-lg { --tw-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1); --tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color); @@ -1372,6 +1457,10 @@ body { transition-duration: 150ms; } +.duration-200 { + transition-duration: 200ms; +} + @keyframes enter { from { opacity: var(--tw-enter-opacity, 1); @@ -1386,6 +1475,10 @@ body { } } +.duration-200 { + animation-duration: 200ms; +} + .file\:border-0::file-selector-button { border-width: 0px; } @@ -1455,6 +1548,10 @@ body { background-color: hsl(var(--primary) / 0.8); } +.hover\:bg-primary\/100:hover { + background-color: hsl(var(--primary) / 1); +} + .hover\:text-accent-foreground:hover { color: hsl(var(--accent-foreground)); } @@ -1675,6 +1772,10 @@ body { color: hsl(var(--primary-foreground)); } +.data-\[state\=open\]\:text-muted-foreground[data-state=open] { + color: hsl(var(--muted-foreground)); +} + .data-\[disabled\]\:opacity-50[data-disabled] { opacity: 0.5; } @@ -1757,6 +1858,22 @@ body { --tw-enter-translate-y: -100%; } +.data-\[state\=closed\]\:slide-out-to-left-1\/2[data-state=closed] { + --tw-exit-translate-x: -50%; +} + +.data-\[state\=closed\]\:slide-out-to-top-\[48\%\][data-state=closed] { + --tw-exit-translate-y: -48%; +} + +.data-\[state\=open\]\:slide-in-from-left-1\/2[data-state=open] { + --tw-enter-translate-x: -50%; +} + +.data-\[state\=open\]\:slide-in-from-top-\[48\%\][data-state=open] { + --tw-enter-translate-y: -48%; +} + @media (min-width: 640px) { .sm\:bottom-0 { bottom: 0px; @@ -1778,6 +1895,10 @@ body { flex-direction: column; } + .sm\:justify-end { + justify-content: flex-end; + } + .sm\:space-x-4 > :not([hidden]) ~ :not([hidden]) { --tw-space-x-reverse: 0; margin-right: calc(1rem * var(--tw-space-x-reverse)); @@ -1790,6 +1911,20 @@ body { margin-bottom: calc(0px * var(--tw-space-y-reverse)); } + .sm\:space-x-2 > :not([hidden]) ~ :not([hidden]) { + --tw-space-x-reverse: 0; + margin-right: calc(0.5rem * var(--tw-space-x-reverse)); + margin-left: calc(0.5rem * calc(1 - var(--tw-space-x-reverse))); + } + + .sm\:rounded-lg { + border-radius: var(--radius); + } + + .sm\:text-left { + text-align: left; + } + .data-\[state\=open\]\:sm\:slide-in-from-bottom-full[data-state=open] { --tw-enter-translate-y: 100%; }