From a36cff7f1357f6709e2087bca78bd7855a27811d Mon Sep 17 00:00:00 2001 From: sajadevo Date: Fri, 14 Feb 2025 08:42:24 +0500 Subject: [PATCH] add new blog post --- app/blog/[slug]/page.tsx | 2 + .../page.tsx | 70 ++++ .../page.tsx | 63 +++ app/globals.css | 39 ++ components/alert.tsx | 42 ++ .../blog/building-a-native-html-dialog.mdx | 380 ++++++++++++++++++ 6 files changed, 596 insertions(+) create mode 100644 app/demo/building-a-native-html-dialog-demo-1/page.tsx create mode 100644 app/demo/building-a-native-html-dialog-demo-2/page.tsx create mode 100644 components/alert.tsx create mode 100644 content/blog/building-a-native-html-dialog.mdx diff --git a/app/blog/[slug]/page.tsx b/app/blog/[slug]/page.tsx index 5ea1b3f..bc9db45 100644 --- a/app/blog/[slug]/page.tsx +++ b/app/blog/[slug]/page.tsx @@ -2,6 +2,7 @@ import React from "react"; // @components import Link from "next/link"; +import { Alert } from "@/components/alert"; import { MDXRemote } from "next-mdx-remote/rsc"; import { CodeBlock } from "@/components/code-block"; import { Typography } from "@/components/typography"; @@ -134,6 +135,7 @@ export default async function Post({ a: (props) => ( ), + Alert, BrowserWindow, }} /> diff --git a/app/demo/building-a-native-html-dialog-demo-1/page.tsx b/app/demo/building-a-native-html-dialog-demo-1/page.tsx new file mode 100644 index 0000000..8a7d870 --- /dev/null +++ b/app/demo/building-a-native-html-dialog-demo-1/page.tsx @@ -0,0 +1,70 @@ +"use client"; + +import React from "react"; + +export default function Page() { + React.useEffect(() => { + const dialog = document.querySelector( + "[data-name=dialog]", + ) as HTMLDialogElement; + const dialogTrigger = document.querySelector("[data-name=dialog-trigger]"); + const dialogCloseTrigger = document.querySelector( + "[data-name=dialog-close-trigger]", + ); + + if (dialog && dialogTrigger && dialogCloseTrigger) { + dialog.showModal(); + + dialogTrigger.addEventListener("click", () => { + dialog.showModal(); + }); + + dialogCloseTrigger.addEventListener("click", () => { + dialog.classList.add("!animate-bnhd-go-out"); + dialog.classList.add("backdrop:!animate-bnhd-fade-out"); + + setTimeout(() => { + dialog.classList.remove("!animate-bnhd-go-out"); + dialog.classList.remove("backdrop:!animate-bnhd-fade-out"); + dialog.close(); + }, 150); + }); + } + }, []); + + return ( +
+ + +

Dialog Title

+

+ This is a simple dialog box using HTML and Tailwind CSS. You can close + this dialog box by clicking the cancel button. +

+
+ + +
+
+
+ ); +} diff --git a/app/demo/building-a-native-html-dialog-demo-2/page.tsx b/app/demo/building-a-native-html-dialog-demo-2/page.tsx new file mode 100644 index 0000000..77a1464 --- /dev/null +++ b/app/demo/building-a-native-html-dialog-demo-2/page.tsx @@ -0,0 +1,63 @@ +"use client"; + +import React from "react"; + +export default function Page() { + React.useEffect(() => { + const dialog = document.querySelector( + "[data-name=dialog]", + ) as HTMLDialogElement; + const dialogTrigger = document.querySelector("[data-name=dialog-trigger]"); + const dialogCloseTrigger = document.querySelector( + "[data-name=dialog-close-trigger]", + ); + + if (dialog && dialogTrigger && dialogCloseTrigger) { + dialog.showModal(); + + dialogTrigger.addEventListener("click", () => { + dialog.showModal(); + }); + + dialogCloseTrigger.addEventListener("click", () => { + dialog.close(); + }); + } + }, []); + + return ( +
+ + +

Dialog Title

+

+ This is a simple dialog box using HTML and Tailwind CSS. You can close + this dialog box by clicking the cancel button. +

+
+ + +
+
+
+ ); +} diff --git a/app/globals.css b/app/globals.css index ffb06a1..0b1fb14 100644 --- a/app/globals.css +++ b/app/globals.css @@ -13,6 +13,45 @@ /* breakpoints */ --breakpoint-xxl: 1400px; --breakpoint-xs: 480px; + + /* animations */ + --animate-bnhd-fade-in: bnhd-fade-in 200ms linear; + --animate-bnhd-fade-out: bnhd-fade-out 200ms linear; + --animate-bnhd-come-in: bnhd-come-in 200ms linear; + --animate-bnhd-go-out: bnhd-go-out 200ms linear; + + @keyframes bnhd-fade-in { + from { + opacity: 0; + } + to { + opacity: 1; + } + } + + @keyframes bnhd-fade-out { + to { + opacity: 0; + } + } + + @keyframes bnhd-come-in { + from { + opacity: 0; + transform: translateY(-40px) scale(0.95); + } + to { + opacity: 1; + transform: translateY(0) scale(1); + } + } + + @keyframes bnhd-go-out { + to { + opacity: 0; + transform: translateY(-40px) scale(0.95); + } + } } @variant dark (&:where(.dark, .dark *)); diff --git a/components/alert.tsx b/components/alert.tsx new file mode 100644 index 0000000..f22bfd3 --- /dev/null +++ b/components/alert.tsx @@ -0,0 +1,42 @@ +import React from "react"; + +// @components +import { Slot } from "@radix-ui/react-slot"; + +// @utils +import { cn } from "@/lib/utils"; +import { cva, type VariantProps } from "class-variance-authority"; + +const alertVariants = cva( + "rounded-2xl border border-dashed px-5 py-4 text-base font-medium text-black [&_*]:m-0 [&_*]:text-black", + { + variants: { + variant: { + info: "border-blue-400 bg-blue-400/10", + }, + }, + defaultVariants: { + variant: "info", + }, + }, +); + +interface AlertProps + extends React.HTMLAttributes, + VariantProps { + asChild?: boolean; + ref?: React.Ref; +} + +export function Alert({ + ref, + variant, + className, + asChild = false, + ...props +}: AlertProps) { + const Component = asChild ? Slot : "div"; + const styles = cn(alertVariants({ variant, className })); + + return ; +} diff --git a/content/blog/building-a-native-html-dialog.mdx b/content/blog/building-a-native-html-dialog.mdx new file mode 100644 index 0000000..6e3becf --- /dev/null +++ b/content/blog/building-a-native-html-dialog.mdx @@ -0,0 +1,380 @@ +--- +title: Building a Native HTML Dialog +date: 02-14-2025 # MM-DD-YYYY +description: Learn how to build a fully functional native HTML dialog with ease. +category: web development +keywords: + - css + - html + - dialog + - javascript + - tailwindcss + - web development +--- + + + +
+ +The `` element provides a powerful and accessible way to create modals and popups without relying on external libraries. In this guide, we'll explore how to build a fully functional native HTML dialog, covering its features, accessibility best practices, styling tips, and JavaScript interactions. Whether you're creating a simple alert or a complex modal, mastering `` will enhance your web development workflow. + +## Prerequisites + +Before we dive into building a native HTML dialog, make sure you have a basic understanding of HTML, CSS, and JavaScript. Familiarity with Tailwind CSS is also recommended, as we'll be using it to style our dialog components. If you're new to Tailwind CSS, check out the official documentation to get started. [Tailwind CSS Documentation](https://tailwindcss.com/docs) + +## Building the Dialog Markup + +To create a native HTML dialog, we'll start by defining the dialog element and its content. Here's a simple example of a dialog box with a title, description, and action buttons: + +```html +
+ +

Dialog Title

+

+ This is a simple dialog box using HTML and Tailwind CSS. You can close + this dialog box by clicking the cancel button. +

+
+ + +
+
+
+``` + +## Styling the Dialog + +To style the dialog, we'll use Tailwind CSS classes to define the appearance and layout of the dialog components. + +```html {2,5,7-8,12,15,21} +
+ +

Dialog Title

+

+ This is a simple dialog box using HTML and Tailwind CSS. You can close + this dialog box by clicking the cancel button. +

+
+ + +
+
+
+``` + +## Adding JavaScript Interactions + +To make the dialog interactive, we'll use JavaScript to handle the opening and closing of dialog. We'll use the `showModal()` and `close()` methods to control the dialog visibility and use the `dataset` attributes to select the elements. + +- First, we'll define `dataset` attributes for the dialog and buttons to access them in JavaScript. + +```html {5,16} +
+ +

Dialog Title

+

+ This is a simple dialog box using HTML and Tailwind CSS. You can close + this dialog box by clicking the cancel button. +

+
+ + +
+
+
+``` + +- Next, we'll add JavaScript code to handle the dialog closing functionality when the cancel button is clicked. We'll use the `close()` method to close the dialog. + +```html {31-44} +
+ +

Dialog Title

+

+ This is a simple dialog box using HTML and Tailwind CSS. You can close + this dialog box by clicking the cancel button. +

+
+ + +
+
+
+ + +``` + +- Now we have a functional dialog that closes when the cancel button is clicked. Now let's add the functionality to open the dialog when a button is clicked. We'll use the `showModal()` method to open the dialog. + +```html {4-9, 46-52} +
+ + +

Dialog Title

+

+ This is a simple dialog box using HTML and Tailwind CSS. You can close + this dialog box by clicking the cancel button. +

+
+ + +
+
+
+ + +``` + +Now you have a fully functional native HTML dialog that opens when the trigger button is clicked and closes when the cancel button is clicked. + + + +## Adding Animation + +To enhance the user experience, we'll add animations to the dialog. We'll use Tailwind CSS to create smooth animations when the dialog opens and closes. + +- First, we'll define the animations in our stylesheet. We'll create `fade-in` and `fade-out` animations for the dialog backdrop and `come-in` and `go-out` animations for the dialog content. + +```css {3-41} +@import "tailwindcss"; + +@theme { + --animate-fade-in: fade-in 200ms linear; + --animate-fade-out: fade-out 200ms linear; + --animate-come-in: come-in 200ms linear; + --animate-go-out: go-out 200ms linear; + + @keyframes fade-in { + from { + opacity: 0; + } + to { + opacity: 1; + } + } + + @keyframes fade-out { + to { + opacity: 0; + } + } + + @keyframes come-in { + from { + opacity: 0; + transform: translateY(-40px) scale(0.95); + } + to { + opacity: 1; + transform: translateY(0) scale(1); + } + } + + @keyframes go-out { + to { + opacity: 0; + transform: translateY(-40px) scale(0.95); + } + } +} +``` + +We created the animations using the `@keyframes` rule and then used the `--animate-*` theme variable to define the animation as utility classes. + +Learn more about Tailwind CSS animations in the official documentation. [Tailwind CSS Animations](https://tailwindcss.com/docs/animation#customizing-your-theme) + +- Next, we'll apply the animations to the dialog elements. We'll use the `backdrop:animate-fade-in` and `backdrop:animate-fade-out` classes for the dialog backdrop and the `open:animate-come-in` and `animate-go-out` classes for the dialog content. + + + The `backdrop:` is used to style the backdrop of a dialog and the `open:` is + used to style the dialog when the dialog is open. + + +```html {12,56-67} +
+ + +

Dialog Title

+

+ This is a simple dialog box using HTML and Tailwind CSS. You can close + this dialog box by clicking the cancel button. +

+
+ + +
+
+
+ + +``` + +Now you have a fully functional native HTML dialog with smooth animations when opening and closing the dialog. + +