From bf2678e8aa8eb9845b6145e0dc959589fcb3203c Mon Sep 17 00:00:00 2001 From: sajadevo Date: Sat, 16 Dec 2023 00:42:25 +0430 Subject: [PATCH 01/38] add sidebar with burger for react version --- docs-content/react/sidebar/index.ts | 1 + .../sidebar/sidebar-with-burger-menu.tsx | 239 +++++++++++++++++ documentation/react/sidebar.mdx | 251 ++++++++++++++++++ package.json | 2 +- 4 files changed, 492 insertions(+), 1 deletion(-) create mode 100644 docs-content/react/sidebar/sidebar-with-burger-menu.tsx diff --git a/docs-content/react/sidebar/index.ts b/docs-content/react/sidebar/index.ts index 16d253ca4..5269bf95a 100644 --- a/docs-content/react/sidebar/index.ts +++ b/docs-content/react/sidebar/index.ts @@ -4,3 +4,4 @@ export * from "./sidebar-with-content-separator"; export * from "./sidebar-with-cta"; export * from "./sidebar-with-logo"; export * from "./sidebar-with-search"; +export * from "./sidebar-with-burger-menu"; diff --git a/docs-content/react/sidebar/sidebar-with-burger-menu.tsx b/docs-content/react/sidebar/sidebar-with-burger-menu.tsx new file mode 100644 index 000000000..8cd3f23b8 --- /dev/null +++ b/docs-content/react/sidebar/sidebar-with-burger-menu.tsx @@ -0,0 +1,239 @@ +import React from "react"; +import { + IconButton, + Typography, + List, + ListItem, + ListItemPrefix, + ListItemSuffix, + Chip, + Accordion, + AccordionHeader, + AccordionBody, + Alert, + Input, + Drawer, + Card, +} from "@material-tailwind/react"; +import { + PresentationChartBarIcon, + ShoppingBagIcon, + UserCircleIcon, + Cog6ToothIcon, + InboxIcon, + PowerIcon, +} from "@heroicons/react/24/solid"; +import { + ChevronRightIcon, + ChevronDownIcon, + CubeTransparentIcon, + MagnifyingGlassIcon, + Bars3Icon, + XMarkIcon, +} from "@heroicons/react/24/outline"; + +export function SidebarWithBurgerMenu() { + const [open, setOpen] = React.useState(0); + const [openAlert, setOpenAlert] = React.useState(true); + const [isDrawerOpen, setIsDrawerOpen] = React.useState(false); + + const handleOpen = (value) => { + setOpen(open === value ? 0 : value); + }; + + const openDrawer = () => setIsDrawerOpen(true); + const closeDrawer = () => setIsDrawerOpen(false); + + return ( + <> + + {isDrawerOpen ? ( + + ) : ( + + )} + + + +
+ brand + + Sidebar + +
+
+ } + label="Search" + /> +
+ + + } + > + + handleOpen(1)} + className="border-b-0 p-3" + > + + + + + Dashboard + + + + + + + + + + Analytics + + + + + + Reporting + + + + + + Projects + + + + + + } + > + + handleOpen(2)} + className="border-b-0 p-3" + > + + + + + E-Commerce + + + + + + + + + + Orders + + + + + + Products + + + + +
+ + + + + Inbox + + + + + + + + + Profile + + + + + + Settings + + + + + + Log Out + +
+ setOpenAlert(false)} + > + + + Upgrade to PRO + + + Upgrade to Material Tailwind PRO and get even more components, + plugins, advanced features and premium. + +
+ setOpenAlert(false)} + > + Dismiss + + + Upgrade Now + +
+
+
+
+ + ); +} diff --git a/documentation/react/sidebar.mdx b/documentation/react/sidebar.mdx index 0a9bfa1b5..322877472 100644 --- a/documentation/react/sidebar.mdx +++ b/documentation/react/sidebar.mdx @@ -9,6 +9,7 @@ navigation: "sidebar-with-cta", "sidebar-with-logo", "sidebar-with-search", + "sidebar-with-burger-menu", ] github: sidebar prev: video @@ -998,4 +999,254 @@ export function SidebarWithSearch() { ); } ``` + + +--- + + +## Sidebar With With Burger Menu + + +}> +```jsx +import React from "react"; +import { + IconButton, + Typography, + List, + ListItem, + ListItemPrefix, + ListItemSuffix, + Chip, + Accordion, + AccordionHeader, + AccordionBody, + Alert, + Input, + Drawer, + Card, +} from "@material-tailwind/react"; +import { + PresentationChartBarIcon, + ShoppingBagIcon, + UserCircleIcon, + Cog6ToothIcon, + InboxIcon, + PowerIcon, +} from "@heroicons/react/24/solid"; +import { + ChevronRightIcon, + ChevronDownIcon, + CubeTransparentIcon, + MagnifyingGlassIcon, + Bars3Icon, + XMarkIcon, +} from "@heroicons/react/24/outline"; + +export function SidebarWithBurgerMenu() { + const [open, setOpen] = React.useState(0); + const [openAlert, setOpenAlert] = React.useState(true); + const [isDrawerOpen, setIsDrawerOpen] = React.useState(false); + + const handleOpen = (value) => { + setOpen(open === value ? 0 : value); + }; + + const openDrawer = () => setIsDrawerOpen(true); + const closeDrawer = () => setIsDrawerOpen(false); + + return ( + <> + + {isDrawerOpen ? ( + + ) : ( + + )} + + + +
+ brand + + Sidebar + +
+
+ } + label="Search" + /> +
+ + + } + > + + handleOpen(1)} + className="border-b-0 p-3" + > + + + + + Dashboard + + + + + + + + + + Analytics + + + + + + Reporting + + + + + + Projects + + + + + + } + > + + handleOpen(2)} + className="border-b-0 p-3" + > + + + + + E-Commerce + + + + + + + + + + Orders + + + + + + Products + + + + +
+ + + + + Inbox + + + + + + + + + Profile + + + + + + Settings + + + + + + Log Out + +
+ setOpenAlert(false)} + > + + + Upgrade to PRO + + + Upgrade to Material Tailwind PRO and get even more components, + plugins, advanced features and premium. + +
+ setOpenAlert(false)} + > + Dismiss + + + Upgrade Now + +
+
+
+
+ + ); +} +```
\ No newline at end of file diff --git a/package.json b/package.json index f3ac3ea0b..f53b716c3 100644 --- a/package.json +++ b/package.json @@ -75,7 +75,7 @@ "prettier": "2.8.1", "prettier-plugin-tailwindcss": "0.1.13", "prompts": "2.4.2", - "tailwindcss": "3.2.4", + "tailwindcss": "3.3.6", "typescript": "4.9.4", "unbuild": "1.2.1" } From 67dbac82308629222888db45e8accd18a08d3c19 Mon Sep 17 00:00:00 2001 From: sajadevo Date: Sat, 16 Dec 2023 00:44:40 +0430 Subject: [PATCH 02/38] update img to image on sidenav --- routes/react.routes.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/routes/react.routes.ts b/routes/react.routes.ts index 55e350751..7dcf6ae1f 100644 --- a/routes/react.routes.ts +++ b/routes/react.routes.ts @@ -159,7 +159,7 @@ export const routes = [ route: "icon-button", }, { - name: "Img", + name: "Image", route: "img", }, { From 41928453068a62b2dc6c643a05650ac46d511698 Mon Sep 17 00:00:00 2001 From: Maisam Afshar Date: Sun, 17 Dec 2023 18:47:56 +0330 Subject: [PATCH 03/38] add: angular installation guide --- documentation/html/guide/angular.mdx | 147 +++++++++++++++++++++++++++ 1 file changed, 147 insertions(+) create mode 100644 documentation/html/guide/angular.mdx diff --git a/documentation/html/guide/angular.mdx b/documentation/html/guide/angular.mdx new file mode 100644 index 000000000..32641fc10 --- /dev/null +++ b/documentation/html/guide/angular.mdx @@ -0,0 +1,147 @@ +--- +title: Angular - Installation Guide +description: Learn how to use Material Tailwind components with Angular and Tailwind CSS to easily create elegant and flexible pages. +navigation: + [ + "installation", + "npm", + "yarn", + "pnpm", + "tailwindcss-config", + "ripple-effect", + "example", + ] +github: guide/angular +prev: installation +next: license +--- + +# Material Tailwind with Angular + + +Learn how to setup and install @material-tailwind/html with Angular. + +
+
+ +First you need to create a new project using Angular, for more details check the Angular Official Documentation + +```bash +ng new my-project +``` + +
+ +Then you need to install Tailwind CSS since @material-tailwind/html is working with Tailwind CSS classes and you need to have Tailwind CSS installed on your project. Check Tailwind CSS Installation for Angular on Tailwind CSS Documentation. + +--- + + +## Using NPM + + +Install @material-tailwind/html as a dependency using NPM by running the following command: + + + +```bash +npm i @material-tailwind/html +``` + +--- + + +## Using Yarn + + +Install @material-tailwind/html as a dependency using Yarn by running the following command: + + + +```bash +yarn add @material-tailwind/html +``` + +--- + +## Using PNPM + +Install @material-tailwind/html as a dependency using PNPM by running the following command: + + + +```bash +pnpm i @material-tailwind/html +``` + +--- + + +## TailwindCSS Configurations + + + + +Once you install @material-tailwind/html you need to wrap your tailwind css configurations with the withMT() function coming from @material-tailwind/html/utils. + +```js {1, 4, 12} +import withMT from "@material-tailwind/html/utils/withMT"; + +/** @type {import('tailwindcss').Config} */ +module.exports = withMT({ + content: [ + "./src/**/*.{html,ts}", + ], + theme: { + extend: {}, + }, + plugins: [], +}); +``` + +--- + +## Ripple Effect + + + +@material-tailwind/html comes with a ripple effect script file same as Material Design ripple effect and you can simply use it by adding it's CDN link to you project and add the data-ripple-light="true" for light ripple effect and data-ripple-dark="true" for dark ripple effect as an attribute for components + +The ripple effect used in @material-tailwind/html is a separate package called material-ripple-effect + + +```html + + + + + +``` + +--- + + +## Example + + +Now you're good to go and use @material-tailwind/html in your project. + + + Button + +}> +```html + +``` + From bb6ad4b7213308baf6eec3406f8f730c30df2d28 Mon Sep 17 00:00:00 2001 From: Maisam Afshar Date: Sun, 17 Dec 2023 18:48:06 +0330 Subject: [PATCH 04/38] add: gatsby installation guide --- documentation/html/guide/gatsby.mdx | 149 ++++++++++++++++++++++++++++ 1 file changed, 149 insertions(+) create mode 100644 documentation/html/guide/gatsby.mdx diff --git a/documentation/html/guide/gatsby.mdx b/documentation/html/guide/gatsby.mdx new file mode 100644 index 000000000..30bec2743 --- /dev/null +++ b/documentation/html/guide/gatsby.mdx @@ -0,0 +1,149 @@ +--- +title: Gatsby - Installation Guide +description: Learn how to use Material Tailwind components with Gatsby and Tailwind CSS to easily create elegant and flexible pages. +navigation: + [ + "installation", + "npm", + "yarn", + "pnpm", + "tailwindcss-config", + "ripple-effect", + "example", + ] +github: guide/gatsby +prev: installation +next: license +--- + +# Material Tailwind with Gatsby + + +Learn how to setup and install @material-tailwind/html with Gatsby. + +
+
+ +First you need to create a new project using Gatsby, for more details check the Gatsby Official Documentation + +```bash +gatsby new my-project +``` + +
+ +Then you need to install Tailwind CSS since @material-tailwind/html is working with Tailwind CSS classes and you need to have Tailwind CSS installed on your project. Check Tailwind CSS Installation for Gatsby on Tailwind CSS Documentation. + +--- + + +## Using NPM + + +Install @material-tailwind/html as a dependency using NPM by running the following command: + + + +```bash +npm i @material-tailwind/html +``` + +--- + + +## Using Yarn + + +Install @material-tailwind/html as a dependency using Yarn by running the following command: + + + +```bash +yarn add @material-tailwind/html +``` + +--- + +## Using PNPM + +Install @material-tailwind/html as a dependency using PNPM by running the following command: + + + +```bash +pnpm i @material-tailwind/html +``` + +--- + + +## TailwindCSS Configurations + + + + +Once you install @material-tailwind/html you need to wrap your tailwind css configurations with the withMT() function coming from @material-tailwind/html/utils. + +```js {3, 5, 14} +/** @type {import('tailwindcss').Config} */ + +import withMT from "@material-tailwind/html/utils/withMT"; + +module.exports = withMT({ + content: [ + "./src/pages/**/*.{js,jsx,ts,tsx}", + "./src/components/**/*.{js,jsx,ts,tsx}", + ], + theme: { + extend: {}, + }, + plugins: [], +}); +``` + +--- + +## Ripple Effect + + + +@material-tailwind/html comes with a ripple effect script file same as Material Design ripple effect and you can simply use it by adding it's CDN link to you project and add the data-ripple-light="true" for light ripple effect and data-ripple-dark="true" for dark ripple effect as an attribute for components + +The ripple effect used in @material-tailwind/html is a separate package called material-ripple-effect + + +```html + + + + + +``` + +--- + + +## Example + + +Now you're good to go and use @material-tailwind/html in your project. + + + Button + +}> +```html + +``` + From 51fda38f2bc6762e0a93c9a1b43dfd973203aa50 Mon Sep 17 00:00:00 2001 From: Maisam Afshar Date: Sun, 17 Dec 2023 18:48:17 +0330 Subject: [PATCH 05/38] add: meteor installation guide --- documentation/html/guide/meteor.mdx | 149 ++++++++++++++++++++++++++++ 1 file changed, 149 insertions(+) create mode 100644 documentation/html/guide/meteor.mdx diff --git a/documentation/html/guide/meteor.mdx b/documentation/html/guide/meteor.mdx new file mode 100644 index 000000000..2031d87fa --- /dev/null +++ b/documentation/html/guide/meteor.mdx @@ -0,0 +1,149 @@ +--- +title: Meteor - Installation Guide +description: Learn how to use Material Tailwind components with Meteor and Tailwind CSS to easily create elegant and flexible pages. +navigation: + [ + "installation", + "npm", + "yarn", + "pnpm", + "tailwindcss-config", + "ripple-effect", + "example", + ] +github: guide/meteor +prev: installation +next: license +--- + +# Material Tailwind with Meteor + + +Learn how to setup and install @material-tailwind/html with Meteor. + +
+
+ +First you need to create a new project using Meteor, for more details check the Meteor Official Documentation + +```bash +meteor create my-project +``` + +
+ +Then you need to install Tailwind CSS since @material-tailwind/html is working with Tailwind CSS classes and you need to have Tailwind CSS installed on your project. Check Tailwind CSS Installation for Meteor on Tailwind CSS Documentation. + +--- + + +## Using NPM + + +Install @material-tailwind/html as a dependency using NPM by running the following command: + + + +```bash +npm i @material-tailwind/html +``` + +--- + + +## Using Yarn + + +Install @material-tailwind/html as a dependency using Yarn by running the following command: + + + +```bash +yarn add @material-tailwind/html +``` + +--- + +## Using PNPM + +Install @material-tailwind/html as a dependency using PNPM by running the following command: + + + +```bash +pnpm i @material-tailwind/html +``` + +--- + + +## TailwindCSS Configurations + + + + +Once you install @material-tailwind/html you need to wrap your tailwind css configurations with the withMT() function coming from @material-tailwind/html/utils. + +```js {3, 5, 14} +/** @type {import('tailwindcss').Config} */ + +import withMT from "@material-tailwind/html/utils/withMT"; + +module.exports = withMT({ + content: [ + "./imports/ui/**/*.{js,jsx,ts,tsx}", + "./client/*.html", + ], + theme: { + extend: {}, + }, + plugins: [], +}); +``` + +--- + +## Ripple Effect + + + +@material-tailwind/html comes with a ripple effect script file same as Material Design ripple effect and you can simply use it by adding it's CDN link to you project and add the data-ripple-light="true" for light ripple effect and data-ripple-dark="true" for dark ripple effect as an attribute for components + +The ripple effect used in @material-tailwind/html is a separate package called material-ripple-effect + + +```html + + + + + +``` + +--- + + +## Example + + +Now you're good to go and use @material-tailwind/html in your project. + + + Button + +}> +```html + +``` + From e560d5e5317c55b25cde4cee3bdc63f23d8cbc6a Mon Sep 17 00:00:00 2001 From: Maisam Afshar Date: Sun, 17 Dec 2023 18:48:26 +0330 Subject: [PATCH 06/38] add: qwik installation guide --- documentation/html/guide/qwik.mdx | 148 ++++++++++++++++++++++++++++++ 1 file changed, 148 insertions(+) create mode 100644 documentation/html/guide/qwik.mdx diff --git a/documentation/html/guide/qwik.mdx b/documentation/html/guide/qwik.mdx new file mode 100644 index 000000000..c20cf0b88 --- /dev/null +++ b/documentation/html/guide/qwik.mdx @@ -0,0 +1,148 @@ +--- +title: Qwik - Installation Guide +description: Learn how to use Material Tailwind components with Qwik and Tailwind CSS to easily create elegant and flexible pages. +navigation: + [ + "installation", + "npm", + "yarn", + "pnpm", + "tailwindcss-config", + "ripple-effect", + "example", + ] +github: guide/Qwik +prev: installation +next: license +--- + +# Material Tailwind with Qwik + + +Learn how to setup and install @material-tailwind/html with Qwik. + +
+
+ +First you need to create a new project using Qwik, for more details check the Qwik Official Documentation + +```bash +npm create qwik@latest +``` + +
+ +Then you need to install Tailwind CSS since @material-tailwind/html is working with Tailwind CSS classes and you need to have Tailwind CSS installed on your project. Check Tailwind CSS Installation for Qwik on Tailwind CSS Documentation. + +--- + + +## Using NPM + + +Install @material-tailwind/html as a dependency using NPM by running the following command: + + + +```bash +npm i @material-tailwind/html +``` + +--- + + +## Using Yarn + + +Install @material-tailwind/html as a dependency using Yarn by running the following command: + + + +```bash +yarn add @material-tailwind/html +``` + +--- + +## Using PNPM + +Install @material-tailwind/html as a dependency using PNPM by running the following command: + + + +```bash +pnpm i @material-tailwind/html +``` + +--- + + +## TailwindCSS Configurations + + + + +Once you install @material-tailwind/html you need to wrap your tailwind css configurations with the withMT() function coming from @material-tailwind/html/utils. + +```js {3, 5, 13} +/** @type {import('tailwindcss').Config} */ + +import withMT from "@material-tailwind/html/utils/withMT"; + +module.exports = withMT({ + content: [ + "./src/**/*.{js,ts,jsx,tsx,mdx}", + ], + theme: { + extend: {}, + }, + plugins: [], +}); +``` + +--- + +## Ripple Effect + + + +@material-tailwind/html comes with a ripple effect script file same as Material Design ripple effect and you can simply use it by adding it's CDN link to you project and add the data-ripple-light="true" for light ripple effect and data-ripple-dark="true" for dark ripple effect as an attribute for components + +The ripple effect used in @material-tailwind/html is a separate package called material-ripple-effect + + +```html + + + + + +``` + +--- + + +## Example + + +Now you're good to go and use @material-tailwind/html in your project. + + + Button + +}> +```html + +``` + From 1ec2d05c401053a57147349058dd5dafd8817c31 Mon Sep 17 00:00:00 2001 From: Maisam Afshar Date: Sun, 17 Dec 2023 18:48:33 +0330 Subject: [PATCH 07/38] add: remix installation guide --- documentation/html/guide/remix.mdx | 146 +++++++++++++++++++++++++++++ 1 file changed, 146 insertions(+) create mode 100644 documentation/html/guide/remix.mdx diff --git a/documentation/html/guide/remix.mdx b/documentation/html/guide/remix.mdx new file mode 100644 index 000000000..d03d87923 --- /dev/null +++ b/documentation/html/guide/remix.mdx @@ -0,0 +1,146 @@ +--- +title: Remix - Installation Guide +description: Learn how to use Material Tailwind components with Remix and Tailwind CSS to easily create elegant and flexible pages. +navigation: + [ + "installation", + "npm", + "yarn", + "pnpm", + "tailwindcss-config", + "ripple-effect", + "example", + ] +github: guide/remix +prev: installation +next: license +--- + +# Material Tailwind with Remix + + +Learn how to setup and install @material-tailwind/html with Remix. + +
+
+ +First you need to create a new project using Remix, for more details check the Remix Official Documentation + +```bash +npx create-remix@latest remix-app +``` + +
+ +Then you need to install Tailwind CSS since @material-tailwind/html is working with Tailwind CSS classes and you need to have Tailwind CSS installed on your project. Check Tailwind CSS Installation for Remix on Tailwind CSS Documentation. + +--- + + +## Using NPM + + +Install @material-tailwind/html as a dependency using NPM by running the following command: + + + +```bash +npm i @material-tailwind/html +``` + +--- + + +## Using Yarn + + +Install @material-tailwind/html as a dependency using Yarn by running the following command: + + + +```bash +yarn add @material-tailwind/html +``` + +--- + +## Using PNPM + +Install @material-tailwind/html as a dependency using PNPM by running the following command: + + + +```bash +pnpm i @material-tailwind/html +``` + +--- + + +## TailwindCSS Configurations + + + + +Once you install @material-tailwind/html you need to wrap your tailwind css configurations with the withMT() function coming from @material-tailwind/html/utils. + +```js {3, 5, 11} +import type { Config } from "tailwindcss"; + +import withMT from "@material-tailwind/html/utils/withMT"; + +export default withMT({ + content: ["./app/**/*.{js,jsx,ts,tsx}"], + theme: { + extend: {}, + }, + plugins: [], +} satisfies Config); +``` + +--- + +## Ripple Effect + + + +@material-tailwind/html comes with a ripple effect script file same as Material Design ripple effect and you can simply use it by adding it's CDN link to you project and add the data-ripple-light="true" for light ripple effect and data-ripple-dark="true" for dark ripple effect as an attribute for components + +The ripple effect used in @material-tailwind/html is a separate package called material-ripple-effect + + +```html + + + + + +``` + +--- + + +## Example + + +Now you're good to go and use @material-tailwind/html in your project. + + + Button + +}> +```html + +``` + From f888032e742c9ade0f517af3502c2ddaf6e3ab1a Mon Sep 17 00:00:00 2001 From: Maisam Afshar Date: Sun, 17 Dec 2023 18:48:41 +0330 Subject: [PATCH 08/38] add: solidjs installation guide --- documentation/html/guide/solid.mdx | 148 +++++++++++++++++++++++++++++ 1 file changed, 148 insertions(+) create mode 100644 documentation/html/guide/solid.mdx diff --git a/documentation/html/guide/solid.mdx b/documentation/html/guide/solid.mdx new file mode 100644 index 000000000..98c6dfa89 --- /dev/null +++ b/documentation/html/guide/solid.mdx @@ -0,0 +1,148 @@ +--- +title: Solid - Installation Guide +description: Learn how to use Material Tailwind components with Solid and Tailwind CSS to easily create elegant and flexible pages. +navigation: + [ + "installation", + "npm", + "yarn", + "pnpm", + "tailwindcss-config", + "ripple-effect", + "example", + ] +github: guide/solid +prev: installation +next: license +--- + +# Material Tailwind with Solid + + +Learn how to setup and install @material-tailwind/html with Solid. + +
+
+ +First you need to create a new project using Solid, for more details check the Solid Official Documentation + +```bash +npm create vite@latest my-app -- --template solid +``` + +
+ +Then you need to install Tailwind CSS since @material-tailwind/html is working with Tailwind CSS classes and you need to have Tailwind CSS installed on your project. Check Tailwind CSS Installation for Solid on Tailwind CSS Documentation. + +--- + + +## Using NPM + + +Install @material-tailwind/html as a dependency using NPM by running the following command: + + + +```bash +npm i @material-tailwind/html +``` + +--- + + +## Using Yarn + + +Install @material-tailwind/html as a dependency using Yarn by running the following command: + + + +```bash +yarn add @material-tailwind/html +``` + +--- + +## Using PNPM + +Install @material-tailwind/html as a dependency using PNPM by running the following command: + + + +```bash +pnpm i @material-tailwind/html +``` + +--- + + +## TailwindCSS Configurations + + + + +Once you install @material-tailwind/html you need to wrap your tailwind css configurations with the withMT() function coming from @material-tailwind/html/utils. + +```js {3, 5, 13} +/** @type {import('tailwindcss').Config} */ + +import withMT from "@material-tailwind/html/utils/withMT"; + +export default withMT({ + content: [ + "./src/**/*.{js,jsx,ts,tsx}", + ], + theme: { + extend: {}, + }, + plugins: [], +}); +``` + +--- + +## Ripple Effect + + + +@material-tailwind/html comes with a ripple effect script file same as Material Design ripple effect and you can simply use it by adding it's CDN link to you project and add the data-ripple-light="true" for light ripple effect and data-ripple-dark="true" for dark ripple effect as an attribute for components + +The ripple effect used in @material-tailwind/html is a separate package called material-ripple-effect + + +```html + + + + + +``` + +--- + + +## Example + + +Now you're good to go and use @material-tailwind/html in your project. + + + Button + +}> +```html + +``` + From f3301f82de3ca7ec1c9d0c962ffc2c2125dee4e0 Mon Sep 17 00:00:00 2001 From: Sayed Murtaza Date: Mon, 18 Dec 2023 13:06:06 +0430 Subject: [PATCH 09/38] skeleton done --- .../react/sidebar/default-sidebar.tsx | 8 +- .../skeleton/card-placeholder-skeleton.tsx | 44 +++ .../react/skeleton/default-skeleton.tsx | 35 ++ .../skeleton/image-placeholder-skeleton.tsx | 48 +++ docs-content/react/skeleton/index.ts | 6 + .../testimonial-placeholder-skeleton.tsx | 38 ++ .../skeleton/text-placeholder-skeleton.tsx | 81 ++++ .../skeleton/video-placeholder-skeleton.tsx | 21 ++ documentation/react/skeleton.mdx | 354 ++++++++++++++++++ package.json | 2 + pages/docs/[...slug].tsx | 2 + routes/react.routes.ts | 4 + 12 files changed, 642 insertions(+), 1 deletion(-) create mode 100644 docs-content/react/skeleton/card-placeholder-skeleton.tsx create mode 100644 docs-content/react/skeleton/default-skeleton.tsx create mode 100644 docs-content/react/skeleton/image-placeholder-skeleton.tsx create mode 100644 docs-content/react/skeleton/index.ts create mode 100644 docs-content/react/skeleton/testimonial-placeholder-skeleton.tsx create mode 100644 docs-content/react/skeleton/text-placeholder-skeleton.tsx create mode 100644 docs-content/react/skeleton/video-placeholder-skeleton.tsx create mode 100644 documentation/react/skeleton.mdx diff --git a/docs-content/react/sidebar/default-sidebar.tsx b/docs-content/react/sidebar/default-sidebar.tsx index 71e4a525e..72b04f4e6 100644 --- a/docs-content/react/sidebar/default-sidebar.tsx +++ b/docs-content/react/sidebar/default-sidebar.tsx @@ -43,7 +43,13 @@ export function DefaultSidebar() { Inbox - + diff --git a/docs-content/react/skeleton/card-placeholder-skeleton.tsx b/docs-content/react/skeleton/card-placeholder-skeleton.tsx new file mode 100644 index 000000000..0a3d7fac7 --- /dev/null +++ b/docs-content/react/skeleton/card-placeholder-skeleton.tsx @@ -0,0 +1,44 @@ +import { Button, Typography } from "@material-tailwind/react"; +import Card, { + CardBody, + CardFooter, + CardHeader, +} from "packages/material-tailwind-react/src/components/Card"; + +export function CardPlacehoderSkeleton() { + return ( + + + + + + +
+ + + + +
+
+ + + +
+ ); +} diff --git a/docs-content/react/skeleton/default-skeleton.tsx b/docs-content/react/skeleton/default-skeleton.tsx new file mode 100644 index 000000000..db36c0944 --- /dev/null +++ b/docs-content/react/skeleton/default-skeleton.tsx @@ -0,0 +1,35 @@ +import { Typography } from "@material-tailwind/react"; + +export function DefaultSkeleton() { + return ( +
+ + + + + + + + Loading... + +
+ ); +} diff --git a/docs-content/react/skeleton/image-placeholder-skeleton.tsx b/docs-content/react/skeleton/image-placeholder-skeleton.tsx new file mode 100644 index 000000000..6f19471f5 --- /dev/null +++ b/docs-content/react/skeleton/image-placeholder-skeleton.tsx @@ -0,0 +1,48 @@ +import { Typography } from "@material-tailwind/react"; + +export function ImagePlacehoderSkeleton() { + return ( +
+
+ +
+
+ + + + + + + + Loading... + +
+
+ ); +} diff --git a/docs-content/react/skeleton/index.ts b/docs-content/react/skeleton/index.ts new file mode 100644 index 000000000..200402968 --- /dev/null +++ b/docs-content/react/skeleton/index.ts @@ -0,0 +1,6 @@ +export * from "./default-skeleton"; +export * from "./image-placeholder-skeleton"; +export * from "./video-placeholder-skeleton"; +export * from "./text-placeholder-skeleton"; +export * from "./card-placeholder-skeleton"; +export * from "./testimonial-placeholder-skeleton"; diff --git a/docs-content/react/skeleton/testimonial-placeholder-skeleton.tsx b/docs-content/react/skeleton/testimonial-placeholder-skeleton.tsx new file mode 100644 index 000000000..65845f2f0 --- /dev/null +++ b/docs-content/react/skeleton/testimonial-placeholder-skeleton.tsx @@ -0,0 +1,38 @@ +import { Typography } from "@material-tailwind/react"; + +export function TestimonialPlacehoderSkeleton() { + return ( +
+ + +
+ + + +
+ Loading... +
+ ); +} diff --git a/docs-content/react/skeleton/text-placeholder-skeleton.tsx b/docs-content/react/skeleton/text-placeholder-skeleton.tsx new file mode 100644 index 000000000..83f64551a --- /dev/null +++ b/docs-content/react/skeleton/text-placeholder-skeleton.tsx @@ -0,0 +1,81 @@ +import { Typography } from "@material-tailwind/react"; + +export function TextPlacehoderSkeleton() { + return ( +
+
+ +
+
+ + + +
+
+ + + +
+
+ + + +
+
+ + + +
+
+ + + +
+ + Loading... + +
+ ); +} diff --git a/docs-content/react/skeleton/video-placeholder-skeleton.tsx b/docs-content/react/skeleton/video-placeholder-skeleton.tsx new file mode 100644 index 000000000..b24c71633 --- /dev/null +++ b/docs-content/react/skeleton/video-placeholder-skeleton.tsx @@ -0,0 +1,21 @@ +import { Typography } from "@material-tailwind/react"; + +export function VideoPlacehoderSkeleton() { + return ( +
+ + + Loading... + +
+ ); +} diff --git a/documentation/react/skeleton.mdx b/documentation/react/skeleton.mdx new file mode 100644 index 000000000..db4406a32 --- /dev/null +++ b/documentation/react/skeleton.mdx @@ -0,0 +1,354 @@ +--- +title: Tailwind CSS Skeleton for React - Material Tailwind +description: Customise your web projects with our easy-to-use skeleton component for Tailwind CSS and React using Material Design guidelines. +navigation: + [ + "skeleton", + "image-placeholder-skeleton", + "video-placeholder-skeleton", + "text-placeholder-skeleton", + "card-placeholder-skeleton", + "testimonial-placeholder-skeleton" + ] +github: skeleton +prev: sidebar +next: speed-dial +--- + + +# Tailwind CSS Skeleton - React + + +The skeleton component can be used as an alternative loading indicator to the spinner by mimicking the content that will be loaded such as text, images, or video + +See below our simple Skeleton example that you can use in your Tailwind CSS and React project. + +
+ +}> +```jsx +import { Typography } from "@material-tailwind/react"; +export function DefaultSkeleton() { + return ( +
+ + + + + + + + Loading... + +
+ ); +} +``` +
+ +--- + + +## Image placeholder Skeleton + + +}> +```jsx +import { Typography } from "@material-tailwind/react"; + +export function ImagePlacehoderSkeleton() { + return ( +
+
+ +
+
+ + + + + + + + Loading... + +
+
+ ); +} +``` +
+ +--- + + + +## Video placeholder Skeleton + + +}> +```jsx +import { Typography } from "@material-tailwind/react"; +export function VideoPlacehoderSkeleton() { + return ( +
+ + + Loading... + +
+ ); +} +``` +
+ +--- + + +## Text placeholder Skeleton + + +}> +```jsx +import { Typography } from "@material-tailwind/react"; +export function TextPlacehoderSkeleton() { + return ( +
+
+ +
+
+ + +
+
+ + + +
+
+ + + +
+
+ + + +
+
+ + + +
+ + Loading... + +
+ ); +} +``` +
+ +--- + + + +## Card placeholder Skeleton + + +}> +```jsx +import { Button, Typography } from "@material-tailwind/react"; +import Card, { + CardBody, + CardFooter, + CardHeader, +} from "packages/material-tailwind-react/src/components/Card"; + +export function CardPlacehoderSkeleton() { + return ( + + + + + + +
+ + + + +
+
+ + + +
+ ); +} +``` +
+ +--- + + + +## Testimonial placeholder Skeleton + + +}> +```jsx +import { Typography } from "@material-tailwind/react"; + +export function TestimonialPlacehoderSkeleton() { + return ( +
+ + +
+ + + +
+ Loading... +
+ ); +} +``` +
+ +--- \ No newline at end of file diff --git a/package.json b/package.json index f53b716c3..1ceaf41d0 100644 --- a/package.json +++ b/package.json @@ -24,6 +24,7 @@ "@fullcalendar/daygrid": "^6.1.9", "@fullcalendar/react": "^6.1.9", "@heroicons/react": "2.0.13", + "@lexical/react": "^0.12.5", "apexcharts": "^3.44.0", "classnames": "2.3.2", "clsx": "1.2.1", @@ -33,6 +34,7 @@ "framer-motion": "6.5.1", "gray-matter": "4.0.3", "js-cookie": "^3.0.5", + "lexical": "^0.12.5", "material-ripple-effects": "2.0.1", "mdx-observable": "0.2.0", "next": "13.1.1", diff --git a/pages/docs/[...slug].tsx b/pages/docs/[...slug].tsx index 76b0ab500..47bc778fa 100644 --- a/pages/docs/[...slug].tsx +++ b/pages/docs/[...slug].tsx @@ -75,6 +75,7 @@ import * as TabsExamples from "docs-content/react/tabs"; import * as TextareaExamples from "docs-content/react/textarea"; import * as Plugins from "docs-content/react/plugins"; import ReleaseNotes from "docs-content/react/release-notes"; +import * as SkeletonExamples from "docs-content/react/skeleton"; // html docs content import * as HtmlPlugins from "docs-content/html/plugins"; @@ -351,6 +352,7 @@ const components = { ReleaseNotes, ColorPalette, Plugins, + SkeletonExamples, // html docs content HtmlPlugins, diff --git a/routes/react.routes.ts b/routes/react.routes.ts index 7dcf6ae1f..e87572f1b 100644 --- a/routes/react.routes.ts +++ b/routes/react.routes.ts @@ -207,6 +207,10 @@ export const routes = [ name: "Sidebar", route: "sidebar", }, + { + name: "Skeleton", + route: "skeleton", + }, { name: "Slider", route: "slider", From 793269945f78a821ab164c1b640abc10159ea526 Mon Sep 17 00:00:00 2001 From: Maisam Afshar Date: Mon, 18 Dec 2023 14:03:45 +0330 Subject: [PATCH 10/38] add: flask installation guide --- documentation/html/guide/flask.mdx | 245 +++++++++++++++++++++++++++++ 1 file changed, 245 insertions(+) create mode 100644 documentation/html/guide/flask.mdx diff --git a/documentation/html/guide/flask.mdx b/documentation/html/guide/flask.mdx new file mode 100644 index 000000000..c83d25e8e --- /dev/null +++ b/documentation/html/guide/flask.mdx @@ -0,0 +1,245 @@ +--- +title: Flask - Installation Guide +description: Learn how to use Material Tailwind components with Flask and Tailwind CSS to easily create elegant and flexible pages. +navigation: + [ + "installation", + "npm", + "yarn", + "pnpm", + "tailwindcss-config", + "ripple-effect", + "example", + ] +github: guide/flask +prev: installation +next: license +--- + +# Material Tailwind with Flask + + +Learn how to setup and install @material-tailwind/html with Flask. + +
+
+ +First you need to create a new project using Flask, for more details check the Flask Official Documentation. +Then, in the root of your project folder create a new file called **app.py** with the following content: + +```js +from flask import Flask, render_template + +app = Flask(__name__) + +@app.route("/") +@app.route("/index") +def index(): + return render_template("index.html") + +if __name__ == '__main__': + app.run(debug=True) +``` + +
+ +Then create two folders naming **templates** and **static** and inside the **templates** folder create an **index.html** file with a basic structure such as: + +```html + + + + + + + Material Tailwind with Flask + + +

Hello, Flask!

+ + +``` +
+ +Then you need to install Tailwind CSS since @material-tailwind/html is working with Tailwind CSS classes and you need to have Tailwind CSS installed on your project. + +```bash +npm install -D tailwindcss +npx tailwindcss init +``` +
+ +Create a new **static/src/** folder and add a new **input.css** file and add the `@tailwind` directives for each of Tailwind’s layers: + +```css +@tailwind base; +@tailwind components; +@tailwind utilities; +``` +
+ +Configure the template files inside the tailwind.config.js: + +```bash {3-6} +/** @type {import('tailwindcss').Config} */ +module.exports = { + content: [ + "./templates/**/*.html", + "./static/src/**/*.js" + ], + theme: { + extend: {}, + }, + plugins: [], +} +``` +
+ +Run the following command to compile and watch for the changes in the Tailwind CSS file: + +```bash +npx tailwindcss -i ./static/src/input.css -o ./static/dist/css/out.css --watch +``` +
+ +This will generate a new **output.css** file inside the `/static/dist/css/` folder that we now need to include in our **index.html**. + +```html {8-11} + + + + + + + Material Tailwind with Flask + + + +

Hello, Flask!

+ + +``` + +--- + + +## Using NPM + + +Install @material-tailwind/html as a dependency using NPM by running the following command: + + + +```bash +npm i @material-tailwind/html +``` + +--- + + +## Using Yarn + + +Install @material-tailwind/html as a dependency using Yarn by running the following command: + + + +```bash +yarn add @material-tailwind/html +``` + +--- + +## Using PNPM + +Install @material-tailwind/html as a dependency using PNPM by running the following command: + + + +```bash +pnpm i @material-tailwind/html +``` + +--- + + +## TailwindCSS Configurations + + + + +Once you install @material-tailwind/html you need to wrap your tailwind css configurations with the withMT() function coming from @material-tailwind/html/utils. + +```js {3, 5, 14} +/** @type {import('tailwindcss').Config} */ + +import withMT from "@material-tailwind/html/utils/withMT"; + +module.exports = withMT({ + content: [ + "./templates/**/*.html", + "./static/src/**/*.js" + ], + theme: { + extend: {}, + }, + plugins: [], +}); +``` + +
+ +Start the local server by running: +```bash +python3 app.py +``` + +--- + +## Ripple Effect + + + +@material-tailwind/html comes with a ripple effect script file same as Material Design ripple effect and you can simply use it by adding it's CDN link to you project and add the data-ripple-light="true" for light ripple effect and data-ripple-dark="true" for dark ripple effect as an attribute for components + +The ripple effect used in @material-tailwind/html is a separate package called material-ripple-effect + + +```html + + + + + +``` + +--- + + +## Example + + +Now you're good to go and use @material-tailwind/html in your project. + + + Button + +}> +```html + +``` + From cca1dc1ab22b81e8b11d111d10004d64c7bf39b4 Mon Sep 17 00:00:00 2001 From: Maisam Afshar Date: Mon, 18 Dec 2023 14:03:54 +0330 Subject: [PATCH 11/38] add: pheonix installation guide --- documentation/html/guide/pheonix.mdx | 150 +++++++++++++++++++++++++++ 1 file changed, 150 insertions(+) create mode 100644 documentation/html/guide/pheonix.mdx diff --git a/documentation/html/guide/pheonix.mdx b/documentation/html/guide/pheonix.mdx new file mode 100644 index 000000000..779e83337 --- /dev/null +++ b/documentation/html/guide/pheonix.mdx @@ -0,0 +1,150 @@ +--- +title: Pheonix - Installation Guide +description: Learn how to use Material Tailwind components with Pheonix and Tailwind CSS to easily create elegant and flexible pages. +navigation: + [ + "installation", + "npm", + "yarn", + "pnpm", + "tailwindcss-config", + "ripple-effect", + "example", + ] +github: guide/pheonix +prev: installation +next: license +--- + +# Material Tailwind with Pheonix + + +Learn how to setup and install @material-tailwind/html with Pheonix. + +
+
+ +First you need to create a new project using Pheonix, for more details check the Pheonix Official Documentation + +```bash +mix phx.new my_app +``` + +
+ +Then you need to install Tailwind CSS since @material-tailwind/html is working with Tailwind CSS classes and you need to have Tailwind CSS installed on your project. Check Tailwind CSS Installation for Pheonix on Tailwind CSS Documentation. + +--- + + +## Using NPM + + +Install @material-tailwind/html as a dependency using NPM by running the following command: + + + +```bash +npm i @material-tailwind/html +``` + +--- + + +## Using Yarn + + +Install @material-tailwind/html as a dependency using Yarn by running the following command: + + + +```bash +yarn add @material-tailwind/html +``` + +--- + +## Using PNPM + +Install @material-tailwind/html as a dependency using PNPM by running the following command: + + + +```bash +pnpm i @material-tailwind/html +``` + +--- + + +## TailwindCSS Configurations + + + + +Once you install @material-tailwind/html you need to wrap your tailwind css configurations with the withMT() function coming from @material-tailwind/html/utils. + +```js {5, 7, 15} +const plugin = require("tailwindcss/plugin") +const fs = require("fs") +const path = require("path") + +const withMT = require("@material-tailwind/html/utils/withMT") + +module.exports = withMT({ + content: [ + './js/**/*.js', + '../lib/*_web.ex', + '../lib/*_web/**/*.*ex', + ], + theme: {}, + plugins: [] +}); +``` + +--- + +## Ripple Effect + + + +@material-tailwind/html comes with a ripple effect script file same as Material Design ripple effect and you can simply use it by adding it's CDN link to you project and add the data-ripple-light="true" for light ripple effect and data-ripple-dark="true" for dark ripple effect as an attribute for components + +The ripple effect used in @material-tailwind/html is a separate package called material-ripple-effect + + +```html + + + + + +``` + +--- + + +## Example + + +Now you're good to go and use @material-tailwind/html in your project. + + + Button + +}> +```html + +``` + From 68b69cb2df5d2ce1386fca5dbd7dbd66fa554b44 Mon Sep 17 00:00:00 2001 From: Maisam Afshar Date: Mon, 18 Dec 2023 14:04:10 +0330 Subject: [PATCH 12/38] add: symfony installation guide --- documentation/html/guide/symfony.mdx | 155 +++++++++++++++++++++++++++ 1 file changed, 155 insertions(+) create mode 100644 documentation/html/guide/symfony.mdx diff --git a/documentation/html/guide/symfony.mdx b/documentation/html/guide/symfony.mdx new file mode 100644 index 000000000..259cc8525 --- /dev/null +++ b/documentation/html/guide/symfony.mdx @@ -0,0 +1,155 @@ +--- +title: Symfony - Installation Guide +description: Learn how to use Material Tailwind components with Symfony and Tailwind CSS to easily create elegant and flexible pages. +navigation: + [ + "installation", + "npm", + "yarn", + "pnpm", + "tailwindcss-config", + "ripple-effect", + "example", + ] +github: guide/symfony +prev: installation +next: license +--- + +# Material Tailwind with Symfony + + +Learn how to setup and install @material-tailwind/html with Symfony. + +
+
+ +First you need to create a new project using Symfony, for more details check the Symfony Official Documentation + +```bash +symfony new --webapp my_project +``` +
+ +To enable front-end integration via Composer, it is recommended to install the Symfony Webpack Encore bundle. + +```bash +composer require symfony/webpack-encore-bundle +``` +
+ +Then you need to install Tailwind CSS since @material-tailwind/html is working with Tailwind CSS classes and you need to have Tailwind CSS installed on your project. Check Tailwind CSS Installation for Symfony on Tailwind CSS Documentation. + +--- + + +## Using NPM + + +Install @material-tailwind/html as a dependency using NPM by running the following command: + + + +```bash +npm i @material-tailwind/html +``` + +--- + + +## Using Yarn + + +Install @material-tailwind/html as a dependency using Yarn by running the following command: + + + +```bash +yarn add @material-tailwind/html +``` + +--- + +## Using PNPM + +Install @material-tailwind/html as a dependency using PNPM by running the following command: + + + +```bash +pnpm i @material-tailwind/html +``` + +--- + + +## TailwindCSS Configurations + + + + +Once you install @material-tailwind/html you need to wrap your tailwind css configurations with the withMT() function coming from @material-tailwind/html/utils. + +```js {3, 5, 14} +/** @type {import('tailwindcss').Config} */ + +import withMT from "@material-tailwind/html/utils/withMT"; + +module.exports = withMT({ + content: [ + "./assets/**/*.js", + "./templates/**/*.html.twig", + ], + theme: { + extend: {}, + }, + plugins: [], +}); +``` + +--- + +## Ripple Effect + + + +@material-tailwind/html comes with a ripple effect script file same as Material Design ripple effect and you can simply use it by adding it's CDN link to you project and add the data-ripple-light="true" for light ripple effect and data-ripple-dark="true" for dark ripple effect as an attribute for components + +The ripple effect used in @material-tailwind/html is a separate package called material-ripple-effect + + +```html + + + + + +``` + +--- + + +## Example + + +Now you're good to go and use @material-tailwind/html in your project. + + + Button + +}> +```html + +``` + From a5e2c1bf192afbcaa0a83d734cb49c8309f2d286 Mon Sep 17 00:00:00 2001 From: Sayed Murtaza Date: Mon, 18 Dec 2023 19:05:33 +0430 Subject: [PATCH 13/38] gallery component done --- .../react/gallery/default-gallery.tsx | 53 ++ .../react/gallery/featured-image-gallery.tsx | 52 ++ .../react/gallery/gallery-with-carousel.tsx | 23 + .../react/gallery/gallery-with-tab.tsx | 193 ++++++ docs-content/react/gallery/index.ts | 6 + .../react/gallery/masonry-grid-gallery.tsx | 91 +++ docs-content/react/gallery/quad-gallery.tsx | 29 + documentation/react/gallery.mdx | 550 ++++++++++++++++++ pages/docs/[...slug].tsx | 3 +- routes/react.routes.ts | 4 + 10 files changed, 1003 insertions(+), 1 deletion(-) create mode 100644 docs-content/react/gallery/default-gallery.tsx create mode 100644 docs-content/react/gallery/featured-image-gallery.tsx create mode 100644 docs-content/react/gallery/gallery-with-carousel.tsx create mode 100644 docs-content/react/gallery/gallery-with-tab.tsx create mode 100644 docs-content/react/gallery/index.ts create mode 100644 docs-content/react/gallery/masonry-grid-gallery.tsx create mode 100644 docs-content/react/gallery/quad-gallery.tsx create mode 100644 documentation/react/gallery.mdx diff --git a/docs-content/react/gallery/default-gallery.tsx b/docs-content/react/gallery/default-gallery.tsx new file mode 100644 index 000000000..5e1910537 --- /dev/null +++ b/docs-content/react/gallery/default-gallery.tsx @@ -0,0 +1,53 @@ +export function DefaultGallery() { + const data = [ + { + imageLink: + "https://images.unsplash.com/photo-1499696010180-025ef6e1a8f9?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1470&q=80", + }, + { + imageLink: + "https://images.unsplash.com/photo-1432462770865-65b70566d673?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=1950&q=80", + }, + { + imageLink: + "https://images.unsplash.com/photo-1497436072909-60f360e1d4b1?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2560&q=80", + }, + { + imageLink: + "https://images.unsplash.com/photo-1493246507139-91e8fad9978e?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2940&q=80", + }, + { + imageLink: + "https://images.unsplash.com/photo-1518623489648-a173ef7824f3?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2762&q=80", + }, + { + imageLink: + "https://images.unsplash.com/photo-1682407186023-12c70a4a35e0?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2832&q=80", + }, + { + imageLink: + "https://demos.creative-tim.com/material-kit-pro/assets/img/examples/blog5.jpg", + }, + { + imageLink: + "https://material-taillwind-pro-ct-tailwind-team.vercel.app/img/content2.jpg", + }, + { + imageLink: + "https://images.unsplash.com/photo-1620064916958-605375619af8?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=1493&q=80", + }, + ]; + return ( +
+ {data.map(({ imageLink }, index) => ( +
+ gallery-photo +
+ ))} +
+ ); +} diff --git a/docs-content/react/gallery/featured-image-gallery.tsx b/docs-content/react/gallery/featured-image-gallery.tsx new file mode 100644 index 000000000..fc946f2ee --- /dev/null +++ b/docs-content/react/gallery/featured-image-gallery.tsx @@ -0,0 +1,52 @@ +import React from "react"; +export function FeaturedImageGallery() { + const data = [ + { + imgelink: + "https://images.unsplash.com/photo-1499696010180-025ef6e1a8f9?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1470&q=80", + }, + { + imgelink: + "https://images.unsplash.com/photo-1432462770865-65b70566d673?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=1950&q=80", + }, + { + imgelink: + "https://images.unsplash.com/photo-1493246507139-91e8fad9978e?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2940&q=80", + }, + { + imgelink: + "https://images.unsplash.com/photo-1518623489648-a173ef7824f3?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2762&q=80", + }, + { + imgelink: + "https://images.unsplash.com/photo-1682407186023-12c70a4a35e0?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2832&q=80", + }, + ]; + + const [active, setActive] = React.useState( + "https://images.unsplash.com/photo-1499696010180-025ef6e1a8f9?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1470&q=80", + ); + return ( +
+
+ +
+
+ {data.map(({ imgelink }, index) => ( +
+ setActive(imgelink)} + src={imgelink} + className="h-20 max-w-full cursor-pointer rounded-lg" + alt="gallery-image" + /> +
+ ))} +
+
+ ); +} diff --git a/docs-content/react/gallery/gallery-with-carousel.tsx b/docs-content/react/gallery/gallery-with-carousel.tsx new file mode 100644 index 000000000..439717e34 --- /dev/null +++ b/docs-content/react/gallery/gallery-with-carousel.tsx @@ -0,0 +1,23 @@ +import { Carousel } from "@material-tailwind/react"; + +export function GalleryWithCarousel() { + return ( + + image 1 + image 2 + image 3 + + ); +} diff --git a/docs-content/react/gallery/gallery-with-tab.tsx b/docs-content/react/gallery/gallery-with-tab.tsx new file mode 100644 index 000000000..412668ed4 --- /dev/null +++ b/docs-content/react/gallery/gallery-with-tab.tsx @@ -0,0 +1,193 @@ +import { + Tabs, + TabsHeader, + TabsBody, + Tab, + TabPanel, +} from "@material-tailwind/react"; + +export function GalleryWithTab() { + const data = [ + { + label: "HTML", + value: "html", + images: [ + { + imageLink: + "https://images.unsplash.com/photo-1493246507139-91e8fad9978e?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2940&q=80", + }, + { + imageLink: + "https://images.unsplash.com/photo-1518623489648-a173ef7824f3?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2762&q=80", + }, + { + imageLink: + "https://images.unsplash.com/photo-1682407186023-12c70a4a35e0?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2832&q=80", + }, + { + imageLink: + "https://demos.creative-tim.com/material-kit-pro/assets/img/examples/blog5.jpg", + }, + { + imageLink: + "https://material-taillwind-pro-ct-tailwind-team.vercel.app/img/content2.jpg", + }, + { + imageLink: + "https://images.unsplash.com/photo-1620064916958-605375619af8?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=1493&q=80", + }, + ], + }, + { + label: "React", + value: "react", + images: [ + { + imageLink: + "https://images.unsplash.com/photo-1499696010180-025ef6e1a8f9?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1470&q=80", + }, + { + imageLink: + "https://images.unsplash.com/photo-1432462770865-65b70566d673?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=1950&q=80", + }, + { + imageLink: + "https://images.unsplash.com/photo-1497436072909-60f360e1d4b1?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2560&q=80", + }, + { + imageLink: + "https://images.unsplash.com/photo-1493246507139-91e8fad9978e?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2940&q=80", + }, + { + imageLink: + "https://images.unsplash.com/photo-1518623489648-a173ef7824f3?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2762&q=80", + }, + { + imageLink: + "https://images.unsplash.com/photo-1682407186023-12c70a4a35e0?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2832&q=80", + }, + ], + }, + { + label: "Vue", + value: "vue", + images: [ + { + imageLink: + "https://images.unsplash.com/photo-1493246507139-91e8fad9978e?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2940&q=80", + }, + { + imageLink: + "https://images.unsplash.com/photo-1518623489648-a173ef7824f3?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2762&q=80", + }, + { + imageLink: + "https://images.unsplash.com/photo-1682407186023-12c70a4a35e0?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2832&q=80", + }, + { + imageLink: + "https://demos.creative-tim.com/material-kit-pro/assets/img/examples/blog5.jpg", + }, + { + imageLink: + "https://material-taillwind-pro-ct-tailwind-team.vercel.app/img/content2.jpg", + }, + { + imageLink: + "https://images.unsplash.com/photo-1620064916958-605375619af8?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=1493&q=80", + }, + ], + }, + { + label: "Angular", + value: "angular", + images: [ + { + imageLink: + "https://images.unsplash.com/photo-1499696010180-025ef6e1a8f9?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1470&q=80", + }, + { + imageLink: + "https://images.unsplash.com/photo-1432462770865-65b70566d673?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=1950&q=80", + }, + { + imageLink: + "https://images.unsplash.com/photo-1497436072909-60f360e1d4b1?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2560&q=80", + }, + { + imageLink: + "https://images.unsplash.com/photo-1493246507139-91e8fad9978e?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2940&q=80", + }, + { + imageLink: + "https://images.unsplash.com/photo-1518623489648-a173ef7824f3?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2762&q=80", + }, + { + imageLink: + "https://images.unsplash.com/photo-1682407186023-12c70a4a35e0?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2832&q=80", + }, + ], + }, + { + label: "Svelte", + value: "svelte", + images: [ + { + imageLink: + "https://demos.creative-tim.com/material-kit-pro/assets/img/examples/blog5.jpg", + }, + { + imageLink: + "https://material-taillwind-pro-ct-tailwind-team.vercel.app/img/content2.jpg", + }, + { + imageLink: + "https://images.unsplash.com/photo-1620064916958-605375619af8?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=1493&q=80", + }, + { + imageLink: + "https://images.unsplash.com/photo-1493246507139-91e8fad9978e?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2940&q=80", + }, + { + imageLink: + "https://images.unsplash.com/photo-1518623489648-a173ef7824f3?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2762&q=80", + }, + { + imageLink: + "https://images.unsplash.com/photo-1682407186023-12c70a4a35e0?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2832&q=80", + }, + ], + }, + ]; + + return ( + + + {data.map(({ label, value }) => ( + + {label} + + ))} + + + {data.map(({ value, images }) => ( + + {images?.map(({ imageLink }, index) => ( +
+ image-photo +
+ ))} +
+ ))} +
+
+ ); +} diff --git a/docs-content/react/gallery/index.ts b/docs-content/react/gallery/index.ts new file mode 100644 index 000000000..29f71ed07 --- /dev/null +++ b/docs-content/react/gallery/index.ts @@ -0,0 +1,6 @@ +export * from "./default-gallery"; +export * from "./masonry-grid-gallery"; +export * from "./featured-image-gallery"; +export * from "./quad-gallery"; +export * from "./gallery-with-carousel"; +export * from "./gallery-with-tab"; diff --git a/docs-content/react/gallery/masonry-grid-gallery.tsx b/docs-content/react/gallery/masonry-grid-gallery.tsx new file mode 100644 index 000000000..def3b0077 --- /dev/null +++ b/docs-content/react/gallery/masonry-grid-gallery.tsx @@ -0,0 +1,91 @@ +export function MasonryGridGallery() { + return ( +
+
+
+ gallery-photo +
+
+ gallery-photo +
+
+ gallery-photo +
+
+
+
+ gallery-photo +
+
+ gallery-photo +
+
+ gallery-photo +
+
+
+
+ gallery-photo +
+
+ gallery-photo +
+
+ gallery-photo +
+
+
+
+ gallery-photo +
+
+ gallery-photo +
+
+
+ ); +} diff --git a/docs-content/react/gallery/quad-gallery.tsx b/docs-content/react/gallery/quad-gallery.tsx new file mode 100644 index 000000000..9757d03bb --- /dev/null +++ b/docs-content/react/gallery/quad-gallery.tsx @@ -0,0 +1,29 @@ +export function QuadGallery() { + const data = [ + { + imageLink: + "https://images.unsplash.com/photo-1499696010180-025ef6e1a8f9?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1470&q=80", + }, + { + imageLink: + "https://images.unsplash.com/photo-1432462770865-65b70566d673?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=1950&q=80", + }, + { + imageLink: + "https://images.unsplash.com/photo-1497436072909-60f360e1d4b1?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2560&q=80", + }, + { + imageLink: + "https://images.unsplash.com/photo-1493246507139-91e8fad9978e?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2940&q=80", + }, + ]; + return ( +
+ {data.map(({ imageLink }, index) => ( +
+ +
+ ))} +
+ ); +} diff --git a/documentation/react/gallery.mdx b/documentation/react/gallery.mdx new file mode 100644 index 000000000..92af79ce8 --- /dev/null +++ b/documentation/react/gallery.mdx @@ -0,0 +1,550 @@ +--- +title: Tailwind CSS Gallery for React - Material Tailwind +description: Customise your web projects with our easy-to-use gallery component for Tailwind CSS and React using Material Design guidelines. +navigation: + [ + "gallery", + "masonry-grid-gallery", + "featured-image-gallery", + "quad-gallery", + "gallery-with-carousel", + "gallery-with-tab" + ] +github: skeleton +prev: form +next: icon-button +--- + + +# Tailwind CSS Gallery - React + + +Use the image gallery component + +See below our simple Gallery example that you can use in your Tailwind CSS and React project. + +
+ +}> +```jsx +export function DefaultGallery() { + const data = [ + { + imageLink: + "https://images.unsplash.com/photo-1499696010180-025ef6e1a8f9?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1470&q=80", + }, + { + imageLink: + "https://images.unsplash.com/photo-1432462770865-65b70566d673?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=1950&q=80", + }, + { + imageLink: + "https://images.unsplash.com/photo-1497436072909-60f360e1d4b1?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2560&q=80", + }, + { + imageLink: + "https://images.unsplash.com/photo-1493246507139-91e8fad9978e?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2940&q=80", + }, + { + imageLink: + "https://images.unsplash.com/photo-1518623489648-a173ef7824f3?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2762&q=80", + }, + { + imageLink: + "https://images.unsplash.com/photo-1682407186023-12c70a4a35e0?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2832&q=80", + }, + { + imageLink: + "https://demos.creative-tim.com/material-kit-pro/assets/img/examples/blog5.jpg", + }, + { + imageLink: + "https://material-taillwind-pro-ct-tailwind-team.vercel.app/img/content2.jpg", + }, + { + imageLink: + "https://images.unsplash.com/photo-1620064916958-605375619af8?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=1493&q=80", + }, + ]; + return ( +
+ {data.map(({ imageLink }, index) => ( +
+ gallery-photo +
+ ))} +
+ ); +} +``` +
+ +--- + + + +## Masonry Grid Galery - React + +
+ +}> +```jsx +export function MasonryGridGallery() { + return ( + export function MasonryGridGallery() { + return ( +
+
+
+ gallery-photo +
+
+ gallery-photo +
+
+ gallery-photo +
+
+
+
+ gallery-photo +
+
+ gallery-photo +
+
+ gallery-photo +
+
+
+
+ gallery-photo +
+
+ gallery-photo +
+
+ gallery-photo +
+
+
+
+ gallery-photo +
+
+ gallery-photo +
+
+
+ ); +} + + ); +} +``` +
+ +--- + + + +## Featured Image Galery - React + +
+ +}> +```jsx +import React from "react"; +export function FeaturedImageGallery() { + const data = [ + { + imgelink: + "https://images.unsplash.com/photo-1499696010180-025ef6e1a8f9?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1470&q=80", + }, + { + imgelink: + "https://images.unsplash.com/photo-1432462770865-65b70566d673?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=1950&q=80", + }, + { + imgelink: + "https://images.unsplash.com/photo-1493246507139-91e8fad9978e?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2940&q=80", + }, + { + imgelink: + "https://images.unsplash.com/photo-1518623489648-a173ef7824f3?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2762&q=80", + }, + { + imgelink: + "https://images.unsplash.com/photo-1682407186023-12c70a4a35e0?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2832&q=80", + }, + ]; + + const [active, setActive] = React.useState( + "https://images.unsplash.com/photo-1499696010180-025ef6e1a8f9?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1470&q=80", + ); + return ( +
+
+ +
+
+ {data.map(({ imgelink }, index) => ( +
+ setActive(imgelink)} + src={imgelink} + className="h-20 max-w-full cursor-pointer rounded-lg" + alt="gallery-image" + /> +
+ ))} +
+
+ ); +} +``` +
+ +--- + + + + +## Quad Galery - React + +
+ +}> +```jsx +export function QuadGallery() { + const data = [ + { + imageLink: + "https://images.unsplash.com/photo-1499696010180-025ef6e1a8f9?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1470&q=80", + }, + { + imageLink: + "https://images.unsplash.com/photo-1432462770865-65b70566d673?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=1950&q=80", + }, + { + imageLink: + "https://images.unsplash.com/photo-1497436072909-60f360e1d4b1?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2560&q=80", + }, + { + imageLink: + "https://images.unsplash.com/photo-1493246507139-91e8fad9978e?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2940&q=80", + }, + ]; + return ( +
+ {data.map(({ imageLink }, index) => ( +
+ +
+ ))} +
+ ); +} +``` +
+ +--- + + + + +## Gallery With Carousel - React + +
+ +}> +```jsx +import { Carousel } from "@material-tailwind/react"; + +export function GalleryWithCarousel() { + return ( + + image 1 + image 2 + image 3 + + ); +} +``` + + +--- + + + +## Gallery With Tab - React + +
+ +}> +```jsx +import { + Tabs, + TabsHeader, + TabsBody, + Tab, + TabPanel, +} from "@material-tailwind/react"; + +export function GalleryWithTab() { + const data = [ + { + label: "HTML", + value: "html", + images: [ + { + imageLink: + "https://images.unsplash.com/photo-1493246507139-91e8fad9978e?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2940&q=80", + }, + { + imageLink: + "https://images.unsplash.com/photo-1518623489648-a173ef7824f3?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2762&q=80", + }, + { + imageLink: + "https://images.unsplash.com/photo-1682407186023-12c70a4a35e0?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2832&q=80", + }, + { + imageLink: + "https://demos.creative-tim.com/material-kit-pro/assets/img/examples/blog5.jpg", + }, + { + imageLink: + "https://material-taillwind-pro-ct-tailwind-team.vercel.app/img/content2.jpg", + }, + { + imageLink: + "https://images.unsplash.com/photo-1620064916958-605375619af8?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=1493&q=80", + }, + ], + }, + { + label: "React", + value: "react", + images: [ + { + imageLink: + "https://images.unsplash.com/photo-1499696010180-025ef6e1a8f9?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1470&q=80", + }, + { + imageLink: + "https://images.unsplash.com/photo-1432462770865-65b70566d673?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=1950&q=80", + }, + { + imageLink: + "https://images.unsplash.com/photo-1497436072909-60f360e1d4b1?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2560&q=80", + }, + { + imageLink: + "https://images.unsplash.com/photo-1493246507139-91e8fad9978e?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2940&q=80", + }, + { + imageLink: + "https://images.unsplash.com/photo-1518623489648-a173ef7824f3?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2762&q=80", + }, + { + imageLink: + "https://images.unsplash.com/photo-1682407186023-12c70a4a35e0?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2832&q=80", + }, + ], + }, + { + label: "Vue", + value: "vue", + images: [ + { + imageLink: + "https://images.unsplash.com/photo-1493246507139-91e8fad9978e?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2940&q=80", + }, + { + imageLink: + "https://images.unsplash.com/photo-1518623489648-a173ef7824f3?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2762&q=80", + }, + { + imageLink: + "https://images.unsplash.com/photo-1682407186023-12c70a4a35e0?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2832&q=80", + }, + { + imageLink: + "https://demos.creative-tim.com/material-kit-pro/assets/img/examples/blog5.jpg", + }, + { + imageLink: + "https://material-taillwind-pro-ct-tailwind-team.vercel.app/img/content2.jpg", + }, + { + imageLink: + "https://images.unsplash.com/photo-1620064916958-605375619af8?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=1493&q=80", + }, + ], + }, + { + label: "Angular", + value: "angular", + images: [ + { + imageLink: + "https://images.unsplash.com/photo-1499696010180-025ef6e1a8f9?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1470&q=80", + }, + { + imageLink: + "https://images.unsplash.com/photo-1432462770865-65b70566d673?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=1950&q=80", + }, + { + imageLink: + "https://images.unsplash.com/photo-1497436072909-60f360e1d4b1?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2560&q=80", + }, + { + imageLink: + "https://images.unsplash.com/photo-1493246507139-91e8fad9978e?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2940&q=80", + }, + { + imageLink: + "https://images.unsplash.com/photo-1518623489648-a173ef7824f3?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2762&q=80", + }, + { + imageLink: + "https://images.unsplash.com/photo-1682407186023-12c70a4a35e0?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2832&q=80", + }, + ], + }, + { + label: "Svelte", + value: "svelte", + images: [ + { + imageLink: + "https://demos.creative-tim.com/material-kit-pro/assets/img/examples/blog5.jpg", + }, + { + imageLink: + "https://material-taillwind-pro-ct-tailwind-team.vercel.app/img/content2.jpg", + }, + { + imageLink: + "https://images.unsplash.com/photo-1620064916958-605375619af8?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=1493&q=80", + }, + { + imageLink: + "https://images.unsplash.com/photo-1493246507139-91e8fad9978e?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2940&q=80", + }, + { + imageLink: + "https://images.unsplash.com/photo-1518623489648-a173ef7824f3?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2762&q=80", + }, + { + imageLink: + "https://images.unsplash.com/photo-1682407186023-12c70a4a35e0?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2832&q=80", + }, + ], + }, + ]; + + return ( + + + {data.map(({ label, value }) => ( + + {label} + + ))} + + + {data.map(({ value, images }) => ( + + {images?.map(({ imageLink }, index) => ( +
+ image-photo +
+ ))} +
+ ))} +
+
+ ); +} +``` +
+ +--- diff --git a/pages/docs/[...slug].tsx b/pages/docs/[...slug].tsx index 47bc778fa..b8389c702 100644 --- a/pages/docs/[...slug].tsx +++ b/pages/docs/[...slug].tsx @@ -76,6 +76,7 @@ import * as TextareaExamples from "docs-content/react/textarea"; import * as Plugins from "docs-content/react/plugins"; import ReleaseNotes from "docs-content/react/release-notes"; import * as SkeletonExamples from "docs-content/react/skeleton"; +import * as GalleryExamples from "docs-content/react/gallery"; // html docs content import * as HtmlPlugins from "docs-content/html/plugins"; @@ -353,7 +354,7 @@ const components = { ColorPalette, Plugins, SkeletonExamples, - + GalleryExamples, // html docs content HtmlPlugins, HTMLButtonExamples, diff --git a/routes/react.routes.ts b/routes/react.routes.ts index e87572f1b..779f02e39 100644 --- a/routes/react.routes.ts +++ b/routes/react.routes.ts @@ -154,6 +154,10 @@ export const routes = [ name: "Form", route: "form", }, + { + name: "Gallery", + route: "gallery", + }, { name: "Icon Button", route: "icon-button", From 672413765f1f86c6fb32de68165b5d02af4c7fcd Mon Sep 17 00:00:00 2001 From: sanam453 Date: Mon, 18 Dec 2023 20:27:00 +0430 Subject: [PATCH 14/38] fixed routes --- routes/html.routes.ts | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/routes/html.routes.ts b/routes/html.routes.ts index a2a64ec6c..d42c7f3ec 100644 --- a/routes/html.routes.ts +++ b/routes/html.routes.ts @@ -102,7 +102,7 @@ export const routes = [ route: "button", }, { - name: "Button-Group", + name: "Button Group", route: "button-group", }, @@ -118,14 +118,6 @@ export const routes = [ name: "Chip", route: "chip", }, - { - name: "Collapse", - route: "collapse", - }, - { - name: "Carousel", - route: "carousel", - }, { name: "Dialog", route: "dialog", From 641f5fba0ac9f19061be106b48fd41b17a7b7921 Mon Sep 17 00:00:00 2001 From: Maisam Afshar Date: Mon, 18 Dec 2023 19:34:30 +0330 Subject: [PATCH 15/38] fix: name typo --- .../html/guide/{pheonix.mdx => phoenix.mdx} | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) rename documentation/html/guide/{pheonix.mdx => phoenix.mdx} (91%) diff --git a/documentation/html/guide/pheonix.mdx b/documentation/html/guide/phoenix.mdx similarity index 91% rename from documentation/html/guide/pheonix.mdx rename to documentation/html/guide/phoenix.mdx index 779e83337..4f6adeb7a 100644 --- a/documentation/html/guide/pheonix.mdx +++ b/documentation/html/guide/phoenix.mdx @@ -1,6 +1,6 @@ --- -title: Pheonix - Installation Guide -description: Learn how to use Material Tailwind components with Pheonix and Tailwind CSS to easily create elegant and flexible pages. +title: Phoenix - Installation Guide +description: Learn how to use Material Tailwind components with Phoenix and Tailwind CSS to easily create elegant and flexible pages. navigation: [ "installation", @@ -11,20 +11,20 @@ navigation: "ripple-effect", "example", ] -github: guide/pheonix +github: guide/phoenix prev: installation next: license --- -# Material Tailwind with Pheonix +# Material Tailwind with Phoenix -Learn how to setup and install @material-tailwind/html with Pheonix. +Learn how to setup and install @material-tailwind/html with Phoenix.

-First you need to create a new project using Pheonix, for more details check the Pheonix Official Documentation +First you need to create a new project using Phoenix, for more details check the Phoenix Official Documentation ```bash mix phx.new my_app @@ -32,7 +32,7 @@ mix phx.new my_app
-Then you need to install Tailwind CSS since @material-tailwind/html is working with Tailwind CSS classes and you need to have Tailwind CSS installed on your project. Check Tailwind CSS Installation for Pheonix on Tailwind CSS Documentation. +Then you need to install Tailwind CSS since @material-tailwind/html is working with Tailwind CSS classes and you need to have Tailwind CSS installed on your project. Check Tailwind CSS Installation for Phoenix on Tailwind CSS Documentation. --- From 4887e818b193b8965367a14666f0159c7d85f84c Mon Sep 17 00:00:00 2001 From: Maisam Afshar Date: Mon, 18 Dec 2023 19:36:29 +0330 Subject: [PATCH 16/38] fix typo --- documentation/html/guide/flask.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/documentation/html/guide/flask.mdx b/documentation/html/guide/flask.mdx index c83d25e8e..b549b2160 100644 --- a/documentation/html/guide/flask.mdx +++ b/documentation/html/guide/flask.mdx @@ -194,7 +194,7 @@ module.exports = withMT({ Start the local server by running: ```bash -python3 app.py +python app.py ``` --- From bba588b2f0f29e54d070123a119f5faa0f150a41 Mon Sep 17 00:00:00 2001 From: Maisam Afshar Date: Mon, 18 Dec 2023 19:36:38 +0330 Subject: [PATCH 17/38] add: django installation guide --- documentation/html/guide/django.mdx | 283 ++++++++++++++++++++++++++++ 1 file changed, 283 insertions(+) create mode 100644 documentation/html/guide/django.mdx diff --git a/documentation/html/guide/django.mdx b/documentation/html/guide/django.mdx new file mode 100644 index 000000000..65ab0d2a1 --- /dev/null +++ b/documentation/html/guide/django.mdx @@ -0,0 +1,283 @@ +--- +title: Django - Installation Guide +description: Learn how to use Material Tailwind components with Django and Tailwind CSS to easily create elegant and flexible pages. +navigation: + [ + "installation", + "npm", + "yarn", + "pnpm", + "tailwindcss-config", + "ripple-effect", + "example", + ] +github: guide/django +prev: installation +next: license +--- + +# Material Tailwind with Django + + +Learn how to setup and install @material-tailwind/html with Django. + +
+
+ +First you need to create a new project using Django, for more details check the Django Official Documentation + +```bash +django-admin startproject mysite +``` +
+ +Create a new **templates** directory inside the project folder and update **settings.py** file: + +```php +TEMPLATES = [ + { + ... + 'DIRS': [BASE_DIR / 'templates'], + ... + }, +] +``` +
+ +Install the **django-compressor** by running the following command in your terminal: + +```bash +python -m pip install django-compressor +``` +
+And add the **compressor** to the installed apps inside the **settings.py** file: + +```php +INSTALLED_APPS = [ + ... + 'compressor', +] +``` + +
+ +Configure the **compressor** inside the **settings.py** file: + +```php +COMPRESS_ROOT = BASE_DIR / 'static' + +COMPRESS_ENABLED = True + +STATICFILES_FINDERS = ('compressor.finders.CompressorFinder',) +``` +
+ +Create two new folders and an **input.css** file inside the **static/src/** folder: +```bash +static +└── src + └── input.css +``` + +
+ +Create a new **views.py** file inside `mysite/` next to **urls.py** and add the following code: + +```php +from django.shortcuts import render + +def index(request): + return render(request, 'index.html') +``` + +
+Import the newly created view instance inside the **urls.py** file: + +```php +from .views import index + +urlpatterns = [ + path('admin/', admin.site.urls), + path('', index, name='index') +] +``` + +
+Create a new **_base.html** file inside the **templates** directory and the following code: + +```html +{% load compress %} +{% load static %} + + + + + + + + + Material Tailwind with Django + + {% compress css %} + + {% endcompress %} + + + + + {% block content %} {% endblock content %} + + + +``` +
+Create an **index.html** file inside the **templates** folder that will serve as the homepage. At the moment ignore the Tailwind CSS classes as we will install it shortly. +```html +{% extends "_base.html" %} + +{% block content %} +

+ Material Tailwind with Django! +

+{% endblock content %} +``` +
+ +Then you need to install Tailwind CSS since @material-tailwind/html works with Tailwind CSS classes and you need to have Tailwind CSS installed on your project. +```bash +npm install -D tailwindcss +npx tailwindcss init +``` + +--- + + +## Using NPM + + +Install @material-tailwind/html as a dependency using NPM by running the following command: + + + +```bash +npm i @material-tailwind/html +``` + +--- + + +## Using Yarn + + +Install @material-tailwind/html as a dependency using Yarn by running the following command: + + + +```bash +yarn add @material-tailwind/html +``` + +--- + +## Using PNPM + +Install @material-tailwind/html as a dependency using PNPM by running the following command: + + + +```bash +pnpm i @material-tailwind/html +``` + +--- + + +## TailwindCSS Configurations + + + + +Once you install @material-tailwind/html you need to wrap your tailwind css configurations with the withMT() function coming from @material-tailwind/html/utils. + +```js {1, 4,6, 12} +import withMT from "@material-tailwind/html/utils/withMT"; + +/** @type {import('tailwindcss').Config} */ +module.exports = withMT({ + content: [ + './templates/**/*.html' + ], + theme: { + extend: {}, + }, + plugins: [], +}); +``` +
+Import the Tailwind CSS directives inside the **input.css** file: +```css +/* static/src/input.css */ + +@tailwind base; +@tailwind components; +@tailwind utilities; +``` +
+Run the following command to watch for changes and compile the Tailwind CSS code: + +```bash +npx tailwindcss -i ./static/src/input.css -o ./static/src/output.css --watch +``` +
+ +Finally, create a local server by running the following command: +```bash +python manage.py runserver +``` +--- + +
+## Ripple Effect + + + +@material-tailwind/html comes with a ripple effect script file same as Material Design ripple effect and you can simply use it by adding it's CDN link to you project and add the data-ripple-light="true" for light ripple effect and data-ripple-dark="true" for dark ripple effect as an attribute for components + +The ripple effect used in @material-tailwind/html is a separate package called material-ripple-effect + + +```html + + + + + +``` + +--- + + +## Example + + +Now you're good to go and use @material-tailwind/html in your project. + + + Button + +}> +```html + +``` + From 751aee500e60becb59955b2caafbcc17a29d7e67 Mon Sep 17 00:00:00 2001 From: Maisam Afshar Date: Mon, 18 Dec 2023 19:41:46 +0330 Subject: [PATCH 18/38] ref: add the new guide routes --- routes/html.routes.ts | 44 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/routes/html.routes.ts b/routes/html.routes.ts index a2a64ec6c..1bebf55dc 100644 --- a/routes/html.routes.ts +++ b/routes/html.routes.ts @@ -47,6 +47,50 @@ export const routes = [ name: "Laravel", route: "guide/laravel", }, + { + name: "Angular", + route: "guide/angular", + }, + { + name: "Remix", + route: "guide/remix", + }, + { + name: "Meteor.js", + route: "guide/meteor", + }, + { + name: "Gatsby", + route: "guide/gatsby", + }, + { + name: "Solid.js", + route: "guide/solid", + }, + { + name: "Qwik", + route: "guide/qwik", + }, + { + name: "Symfony", + route: "guide/symfony", + }, + { + name: "Rails", + route: "guide/rails", + }, + { + name: "Phoenix", + route: "guide/phoenix", + }, + { + name: "Django", + route: "guide/django", + }, + { + name: "Flask", + route: "guide/flask", + }, ], }, { From 51ece050958e241fbcbe536926cff881fd25c90b Mon Sep 17 00:00:00 2001 From: sanam453 Date: Mon, 18 Dec 2023 21:17:16 +0430 Subject: [PATCH 19/38] Material Tailwind Reac Docs Update --- documentation/html/accordion.mdx | 2 +- documentation/html/alert.mdx | 2 +- documentation/html/dialog.mdx | 34 +++++++++--------- documentation/html/installation.mdx | 10 +++--- documentation/html/menu.mdx | 24 ++++++------- documentation/html/popover.mdx | 56 ++++++++++++++--------------- documentation/html/tooltip.mdx | 56 ++++++++++++++--------------- 7 files changed, 92 insertions(+), 92 deletions(-) diff --git a/documentation/html/accordion.mdx b/documentation/html/accordion.mdx index 89eb12dcc..9bfc67c30 100644 --- a/documentation/html/accordion.mdx +++ b/documentation/html/accordion.mdx @@ -21,7 +21,7 @@ Use our Tailwind CSS accordion component to allow the user to show and hide sect See below our simple and versatile accordion example that you can use in your Tailwind CSS projects. We also included some accordion props that are available. -To use an accordion example that has items expanded, add the .open class on the .collapse `
`. +To use an accordion example that has items expanded, add the .open class on the .collapse `
`.
diff --git a/documentation/html/alert.mdx b/documentation/html/alert.mdx index b808bd692..fd1664894 100644 --- a/documentation/html/alert.mdx +++ b/documentation/html/alert.mdx @@ -233,7 +233,7 @@ You can add any element you want for the Alert component, below is a example of ## Alert Dismissible -You can make an alert dismissible by adding the data-dismissible="{`alertName`}" data attribute to the alert element and the data-dismissible-target="{`alertName`}" data attribute to the element that you want to close the alert with. +You can make an alert dismissible by adding the data-dismissible="alertName" data attribute to the alert element and the data-dismissible-target="{`alertName`}" data attribute to the element that you want to close the alert with.
@@ -119,7 +119,7 @@ You can set the size of the dialog by your own using the tailwind css classes, c
@@ -150,7 +150,7 @@ You can set the size of the dialog by your own using the tailwind css classes, c
@@ -158,23 +158,23 @@ You can set the size of the dialog by your own using the tailwind css classes, c class="relative m-4 w-2/5 min-w-[40%] max-w-[40%] rounded-lg bg-white font-sans text-base font-light leading-relaxed text-blue-gray-500 antialiased shadow-2xl">
- {`Its a simple dialog.`} + Its a simple dialog.
- {`The key to more success is to have a lot of pillows. Put it this way, it took me + The key to more success is to have a lot of pillows. Put it this way, it took me twenty five years to get these plants, twenty five years of blood sweat and tears, and I'm never giving up, I'm just getting started. I'm up to something. Fan - luv.`} + luv.
@@ -183,7 +183,7 @@ You can set the size of the dialog by your own using the tailwind css classes, c
@@ -214,7 +214,7 @@ You can set the size of the dialog by your own using the tailwind css classes, c
@@ -245,7 +245,7 @@ You can set the size of the dialog by your own using the tailwind css classes, c
@@ -253,23 +253,23 @@ You can set the size of the dialog by your own using the tailwind css classes, c class="relative h-screen w-screen min-w-[100vw] max-w-[100vw] bg-white font-sans text-base font-light leading-relaxed text-blue-gray-500 antialiased">
- {`Its a simple dialog.`} + Its a simple dialog.
- {`The key to more success is to have a lot of pillows. Put it this way, it took me + The key to more success is to have a lot of pillows. Put it this way, it took me twenty five years to get these plants, twenty five years of blood sweat and tears, and I'm never giving up, I'm just getting started. I'm up to something. Fan - luv.`} + luv.
@@ -293,7 +293,7 @@ You can modify the open/close state animation for dialog by adding the - {`Open Dialog`} + Open Dialog
diff --git a/documentation/html/installation.mdx b/documentation/html/installation.mdx index 7115d2185..f122d4f24 100644 --- a/documentation/html/installation.mdx +++ b/documentation/html/installation.mdx @@ -161,17 +161,17 @@ Now you're good to go and use @material-tailwind/html in your project. - {`Button`} + Button } > ```html ``` @@ -69,40 +69,40 @@ You can created nested/multi-level menus by setting the - {`Open Nested Menu`} + Open Nested Menu ``` diff --git a/documentation/html/popover.mdx b/documentation/html/popover.mdx index 81108d172..280df533e 100644 --- a/documentation/html/popover.mdx +++ b/documentation/html/popover.mdx @@ -37,11 +37,11 @@ You can initialize a new popover by adding the data-popover-target="` ```html
- {`This is a very beautiful popover, show some love.`} + This is a very beautiful popover, show some love.
```
@@ -61,105 +61,105 @@ You can change the position of the popover relative to it's trigger element by a
- {`This is a very beautiful popover, show some love.`} + This is a very beautiful popover, show some love.
- {`This is a very beautiful popover, show some love.`} + This is a very beautiful popover, show some love.
- {`This is a very beautiful popover, show some love.`} + This is a very beautiful popover, show some love.
- {`This is a very beautiful popover, show some love.`} + This is a very beautiful popover, show some love.
- {`This is a very beautiful popover, show some love.`} + This is a very beautiful popover, show some love.
- {`This is a very beautiful popover, show some love.`} + This is a very beautiful popover, show some love.
- {`This is a very beautiful popover, show some love.`} + This is a very beautiful popover, show some love.
- {`This is a very beautiful popover, show some love.`} + This is a very beautiful popover, show some love.
- {`This is a very beautiful popover, show some love.`} + This is a very beautiful popover, show some love.
- {`This is a very beautiful popover, show some love.`} + This is a very beautiful popover, show some love.
- {`This is a very beautiful popover, show some love.`} + This is a very beautiful popover, show some love.
- {`This is a very beautiful popover, show some love.`} + This is a very beautiful popover, show some love.
``` @@ -179,13 +179,13 @@ You can modify the open/close state animation for popover by adding the - {`POPOVER`} + POPOVER
- {`This is a very beautiful popover, show some love.`} + This is a very beautiful popover, show some love.
``` diff --git a/documentation/html/tooltip.mdx b/documentation/html/tooltip.mdx index e86065c8a..9a1194e30 100644 --- a/documentation/html/tooltip.mdx +++ b/documentation/html/tooltip.mdx @@ -35,11 +35,11 @@ You can initialize a new tooltip by adding the data-tooltip-target="` ```html
- {`Material Tailwind`} + Material Tailwind
``` @@ -59,105 +59,105 @@ You can change the position of the tooltip relative to it's trigger element by a
- {`Material Tailwind`} + Material Tailwind
- {`Material Tailwind`} + Material Tailwind
- {`Material Tailwind`} + Material Tailwind
- {`Material Tailwind`} + Material Tailwind
- {`Material Tailwind`} + Material Tailwind
- {`Material Tailwind`} + Material Tailwind
- {`Material Tailwind`} + Material Tailwind
- {`Material Tailwind`} + Material Tailwind
- {`Material Tailwind`} + Material Tailwind
- {`Material Tailwind`} + Material Tailwind
- {`Material Tailwind`} + Material Tailwind
- {`Material Tailwind`} + Material Tailwind
``` @@ -177,13 +177,13 @@ You can modify the open/close state animation for tooltip by adding the - {`Show Tooltip`} + Show Tooltip
- {`Material Tailwind`} + Material Tailwind
``` From 125fae5b6243cc06408c65b5d08d7bc30e81eae3 Mon Sep 17 00:00:00 2001 From: Maisam Afshar Date: Tue, 19 Dec 2023 00:11:48 +0330 Subject: [PATCH 20/38] remove extra import from the code --- documentation/html/guide/laravel.mdx | 2 -- 1 file changed, 2 deletions(-) diff --git a/documentation/html/guide/laravel.mdx b/documentation/html/guide/laravel.mdx index 3c9e87426..380a92e9e 100644 --- a/documentation/html/guide/laravel.mdx +++ b/documentation/html/guide/laravel.mdx @@ -57,7 +57,6 @@ export default { "./resources/**/*.blade.php", "./resources/**/*.js", "./resources/**/*.vue", - "./node_modules/flowbite/**/*.js", ], theme: { extend: {}, @@ -129,7 +128,6 @@ export default withMT({ "./resources/**/*.blade.php", "./resources/**/*.js", "./resources/**/*.vue", - "./node_modules/flowbite/**/*.js", ], theme: { extend: {}, From 0f3e8695337071c7d9269272c4e5d00f25dbb930 Mon Sep 17 00:00:00 2001 From: sajadevo Date: Tue, 19 Dec 2023 11:53:12 +0430 Subject: [PATCH 21/38] update docs pages --- documentation/html/accordion.mdx | 2 +- documentation/html/alert.mdx | 4 ++-- documentation/html/breadcrumbs.mdx | 2 +- documentation/html/button.mdx | 10 +++++----- documentation/html/chip.mdx | 2 +- documentation/html/colors.mdx | 4 ++-- documentation/html/dialog.mdx | 12 ++++++------ documentation/html/fonts.mdx | 2 +- documentation/html/icon-button.mdx | 2 +- documentation/html/installation.mdx | 13 +++++++------ documentation/html/menu.mdx | 4 ++-- documentation/html/popover.mdx | 14 +++++++------- documentation/html/screens.mdx | 4 ++-- documentation/html/shadows.mdx | 4 ++-- documentation/html/tabs.mdx | 2 +- documentation/html/theming.mdx | 8 ++++---- documentation/html/tooltip.mdx | 14 +++++++------- 17 files changed, 52 insertions(+), 51 deletions(-) diff --git a/documentation/html/accordion.mdx b/documentation/html/accordion.mdx index 9bfc67c30..e22364f01 100644 --- a/documentation/html/accordion.mdx +++ b/documentation/html/accordion.mdx @@ -104,7 +104,7 @@ To use an accordion example that has items expanded, add the .open ## Custom Accordion Icon -You can use custom icons for the accordion trigger element and using the group-open attribute selector in tailwind css you can control the icon for open and close states of accordion. +You can use custom icons for the accordion trigger element and using the group-open attribute selector in tailwind css you can control the icon for open and close states of accordion. i
tag. +You can add an icon at the beginning of alert component using the i tag. data-dismissible="alertName"
data attribute to the alert element and the data-dismissible-target="{`alertName`}" data attribute to the element that you want to close the alert with. +You can make an alert dismissible by adding the data-dismissible="alertName" data attribute to the alert element and the data-dismissible-target="{`alertName`}" data attribute to the element that you want to close the alert with. w-full
class. +A breadcrumbs could be a block level component as well that get's all the available space in a row. You can display a breadcrumbs as a block level element using the w-full class. w-full
class. +A button could be a block-level component as well that gets all the available space in a row. You can render a button as a block-level element using the w-full class. rounded-full
class with Button to create rounded buttons. +You can use tailwind css rounded-full class with Button to create rounded buttons. rounded-full class with Button to cre ### Button With Link -You can wrap Button component with {``} tag to make it a link. +You can wrap Button component with {``} tag to make it a link. Button component with {``} t ## Button Ripple Effect -You can turn on/off the ripple effect for the button component by changing data-ripple-light or data-ripple-dark data attributes to true/false. +You can turn on/off the ripple effect for the button component by changing data-ripple-light or data-ripple-dark data attributes to true/false. Button to create beautiful buttons for different purposes, below you can use some button examples used for authentication with social media and web 3.0. +You can use tailwind css classes with Button to create beautiful buttons for different purposes, below you can use some button examples used for authentication with social media and web 3.0. data-dismissible="{`chipName`}" data attribute to the chip element and the data-dismissible-target="{`chipName`}" data attribute to the element that you want to close the chip with. +You can make a chip dismissible by adding the data-dismissible="{`chipName`}" data attribute to the chip element and the data-dismissible-target="{`chipName`}" data attribute to the element that you want to close the chip with. colors object for the tailwind.config.js file. +You just need to modify the colors object for the tailwind.config.js file. ```js module.exports = withMT({ @@ -338,7 +338,7 @@ module.exports = withMT({ You can add new color to @material-tailwind/html color palette very easy and straightforward, it's the same as adding new color for tailwindcss. -You just need to add your own color to the extend and colors object for tailwind.config.js file. +You just need to add your own color to the extend and colors object for tailwind.config.js file. ```js {5-16} module.exports = withMT({ diff --git a/documentation/html/dialog.mdx b/documentation/html/dialog.mdx index 521a4dae5..5b0ab9268 100644 --- a/documentation/html/dialog.mdx +++ b/documentation/html/dialog.mdx @@ -27,9 +27,9 @@ A dialog is a type of modal window with critical information which disable all a See below our dialog example that you can use for your Tailwind CSS project. -You can initialize a new dialog by adding the data-dialog-target="`{dialog}`" data attribute to the trigger element, the data-dialog-backdrop="`{dialogName}`" to the backdrop element and the
data-dialog="`{dialogName}`" to the dialog element itself and make sure that the values for those data attributes are the same. +You can initialize a new dialog by adding the data-dialog-target="`{dialog}`" data attribute to the trigger element, the data-dialog-backdrop="`{dialogName}`" to the backdrop element and the
data-dialog="`{dialogName}`" to the dialog element itself and make sure that the values for those data attributes are the same. -You can also use the data-dialog-close="true" for the element that you want to close the dialog with when clicking. +You can also use the data-dialog-close="true" for the element that you want to close the dialog with when clicking.
@@ -282,7 +282,7 @@ You can set the size of the dialog by your own using the tailwind css classes, c ## Custom Dialog Animation -You can modify the open/close state animation for dialog by adding the data-dialog-mount="`{opacity-100}`", data-dialog-unmount="`{opacity-0}`" and data-dialog-transition="`{transition-opacity}`" data attributes to the dialog element. You can pass tailwind css classnames for those data attributes for animating the dialog.
Check more about animation data attributes for dialog
here. +You can modify the open/close state animation for dialog by adding the data-dialog-mount="`{opacity-100}`", data-dialog-unmount="`{opacity-0}`" and data-dialog-transition="`{transition-opacity}`" data attributes to the dialog element. You can pass tailwind css classnames for those data attributes for animating the dialog.
Check more about animation data attributes for dialog here. dialog trigger and backdrop elements. | | -| `data-popover-mount` | Set the classnaes that should be used when the
dialog is visible. | opacity-1
translate-y-0 | -| `data-popover-unmount` | Set the classnaes that should be used when the
dialog is hidden. | opacity-0
-translate-y-14
pointer-events-none | -| `data-popover-transition` | Set the classnaes that should be used for
transition of the dialog. | transition-all
duration-300 | +| `data-popover-mount` | Set the classnaes that should be used when the
dialog is visible. | opacity-1
translate-y-0 | +| `data-popover-unmount` | Set the classnaes that should be used when the
dialog is hidden. | opacity-0
-translate-y-14
pointer-events-none | +| `data-popover-transition` | Set the classnaes that should be used for
transition of the dialog. | transition-all
duration-300 | --- diff --git a/documentation/html/fonts.mdx b/documentation/html/fonts.mdx index 0191987fc..7ab236681 100644 --- a/documentation/html/fonts.mdx +++ b/documentation/html/fonts.mdx @@ -45,7 +45,7 @@ const fontFamily = { You can customize the default font families for @material-tailwind/html very easy and straightforward, it's the same as customizing font families for tailwindcss. -You just need to customize the font family that you like through the fontFamily object for tailwind.config.js file. +You just need to customize the font family that you like through the fontFamily object for tailwind.config.js file. ```js {4} module.exports = withMT({ diff --git a/documentation/html/icon-button.mdx b/documentation/html/icon-button.mdx index 31d07a1d2..e52c9362d 100644 --- a/documentation/html/icon-button.mdx +++ b/documentation/html/icon-button.mdx @@ -255,7 +255,7 @@ Use this example to create a icon button with link element for your Tailwind CS ## Icon Button Ripple Effect -You can turn on/off the ripple effect for the icon button component by changing data-ripple-light or data-ripple-dark data attributes to true/false. +You can turn on/off the ripple effect for the icon button component by changing data-ripple-light or data-ripple-dark data attributes to true/false. -Once you install @material-tailwind/html you need to wrap your tailwind css configurations with the withMT() function coming from @material-tailwind/html/utils. +Once you install @material-tailwind/html you need to wrap your tailwind css configurations with the withMT() function coming from @material-tailwind/html/utils. ```js {1, 3, 9} const withMT = require("@material-tailwind/html/utils/withMT"); @@ -97,7 +97,7 @@ module.exports = withMT({ -@material-tailwind/html comes with a ripple effect script file same as Material Design ripple effect and you can simply use it by adding it's CDN link to you project and add the data-ripple-light="true" for light ripple effect and data-ripple-dark="true" for dark ripple effect as an attribute for components +@material-tailwind/html comes with a ripple effect script file same as Material Design ripple effect and you can simply use it by adding it's CDN link to you project and add the data-ripple-light="true" for light ripple effect and data-ripple-dark="true" for dark ripple effect as an attribute for components The ripple effect used in @material-tailwind/html is a separate package called material-ripple-effect @@ -161,20 +161,21 @@ Now you're good to go and use @material-tailwind/html in your project. Button } > - ```html +```html - ``` +``` diff --git a/documentation/html/menu.mdx b/documentation/html/menu.mdx index adba14c25..7198e90db 100644 --- a/documentation/html/menu.mdx +++ b/documentation/html/menu.mdx @@ -23,7 +23,7 @@ A menu displays a list of choices on temporary surfaces. It appears when users i See below our menu examples that you can use in your Tailwind CSS project. The example comes in different colors and styles, so you can adapt them easily to your needs. -To create a menu you can use the data-popover-target="`{menuName}`" and data-popover="`{menuName}`" data attributes. +To create a menu you can use the data-popover-target="`{menuName}`" and data-popover="`{menuName}`" data attributes.
@@ -59,7 +59,7 @@ To create a menu you can use the data-popover-nested="true" data attribure to the menu trigger element. +You can created nested/multi-level menus by setting the data-popover-nested="true" data attribure to the menu trigger element. -You can initialize a new popover by adding the data-popover-target="`{popoverName}`" data attribute to the trigger element and the data-popover="`{popoverName}`" to the element that you want to use as the popover. +You can initialize a new popover by adding the data-popover-target="`{popoverName}`" data attribute to the trigger element and the data-popover="`{popoverName}`" to the element that you want to use as the popover. data-popover-target="` ## Popover Placement -You can change the position of the popover relative to it's trigger element by adding the data-popover-placement="`{top}`" data attribute to the popover element by default it set's to top.
Check the placement values for popover here. +You can change the position of the popover relative to it's trigger element by adding the data-popover-placement="`{top}`" data attribute to the popover element by default it set's to top.
Check the placement values for popover here. data-popover-mount="`{opacity-100}`", data-popover-unmount="`{opacity-0}`" and data-popover-transition="`{transition-opacity}`" data attributes to the popover element. You can pass tailwind css classnames for those data attributes for animation the popover.
Check more about animation data attributes for popover here. +You can modify the open/close state animation for popover by adding the data-popover-mount="`{opacity-100}`", data-popover-unmount="`{opacity-0}`" and data-popover-transition="`{transition-opacity}`" data attributes to the popover element. You can pass tailwind css classnames for those data attributes for animation the popover.
Check more about animation data attributes for popover here. popover trigger element. | | | `data-popover-offset` | Set the offset between the popover and the popover trigger element. | 5 | -| `data-popover-placement` | Set the position of the popover relative to it's trigger element. | top | -| `data-popover-mount` | Set the classnaes that should be used when the
popover is visible. | opacity-1 | -| `data-popover-unmount` | Set the classnaes that should be used when the
popover is hidden. | opacity-0
pointer-events-none | -| `data-popover-transition` | Set the classnaes that should be used for
transition of the popover. | transition-opacity
duration-300 | +| `data-popover-placement` | Set the position of the popover relative to it's trigger element. | top | +| `data-popover-mount` | Set the classnaes that should be used when the
popover is visible. | opacity-1 | +| `data-popover-unmount` | Set the classnaes that should be used when the
popover is hidden. | opacity-0
pointer-events-none | +| `data-popover-transition` | Set the classnaes that should be used for
transition of the popover. | transition-opacity
duration-300 | --- diff --git a/documentation/html/screens.mdx b/documentation/html/screens.mdx index 68b201ea4..9c94cb9d8 100644 --- a/documentation/html/screens.mdx +++ b/documentation/html/screens.mdx @@ -40,7 +40,7 @@ const screens = { You can customize the default breakpoints for @material-tailwind/html very easy and straightforward, it's the same as customizing breakpoints for tailwindcss. -You just need to customize the breakpoint that you like through the screens object for tailwind.config.js file. +You just need to customize the breakpoint that you like through the screens object for tailwind.config.js file. ```js {4} module.exports = withMT({ @@ -61,7 +61,7 @@ module.exports = withMT({ You can add new breakpoint for @material-tailwind/html very easy and straightforward, it's the same as adding new breakpoint for tailwindcss. -You just need to add your own breakpoint to the extend and screens object for tailwind.config.js file. +You just need to add your own breakpoint to the extend and screens object for tailwind.config.js file. ```js {5} module.exports = withMT({ diff --git a/documentation/html/shadows.mdx b/documentation/html/shadows.mdx index 8159c7a6b..59afb7d7f 100644 --- a/documentation/html/shadows.mdx +++ b/documentation/html/shadows.mdx @@ -42,7 +42,7 @@ const boxShadow = { You can customize the default box shadow values for @material-tailwind/html very easy and straightforward, it's the same as customizing box shadow values for tailwindcss. -You just need to customize the box shadow value that you like through the boxShadow object for tailwind.config.js file. +You just need to customize the box shadow value that you like through the boxShadow object for tailwind.config.js file. ```js {4} module.exports = withMT({ @@ -63,7 +63,7 @@ module.exports = withMT({ You can add new box shadow value for @material-tailwind/html very easy and straightforward, it's the same as adding new box shadow value for tailwindcss. -You just need to add your own box shadow value to the extend and boxShadow object for tailwind.config.js file. +You just need to add your own box shadow value to the extend and boxShadow object for tailwind.config.js file. ```js {5} module.exports = withMT({ diff --git a/documentation/html/tabs.mdx b/documentation/html/tabs.mdx index 95adba07f..eaa091f5a 100644 --- a/documentation/html/tabs.mdx +++ b/documentation/html/tabs.mdx @@ -135,7 +135,7 @@ The tabs component comes with different variants including icons. ## Tabs with Content -You can reference a specific content for each tab option, using the data-tab-content data attribute. +You can reference a specific content for each tab option, using the data-tab-content data attribute. tailwind.config.js and you can set your own theme and styles through the Tailwind CSS configurations for all of the components. +@material-tailwind/html is customizable using the tailwind.config.js and you can set your own theme and styles through the Tailwind CSS configurations for all of the components. --- @@ -22,11 +22,11 @@ style. -Each component has a class attribute that you can use to add tailwindcss classnames or your own custom classnames. +Each component has a class attribute that you can use to add tailwindcss classnames or your own custom classnames. -The class attribute overrides the tailwindcss classnames for a component and sometimes you need to use the ! modifier before the tailwindcss classnames to override the classnames for a component. +The class attribute overrides the tailwindcss classnames for a component and sometimes you need to use the ! modifier before the tailwindcss classnames to override the classnames for a component. -e.g. !text-blue-500 +e.g. !text-blue-500 ```html +
+ ); +} diff --git a/docs-content/react/plugins/clipboard/clipboard-copy-input.tsx b/docs-content/react/plugins/clipboard/clipboard-copy-input.tsx new file mode 100644 index 000000000..1c2145921 --- /dev/null +++ b/docs-content/react/plugins/clipboard/clipboard-copy-input.tsx @@ -0,0 +1,51 @@ +import React from "react"; +import { Input, Typography, Button } from "@material-tailwind/react"; +import { useCopyToClipboard } from "usehooks-ts"; +import { CheckIcon, DocumentDuplicateIcon } from "@heroicons/react/24/outline"; + +export function ClipboardCopyInput() { + const [value, copy] = useCopyToClipboard(); + const [copied, setCopied] = React.useState(false); + const [inputValue, setInputValue] = React.useState( + "npm i @material-tailwind", + ); + + return ( +
+
+ { + setInputValue(e.target.value); + }} + containerProps={{ className: "min-w-[100px]" }} + /> +
+ +
+ ); +} diff --git a/docs-content/react/plugins/clipboard/clipboard-default.tsx b/docs-content/react/plugins/clipboard/clipboard-default.tsx new file mode 100644 index 000000000..638c2fcfe --- /dev/null +++ b/docs-content/react/plugins/clipboard/clipboard-default.tsx @@ -0,0 +1,30 @@ +import React from "react"; +import { IconButton, Typography } from "@material-tailwind/react"; +import { useCopyToClipboard } from "usehooks-ts"; +import { CheckIcon, DocumentDuplicateIcon } from "@heroicons/react/24/outline"; + +export function ClipboardDefault() { + const [value, copy] = useCopyToClipboard(); + const [copied, setCopied] = React.useState(false); + + return ( +
+
+ npm i @material-tailwind + setCopied(false)} + onClick={() => { + copy("npm i @material-tailwind"); + setCopied(true); + }} + > + {copied ? ( + + ) : ( + + )} + +
+
+ ); +} diff --git a/docs-content/react/plugins/clipboard/clipboard-with-tooltip.tsx b/docs-content/react/plugins/clipboard/clipboard-with-tooltip.tsx new file mode 100644 index 000000000..a87f667e9 --- /dev/null +++ b/docs-content/react/plugins/clipboard/clipboard-with-tooltip.tsx @@ -0,0 +1,40 @@ +import React from "react"; +import { Input, Typography, Button, Tooltip } from "@material-tailwind/react"; +import { useCopyToClipboard } from "usehooks-ts"; +import { CheckIcon, DocumentDuplicateIcon } from "@heroicons/react/24/outline"; + +export function ClipboardWithTooltip() { + const [value, copy] = useCopyToClipboard(); + const [copied, setCopied] = React.useState(false); + + return ( +
+ + + +
+ ); +} diff --git a/docs-content/react/plugins/index.ts b/docs-content/react/plugins/index.ts index 891531dba..311a95318 100644 --- a/docs-content/react/plugins/index.ts +++ b/docs-content/react/plugins/index.ts @@ -3,3 +3,7 @@ export * from "./algolia-search"; export * from "./charts/line-chart"; export * from "./charts/bar-chart"; export * from "./charts/pie-chart"; +export * from "./clipboard/clipboard-default"; +export * from "./clipboard/clipboard-copy-input"; +export * from "./clipboard/clipboard-copy-button"; +export * from "./clipboard/clipboard-with-tooltip"; diff --git a/documentation/react/gallery.mdx b/documentation/react/gallery.mdx index 92af79ce8..2c8ca7b25 100644 --- a/documentation/react/gallery.mdx +++ b/documentation/react/gallery.mdx @@ -196,7 +196,7 @@ export function MasonryGridGallery() { -## Featured Image Galery - React +## Featured Image Galery
@@ -262,7 +262,7 @@ export function FeaturedImageGallery() { -## Quad Galery - React +## Quad Galery
@@ -309,7 +309,7 @@ export function QuadGallery() { -## Gallery With Carousel - React +## Gallery With Carousel
diff --git a/documentation/react/mega-menu.mdx b/documentation/react/mega-menu.mdx new file mode 100644 index 000000000..7b62f6cce --- /dev/null +++ b/documentation/react/mega-menu.mdx @@ -0,0 +1,724 @@ +--- +title: Tailwind CSS Mega Menu for React - Material Tailwind +description: Customise your web projects with our mega menu component for Tailwind CSS and React using Material Design guidelines. +navigation: + [ + "mega-menu", + "mega-menu-with-hover", + "mage-menu-placement", + + ] +github: menu +prev: input +next: navbar +--- + + +# Tailwind CSS Mega Menu - React + + +Use our responsive Tailwind CSS Mega Menu, that can take the user anywhere on your web app! + + +See below our Mega Menu example that you can use in your Tailwind CSS and React project. + +
+ +}> +```jsx +import React from "react"; +import { + Navbar, + Collapse, + Typography, + IconButton, + List, + ListItem, + Menu, + MenuHandler, + MenuList, + MenuItem, +} from "@material-tailwind/react"; +import { + ChevronDownIcon, + Bars3Icon, + XMarkIcon, +} from "@heroicons/react/24/outline"; +import { + Bars4Icon, + GlobeAmericasIcon, + NewspaperIcon, + PhoneIcon, + RectangleGroupIcon, + SquaresPlusIcon, + SunIcon, + TagIcon, + UserGroupIcon, +} from "@heroicons/react/24/solid"; + +const navListMenuItems = [ + { + title: "Products", + description: "Find the perfect solution for your needs.", + icon: SquaresPlusIcon, + }, + { + title: "About Us", + description: "Meet and learn about our dedication", + icon: UserGroupIcon, + }, + { + title: "Blog", + description: "Find the perfect solution for your needs.", + icon: Bars4Icon, + }, + { + title: "Services", + description: "Learn how we can help you achieve your goals.", + icon: SunIcon, + }, + { + title: "Support", + description: "Reach out to us for assistance or inquiries", + icon: GlobeAmericasIcon, + }, + { + title: "Contact", + description: "Find the perfect solution for your needs.", + icon: PhoneIcon, + }, + { + title: "News", + description: "Read insightful articles, tips, and expert opinions.", + icon: NewspaperIcon, + }, + { + title: "Products", + description: "Find the perfect solution for your needs.", + icon: RectangleGroupIcon, + }, + { + title: "Special Offers", + description: "Explore limited-time deals and bundles", + icon: TagIcon, + }, +]; + +function NavListMenu() { + const [isMenuOpen, setIsMenuOpen] = React.useState(false); + const [isMobileMenuOpen, setIsMobileMenuOpen] = React.useState(false); + const renderItems = navListMenuItems.map( + ({ icon, title, description }, key) => ( + + +
+ {" "} + {React.createElement(icon, { + strokeWidth: 2, + className: "h-6 text-gray-900 w-6", + })} +
+
+ + {title} + + + {description} + +
+
+
+ ), + ); + + return ( + + + + + setIsMobileMenuOpen((cur) => !cur)} + > + Resources + + + + + + +
    + {renderItems} +
+
+
+
+ {renderItems} +
+
+ ); +} + +function NavList() { + return ( + + + Home + + + + + Contact Us + + + + ); +} + +export function MegaMenuDefault() { + const [openNav, setOpenNav] = React.useState(false); + + React.useEffect(() => { + window.addEventListener( + "resize", + () => window.innerWidth >= 960 && setOpenNav(false), + ); + }, []); + + return ( + +
+ + Material Tailwind + +
+ +
+ setOpenNav(!openNav)} + > + {openNav ? ( + + ) : ( + + )} + +
+ + + +
+ ); +} +``` +
+ +--- + + + +## Mega Menu With Hover + + +The default trigger mode is click, you can change it hover by changing allowHover props. + +}> +```jsx +import React from "react"; +import { + Navbar, + Collapse, + Typography, + IconButton, + List, + ListItem, + Menu, + MenuHandler, + MenuList, + MenuItem, +} from "@material-tailwind/react"; +import { + ChevronDownIcon, + Bars3Icon, + XMarkIcon, +} from "@heroicons/react/24/outline"; +import { + Bars4Icon, + GlobeAmericasIcon, + NewspaperIcon, + PhoneIcon, + RectangleGroupIcon, + SquaresPlusIcon, + SunIcon, + TagIcon, + UserGroupIcon, +} from "@heroicons/react/24/solid"; + +const navListMenuItems = [ + { + title: "Products", + description: "Find the perfect solution for your needs.", + icon: SquaresPlusIcon, + }, + { + title: "About Us", + description: "Meet and learn about our dedication", + icon: UserGroupIcon, + }, + { + title: "Blog", + description: "Find the perfect solution for your needs.", + icon: Bars4Icon, + }, + { + title: "Services", + description: "Learn how we can help you achieve your goals.", + icon: SunIcon, + }, + { + title: "Support", + description: "Reach out to us for assistance or inquiries", + icon: GlobeAmericasIcon, + }, + { + title: "Contact", + description: "Find the perfect solution for your needs.", + icon: PhoneIcon, + }, + { + title: "News", + description: "Read insightful articles, tips, and expert opinions.", + icon: NewspaperIcon, + }, + { + title: "Products", + description: "Find the perfect solution for your needs.", + icon: RectangleGroupIcon, + }, + { + title: "Special Offers", + description: "Explore limited-time deals and bundles", + icon: TagIcon, + }, +]; + +function NavListMenu() { + const [isMenuOpen, setIsMenuOpen] = React.useState(false); + const [isMobileMenuOpen, setIsMobileMenuOpen] = React.useState(false); + const renderItems = navListMenuItems.map( + ({ icon, title, description }, key) => ( + + +
+ {" "} + {React.createElement(icon, { + strokeWidth: 2, + className: "h-6 text-gray-900 w-6", + })} +
+
+ + {title} + + + {description} + +
+
+
+ ), + ); + + return ( + + + + + setIsMobileMenuOpen((cur) => !cur)} + > + Resources + + + + + + +
    + {renderItems} +
+
+
+
+ {renderItems} +
+
+ ); +} + +function NavList() { + return ( + + + Home + + + + + Contact Us + + + + ); +} + +export function MegaMenuWithHover() { + const [openNav, setOpenNav] = React.useState(false); + + React.useEffect(() => { + window.addEventListener( + "resize", + () => window.innerWidth >= 960 && setOpenNav(false), + ); + }, []); + + return ( + +
+ + Material Tailwind + +
+ +
+ setOpenNav(!openNav)} + > + {openNav ? ( + + ) : ( + + )} + +
+ + + +
+ ); +} +``` +
+ +--- + + +## Mega Menu Placement + + +You can change the position of the Mega Menu component using the placement prop. + +}> +```jsx +import React from "react"; +import { + Navbar, + Collapse, + Typography, + IconButton, + List, + ListItem, + Menu, + MenuHandler, + MenuList, + MenuItem, +} from "@material-tailwind/react"; +import { + ChevronDownIcon, + Bars3Icon, + XMarkIcon, +} from "@heroicons/react/24/outline"; +import { + Bars4Icon, + GlobeAmericasIcon, + PhoneIcon, + SquaresPlusIcon, + SunIcon, + UserGroupIcon, +} from "@heroicons/react/24/solid"; + +const navListMenuItems = [ + { + title: "Products", + description: "Find the perfect solution for your needs.", + icon: SquaresPlusIcon, + }, + { + title: "About Us", + description: "Meet and learn about our dedication", + icon: UserGroupIcon, + }, + { + title: "Blog", + description: "Find the perfect solution for your needs.", + icon: Bars4Icon, + }, + { + title: "Services", + description: "Learn how we can help you achieve your goals.", + icon: SunIcon, + }, + { + title: "Support", + description: "Reach out to us for assistance or inquiries", + icon: GlobeAmericasIcon, + }, + { + title: "Contact", + description: "Find the perfect solution for your needs.", + icon: PhoneIcon, + }, +]; + +function NavListMenu() { + const [isMenuOpen, setIsMenuOpen] = React.useState(false); + const [isMobileMenuOpen, setIsMobileMenuOpen] = React.useState(false); + const renderItems = navListMenuItems.map( + ({ icon, title, description }, key) => ( + + +
+ {" "} + {React.createElement(icon, { + strokeWidth: 2, + className: "h-6 text-gray-900 w-6", + })} +
+
+ + {title} + + + {description} + +
+
+
+ ), + ); + + return ( + + + + + setIsMobileMenuOpen((cur) => !cur)} + > + Resources + + + + + + +
    + {renderItems} +
+
+
+
+ {renderItems} +
+
+ ); +} + +function NavList() { + return ( + + + Home + + + + + Contact Us + + + + ); +} + +export function MegaMenuWithPlacement() { + const [openNav, setOpenNav] = React.useState(false); + + React.useEffect(() => { + window.addEventListener( + "resize", + () => window.innerWidth >= 960 && setOpenNav(false), + ); + }, []); + + return ( + +
+ + Material Tailwind + +
+ +
+ setOpenNav(!openNav)} + > + {openNav ? ( + + ) : ( + + )} + +
+ + + +
+ ); +} +``` +
+ +--- diff --git a/documentation/react/plugins/clipboard.mdx b/documentation/react/plugins/clipboard.mdx new file mode 100644 index 000000000..80f363300 --- /dev/null +++ b/documentation/react/plugins/clipboard.mdx @@ -0,0 +1,236 @@ +--- +title: Tailwind CSS Clipboard for React - Material Tailwind +description: Customise your web projects with our easy-to-use clipboard example for Tailwind CSS and React using Material Design guidelines. +navigation: + [ + "clipboard", + "clipboard-copy-input", + "clipboard-copy-button", + "clipboard-with-tooltip", + + ] +github: plugins/clipboard +prev: plugins/charts +next: plugins/date-picker +--- + + +# Tailwind CSS Clipboard - React + + +Use our Tailwind CSS Date Picker example to to facilitate the copying and pasting of data within an application. + +See below our beautiful clipboard example that you can use in your Tailwind CSS and React project. The example below is using the `usehooks-ts` libraries, make sure to install them before using the example. + +```bash +npm i usehooks-ts +``` + +
+
+ +}> +```jsx +import React from "react"; +import { IconButton, Typography } from "@material-tailwind/react"; +import { useCopyToClipboard } from "usehooks-ts"; +import { CheckIcon, DocumentDuplicateIcon } from "@heroicons/react/24/outline"; + +export function ClipboardDefault() { + const [value, copy] = useCopyToClipboard(); + const [copied, setCopied] = React.useState(false); + + return ( +
+
+ npm i @material-tailwind + setCopied(false)} + onClick={() => { + copy("npm i @material-tailwind"); + setCopied(true); + }} + > + {copied ? ( + + ) : ( + + )} + +
+
+ ); +} +``` +
+ +--- + + + +## Copy from Input + + + +}> +```jsx +import React from "react"; +import { Input, Typography, Button } from "@material-tailwind/react"; +import { useCopyToClipboard } from "usehooks-ts"; +import { CheckIcon, DocumentDuplicateIcon } from "@heroicons/react/24/outline"; + +export function ClipboardCopyInput() { + const [value, copy] = useCopyToClipboard(); + const [copied, setCopied] = React.useState(false); + const [inputValue, setInputValue] = React.useState( + "npm i @material-tailwind", + ); + + return ( +
+
+ { + setInputValue(e.target.value); + }} + containerProps={{ className: "min-w-[100px]" }} + /> +
+ +
+ ); +} +``` +
+ +--- + + + +## Copy Button + + + +}> +```jsx +import React from "react"; +import { Input, Typography, Button } from "@material-tailwind/react"; +import { useCopyToClipboard } from "usehooks-ts"; +import { CheckIcon, DocumentDuplicateIcon } from "@heroicons/react/24/outline"; + +export function ClipboardCopyButton() { + const [value, copy] = useCopyToClipboard(); + const [copied, setCopied] = React.useState(false); + + return ( +
+ +
+ ); +} +``` +
+ +--- + + + + +## Copy Button With Tooltip + + + +}> +```jsx +import React from "react"; +import { Input, Typography, Button, Tooltip } from "@material-tailwind/react"; +import { useCopyToClipboard } from "usehooks-ts"; +import { CheckIcon, DocumentDuplicateIcon } from "@heroicons/react/24/outline"; + +export function ClipboardWithTooltip() { + const [value, copy] = useCopyToClipboard(); + const [copied, setCopied] = React.useState(false); + + return ( +
+ + + +
+ ); +} +``` +
+ +--- \ No newline at end of file diff --git a/pages/docs/[...slug].tsx b/pages/docs/[...slug].tsx index b8389c702..b788501fd 100644 --- a/pages/docs/[...slug].tsx +++ b/pages/docs/[...slug].tsx @@ -77,6 +77,7 @@ import * as Plugins from "docs-content/react/plugins"; import ReleaseNotes from "docs-content/react/release-notes"; import * as SkeletonExamples from "docs-content/react/skeleton"; import * as GalleryExamples from "docs-content/react/gallery"; +import * as MegaMenuExamples from "docs-content/react/mega-menu"; // html docs content import * as HtmlPlugins from "docs-content/html/plugins"; @@ -355,6 +356,7 @@ const components = { Plugins, SkeletonExamples, GalleryExamples, + MegaMenuExamples, // html docs content HtmlPlugins, HTMLButtonExamples, diff --git a/routes/react.routes.ts b/routes/react.routes.ts index 779f02e39..332a6a9e4 100644 --- a/routes/react.routes.ts +++ b/routes/react.routes.ts @@ -179,6 +179,10 @@ export const routes = [ name: "Menu", route: "menu", }, + { + name: "Mega Menu", + route: "mega-menu", + }, { name: "Navbar", route: "navbar", @@ -277,6 +281,10 @@ export const routes = [ name: "Charts", route: "/plugins/charts", }, + { + name: "Clipboard", + route: "/plugins/clipboard", + }, { name: "Date Picker", route: "/plugins/date-picker", From 67c52cb28debf97f1ec2da0bbfc4a8df3969dc9e Mon Sep 17 00:00:00 2001 From: sajadevo Date: Tue, 19 Dec 2023 12:11:49 +0430 Subject: [PATCH 23/38] update the react installation guide --- documentation/react/installation.mdx | 60 ++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/documentation/react/installation.mdx b/documentation/react/installation.mdx index 9d88fc492..715c6a5b0 100644 --- a/documentation/react/installation.mdx +++ b/documentation/react/installation.mdx @@ -34,6 +34,66 @@ Learn how to use @material-tailwind/react components from this documentation to

+## Using NPM + +Install @material-tailwind/react as a dependency using NPM by running the following command: + + + +```bash +npm i @material-tailwind/react +``` + +--- + +## Using Yarn + +Install @material-tailwind/react as a dependency using Yarn by running the following command: + + + +```bash +yarn add @material-tailwind/react +``` + +--- + +## Using PNPM + +Install @material-tailwind/react as a dependency using PNPM by running the following command: + + + +```bash +pnpm i @material-tailwind/react +``` + +--- + +## TailwindCSS Configurations + + + +Once you install @material-tailwind/react you need to wrap your tailwind css configurations with the withMT() function coming from @material-tailwind/react/utils. + +```js {1, 3, 9} +const withMT = require("@material-tailwind/react/utils/withMT"); + +module.exports = withMT({ + content: [], + theme: { + extend: {}, + }, + plugins: [], +}); +``` + +
+ +For more guides on how to use @material-tailwind/react with different frameworks, check the Frameworks Integration section. + +--- + ## Frameworks Integration From 52b02d050fa0cc70c4942e002fb2bedfac447717 Mon Sep 17 00:00:00 2001 From: Maisam Afshar Date: Tue, 19 Dec 2023 15:26:27 +0330 Subject: [PATCH 24/38] fix script links --- documentation/html/guide/angular.mdx | 2 +- documentation/html/guide/django.mdx | 2 +- documentation/html/guide/flask.mdx | 6 +++--- documentation/html/guide/gatsby.mdx | 2 +- documentation/html/guide/laravel.mdx | 2 +- documentation/html/guide/meteor.mdx | 2 +- documentation/html/guide/next.mdx | 2 +- documentation/html/guide/nuxt.mdx | 2 +- documentation/html/guide/phoenix.mdx | 3 --- documentation/html/guide/qwik.mdx | 2 +- documentation/html/guide/react-vite.mdx | 2 +- documentation/html/guide/remix.mdx | 2 +- documentation/html/guide/solid.mdx | 2 +- documentation/html/guide/svelte.mdx | 2 +- documentation/html/guide/symfony.mdx | 2 +- documentation/html/guide/vue-vite.mdx | 2 +- 16 files changed, 17 insertions(+), 20 deletions(-) diff --git a/documentation/html/guide/angular.mdx b/documentation/html/guide/angular.mdx index 32641fc10..581ca84b6 100644 --- a/documentation/html/guide/angular.mdx +++ b/documentation/html/guide/angular.mdx @@ -112,7 +112,7 @@ The ripple effect used in @material-tailwind/html is a separate package called < ```html - +"scripts": ["./node_modules/@material-tailwind/html/scripts/ripple.js"] diff --git a/documentation/html/guide/django.mdx b/documentation/html/guide/django.mdx index 65ab0d2a1..11cb4ac2a 100644 --- a/documentation/html/guide/django.mdx +++ b/documentation/html/guide/django.mdx @@ -248,7 +248,7 @@ The ripple effect used in @material-tailwind/html is a separate package called < ```html - + diff --git a/documentation/html/guide/flask.mdx b/documentation/html/guide/flask.mdx index b549b2160..d07780982 100644 --- a/documentation/html/guide/flask.mdx +++ b/documentation/html/guide/flask.mdx @@ -192,9 +192,9 @@ module.exports = withMT({
-Start the local server by running: +Activate the environment and start the local server by running: ```bash -python app.py +. venv/bin/activate && python app.py ``` --- @@ -210,7 +210,7 @@ The ripple effect used in @material-tailwind/html is a separate package called < ```html - + diff --git a/documentation/html/guide/gatsby.mdx b/documentation/html/guide/gatsby.mdx index 30bec2743..6515ed197 100644 --- a/documentation/html/guide/gatsby.mdx +++ b/documentation/html/guide/gatsby.mdx @@ -114,7 +114,7 @@ The ripple effect used in @material-tailwind/html is a separate package called < ```html - + diff --git a/documentation/html/guide/laravel.mdx b/documentation/html/guide/laravel.mdx index 380a92e9e..3e76eaf46 100644 --- a/documentation/html/guide/laravel.mdx +++ b/documentation/html/guide/laravel.mdx @@ -149,7 +149,7 @@ The ripple effect used in @material-tailwind/html is a separate package called < ```html - + diff --git a/documentation/html/guide/meteor.mdx b/documentation/html/guide/meteor.mdx index 2031d87fa..2981e2e33 100644 --- a/documentation/html/guide/meteor.mdx +++ b/documentation/html/guide/meteor.mdx @@ -114,7 +114,7 @@ The ripple effect used in @material-tailwind/html is a separate package called < ```html - + diff --git a/documentation/html/guide/next.mdx b/documentation/html/guide/next.mdx index d00891a41..1e6fe9e16 100644 --- a/documentation/html/guide/next.mdx +++ b/documentation/html/guide/next.mdx @@ -114,7 +114,7 @@ Add the following script tag to the `/src/app/layout.js` file in your project. ```html - + diff --git a/documentation/html/guide/nuxt.mdx b/documentation/html/guide/nuxt.mdx index 2ded2e9f1..ec391d6f9 100644 --- a/documentation/html/guide/nuxt.mdx +++ b/documentation/html/guide/nuxt.mdx @@ -125,7 +125,7 @@ export default defineNuxtConfig({ script: [ { async: true, - src: "https://unpkg.com/@material-tailwind/html@latest/scripts/ripple.js", + src: "https://unpkg.com/@material-tailwind/html/scripts/ripple.js", }, ], }, diff --git a/documentation/html/guide/phoenix.mdx b/documentation/html/guide/phoenix.mdx index 4f6adeb7a..d3350e3ae 100644 --- a/documentation/html/guide/phoenix.mdx +++ b/documentation/html/guide/phoenix.mdx @@ -114,9 +114,6 @@ The ripple effect used in @material-tailwind/html is a separate package called < ```html - - - ``` diff --git a/documentation/html/guide/qwik.mdx b/documentation/html/guide/qwik.mdx index c20cf0b88..3be6d7b0c 100644 --- a/documentation/html/guide/qwik.mdx +++ b/documentation/html/guide/qwik.mdx @@ -113,7 +113,7 @@ The ripple effect used in @material-tailwind/html is a separate package called < ```html - + diff --git a/documentation/html/guide/react-vite.mdx b/documentation/html/guide/react-vite.mdx index 50bb66b0a..e492dc2d2 100644 --- a/documentation/html/guide/react-vite.mdx +++ b/documentation/html/guide/react-vite.mdx @@ -111,7 +111,7 @@ Add the following script tag to the `index.html` file in your project. ```html - + diff --git a/documentation/html/guide/remix.mdx b/documentation/html/guide/remix.mdx index d03d87923..94597f1b2 100644 --- a/documentation/html/guide/remix.mdx +++ b/documentation/html/guide/remix.mdx @@ -111,7 +111,7 @@ The ripple effect used in @material-tailwind/html is a separate package called < ```html - + diff --git a/documentation/html/guide/solid.mdx b/documentation/html/guide/solid.mdx index 98c6dfa89..c0eda7390 100644 --- a/documentation/html/guide/solid.mdx +++ b/documentation/html/guide/solid.mdx @@ -113,7 +113,7 @@ The ripple effect used in @material-tailwind/html is a separate package called < ```html - + diff --git a/documentation/html/guide/svelte.mdx b/documentation/html/guide/svelte.mdx index b60c8c2c6..1a6f12f64 100644 --- a/documentation/html/guide/svelte.mdx +++ b/documentation/html/guide/svelte.mdx @@ -112,7 +112,7 @@ Add the following script tag to the `/src/app.html` file in your project. ```html - + diff --git a/documentation/html/guide/symfony.mdx b/documentation/html/guide/symfony.mdx index 259cc8525..e03958ec9 100644 --- a/documentation/html/guide/symfony.mdx +++ b/documentation/html/guide/symfony.mdx @@ -120,7 +120,7 @@ The ripple effect used in @material-tailwind/html is a separate package called < ```html - + diff --git a/documentation/html/guide/vue-vite.mdx b/documentation/html/guide/vue-vite.mdx index b476ae225..02ccaac8c 100644 --- a/documentation/html/guide/vue-vite.mdx +++ b/documentation/html/guide/vue-vite.mdx @@ -111,7 +111,7 @@ Add the following script tag to the `index.html` file in your project. ```html - + From 07f8ed512c91d88f76d1da0f3307b15b688ce4ad Mon Sep 17 00:00:00 2001 From: Sayed Murtaza Date: Tue, 19 Dec 2023 20:41:49 +0430 Subject: [PATCH 25/38] html version --- docs-content/html/gallery/default-gallery.tsx | 69 ++ .../html/gallery/featured-image-gallery.tsx | 51 ++ .../html/gallery/gallery-with-tab.tsx | 200 +++++ docs-content/html/gallery/index.ts | 5 + .../html/gallery/masonry-grid-gallery.tsx | 91 ++ docs-content/html/gallery/quad-gallery.tsx | 34 + docs-content/html/mega-menu/index.ts | 1 + docs-content/html/mega-menu/mega-menu.tsx | 107 +++ .../clipboard/clipboard-copy-button.tsx | 38 + .../clipboard/clipboard-copy-input.tsx | 51 ++ .../plugins/clipboard/clipboard-default.tsx | 30 + .../clipboard/clipboard-with-tooltip.tsx | 40 + docs-content/html/plugins/index.ts | 1 + .../skeleton/card-placeholder-skeleton.tsx | 33 + .../html/skeleton/default-skeleton.tsx | 15 + .../skeleton/image-placeholder-skeleton.tsx | 28 + docs-content/html/skeleton/index.ts | 6 + .../testimonial-placeholder-skeleton.tsx | 25 + .../skeleton/text-placeholder-skeleton.tsx | 35 + .../skeleton/video-placeholder-skeleton.tsx | 19 + docs-content/react/plugins/index.ts | 1 + .../react/plugins/text-editor-react.tsx | 753 +++++++++++++++++ documentation/html/gallery.mdx | 376 +++++++++ documentation/html/mega-menu.mdx | 260 ++++++ documentation/html/plugins/clipboard.mdx | 122 +++ documentation/html/skeleton.mdx | 281 +++++++ documentation/react/plugins/text-editor.mdx | 785 ++++++++++++++++++ package.json | 1 + pages/_document.tsx | 16 + pages/docs/[...slug].tsx | 6 + public/images/icons/arrow-clockwise.svg | 4 + .../images/icons/arrow-counterclockwise.svg | 4 + public/images/icons/chat-square-quote.svg | 4 + public/images/icons/chevron-down.svg | 3 + public/images/icons/code.svg | 3 + public/images/icons/journal-code.svg | 5 + public/images/icons/journal-text.svg | 5 + public/images/icons/justify.svg | 3 + public/images/icons/link.svg | 4 + public/images/icons/list-ol.svg | 4 + public/images/icons/list-ul.svg | 3 + public/images/icons/markdown.svg | 1 + public/images/icons/pencil-fill.svg | 3 + public/images/icons/text-center.svg | 3 + public/images/icons/text-left.svg | 3 + public/images/icons/text-paragraph.svg | 3 + public/images/icons/text-right.svg | 3 + public/images/icons/type-bold.svg | 3 + public/images/icons/type-h1.svg | 3 + public/images/icons/type-h2.svg | 3 + public/images/icons/type-h3.svg | 3 + public/images/icons/type-italic.svg | 3 + public/images/icons/type-strikethrough.svg | 3 + public/images/icons/type-underline.svg | 3 + routes/html.routes.ts | 16 + routes/react.routes.ts | 4 + styles/globals.css | 706 ++++++++++++++++ 57 files changed, 4285 insertions(+) create mode 100644 docs-content/html/gallery/default-gallery.tsx create mode 100644 docs-content/html/gallery/featured-image-gallery.tsx create mode 100644 docs-content/html/gallery/gallery-with-tab.tsx create mode 100644 docs-content/html/gallery/index.ts create mode 100644 docs-content/html/gallery/masonry-grid-gallery.tsx create mode 100644 docs-content/html/gallery/quad-gallery.tsx create mode 100644 docs-content/html/mega-menu/index.ts create mode 100644 docs-content/html/mega-menu/mega-menu.tsx create mode 100644 docs-content/html/plugins/clipboard/clipboard-copy-button.tsx create mode 100644 docs-content/html/plugins/clipboard/clipboard-copy-input.tsx create mode 100644 docs-content/html/plugins/clipboard/clipboard-default.tsx create mode 100644 docs-content/html/plugins/clipboard/clipboard-with-tooltip.tsx create mode 100644 docs-content/html/skeleton/card-placeholder-skeleton.tsx create mode 100644 docs-content/html/skeleton/default-skeleton.tsx create mode 100644 docs-content/html/skeleton/image-placeholder-skeleton.tsx create mode 100644 docs-content/html/skeleton/index.ts create mode 100644 docs-content/html/skeleton/testimonial-placeholder-skeleton.tsx create mode 100644 docs-content/html/skeleton/text-placeholder-skeleton.tsx create mode 100644 docs-content/html/skeleton/video-placeholder-skeleton.tsx create mode 100644 docs-content/react/plugins/text-editor-react.tsx create mode 100644 documentation/html/gallery.mdx create mode 100644 documentation/html/mega-menu.mdx create mode 100644 documentation/html/plugins/clipboard.mdx create mode 100644 documentation/html/skeleton.mdx create mode 100644 documentation/react/plugins/text-editor.mdx create mode 100644 public/images/icons/arrow-clockwise.svg create mode 100644 public/images/icons/arrow-counterclockwise.svg create mode 100644 public/images/icons/chat-square-quote.svg create mode 100644 public/images/icons/chevron-down.svg create mode 100644 public/images/icons/code.svg create mode 100644 public/images/icons/journal-code.svg create mode 100644 public/images/icons/journal-text.svg create mode 100644 public/images/icons/justify.svg create mode 100644 public/images/icons/link.svg create mode 100644 public/images/icons/list-ol.svg create mode 100644 public/images/icons/list-ul.svg create mode 100644 public/images/icons/markdown.svg create mode 100644 public/images/icons/pencil-fill.svg create mode 100644 public/images/icons/text-center.svg create mode 100644 public/images/icons/text-left.svg create mode 100644 public/images/icons/text-paragraph.svg create mode 100644 public/images/icons/text-right.svg create mode 100644 public/images/icons/type-bold.svg create mode 100644 public/images/icons/type-h1.svg create mode 100644 public/images/icons/type-h2.svg create mode 100644 public/images/icons/type-h3.svg create mode 100644 public/images/icons/type-italic.svg create mode 100644 public/images/icons/type-strikethrough.svg create mode 100644 public/images/icons/type-underline.svg diff --git a/docs-content/html/gallery/default-gallery.tsx b/docs-content/html/gallery/default-gallery.tsx new file mode 100644 index 000000000..e8e194d38 --- /dev/null +++ b/docs-content/html/gallery/default-gallery.tsx @@ -0,0 +1,69 @@ +export function DefaultGallery() { + return ( +
+
+ gallery-photo +
+
+ gallery-photo +
+
+ gallery-photo +
+
+ gallery-photo +
+
+ gallery-photo +
+
+ gallery-photo +
+
+ gallery-photo +
+
+ gallery-photo +
+
+ gallery-photo +
+
+ ); +} diff --git a/docs-content/html/gallery/featured-image-gallery.tsx b/docs-content/html/gallery/featured-image-gallery.tsx new file mode 100644 index 000000000..72f1b88a1 --- /dev/null +++ b/docs-content/html/gallery/featured-image-gallery.tsx @@ -0,0 +1,51 @@ +import React from "react"; +export function FeaturedImageGallery() { + return ( +
+
+ +
+
+
+ gallery-image +
+
+ gallery-image +
+
+ gallery-image +
+
+ gallery-image +
+
+ gallery-image +
+
+
+ ); +} diff --git a/docs-content/html/gallery/gallery-with-tab.tsx b/docs-content/html/gallery/gallery-with-tab.tsx new file mode 100644 index 000000000..6db5111f7 --- /dev/null +++ b/docs-content/html/gallery/gallery-with-tab.tsx @@ -0,0 +1,200 @@ +export function GalleryWithTab() { + return ( +
+
+ +
+
+
+
+ image-photo +
+
+ image-photo +
+
+ image-photo +
+
+ image-photo +
+
+ image-photo +
+
+ image-photo +
+
+
+
+
+
+ image-photo +
+
+ image-photo +
+
+ image-photo +
+
+ image-photo +
+
+ image-photo +
+
+ image-photo +
+
+
+
+
+
+ image-photo +
+
+ image-photo +
+
+ image-photo +
+
+ image-photo +
+
+ image-photo +
+ +
+ image-photo +
+
+
+
+
+
+ ); +} diff --git a/docs-content/html/gallery/index.ts b/docs-content/html/gallery/index.ts new file mode 100644 index 000000000..f3fd84ad0 --- /dev/null +++ b/docs-content/html/gallery/index.ts @@ -0,0 +1,5 @@ +export * from "./default-gallery"; +export * from "./masonry-grid-gallery"; +export * from "./featured-image-gallery"; +export * from "./quad-gallery"; +export * from "./gallery-with-tab"; diff --git a/docs-content/html/gallery/masonry-grid-gallery.tsx b/docs-content/html/gallery/masonry-grid-gallery.tsx new file mode 100644 index 000000000..def3b0077 --- /dev/null +++ b/docs-content/html/gallery/masonry-grid-gallery.tsx @@ -0,0 +1,91 @@ +export function MasonryGridGallery() { + return ( +
+
+
+ gallery-photo +
+
+ gallery-photo +
+
+ gallery-photo +
+
+
+
+ gallery-photo +
+
+ gallery-photo +
+
+ gallery-photo +
+
+
+
+ gallery-photo +
+
+ gallery-photo +
+
+ gallery-photo +
+
+
+
+ gallery-photo +
+
+ gallery-photo +
+
+
+ ); +} diff --git a/docs-content/html/gallery/quad-gallery.tsx b/docs-content/html/gallery/quad-gallery.tsx new file mode 100644 index 000000000..40976d8ae --- /dev/null +++ b/docs-content/html/gallery/quad-gallery.tsx @@ -0,0 +1,34 @@ +export function QuadGallery() { + return ( +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ ); +} diff --git a/docs-content/html/mega-menu/index.ts b/docs-content/html/mega-menu/index.ts new file mode 100644 index 000000000..9a3c77c54 --- /dev/null +++ b/docs-content/html/mega-menu/index.ts @@ -0,0 +1 @@ +export * from "./mega-menu"; diff --git a/docs-content/html/mega-menu/mega-menu.tsx b/docs-content/html/mega-menu/mega-menu.tsx new file mode 100644 index 000000000..c9e0ca89d --- /dev/null +++ b/docs-content/html/mega-menu/mega-menu.tsx @@ -0,0 +1,107 @@ +export function MegaMenuDefault() { + return ( + + ); +} diff --git a/docs-content/html/plugins/clipboard/clipboard-copy-button.tsx b/docs-content/html/plugins/clipboard/clipboard-copy-button.tsx new file mode 100644 index 000000000..9f1d406ee --- /dev/null +++ b/docs-content/html/plugins/clipboard/clipboard-copy-button.tsx @@ -0,0 +1,38 @@ +import React from "react"; +import { Input, Typography, Button } from "@material-tailwind/react"; +import { useCopyToClipboard } from "usehooks-ts"; +import { CheckIcon, DocumentDuplicateIcon } from "@heroicons/react/24/outline"; + +export function ClipboardCopyButton() { + const [value, copy] = useCopyToClipboard(); + const [copied, setCopied] = React.useState(false); + + return ( +
+ +
+ ); +} diff --git a/docs-content/html/plugins/clipboard/clipboard-copy-input.tsx b/docs-content/html/plugins/clipboard/clipboard-copy-input.tsx new file mode 100644 index 000000000..1c2145921 --- /dev/null +++ b/docs-content/html/plugins/clipboard/clipboard-copy-input.tsx @@ -0,0 +1,51 @@ +import React from "react"; +import { Input, Typography, Button } from "@material-tailwind/react"; +import { useCopyToClipboard } from "usehooks-ts"; +import { CheckIcon, DocumentDuplicateIcon } from "@heroicons/react/24/outline"; + +export function ClipboardCopyInput() { + const [value, copy] = useCopyToClipboard(); + const [copied, setCopied] = React.useState(false); + const [inputValue, setInputValue] = React.useState( + "npm i @material-tailwind", + ); + + return ( +
+
+ { + setInputValue(e.target.value); + }} + containerProps={{ className: "min-w-[100px]" }} + /> +
+ +
+ ); +} diff --git a/docs-content/html/plugins/clipboard/clipboard-default.tsx b/docs-content/html/plugins/clipboard/clipboard-default.tsx new file mode 100644 index 000000000..638c2fcfe --- /dev/null +++ b/docs-content/html/plugins/clipboard/clipboard-default.tsx @@ -0,0 +1,30 @@ +import React from "react"; +import { IconButton, Typography } from "@material-tailwind/react"; +import { useCopyToClipboard } from "usehooks-ts"; +import { CheckIcon, DocumentDuplicateIcon } from "@heroicons/react/24/outline"; + +export function ClipboardDefault() { + const [value, copy] = useCopyToClipboard(); + const [copied, setCopied] = React.useState(false); + + return ( +
+
+ npm i @material-tailwind + setCopied(false)} + onClick={() => { + copy("npm i @material-tailwind"); + setCopied(true); + }} + > + {copied ? ( + + ) : ( + + )} + +
+
+ ); +} diff --git a/docs-content/html/plugins/clipboard/clipboard-with-tooltip.tsx b/docs-content/html/plugins/clipboard/clipboard-with-tooltip.tsx new file mode 100644 index 000000000..a87f667e9 --- /dev/null +++ b/docs-content/html/plugins/clipboard/clipboard-with-tooltip.tsx @@ -0,0 +1,40 @@ +import React from "react"; +import { Input, Typography, Button, Tooltip } from "@material-tailwind/react"; +import { useCopyToClipboard } from "usehooks-ts"; +import { CheckIcon, DocumentDuplicateIcon } from "@heroicons/react/24/outline"; + +export function ClipboardWithTooltip() { + const [value, copy] = useCopyToClipboard(); + const [copied, setCopied] = React.useState(false); + + return ( +
+ + + +
+ ); +} diff --git a/docs-content/html/plugins/index.ts b/docs-content/html/plugins/index.ts index d48d75738..f72c351c8 100644 --- a/docs-content/html/plugins/index.ts +++ b/docs-content/html/plugins/index.ts @@ -1 +1,2 @@ export * from "./date-picker"; +export * from "./clipboard/clipboard-default"; diff --git a/docs-content/html/skeleton/card-placeholder-skeleton.tsx b/docs-content/html/skeleton/card-placeholder-skeleton.tsx new file mode 100644 index 000000000..661a2e006 --- /dev/null +++ b/docs-content/html/skeleton/card-placeholder-skeleton.tsx @@ -0,0 +1,33 @@ +export function CardPlacehoderSkeleton() { + return ( +
+
+ +
+
+
+
+

+

+

+

+
+
+
+ +
+
+ ); +} diff --git a/docs-content/html/skeleton/default-skeleton.tsx b/docs-content/html/skeleton/default-skeleton.tsx new file mode 100644 index 000000000..a4ecad97c --- /dev/null +++ b/docs-content/html/skeleton/default-skeleton.tsx @@ -0,0 +1,15 @@ +export function DefaultSkeleton() { + return ( +
+

+

+

+

+

+

+

+ Loading... +

+
+ ); +} diff --git a/docs-content/html/skeleton/image-placeholder-skeleton.tsx b/docs-content/html/skeleton/image-placeholder-skeleton.tsx new file mode 100644 index 000000000..9a5f98fca --- /dev/null +++ b/docs-content/html/skeleton/image-placeholder-skeleton.tsx @@ -0,0 +1,28 @@ +export function ImagePlacehoderSkeleton() { + return ( +
+
+ +
+
+

+

+

+

+

+

+

+ Loading... +

+
+
+ ); +} diff --git a/docs-content/html/skeleton/index.ts b/docs-content/html/skeleton/index.ts new file mode 100644 index 000000000..200402968 --- /dev/null +++ b/docs-content/html/skeleton/index.ts @@ -0,0 +1,6 @@ +export * from "./default-skeleton"; +export * from "./image-placeholder-skeleton"; +export * from "./video-placeholder-skeleton"; +export * from "./text-placeholder-skeleton"; +export * from "./card-placeholder-skeleton"; +export * from "./testimonial-placeholder-skeleton"; diff --git a/docs-content/html/skeleton/testimonial-placeholder-skeleton.tsx b/docs-content/html/skeleton/testimonial-placeholder-skeleton.tsx new file mode 100644 index 000000000..fd284a2d7 --- /dev/null +++ b/docs-content/html/skeleton/testimonial-placeholder-skeleton.tsx @@ -0,0 +1,25 @@ +export function TestimonialPlacehoderSkeleton() { + return ( +
+

+ +

+
+ +

+

+
+

+ Loading... +

+
+ ); +} diff --git a/docs-content/html/skeleton/text-placeholder-skeleton.tsx b/docs-content/html/skeleton/text-placeholder-skeleton.tsx new file mode 100644 index 000000000..e5f4d77f5 --- /dev/null +++ b/docs-content/html/skeleton/text-placeholder-skeleton.tsx @@ -0,0 +1,35 @@ +export function TextPlacehoderSkeleton() { + return ( +
+
+

+
+
+

+

+
+
+

+

+

+
+
+

+

+

+
+
+

+

+

+
+
+

+

+
+

+ Loading... +

+
+ ); +} diff --git a/docs-content/html/skeleton/video-placeholder-skeleton.tsx b/docs-content/html/skeleton/video-placeholder-skeleton.tsx new file mode 100644 index 000000000..9dbd9a1f1 --- /dev/null +++ b/docs-content/html/skeleton/video-placeholder-skeleton.tsx @@ -0,0 +1,19 @@ +export function VideoPlacehoderSkeleton() { + return ( +
+ +

+ Loading... +

+
+ ); +} diff --git a/docs-content/react/plugins/index.ts b/docs-content/react/plugins/index.ts index 311a95318..6a1246ca8 100644 --- a/docs-content/react/plugins/index.ts +++ b/docs-content/react/plugins/index.ts @@ -7,3 +7,4 @@ export * from "./clipboard/clipboard-default"; export * from "./clipboard/clipboard-copy-input"; export * from "./clipboard/clipboard-copy-button"; export * from "./clipboard/clipboard-with-tooltip"; +export * from "./text-editor-react"; diff --git a/docs-content/react/plugins/text-editor-react.tsx b/docs-content/react/plugins/text-editor-react.tsx new file mode 100644 index 000000000..c2084a095 --- /dev/null +++ b/docs-content/react/plugins/text-editor-react.tsx @@ -0,0 +1,753 @@ +// import ExampleTheme from "./themes/ExampleTheme"; +import { LexicalComposer } from "@lexical/react/LexicalComposer"; +import { RichTextPlugin } from "@lexical/react/LexicalRichTextPlugin"; +import { ContentEditable } from "@lexical/react/LexicalContentEditable"; +import { AutoFocusPlugin } from "@lexical/react/LexicalAutoFocusPlugin"; + +import { HeadingNode, QuoteNode } from "@lexical/rich-text"; +import { TableCellNode, TableNode, TableRowNode } from "@lexical/table"; +import { ListItemNode, ListNode } from "@lexical/list"; +import { CodeHighlightNode, CodeNode } from "@lexical/code"; +import { AutoLinkNode, LinkNode } from "@lexical/link"; +import { LinkPlugin } from "@lexical/react/LexicalLinkPlugin"; +import { ListPlugin } from "@lexical/react/LexicalListPlugin"; +import { MarkdownShortcutPlugin } from "@lexical/react/LexicalMarkdownShortcutPlugin"; +import { TRANSFORMERS } from "@lexical/markdown"; + +//Toolbar Plugins +import { useLexicalComposerContext } from "@lexical/react/LexicalComposerContext"; +import { useCallback, useEffect, useMemo, useRef, useState } from "react"; +import { + SELECTION_CHANGE_COMMAND, + FORMAT_TEXT_COMMAND, + $getSelection, + $isRangeSelection, + $createParagraphNode, + $getNodeByKey, +} from "lexical"; +import { $isLinkNode, TOGGLE_LINK_COMMAND } from "@lexical/link"; +import { $wrapNodes, $isAtNodeEnd } from "@lexical/selection"; +import { $getNearestNodeOfType, mergeRegister } from "@lexical/utils"; +import { + INSERT_ORDERED_LIST_COMMAND, + INSERT_UNORDERED_LIST_COMMAND, + REMOVE_LIST_COMMAND, + $isListNode, +} from "@lexical/list"; +import { createPortal } from "react-dom"; +import { + $createHeadingNode, + $createQuoteNode, + $isHeadingNode, +} from "@lexical/rich-text"; +import { + $createCodeNode, + $isCodeNode, + getDefaultCodeLanguage, + getCodeLanguages, +} from "@lexical/code"; + +const LowPriority = 1; + +const supportedBlockTypes = new Set([ + "paragraph", + "quote", + "code", + "h1", + "h2", + "ul", + "ol", +]); + +const blockTypeToBlockName = { + code: "Code Block", + h1: "Large Heading", + h2: "Small Heading", + h3: "Heading", + h4: "Heading", + h5: "Heading", + ol: "Numbered List", + paragraph: "Normal", + quote: "Quote", + ul: "Bulleted List", +}; + +function Divider() { + return
; +} + +function positionEditorElement(editor, rect) { + if (rect === null) { + editor.style.opacity = "0"; + editor.style.top = "-1000px"; + editor.style.left = "-1000px"; + } else { + editor.style.opacity = "1"; + editor.style.top = `${rect.top + rect.height + window.pageYOffset + 10}px`; + editor.style.left = `${ + rect.left + window.pageXOffset - editor.offsetWidth / 2 + rect.width / 2 + }px`; + } +} + +function FloatingLinkEditor({ editor }) { + const editorRef = useRef(null); + const inputRef = useRef(null); + const mouseDownRef = useRef(false); + const [linkUrl, setLinkUrl] = useState(""); + const [isEditMode, setEditMode] = useState(false); + const [lastSelection, setLastSelection] = useState(null); + + const updateLinkEditor = useCallback(() => { + const selection = $getSelection(); + if ($isRangeSelection(selection)) { + const node = getSelectedNode(selection); + const parent = node.getParent(); + if ($isLinkNode(parent)) { + setLinkUrl(parent.getURL()); + } else if ($isLinkNode(node)) { + setLinkUrl(node.getURL()); + } else { + setLinkUrl(""); + } + } + const editorElem = editorRef.current; + const nativeSelection = window.getSelection(); + const activeElement = document.activeElement; + + if (editorElem === null) { + return; + } + + const rootElement = editor.getRootElement(); + if ( + selection !== null && + !nativeSelection.isCollapsed && + rootElement !== null && + rootElement.contains(nativeSelection.anchorNode) + ) { + const domRange = nativeSelection.getRangeAt(0); + let rect; + if (nativeSelection.anchorNode === rootElement) { + let inner = rootElement; + while (inner.firstElementChild != null) { + inner = inner.firstElementChild; + } + rect = inner.getBoundingClientRect(); + } else { + rect = domRange.getBoundingClientRect(); + } + + if (!mouseDownRef.current) { + positionEditorElement(editorElem, rect); + } + setLastSelection(selection); + } else if (!activeElement || activeElement.className !== "link-input") { + positionEditorElement(editorElem, null); + setLastSelection(null); + setEditMode(false); + setLinkUrl(""); + } + + return true; + }, [editor]); + + useEffect(() => { + return mergeRegister( + editor.registerUpdateListener(({ editorState }) => { + editorState.read(() => { + updateLinkEditor(); + }); + }), + + editor.registerCommand( + SELECTION_CHANGE_COMMAND, + () => { + updateLinkEditor(); + return true; + }, + LowPriority, + ), + ); + }, [editor, updateLinkEditor]); + + useEffect(() => { + editor.getEditorState().read(() => { + updateLinkEditor(); + }); + }, [editor, updateLinkEditor]); + + useEffect(() => { + if (isEditMode && inputRef.current) { + inputRef.current.focus(); + } + }, [isEditMode]); + + return ( +
+ {isEditMode ? ( + { + setLinkUrl(event.target.value); + }} + onKeyDown={(event) => { + if (event.key === "Enter") { + event.preventDefault(); + if (lastSelection !== null) { + if (linkUrl !== "") { + editor.dispatchCommand(TOGGLE_LINK_COMMAND, linkUrl); + } + setEditMode(false); + } + } else if (event.key === "Escape") { + event.preventDefault(); + setEditMode(false); + } + }} + /> + ) : ( + <> +
+ + {linkUrl} + +
event.preventDefault()} + onClick={() => { + setEditMode(true); + }} + /> +
+ + )} +
+ ); +} + +function Select({ onChange, className, options, value }) { + return ( + + ); +} + +function getSelectedNode(selection) { + const anchor = selection.anchor; + const focus = selection.focus; + const anchorNode = selection.anchor.getNode(); + const focusNode = selection.focus.getNode(); + if (anchorNode === focusNode) { + return anchorNode; + } + const isBackward = selection.isBackward(); + if (isBackward) { + return $isAtNodeEnd(focus) ? anchorNode : focusNode; + } else { + return $isAtNodeEnd(anchor) ? focusNode : anchorNode; + } +} + +function BlockOptionsDropdownList({ + editor, + blockType, + toolbarRef, + setShowBlockOptionsDropDown, +}) { + const dropDownRef = useRef(null); + + useEffect(() => { + const toolbar = toolbarRef.current; + const dropDown = dropDownRef.current; + + if (toolbar !== null && dropDown !== null) { + const { top, left } = toolbar.getBoundingClientRect(); + dropDown.style.top = `${top + 40}px`; + dropDown.style.left = `${left}px`; + } + }, [dropDownRef, toolbarRef]); + + useEffect(() => { + const dropDown = dropDownRef.current; + const toolbar = toolbarRef.current; + + if (dropDown !== null && toolbar !== null) { + const handle = (event) => { + const target = event.target; + + if (!dropDown.contains(target) && !toolbar.contains(target)) { + setShowBlockOptionsDropDown(false); + } + }; + document.addEventListener("click", handle); + + return () => { + document.removeEventListener("click", handle); + }; + } + }, [dropDownRef, setShowBlockOptionsDropDown, toolbarRef]); + + const formatParagraph = () => { + if (blockType !== "paragraph") { + editor.update(() => { + const selection = $getSelection(); + + if ($isRangeSelection(selection)) { + $wrapNodes(selection, () => $createParagraphNode()); + } + }); + } + setShowBlockOptionsDropDown(false); + }; + + const formatLargeHeading = () => { + if (blockType !== "h1") { + editor.update(() => { + const selection = $getSelection(); + + if ($isRangeSelection(selection)) { + $wrapNodes(selection, () => $createHeadingNode("h1")); + } + }); + } + setShowBlockOptionsDropDown(false); + }; + + const formatSmallHeading = () => { + if (blockType !== "h2") { + editor.update(() => { + const selection = $getSelection(); + + if ($isRangeSelection(selection)) { + $wrapNodes(selection, () => $createHeadingNode("h2")); + } + }); + } + setShowBlockOptionsDropDown(false); + }; + + const formatBulletList = () => { + if (blockType !== "ul") { + editor.dispatchCommand(INSERT_UNORDERED_LIST_COMMAND); + } else { + editor.dispatchCommand(REMOVE_LIST_COMMAND); + } + setShowBlockOptionsDropDown(false); + }; + + const formatNumberedList = () => { + if (blockType !== "ol") { + editor.dispatchCommand(INSERT_ORDERED_LIST_COMMAND); + } else { + editor.dispatchCommand(REMOVE_LIST_COMMAND); + } + setShowBlockOptionsDropDown(false); + }; + + const formatQuote = () => { + if (blockType !== "quote") { + editor.update(() => { + const selection = $getSelection(); + + if ($isRangeSelection(selection)) { + $wrapNodes(selection, () => $createQuoteNode()); + } + }); + } + setShowBlockOptionsDropDown(false); + }; + + const formatCode = () => { + if (blockType !== "code") { + editor.update(() => { + const selection = $getSelection(); + + if ($isRangeSelection(selection)) { + $wrapNodes(selection, () => $createCodeNode()); + } + }); + } + setShowBlockOptionsDropDown(false); + }; + + return ( +
+ + + + + + + +
+ ); +} + +function ToolbarPlugin() { + const [editor] = useLexicalComposerContext(); + const toolbarRef = useRef(null); + const [blockType, setBlockType] = useState("paragraph"); + const [selectedElementKey, setSelectedElementKey] = useState(null); + const [showBlockOptionsDropDown, setShowBlockOptionsDropDown] = + useState(false); + const [codeLanguage, setCodeLanguage] = useState(""); + const [isLink, setIsLink] = useState(false); + const [isBold, setIsBold] = useState(false); + const [isItalic, setIsItalic] = useState(false); + const [isUnderline, setIsUnderline] = useState(false); + const [isStrikethrough, setIsStrikethrough] = useState(false); + const [isCode, setIsCode] = useState(false); + + const updateToolbar = useCallback(() => { + const selection = $getSelection(); + if ($isRangeSelection(selection)) { + const anchorNode = selection.anchor.getNode(); + const element = + anchorNode.getKey() === "root" + ? anchorNode + : anchorNode.getTopLevelElementOrThrow(); + const elementKey = element.getKey(); + const elementDOM = editor.getElementByKey(elementKey); + if (elementDOM !== null) { + setSelectedElementKey(elementKey); + if ($isListNode(element)) { + const parentList = $getNearestNodeOfType(anchorNode, ListNode); + const type = parentList ? parentList.getTag() : element.getTag(); + setBlockType(type); + } else { + const type = $isHeadingNode(element) + ? element.getTag() + : element.getType(); + setBlockType(type); + if ($isCodeNode(element)) { + setCodeLanguage(element.getLanguage() || getDefaultCodeLanguage()); + } + } + } + // Update text format + setIsBold(selection.hasFormat("bold")); + setIsItalic(selection.hasFormat("italic")); + setIsUnderline(selection.hasFormat("underline")); + setIsStrikethrough(selection.hasFormat("strikethrough")); + setIsCode(selection.hasFormat("code")); + + // Update links + const node = getSelectedNode(selection); + const parent = node.getParent(); + if ($isLinkNode(parent) || $isLinkNode(node)) { + setIsLink(true); + } else { + setIsLink(false); + } + } + }, [editor]); + + useEffect(() => { + return mergeRegister( + editor.registerUpdateListener(({ editorState }) => { + editorState.read(() => { + updateToolbar(); + }); + }), + editor.registerCommand( + SELECTION_CHANGE_COMMAND, + (_payload, newEditor) => { + updateToolbar(); + return false; + }, + LowPriority, + ), + ); + }, [editor, updateToolbar]); + + const codeLanguges = useMemo(() => getCodeLanguages(), []); + const onCodeLanguageSelect = useCallback( + (e) => { + editor.update(() => { + if (selectedElementKey !== null) { + const node = $getNodeByKey(selectedElementKey); + if ($isCodeNode(node)) { + node.setLanguage(e.target.value); + } + } + }); + }, + [editor, selectedElementKey], + ); + + const insertLink = useCallback(() => { + if (!isLink) { + editor.dispatchCommand(TOGGLE_LINK_COMMAND, "https://"); + } else { + editor.dispatchCommand(TOGGLE_LINK_COMMAND, null); + } + }, [editor, isLink]); + + return ( +
+ {supportedBlockTypes.has(blockType) && ( + <> + + {showBlockOptionsDropDown && + createPortal( + , + document.body, + )} + + + )} + {blockType === "code" ? ( + <> + + +
+
+ +
+``` + + +--- + + + +## Copy Button + + + +}> +```html +
+ +
+``` +
+ +--- + diff --git a/documentation/html/skeleton.mdx b/documentation/html/skeleton.mdx new file mode 100644 index 000000000..2596805fe --- /dev/null +++ b/documentation/html/skeleton.mdx @@ -0,0 +1,281 @@ +--- +title: Tailwind CSS Skeleton for HTML - Material Tailwind +description: Customise your web projects with our easy-to-use skeleton component for Tailwind CSS and HTML using Material Design guidelines. +navigation: + [ + "skeleton", + "image-placeholder-skeleton", + "video-placeholder-skeleton", + "text-placeholder-skeleton", + "card-placeholder-skeleton", + "testimonial-placeholder-skeleton" + ] +github: skeleton +prev: sidebar +next: speed-dial +--- + + +# Tailwind CSS Skeleton - HTML + + +The skeleton component can be used as an alternative loading indicator to the spinner by mimicking the content that will be loaded such as text, images, or video + +See below our simple Skeleton example that you can use in your Tailwind CSS and HTML project. + +
+ +}> +```jsx +
+

+

+

+

+

+

+

+

+

+

+

+

+

+ Loading... +

+
+``` +
+ +--- + + +## Image placeholder Skeleton + + +}> +```html +
+
+ +
+
+

+

+

+

+

+

+

+

+

+

+

+

+

+ Loading... +

+
+
+``` +
+ +--- + + + +## Video placeholder Skeleton + + +}> +```html +
+ +

+ Loading... +

+
+``` +
+ +--- + + +## Text placeholder Skeleton + + +}> +```html +
+
+

+ +
+
+

+

+

+

+
+
+

+

+

+

+

+

+
+
+

+

+

+

+

+

+
+
+

+

+

+

+

+

+
+
+

+

+

+

+
+

+ Loading... +

+
+``` +
+ +--- + + + +## Card placeholder Skeleton + + +}> +```html +
+
+ +
+
+
+
+
+

+

+

+

+

+

+

+

+
+
+
+ +
+
+``` +
+ +--- + + + +## Testimonial placeholder Skeleton + + +}> +```html +
+

+

+ +

+

+
+ +

+

+

+

+
+

+ Loading... +

+
+``` +
+ +--- \ No newline at end of file diff --git a/documentation/react/plugins/text-editor.mdx b/documentation/react/plugins/text-editor.mdx new file mode 100644 index 000000000..dceba5e2b --- /dev/null +++ b/documentation/react/plugins/text-editor.mdx @@ -0,0 +1,785 @@ +--- +title: Tailwind CSS WYSIWYG Editor for React - Material Tailwind +description: Customise your web projects with our easy-to-use WYSIWYG Editor example for Tailwind CSS and React using Material Design guidelines. +navigation: + [ + "wysiwyg-editor", + ] +github: plugins/wysiwyg-editor +prev: table +next: plugins/algolia-search +--- + + +# Tailwind CSS WYSIWYG Editor - React + + +Use our Tailwind CSS WYSIWYG Editor in your web projects. + +See below our beautiful WYSIWYG Editor example that you can use in your Tailwind CSS and React project. The example below is using the `npm install lexical ` and `@lexical/react` libraries, make sure to install them before using the example. + +```bash +npm install --save lexical @lexical/react +``` + +
+
+ +}> +```jsx +// import ExampleTheme from "./themes/ExampleTheme"; +import { LexicalComposer } from "@lexical/react/LexicalComposer"; +import { RichTextPlugin } from "@lexical/react/LexicalRichTextPlugin"; +import { ContentEditable } from "@lexical/react/LexicalContentEditable"; +import { AutoFocusPlugin } from "@lexical/react/LexicalAutoFocusPlugin"; + +import { HeadingNode, QuoteNode } from "@lexical/rich-text"; +import { TableCellNode, TableNode, TableRowNode } from "@lexical/table"; +import { ListItemNode, ListNode } from "@lexical/list"; +import { CodeHighlightNode, CodeNode } from "@lexical/code"; +import { AutoLinkNode, LinkNode } from "@lexical/link"; +import { LinkPlugin } from "@lexical/react/LexicalLinkPlugin"; +import { ListPlugin } from "@lexical/react/LexicalListPlugin"; +import { MarkdownShortcutPlugin } from "@lexical/react/LexicalMarkdownShortcutPlugin"; +import { TRANSFORMERS } from "@lexical/markdown"; + +//Toolbar Plugins +import { useLexicalComposerContext } from "@lexical/react/LexicalComposerContext"; +import { useCallback, useEffect, useMemo, useRef, useState } from "react"; +import { + SELECTION_CHANGE_COMMAND, + FORMAT_TEXT_COMMAND, + $getSelection, + $isRangeSelection, + $createParagraphNode, + $getNodeByKey, +} from "lexical"; +import { $isLinkNode, TOGGLE_LINK_COMMAND } from "@lexical/link"; +import { $wrapNodes, $isAtNodeEnd } from "@lexical/selection"; +import { $getNearestNodeOfType, mergeRegister } from "@lexical/utils"; +import { + INSERT_ORDERED_LIST_COMMAND, + INSERT_UNORDERED_LIST_COMMAND, + REMOVE_LIST_COMMAND, + $isListNode, +} from "@lexical/list"; +import { createPortal } from "react-dom"; +import { + $createHeadingNode, + $createQuoteNode, + $isHeadingNode, +} from "@lexical/rich-text"; +import { + $createCodeNode, + $isCodeNode, + getDefaultCodeLanguage, + getCodeLanguages, +} from "@lexical/code"; + +const LowPriority = 1; + +const supportedBlockTypes = new Set([ + "paragraph", + "quote", + "code", + "h1", + "h2", + "ul", + "ol", +]); + +const blockTypeToBlockName = { + code: "Code Block", + h1: "Large Heading", + h2: "Small Heading", + h3: "Heading", + h4: "Heading", + h5: "Heading", + ol: "Numbered List", + paragraph: "Normal", + quote: "Quote", + ul: "Bulleted List", +}; + +function Divider() { + return
; +} + +function positionEditorElement(editor, rect) { + if (rect === null) { + editor.style.opacity = "0"; + editor.style.top = "-1000px"; + editor.style.left = "-1000px"; + } else { + editor.style.opacity = "1"; + editor.style.top = `${rect.top + rect.height + window.pageYOffset + 10}px`; + editor.style.left = `${ + rect.left + window.pageXOffset - editor.offsetWidth / 2 + rect.width / 2 + }px`; + } +} + +function FloatingLinkEditor({ editor }) { + const editorRef = useRef(null); + const inputRef = useRef(null); + const mouseDownRef = useRef(false); + const [linkUrl, setLinkUrl] = useState(""); + const [isEditMode, setEditMode] = useState(false); + const [lastSelection, setLastSelection] = useState(null); + + const updateLinkEditor = useCallback(() => { + const selection = $getSelection(); + if ($isRangeSelection(selection)) { + const node = getSelectedNode(selection); + const parent = node.getParent(); + if ($isLinkNode(parent)) { + setLinkUrl(parent.getURL()); + } else if ($isLinkNode(node)) { + setLinkUrl(node.getURL()); + } else { + setLinkUrl(""); + } + } + const editorElem = editorRef.current; + const nativeSelection = window.getSelection(); + const activeElement = document.activeElement; + + if (editorElem === null) { + return; + } + + const rootElement = editor.getRootElement(); + if ( + selection !== null && + !nativeSelection.isCollapsed && + rootElement !== null && + rootElement.contains(nativeSelection.anchorNode) + ) { + const domRange = nativeSelection.getRangeAt(0); + let rect; + if (nativeSelection.anchorNode === rootElement) { + let inner = rootElement; + while (inner.firstElementChild != null) { + inner = inner.firstElementChild; + } + rect = inner.getBoundingClientRect(); + } else { + rect = domRange.getBoundingClientRect(); + } + + if (!mouseDownRef.current) { + positionEditorElement(editorElem, rect); + } + setLastSelection(selection); + } else if (!activeElement || activeElement.className !== "link-input") { + positionEditorElement(editorElem, null); + setLastSelection(null); + setEditMode(false); + setLinkUrl(""); + } + + return true; + }, [editor]); + + useEffect(() => { + return mergeRegister( + editor.registerUpdateListener(({ editorState }) => { + editorState.read(() => { + updateLinkEditor(); + }); + }), + + editor.registerCommand( + SELECTION_CHANGE_COMMAND, + () => { + updateLinkEditor(); + return true; + }, + LowPriority, + ), + ); + }, [editor, updateLinkEditor]); + + useEffect(() => { + editor.getEditorState().read(() => { + updateLinkEditor(); + }); + }, [editor, updateLinkEditor]); + + useEffect(() => { + if (isEditMode && inputRef.current) { + inputRef.current.focus(); + } + }, [isEditMode]); + + return ( +
+ {isEditMode ? ( + { + setLinkUrl(event.target.value); + }} + onKeyDown={(event) => { + if (event.key === "Enter") { + event.preventDefault(); + if (lastSelection !== null) { + if (linkUrl !== "") { + editor.dispatchCommand(TOGGLE_LINK_COMMAND, linkUrl); + } + setEditMode(false); + } + } else if (event.key === "Escape") { + event.preventDefault(); + setEditMode(false); + } + }} + /> + ) : ( + <> +
+ + {linkUrl} + +
event.preventDefault()} + onClick={() => { + setEditMode(true); + }} + /> +
+ + )} +
+ ); +} + +function Select({ onChange, className, options, value }) { + return ( + + ); +} + +function getSelectedNode(selection) { + const anchor = selection.anchor; + const focus = selection.focus; + const anchorNode = selection.anchor.getNode(); + const focusNode = selection.focus.getNode(); + if (anchorNode === focusNode) { + return anchorNode; + } + const isBackward = selection.isBackward(); + if (isBackward) { + return $isAtNodeEnd(focus) ? anchorNode : focusNode; + } else { + return $isAtNodeEnd(anchor) ? focusNode : anchorNode; + } +} + +function BlockOptionsDropdownList({ + editor, + blockType, + toolbarRef, + setShowBlockOptionsDropDown, +}) { + const dropDownRef = useRef(null); + + useEffect(() => { + const toolbar = toolbarRef.current; + const dropDown = dropDownRef.current; + + if (toolbar !== null && dropDown !== null) { + const { top, left } = toolbar.getBoundingClientRect(); + dropDown.style.top = `${top + 40}px`; + dropDown.style.left = `${left}px`; + } + }, [dropDownRef, toolbarRef]); + + useEffect(() => { + const dropDown = dropDownRef.current; + const toolbar = toolbarRef.current; + + if (dropDown !== null && toolbar !== null) { + const handle = (event) => { + const target = event.target; + + if (!dropDown.contains(target) && !toolbar.contains(target)) { + setShowBlockOptionsDropDown(false); + } + }; + document.addEventListener("click", handle); + + return () => { + document.removeEventListener("click", handle); + }; + } + }, [dropDownRef, setShowBlockOptionsDropDown, toolbarRef]); + + const formatParagraph = () => { + if (blockType !== "paragraph") { + editor.update(() => { + const selection = $getSelection(); + + if ($isRangeSelection(selection)) { + $wrapNodes(selection, () => $createParagraphNode()); + } + }); + } + setShowBlockOptionsDropDown(false); + }; + + const formatLargeHeading = () => { + if (blockType !== "h1") { + editor.update(() => { + const selection = $getSelection(); + + if ($isRangeSelection(selection)) { + $wrapNodes(selection, () => $createHeadingNode("h1")); + } + }); + } + setShowBlockOptionsDropDown(false); + }; + + const formatSmallHeading = () => { + if (blockType !== "h2") { + editor.update(() => { + const selection = $getSelection(); + + if ($isRangeSelection(selection)) { + $wrapNodes(selection, () => $createHeadingNode("h2")); + } + }); + } + setShowBlockOptionsDropDown(false); + }; + + const formatBulletList = () => { + if (blockType !== "ul") { + editor.dispatchCommand(INSERT_UNORDERED_LIST_COMMAND); + } else { + editor.dispatchCommand(REMOVE_LIST_COMMAND); + } + setShowBlockOptionsDropDown(false); + }; + + const formatNumberedList = () => { + if (blockType !== "ol") { + editor.dispatchCommand(INSERT_ORDERED_LIST_COMMAND); + } else { + editor.dispatchCommand(REMOVE_LIST_COMMAND); + } + setShowBlockOptionsDropDown(false); + }; + + const formatQuote = () => { + if (blockType !== "quote") { + editor.update(() => { + const selection = $getSelection(); + + if ($isRangeSelection(selection)) { + $wrapNodes(selection, () => $createQuoteNode()); + } + }); + } + setShowBlockOptionsDropDown(false); + }; + + const formatCode = () => { + if (blockType !== "code") { + editor.update(() => { + const selection = $getSelection(); + + if ($isRangeSelection(selection)) { + $wrapNodes(selection, () => $createCodeNode()); + } + }); + } + setShowBlockOptionsDropDown(false); + }; + + return ( +
+ + + + + + + +
+ ); +} + +function ToolbarPlugin() { + const [editor] = useLexicalComposerContext(); + const toolbarRef = useRef(null); + const [blockType, setBlockType] = useState("paragraph"); + const [selectedElementKey, setSelectedElementKey] = useState(null); + const [showBlockOptionsDropDown, setShowBlockOptionsDropDown] = + useState(false); + const [codeLanguage, setCodeLanguage] = useState(""); + const [isLink, setIsLink] = useState(false); + const [isBold, setIsBold] = useState(false); + const [isItalic, setIsItalic] = useState(false); + const [isUnderline, setIsUnderline] = useState(false); + const [isStrikethrough, setIsStrikethrough] = useState(false); + const [isCode, setIsCode] = useState(false); + + const updateToolbar = useCallback(() => { + const selection = $getSelection(); + if ($isRangeSelection(selection)) { + const anchorNode = selection.anchor.getNode(); + const element = + anchorNode.getKey() === "root" + ? anchorNode + : anchorNode.getTopLevelElementOrThrow(); + const elementKey = element.getKey(); + const elementDOM = editor.getElementByKey(elementKey); + if (elementDOM !== null) { + setSelectedElementKey(elementKey); + if ($isListNode(element)) { + const parentList = $getNearestNodeOfType(anchorNode, ListNode); + const type = parentList ? parentList.getTag() : element.getTag(); + setBlockType(type); + } else { + const type = $isHeadingNode(element) + ? element.getTag() + : element.getType(); + setBlockType(type); + if ($isCodeNode(element)) { + setCodeLanguage(element.getLanguage() || getDefaultCodeLanguage()); + } + } + } + // Update text format + setIsBold(selection.hasFormat("bold")); + setIsItalic(selection.hasFormat("italic")); + setIsUnderline(selection.hasFormat("underline")); + setIsStrikethrough(selection.hasFormat("strikethrough")); + setIsCode(selection.hasFormat("code")); + + // Update links + const node = getSelectedNode(selection); + const parent = node.getParent(); + if ($isLinkNode(parent) || $isLinkNode(node)) { + setIsLink(true); + } else { + setIsLink(false); + } + } + }, [editor]); + + useEffect(() => { + return mergeRegister( + editor.registerUpdateListener(({ editorState }) => { + editorState.read(() => { + updateToolbar(); + }); + }), + editor.registerCommand( + SELECTION_CHANGE_COMMAND, + (_payload, newEditor) => { + updateToolbar(); + return false; + }, + LowPriority, + ), + ); + }, [editor, updateToolbar]); + + const codeLanguges = useMemo(() => getCodeLanguages(), []); + const onCodeLanguageSelect = useCallback( + (e) => { + editor.update(() => { + if (selectedElementKey !== null) { + const node = $getNodeByKey(selectedElementKey); + if ($isCodeNode(node)) { + node.setLanguage(e.target.value); + } + } + }); + }, + [editor, selectedElementKey], + ); + + const insertLink = useCallback(() => { + if (!isLink) { + editor.dispatchCommand(TOGGLE_LINK_COMMAND, "https://"); + } else { + editor.dispatchCommand(TOGGLE_LINK_COMMAND, null); + } + }, [editor, isLink]); + + return ( +
+ {supportedBlockTypes.has(blockType) && ( + <> + + {showBlockOptionsDropDown && + createPortal( + , + document.body, + )} + + + )} + {blockType === "code" ? ( + <> + { - setLinkUrl(event.target.value); - }} - onKeyDown={(event) => { - if (event.key === "Enter") { - event.preventDefault(); - if (lastSelection !== null) { - if (linkUrl !== "") { - editor.dispatchCommand(TOGGLE_LINK_COMMAND, linkUrl); - } - setEditMode(false); - } - } else if (event.key === "Escape") { - event.preventDefault(); - setEditMode(false); - } - }} - /> - ) : ( - <> -
- - {linkUrl} - -
event.preventDefault()} - onClick={() => { - setEditMode(true); - }} - /> -
- - )} +
+ Play around with the editor...
); } @@ -382,42 +245,504 @@ function BlockOptionsDropdownList({ }; return ( -
- - - - - - - + + + + + + + + + Normal + + + + + + + + + + Large Heading + + + + + + + + + + + Small Heading + + + + + + + + + + + + + Bullet List + + + + + + + + + + + + + + Numbered List + + + + + + + + + Quote + + + + + + + + + + Code + + + ); +} + +function positionEditorElement(editor, rect) { + if (rect === null) { + editor.style.opacity = "0"; + editor.style.top = "-1000px"; + editor.style.left = "-1000px"; + } else { + editor.style.opacity = "1"; + editor.style.top = `${rect.top + rect.height + window.pageYOffset + 10}px`; + editor.style.left = `${ + rect.left + window.pageXOffset - editor.offsetWidth / 2 + rect.width / 2 + }px`; + } +} + +function FloatingLinkEditor({ editor }) { + const editorRef = useRef(null); + const inputRef = useRef(null); + const mouseDownRef = useRef(false); + const [linkUrl, setLinkUrl] = useState(""); + const [isEditMode, setEditMode] = useState(false); + const [lastSelection, setLastSelection] = useState(null); + + const updateLinkEditor = useCallback(() => { + const selection = $getSelection(); + if ($isRangeSelection(selection)) { + const node = getSelectedNode(selection); + const parent = node.getParent(); + if ($isLinkNode(parent)) { + setLinkUrl(parent.getURL()); + } else if ($isLinkNode(node)) { + setLinkUrl(node.getURL()); + } else { + setLinkUrl(""); + } + } + const editorElem = editorRef.current; + const nativeSelection = window.getSelection(); + const activeElement = document.activeElement; + + if (editorElem === null) { + return; + } + + const rootElement = editor.getRootElement(); + if ( + selection !== null && + !nativeSelection.isCollapsed && + rootElement !== null && + rootElement.contains(nativeSelection.anchorNode) + ) { + const domRange = nativeSelection.getRangeAt(0); + let rect; + if (nativeSelection.anchorNode === rootElement) { + let inner = rootElement; + while (inner.firstElementChild != null) { + inner = inner.firstElementChild; + } + rect = inner.getBoundingClientRect(); + } else { + rect = domRange.getBoundingClientRect(); + } + + if (!mouseDownRef.current) { + positionEditorElement(editorElem, rect); + } + setLastSelection(selection); + } else if (!activeElement || activeElement.className !== "link-input") { + positionEditorElement(editorElem, null); + setLastSelection(null); + setEditMode(false); + setLinkUrl(""); + } + + return true; + }, [editor]); + + useEffect(() => { + return mergeRegister( + editor.registerUpdateListener(({ editorState }) => { + editorState.read(() => { + updateLinkEditor(); + }); + }), + + editor.registerCommand( + SELECTION_CHANGE_COMMAND, + () => { + updateLinkEditor(); + return true; + }, + LowPriority, + ), + ); + }, [editor, updateLinkEditor]); + + useEffect(() => { + editor.getEditorState().read(() => { + updateLinkEditor(); + }); + }, [editor, updateLinkEditor]); + + useEffect(() => { + if (isEditMode && inputRef.current) { + inputRef.current.focus(); + } + }, [isEditMode]); + + return ( +
+ {isEditMode ? ( + { + setLinkUrl(event.target.value); + }} + onKeyDown={(event) => { + if (event.key === "Enter") { + event.preventDefault(); + if (lastSelection !== null) { + if (linkUrl !== "") { + editor.dispatchCommand(TOGGLE_LINK_COMMAND, linkUrl); + } + setEditMode(false); + } + } else if (event.key === "Escape") { + event.preventDefault(); + setEditMode(false); + } + }} + className="border-gray-200 !border-t-gray-200 focus:!border-gray-900 focus:!border-t-gray-900" + labelProps={{ + className: "hidden", + }} + /> + ) : ( + <> +
+ + {linkUrl} + + event.preventDefault()} + onClick={() => { + setEditMode(true); + }} + > + + + + +
+ + )}
); } @@ -433,7 +758,6 @@ function ToolbarPlugin() { const [isLink, setIsLink] = useState(false); const [isBold, setIsBold] = useState(false); const [isItalic, setIsItalic] = useState(false); - const [isUnderline, setIsUnderline] = useState(false); const [isStrikethrough, setIsStrikethrough] = useState(false); const [isCode, setIsCode] = useState(false); @@ -466,7 +790,6 @@ function ToolbarPlugin() { // Update text format setIsBold(selection.hasFormat("bold")); setIsItalic(selection.hasFormat("italic")); - setIsUnderline(selection.hasFormat("underline")); setIsStrikethrough(selection.hasFormat("strikethrough")); setIsCode(selection.hasFormat("code")); @@ -523,20 +846,35 @@ function ToolbarPlugin() { }, [editor, isLink]); return ( -
+
{supportedBlockTypes.has(blockType) && ( <> - + {blockTypeToBlockName[blockType]} + + + + {showBlockOptionsDropDown && createPortal( { - setLinkUrl(event.target.value); - }} - onKeyDown={(event) => { - if (event.key === "Enter") { - event.preventDefault(); - if (lastSelection !== null) { - if (linkUrl !== "") { - editor.dispatchCommand(TOGGLE_LINK_COMMAND, linkUrl); - } - setEditMode(false); - } - } else if (event.key === "Escape") { - event.preventDefault(); - setEditMode(false); - } - }} - /> - ) : ( - <> -
- - {linkUrl} - -
event.preventDefault()} - onClick={() => { - setEditMode(true); - }} - /> -
- - )} +
+ Play around with the editor...
); } @@ -411,42 +289,504 @@ function BlockOptionsDropdownList({ }; return ( -
- - - - - - - + + + + + + + + + Normal + + + + + + + + + + Large Heading + + + + + + + + + + + Small Heading + + + + + + + + + + + + + Bullet List + + + + + + + + + + + + + + Numbered List + + + + + + + + + Quote + + + + + + + + + + Code + + + ); +} + +function positionEditorElement(editor, rect) { + if (rect === null) { + editor.style.opacity = "0"; + editor.style.top = "-1000px"; + editor.style.left = "-1000px"; + } else { + editor.style.opacity = "1"; + editor.style.top = `${rect.top + rect.height + window.pageYOffset + 10}px`; + editor.style.left = `${ + rect.left + window.pageXOffset - editor.offsetWidth / 2 + rect.width / 2 + }px`; + } +} + +function FloatingLinkEditor({ editor }) { + const editorRef = useRef(null); + const inputRef = useRef(null); + const mouseDownRef = useRef(false); + const [linkUrl, setLinkUrl] = useState(""); + const [isEditMode, setEditMode] = useState(false); + const [lastSelection, setLastSelection] = useState(null); + + const updateLinkEditor = useCallback(() => { + const selection = $getSelection(); + if ($isRangeSelection(selection)) { + const node = getSelectedNode(selection); + const parent = node.getParent(); + if ($isLinkNode(parent)) { + setLinkUrl(parent.getURL()); + } else if ($isLinkNode(node)) { + setLinkUrl(node.getURL()); + } else { + setLinkUrl(""); + } + } + const editorElem = editorRef.current; + const nativeSelection = window.getSelection(); + const activeElement = document.activeElement; + + if (editorElem === null) { + return; + } + + const rootElement = editor.getRootElement(); + if ( + selection !== null && + !nativeSelection.isCollapsed && + rootElement !== null && + rootElement.contains(nativeSelection.anchorNode) + ) { + const domRange = nativeSelection.getRangeAt(0); + let rect; + if (nativeSelection.anchorNode === rootElement) { + let inner = rootElement; + while (inner.firstElementChild != null) { + inner = inner.firstElementChild; + } + rect = inner.getBoundingClientRect(); + } else { + rect = domRange.getBoundingClientRect(); + } + + if (!mouseDownRef.current) { + positionEditorElement(editorElem, rect); + } + setLastSelection(selection); + } else if (!activeElement || activeElement.className !== "link-input") { + positionEditorElement(editorElem, null); + setLastSelection(null); + setEditMode(false); + setLinkUrl(""); + } + + return true; + }, [editor]); + + useEffect(() => { + return mergeRegister( + editor.registerUpdateListener(({ editorState }) => { + editorState.read(() => { + updateLinkEditor(); + }); + }), + + editor.registerCommand( + SELECTION_CHANGE_COMMAND, + () => { + updateLinkEditor(); + return true; + }, + LowPriority, + ), + ); + }, [editor, updateLinkEditor]); + + useEffect(() => { + editor.getEditorState().read(() => { + updateLinkEditor(); + }); + }, [editor, updateLinkEditor]); + + useEffect(() => { + if (isEditMode && inputRef.current) { + inputRef.current.focus(); + } + }, [isEditMode]); + + return ( +
+ {isEditMode ? ( + { + setLinkUrl(event.target.value); + }} + onKeyDown={(event) => { + if (event.key === "Enter") { + event.preventDefault(); + if (lastSelection !== null) { + if (linkUrl !== "") { + editor.dispatchCommand(TOGGLE_LINK_COMMAND, linkUrl); + } + setEditMode(false); + } + } else if (event.key === "Escape") { + event.preventDefault(); + setEditMode(false); + } + }} + className="border-gray-200 !border-t-gray-200 focus:!border-gray-900 focus:!border-t-gray-900" + labelProps={{ + className: "hidden", + }} + /> + ) : ( + <> +
+ + {linkUrl} + + event.preventDefault()} + onClick={() => { + setEditMode(true); + }} + > + + + + +
+ + )}
); } @@ -462,7 +802,6 @@ function ToolbarPlugin() { const [isLink, setIsLink] = useState(false); const [isBold, setIsBold] = useState(false); const [isItalic, setIsItalic] = useState(false); - const [isUnderline, setIsUnderline] = useState(false); const [isStrikethrough, setIsStrikethrough] = useState(false); const [isCode, setIsCode] = useState(false); @@ -495,7 +834,6 @@ function ToolbarPlugin() { // Update text format setIsBold(selection.hasFormat("bold")); setIsItalic(selection.hasFormat("italic")); - setIsUnderline(selection.hasFormat("underline")); setIsStrikethrough(selection.hasFormat("strikethrough")); setIsCode(selection.hasFormat("code")); @@ -552,20 +890,35 @@ function ToolbarPlugin() { }, [editor, isLink]); return ( -
+
{supportedBlockTypes.has(blockType) && ( <> - + {blockTypeToBlockName[blockType]} + + + + {showBlockOptionsDropDown && createPortal( + + ))} + + ); +} + +function getSelectedNode(selection) { + const anchor = selection.anchor; + const focus = selection.focus; + const anchorNode = selection.anchor.getNode(); + const focusNode = selection.focus.getNode(); + if (anchorNode === focusNode) { + return anchorNode; + } + const isBackward = selection.isBackward(); + if (isBackward) { + return $isAtNodeEnd(focus) ? anchorNode : focusNode; + } else { + return $isAtNodeEnd(anchor) ? focusNode : anchorNode; + } +} + +function BlockOptionsDropdownList({ + editor, + blockType, + toolbarRef, + setShowBlockOptionsDropDown, +}) { + const dropDownRef = useRef(null); + + useEffect(() => { + const toolbar = toolbarRef.current; + const dropDown = dropDownRef.current; + + if (toolbar !== null && dropDown !== null) { + const { top, left } = toolbar.getBoundingClientRect(); + dropDown.style.top = `${top + 40}px`; + dropDown.style.left = `${left}px`; + } + }, [dropDownRef, toolbarRef]); + + useEffect(() => { + const dropDown = dropDownRef.current; + const toolbar = toolbarRef.current; + + if (dropDown !== null && toolbar !== null) { + const handle = (event) => { + const target = event.target; + + if (!dropDown.contains(target) && !toolbar.contains(target)) { + setShowBlockOptionsDropDown(false); + } + }; + document.addEventListener("click", handle); + + return () => { + document.removeEventListener("click", handle); + }; + } + }, [dropDownRef, setShowBlockOptionsDropDown, toolbarRef]); + + const formatParagraph = () => { + if (blockType !== "paragraph") { + editor.update(() => { + const selection = $getSelection(); + + if ($isRangeSelection(selection)) { + $wrapNodes(selection, () => $createParagraphNode()); + } + }); + } + setShowBlockOptionsDropDown(false); + }; + + const formatLargeHeading = () => { + if (blockType !== "h1") { + editor.update(() => { + const selection = $getSelection(); + + if ($isRangeSelection(selection)) { + $wrapNodes(selection, () => $createHeadingNode("h1")); + } + }); + } + setShowBlockOptionsDropDown(false); + }; + + const formatSmallHeading = () => { + if (blockType !== "h2") { + editor.update(() => { + const selection = $getSelection(); + + if ($isRangeSelection(selection)) { + $wrapNodes(selection, () => $createHeadingNode("h2")); + } + }); + } + setShowBlockOptionsDropDown(false); + }; + + const formatBulletList = () => { + if (blockType !== "ul") { + editor.dispatchCommand(INSERT_UNORDERED_LIST_COMMAND); + } else { + editor.dispatchCommand(REMOVE_LIST_COMMAND); + } + setShowBlockOptionsDropDown(false); + }; + + const formatNumberedList = () => { + if (blockType !== "ol") { + editor.dispatchCommand(INSERT_ORDERED_LIST_COMMAND); + } else { + editor.dispatchCommand(REMOVE_LIST_COMMAND); + } + setShowBlockOptionsDropDown(false); + }; + + const formatQuote = () => { + if (blockType !== "quote") { + editor.update(() => { + const selection = $getSelection(); + + if ($isRangeSelection(selection)) { + $wrapNodes(selection, () => $createQuoteNode()); + } + }); + } + setShowBlockOptionsDropDown(false); + }; + + const formatCode = () => { + if (blockType !== "code") { + editor.update(() => { + const selection = $getSelection(); + + if ($isRangeSelection(selection)) { + $wrapNodes(selection, () => $createCodeNode()); + } + }); + } + setShowBlockOptionsDropDown(false); + }; + + return ( + + + + + + + + + Normal + + + + + + + + + + Large Heading + + + + + + + + + + + Small Heading + + + + + + + + + + + + + Bullet List + + + + + + + + + + + + + + Numbered List + + + + + + + + + Quote + + + + + + + + + + Code + + + ); +} + +function positionEditorElement(editor, rect) { + if (rect === null) { + editor.style.opacity = "0"; + editor.style.top = "-1000px"; + editor.style.left = "-1000px"; + } else { + editor.style.opacity = "1"; + editor.style.top = `${rect.top + rect.height + window.pageYOffset + 10}px`; + editor.style.left = `${ + rect.left + window.pageXOffset - editor.offsetWidth / 2 + rect.width / 2 + }px`; + } +} + +function FloatingLinkEditor({ editor }) { + const editorRef = useRef(null); + const inputRef = useRef(null); + const mouseDownRef = useRef(false); + const [linkUrl, setLinkUrl] = useState(""); + const [isEditMode, setEditMode] = useState(false); + const [lastSelection, setLastSelection] = useState(null); + + const updateLinkEditor = useCallback(() => { + const selection = $getSelection(); + if ($isRangeSelection(selection)) { + const node = getSelectedNode(selection); + const parent = node.getParent(); + if ($isLinkNode(parent)) { + setLinkUrl(parent.getURL()); + } else if ($isLinkNode(node)) { + setLinkUrl(node.getURL()); + } else { + setLinkUrl(""); + } + } + const editorElem = editorRef.current; + const nativeSelection = window.getSelection(); + const activeElement = document.activeElement; + + if (editorElem === null) { + return; + } + + const rootElement = editor.getRootElement(); + if ( + selection !== null && + !nativeSelection.isCollapsed && + rootElement !== null && + rootElement.contains(nativeSelection.anchorNode) + ) { + const domRange = nativeSelection.getRangeAt(0); + let rect; + if (nativeSelection.anchorNode === rootElement) { + let inner = rootElement; + while (inner.firstElementChild != null) { + inner = inner.firstElementChild; + } + rect = inner.getBoundingClientRect(); + } else { + rect = domRange.getBoundingClientRect(); + } + + if (!mouseDownRef.current) { + positionEditorElement(editorElem, rect); + } + setLastSelection(selection); + } else if (!activeElement || activeElement.className !== "link-input") { + positionEditorElement(editorElem, null); + setLastSelection(null); + setEditMode(false); + setLinkUrl(""); + } + + return true; + }, [editor]); + + useEffect(() => { + return mergeRegister( + editor.registerUpdateListener(({ editorState }) => { + editorState.read(() => { + updateLinkEditor(); + }); + }), + + editor.registerCommand( + SELECTION_CHANGE_COMMAND, + () => { + updateLinkEditor(); + return true; + }, + LowPriority, + ), + ); + }, [editor, updateLinkEditor]); + + useEffect(() => { + editor.getEditorState().read(() => { + updateLinkEditor(); + }); + }, [editor, updateLinkEditor]); + + useEffect(() => { + if (isEditMode && inputRef.current) { + inputRef.current.focus(); + } + }, [isEditMode]); + + return ( +
+ {isEditMode ? ( + { + setLinkUrl(event.target.value); + }} + onKeyDown={(event) => { + if (event.key === "Enter") { + event.preventDefault(); + if (lastSelection !== null) { + if (linkUrl !== "") { + editor.dispatchCommand(TOGGLE_LINK_COMMAND, linkUrl); + } + setEditMode(false); + } + } else if (event.key === "Escape") { + event.preventDefault(); + setEditMode(false); + } + }} + className="border-gray-200 !border-t-gray-200 focus:!border-gray-900 focus:!border-t-gray-900" + labelProps={{ + className: "hidden", + }} + /> + ) : ( + <> +
+ + {linkUrl} + + event.preventDefault()} + onClick={() => { + setEditMode(true); + }} + > + + + + +
+ + )} +
+ ); +} + +function ToolbarPlugin() { + const [editor] = useLexicalComposerContext(); + const toolbarRef = useRef(null); + const [blockType, setBlockType] = useState("paragraph"); + const [selectedElementKey, setSelectedElementKey] = useState(null); + const [showBlockOptionsDropDown, setShowBlockOptionsDropDown] = + useState(false); + const [codeLanguage, setCodeLanguage] = useState(""); + const [isLink, setIsLink] = useState(false); + const [isBold, setIsBold] = useState(false); + const [isItalic, setIsItalic] = useState(false); + const [isStrikethrough, setIsStrikethrough] = useState(false); + const [isCode, setIsCode] = useState(false); + + const updateToolbar = useCallback(() => { + const selection = $getSelection(); + if ($isRangeSelection(selection)) { + const anchorNode = selection.anchor.getNode(); + const element = + anchorNode.getKey() === "root" + ? anchorNode + : anchorNode.getTopLevelElementOrThrow(); + const elementKey = element.getKey(); + const elementDOM = editor.getElementByKey(elementKey); + if (elementDOM !== null) { + setSelectedElementKey(elementKey); + if ($isListNode(element)) { + const parentList = $getNearestNodeOfType(anchorNode, ListNode); + const type = parentList ? parentList.getTag() : element.getTag(); + setBlockType(type); + } else { + const type = $isHeadingNode(element) + ? element.getTag() + : element.getType(); + setBlockType(type); + if ($isCodeNode(element)) { + setCodeLanguage(element.getLanguage() || getDefaultCodeLanguage()); + } + } + } + // Update text format + setIsBold(selection.hasFormat("bold")); + setIsItalic(selection.hasFormat("italic")); + setIsStrikethrough(selection.hasFormat("strikethrough")); + setIsCode(selection.hasFormat("code")); + + // Update links + const node = getSelectedNode(selection); + const parent = node.getParent(); + if ($isLinkNode(parent) || $isLinkNode(node)) { + setIsLink(true); + } else { + setIsLink(false); + } + } + }, [editor]); + + useEffect(() => { + return mergeRegister( + editor.registerUpdateListener(({ editorState }) => { + editorState.read(() => { + updateToolbar(); + }); + }), + editor.registerCommand( + SELECTION_CHANGE_COMMAND, + (_payload, newEditor) => { + updateToolbar(); + return false; + }, + LowPriority, + ), + ); + }, [editor, updateToolbar]); + + const codeLanguges = useMemo(() => getCodeLanguages(), []); + const onCodeLanguageSelect = useCallback( + (e) => { + editor.update(() => { + if (selectedElementKey !== null) { + const node = $getNodeByKey(selectedElementKey); + if ($isCodeNode(node)) { + node.setLanguage(e.target.value); + } + } + }); + }, + [editor, selectedElementKey], + ); + + const insertLink = useCallback(() => { + if (!isLink) { + editor.dispatchCommand(TOGGLE_LINK_COMMAND, "https://"); + } else { + editor.dispatchCommand(TOGGLE_LINK_COMMAND, null); + } + }, [editor, isLink]); + + return ( +
+ {supportedBlockTypes.has(blockType) && ( + <> + + {showBlockOptionsDropDown && + createPortal( + , + document.body, + )} + + + )} + {blockType === "code" ? ( + <> + { - setInputValue(e.target.value); - }} - containerProps={{ className: "min-w-[100px]" }} - /> -
- -
- ); -} diff --git a/docs-content/html/plugins/clipboard/clipboard-with-tooltip.tsx b/docs-content/html/plugins/clipboard/clipboard-with-tooltip.tsx deleted file mode 100644 index a87f667e9..000000000 --- a/docs-content/html/plugins/clipboard/clipboard-with-tooltip.tsx +++ /dev/null @@ -1,40 +0,0 @@ -import React from "react"; -import { Input, Typography, Button, Tooltip } from "@material-tailwind/react"; -import { useCopyToClipboard } from "usehooks-ts"; -import { CheckIcon, DocumentDuplicateIcon } from "@heroicons/react/24/outline"; - -export function ClipboardWithTooltip() { - const [value, copy] = useCopyToClipboard(); - const [copied, setCopied] = React.useState(false); - - return ( -
- - - -
- ); -} diff --git a/docs-content/html/plugins/test.html b/docs-content/html/plugins/test.html new file mode 100644 index 000000000..14e9542e7 --- /dev/null +++ b/docs-content/html/plugins/test.html @@ -0,0 +1,21 @@ +
+
+
+ +
+
+ +
\ No newline at end of file diff --git a/docs-content/html/skeleton/card-placeholder-skeleton.tsx b/docs-content/html/skeleton/card-placeholder-skeleton.tsx index 661a2e006..f9d80c1be 100644 --- a/docs-content/html/skeleton/card-placeholder-skeleton.tsx +++ b/docs-content/html/skeleton/card-placeholder-skeleton.tsx @@ -1,32 +1,46 @@ export function CardPlacehoderSkeleton() { return (
-
+
-
-
-

-

-

-

+
+   +
+
+   +
+
+   +
+
+   +
+
+  
+ > +   +
); diff --git a/docs-content/html/skeleton/default-skeleton.tsx b/docs-content/html/skeleton/default-skeleton.tsx index a4ecad97c..5ee52d3d5 100644 --- a/docs-content/html/skeleton/default-skeleton.tsx +++ b/docs-content/html/skeleton/default-skeleton.tsx @@ -1,15 +1,21 @@ export function DefaultSkeleton() { return (
-

-

-

-

-

-

-

- Loading... -

+
+   +
+
+   +
+
+   +
+
+   +
+
+   +
); } diff --git a/docs-content/html/skeleton/image-placeholder-skeleton.tsx b/docs-content/html/skeleton/image-placeholder-skeleton.tsx index 9a5f98fca..221efc4cf 100644 --- a/docs-content/html/skeleton/image-placeholder-skeleton.tsx +++ b/docs-content/html/skeleton/image-placeholder-skeleton.tsx @@ -1,27 +1,44 @@ export function ImagePlacehoderSkeleton() { return ( -
-
+
+
-
-

-

-

-

-

-

-

- Loading... -

+
+
+   +
+
+   +
+
+   +
+
+   +
+
+   +
+
+   +
+
+   +
); diff --git a/docs-content/html/skeleton/index.ts b/docs-content/html/skeleton/index.ts index 200402968..84a69c265 100644 --- a/docs-content/html/skeleton/index.ts +++ b/docs-content/html/skeleton/index.ts @@ -1,6 +1,4 @@ export * from "./default-skeleton"; export * from "./image-placeholder-skeleton"; export * from "./video-placeholder-skeleton"; -export * from "./text-placeholder-skeleton"; export * from "./card-placeholder-skeleton"; -export * from "./testimonial-placeholder-skeleton"; diff --git a/docs-content/html/skeleton/testimonial-placeholder-skeleton.tsx b/docs-content/html/skeleton/testimonial-placeholder-skeleton.tsx deleted file mode 100644 index fd284a2d7..000000000 --- a/docs-content/html/skeleton/testimonial-placeholder-skeleton.tsx +++ /dev/null @@ -1,25 +0,0 @@ -export function TestimonialPlacehoderSkeleton() { - return ( -
-

- -

-
- -

-

-
-

- Loading... -

-
- ); -} diff --git a/docs-content/html/skeleton/text-placeholder-skeleton.tsx b/docs-content/html/skeleton/text-placeholder-skeleton.tsx deleted file mode 100644 index e5f4d77f5..000000000 --- a/docs-content/html/skeleton/text-placeholder-skeleton.tsx +++ /dev/null @@ -1,35 +0,0 @@ -export function TextPlacehoderSkeleton() { - return ( -
-
-

-
-
-

-

-
-
-

-

-

-
-
-

-

-

-
-
-

-

-

-
-
-

-

-
-

- Loading... -

-
- ); -} diff --git a/docs-content/html/skeleton/video-placeholder-skeleton.tsx b/docs-content/html/skeleton/video-placeholder-skeleton.tsx index 9dbd9a1f1..948871af3 100644 --- a/docs-content/html/skeleton/video-placeholder-skeleton.tsx +++ b/docs-content/html/skeleton/video-placeholder-skeleton.tsx @@ -1,19 +1,20 @@ export function VideoPlacehoderSkeleton() { return ( -
+
-

- Loading... -

); } diff --git a/docs-content/react/plugins/clipboard/clipboard-copy-button.tsx b/docs-content/react/plugins/clipboard/clipboard-copy-button.tsx index 62a00cd47..1b63a6f1d 100644 --- a/docs-content/react/plugins/clipboard/clipboard-copy-button.tsx +++ b/docs-content/react/plugins/clipboard/clipboard-copy-button.tsx @@ -20,7 +20,7 @@ export function ClipboardCopyButton() { className="border-r border-gray-400/50 pr-3 font-normal" variant="small" > - npm i @material-tailwind + npm i @material-tailwind/react {copied ? ( diff --git a/docs-content/react/plugins/clipboard/clipboard-with-tooltip.tsx b/docs-content/react/plugins/clipboard/clipboard-with-tooltip.tsx index d2013ebcb..e92e636d6 100644 --- a/docs-content/react/plugins/clipboard/clipboard-with-tooltip.tsx +++ b/docs-content/react/plugins/clipboard/clipboard-with-tooltip.tsx @@ -21,7 +21,7 @@ export function ClipboardWithTooltip() { className="border-r border-gray-400/50 pr-3 font-normal" variant="small" > - npm i @material-tailwind + npm i @material-tailwind/react {copied ? ( diff --git a/documentation/html/plugins/clipboard.mdx b/documentation/html/plugins/clipboard.mdx index 9a6a4987e..1d48501be 100644 --- a/documentation/html/plugins/clipboard.mdx +++ b/documentation/html/plugins/clipboard.mdx @@ -17,7 +17,7 @@ next: plugins/date-picker # Tailwind CSS Clipboard - HTML -Use our Tailwind CSS Date Picker example to to facilitate the copying and pasting of data within an application. +Use our Tailwind CSS Clipboard example to to facilitate the copying and pasting of data within an application. See below our beautiful clipboard example that you can use in your Tailwind CSS and HTML project. The example below is using the `clipboard` libraries, make sure to install them before using the example. @@ -28,26 +28,30 @@ npm install clipboard

-}> +}> ```html
-
-

- npm i @material-tailwind -

- +
+

+ npm i @material-tailwind/html +

+ +
+ +
-
```
@@ -61,32 +65,34 @@ npm install clipboard }> ```html -
-
-
- - +
+
+
+
+ + +
+
+
+ +
- -
``` @@ -100,20 +106,23 @@ npm install clipboard }> ```html -
- + +
```
diff --git a/documentation/html/skeleton.mdx b/documentation/html/skeleton.mdx index 2596805fe..e72eee942 100644 --- a/documentation/html/skeleton.mdx +++ b/documentation/html/skeleton.mdx @@ -28,27 +28,26 @@ See below our simple Skeleton example that you can use in your Tail }> ```jsx
-

-

-

-

-

-

-

-

-

-

-

-

-

- Loading... -

+
+   +
+
+   +
+
+   +
+
+   +
+
+   +
```
@@ -61,37 +60,44 @@ See below our simple Skeleton example that you can use in your Tail }> ```html -
-
-
+
+ +
-
-

-

-

-

-

-

-

-

-

-

-

-

-

- Loading... -

+
+
+   +
+
+   +
+
+   +
+
+   +
+
+   +
+
+   +
+
+   +
``` @@ -107,92 +113,19 @@ See below our simple Skeleton example that you can use in your Tail }> ```html
-

- Loading... -

```
--- - -## Text placeholder Skeleton - - -}> -```html -
-
-

- -
-
-

-

-

-

-
-
-

-

-

-

-

-

-
-
-

-

-

-

-

-

-
-
-

-

-

-

-

-

-
-
-

-

-

-

-
-

- Loading... -

-
-``` -
- ---- @@ -201,81 +134,47 @@ See below our simple Skeleton example that you can use in your Tail }> ```html -
+
-
-
-
-
-

-

-

-

-

-

-

-

+
+   +
+
+   +
+
+   +
+
+   +
+
+  
- +
``` --- - - - -## Testimonial placeholder Skeleton - - -}> -```html -
-

-

- -

-

-
- -

-

-

-

-
-

- Loading... -

-
-``` -
- ---- \ No newline at end of file diff --git a/documentation/react/plugins/clipboard.mdx b/documentation/react/plugins/clipboard.mdx index 80f363300..92b544a93 100644 --- a/documentation/react/plugins/clipboard.mdx +++ b/documentation/react/plugins/clipboard.mdx @@ -43,16 +43,16 @@ export function ClipboardDefault() { return (
- npm i @material-tailwind + npm i @material-tailwind/react setCopied(false)} onClick={() => { - copy("npm i @material-tailwind"); + copy("npm i @material-tailwind/react"); setCopied(true); }} > {copied ? ( - + ) : ( )} @@ -75,7 +75,7 @@ export function ClipboardDefault() { }> ```jsx import React from "react"; -import { Input, Typography, Button } from "@material-tailwind/react"; +import { Input, Button } from "@material-tailwind/react"; import { useCopyToClipboard } from "usehooks-ts"; import { CheckIcon, DocumentDuplicateIcon } from "@heroicons/react/24/outline"; @@ -83,11 +83,11 @@ export function ClipboardCopyInput() { const [value, copy] = useCopyToClipboard(); const [copied, setCopied] = React.useState(false); const [inputValue, setInputValue] = React.useState( - "npm i @material-tailwind", + "npm i @material-tailwind/react", ); return ( -
+
@@ -139,7 +141,7 @@ export function ClipboardCopyInput() { }> ```jsx import React from "react"; -import { Input, Typography, Button } from "@material-tailwind/react"; +import { Typography, Button } from "@material-tailwind/react"; import { useCopyToClipboard } from "usehooks-ts"; import { CheckIcon, DocumentDuplicateIcon } from "@heroicons/react/24/outline"; @@ -148,32 +150,26 @@ export function ClipboardCopyButton() { const [copied, setCopied] = React.useState(false); return ( -
- -
+ npm i @material-tailwind/react + + {copied ? ( + + ) : ( + + )} + ); } ``` @@ -191,7 +187,7 @@ export function ClipboardCopyButton() { }> ```jsx import React from "react"; -import { Input, Typography, Button, Tooltip } from "@material-tailwind/react"; +import { Typography, Button, Tooltip } from "@material-tailwind/react"; import { useCopyToClipboard } from "usehooks-ts"; import { CheckIcon, DocumentDuplicateIcon } from "@heroicons/react/24/outline"; @@ -200,34 +196,28 @@ export function ClipboardWithTooltip() { const [copied, setCopied] = React.useState(false); return ( -
- - - -
+ npm i @material-tailwind/react + + {copied ? ( + + ) : ( + + )} + + ); } ``` diff --git a/documentation/react/skeleton.mdx b/documentation/react/skeleton.mdx index 7d6388f07..7c34b297b 100644 --- a/documentation/react/skeleton.mdx +++ b/documentation/react/skeleton.mdx @@ -27,35 +27,44 @@ See below our simple Skeleton example that you can use in your Tail }> ```jsx import { Typography } from "@material-tailwind/react"; + export function DefaultSkeleton() { return ( -
+
- + className="mb-4 h-3 w-56 rounded-full bg-gray-300" + > +   + + as="div" + variant="paragraph" + className="mb-2 h-2 w-72 rounded-full bg-gray-300" + > +   + + as="div" + variant="paragraph" + className="mb-2 h-2 w-72 rounded-full bg-gray-300" + > +   + + as="div" + variant="paragraph" + className="mb-2 h-2 w-72 rounded-full bg-gray-300" + > +   + - - Loading... + as="div" + variant="paragraph" + className="mb-2 h-2 w-72 rounded-full bg-gray-300" + > +  
); @@ -75,45 +84,72 @@ import { Typography } from "@material-tailwind/react"; export function ImagePlacehoderSkeleton() { return ( -
-
+
+
-
+
+ className="mb-4 h-3 w-56 rounded-full bg-gray-300" + > +   + + as="div" + variant="paragraph" + className="mb-2 h-2 w-72 rounded-full bg-gray-300" + > +   + + as="div" + variant="paragraph" + className="mb-2 h-2 w-72 rounded-full bg-gray-300" + > +   + + as="div" + variant="paragraph" + className="mb-2 h-2 w-72 rounded-full bg-gray-300" + > +   + + as="div" + variant="paragraph" + className="mb-2 h-2 w-72 rounded-full bg-gray-300" + > +   + - - Loading... + as="div" + variant="paragraph" + className="mb-2 h-2 w-72 rounded-full bg-gray-300" + > +   + + +  
@@ -132,22 +168,24 @@ export function ImagePlacehoderSkeleton() { }> ```jsx import { Typography } from "@material-tailwind/react"; + export function VideoPlacehoderSkeleton() { return ( -
+
- - Loading... -
); } @@ -174,35 +212,70 @@ export function CardPlacehoderSkeleton() { return ( -
- - - - -
+ as="div" + variant="h1" + className="mb-4 h-3 w-56 rounded-full bg-gray-300" + > +   + + +   + + +   + + +   + + +   +
- +
); diff --git a/routes/html.routes.ts b/routes/html.routes.ts index 0be8593e3..4756a8efb 100644 --- a/routes/html.routes.ts +++ b/routes/html.routes.ts @@ -199,10 +199,10 @@ export const routes = [ name: "Menu", route: "menu", }, - // { - // name: "Mega Menu", - // route: "mega-menu", - // }, + { + name: "Mega Menu", + route: "mega-menu", + }, { name: "Navbar", route: "navbar", From c3477f330478145da4dfca2978ae5d26580229e4 Mon Sep 17 00:00:00 2001 From: Sayed Murtaza Date: Wed, 20 Dec 2023 13:46:08 +0430 Subject: [PATCH 29/38] gallery update --- docs-content/html/gallery/default-gallery.tsx | 20 +-- .../html/gallery/featured-image-gallery.tsx | 14 +- .../html/gallery/masonry-grid-gallery.tsx | 36 +++--- docs-content/html/gallery/quad-gallery.tsx | 58 +++++---- documentation/html/gallery.mdx | 120 +++++++++--------- documentation/react/gallery.mdx | 53 ++++---- 6 files changed, 152 insertions(+), 149 deletions(-) diff --git a/docs-content/html/gallery/default-gallery.tsx b/docs-content/html/gallery/default-gallery.tsx index e8e194d38..8b64fef79 100644 --- a/docs-content/html/gallery/default-gallery.tsx +++ b/docs-content/html/gallery/default-gallery.tsx @@ -1,65 +1,65 @@ export function DefaultGallery() { return ( -
+
gallery-photo
gallery-photo
gallery-photo
gallery-photo
gallery-photo
gallery-photo
gallery-photo
gallery-photo
gallery-photo diff --git a/docs-content/html/gallery/featured-image-gallery.tsx b/docs-content/html/gallery/featured-image-gallery.tsx index 72f1b88a1..8719463bc 100644 --- a/docs-content/html/gallery/featured-image-gallery.tsx +++ b/docs-content/html/gallery/featured-image-gallery.tsx @@ -4,8 +4,8 @@ export function FeaturedImageGallery() {
@@ -13,35 +13,35 @@ export function FeaturedImageGallery() {
gallery-image
gallery-image
gallery-image
gallery-image
gallery-image
diff --git a/docs-content/html/gallery/masonry-grid-gallery.tsx b/docs-content/html/gallery/masonry-grid-gallery.tsx index def3b0077..5a80d242c 100644 --- a/docs-content/html/gallery/masonry-grid-gallery.tsx +++ b/docs-content/html/gallery/masonry-grid-gallery.tsx @@ -4,21 +4,21 @@ export function MasonryGridGallery() {
gallery-photo
gallery-photo
gallery-photo @@ -27,21 +27,21 @@ export function MasonryGridGallery() {
gallery-photo
gallery-photo
gallery-photo @@ -50,22 +50,22 @@ export function MasonryGridGallery() {
gallery-photo
gallery-photo
gallery-photo
@@ -73,15 +73,15 @@ export function MasonryGridGallery() {
gallery-photo
gallery-photo
diff --git a/docs-content/html/gallery/quad-gallery.tsx b/docs-content/html/gallery/quad-gallery.tsx index 40976d8ae..8ce8c1fd2 100644 --- a/docs-content/html/gallery/quad-gallery.tsx +++ b/docs-content/html/gallery/quad-gallery.tsx @@ -1,33 +1,35 @@ export function QuadGallery() { return ( -
-
- -
-
- -
-
- -
-
- +
+
+
+ +
+
+ +
+
+ +
+
+ +
); diff --git a/documentation/html/gallery.mdx b/documentation/html/gallery.mdx index 8c60ec59f..e28ba28e4 100644 --- a/documentation/html/gallery.mdx +++ b/documentation/html/gallery.mdx @@ -26,47 +26,47 @@ See below our simple Gallery example that you can use in your Tailw }> ```html -
+
- gallery-photo
- gallery-photo
- gallery-photo
- gallery-photo
- gallery-photo
- gallery-photo
- gallery-photo
- gallery-photo
- gallery-photo
@@ -87,60 +87,60 @@ See below our simple Gallery example that you can use in your Tailw
- gallery-photo
- gallery-photo + gallery-photo
- gallery-photo + gallery-photo
- gallery-photo
- gallery-photo
- gallery-photo + gallery-photo
- gallery-photo
- gallery-photo + gallery-photo
- gallery-photo
- gallery-photo
- gallery-photo
@@ -160,35 +160,35 @@ See below our simple Gallery example that you can use in your Tailw ```html
-
gallery-image + class="object-cover object-center h-20 max-w-full rounded-lg cursor-pointer" alt="gallery-image" />
gallery-image + class="object-cover object-center h-20 max-w-full rounded-lg cursor-pointer" alt="gallery-image" />
gallery-image + class="object-cover object-center h-20 max-w-full rounded-lg cursor-pointer" alt="gallery-image" />
gallery-image + class="object-cover object-center h-20 max-w-full rounded-lg cursor-pointer" alt="gallery-image" />
gallery-image + class="object-cover object-center h-20 max-w-full rounded-lg cursor-pointer" alt="gallery-image" />
@@ -206,26 +206,28 @@ See below our simple Gallery example that you can use in your Tailw }> ```html -
-
- -
-
- -
-
- -
-
- +
+
+
+ +
+
+ +
+
+ +
+
+ +
``` diff --git a/documentation/react/gallery.mdx b/documentation/react/gallery.mdx index 2c8ca7b25..14d1d27e1 100644 --- a/documentation/react/gallery.mdx +++ b/documentation/react/gallery.mdx @@ -66,12 +66,13 @@ export function DefaultGallery() { "https://images.unsplash.com/photo-1620064916958-605375619af8?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=1493&q=80", }, ]; + return ( -
+
{data.map(({ imageLink }, index) => (
gallery-photo @@ -80,6 +81,7 @@ export function DefaultGallery() {
); } + ``` @@ -94,28 +96,26 @@ export function DefaultGallery() { }> ```jsx export function MasonryGridGallery() { - return ( - export function MasonryGridGallery() { return (
gallery-photo
gallery-photo
gallery-photo @@ -124,21 +124,21 @@ export function MasonryGridGallery() {
gallery-photo
gallery-photo
gallery-photo @@ -147,21 +147,21 @@ export function MasonryGridGallery() {
gallery-photo
gallery-photo
gallery-photo @@ -170,14 +170,14 @@ export function MasonryGridGallery() {
gallery-photo
gallery-photo @@ -186,9 +186,6 @@ export function MasonryGridGallery() {
); } - - ); -} ``` @@ -230,11 +227,12 @@ export function FeaturedImageGallery() { const [active, setActive] = React.useState( "https://images.unsplash.com/photo-1499696010180-025ef6e1a8f9?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1470&q=80", ); + return (
@@ -245,7 +243,7 @@ export function FeaturedImageGallery() { setActive(imgelink)} src={imgelink} - className="h-20 max-w-full cursor-pointer rounded-lg" + className="h-20 max-w-full cursor-pointer rounded-lg object-cover object-center" alt="gallery-image" />
@@ -287,12 +285,13 @@ export function QuadGallery() { "https://images.unsplash.com/photo-1493246507139-91e8fad9978e?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2940&q=80", }, ]; + return (
{data.map(({ imageLink }, index) => (
@@ -319,21 +318,21 @@ import { Carousel } from "@material-tailwind/react"; export function GalleryWithCarousel() { return ( - + image 1 image 2 image 3 ); @@ -525,14 +524,14 @@ export function GalleryWithTab() { {data.map(({ value, images }) => ( {images?.map(({ imageLink }, index) => (
image-photo From 51c32b742d8adfc618c185318113a45c486c073d Mon Sep 17 00:00:00 2001 From: Sayed Murtaza Date: Wed, 20 Dec 2023 14:08:34 +0430 Subject: [PATCH 30/38] html mega menu --- docs-content/html/mega-menu/mega-menu.tsx | 454 ++++++++++++++++---- documentation/html/mega-menu.mdx | 500 ++++++++++++---------- 2 files changed, 648 insertions(+), 306 deletions(-) diff --git a/docs-content/html/mega-menu/mega-menu.tsx b/docs-content/html/mega-menu/mega-menu.tsx index 338f12226..97c6dc379 100644 --- a/docs-content/html/mega-menu/mega-menu.tsx +++ b/docs-content/html/mega-menu/mega-menu.tsx @@ -1,107 +1,403 @@ export function MegaMenuDefault() { return ( - -
-
+ + + + +
+ {" "} + +
+
+
+ Support +
+

+ Reach out to us for assistance or inquiries +

+
+ +
+ + + + + + + + + + + + +
- + ); } diff --git a/documentation/html/mega-menu.mdx b/documentation/html/mega-menu.mdx index 70325ebde..295c3f365 100644 --- a/documentation/html/mega-menu.mdx +++ b/documentation/html/mega-menu.mdx @@ -1,11 +1,10 @@ --- -title: Tailwind CSS Mega Menu for React - Material Tailwind +title: Tailwind CSS Mega Menu for HTML - Material Tailwind description: Customise your web projects with our mega menu component for Tailwind CSS and React using Material Design guidelines. navigation: [ "mega-menu", - "mega-menu-with-hover", - "mage-menu-placement", + ] github: menu @@ -20,239 +19,286 @@ next: navbar Use our responsive Tailwind CSS Mega Menu, that can take the user anywhere on your web app! -See below our Mega Menu example that you can use in your Tailwind CSS and React project. +See below our Mega Menu example that you can use in your Tailwind CSS and HTML project.
}> -```jsx -import React from "react"; -import { - Navbar, - Collapse, - Typography, - IconButton, - List, - ListItem, - Menu, - MenuHandler, - MenuList, - MenuItem, -} from "@material-tailwind/react"; -import { - ChevronDownIcon, - Bars3Icon, - XMarkIcon, -} from "@heroicons/react/24/outline"; -import { - Bars4Icon, - GlobeAmericasIcon, - NewspaperIcon, - PhoneIcon, - RectangleGroupIcon, - SquaresPlusIcon, - SunIcon, - TagIcon, - UserGroupIcon, -} from "@heroicons/react/24/solid"; - -const navListMenuItems = [ - { - title: "Products", - description: "Find the perfect solution for your needs.", - icon: SquaresPlusIcon, - }, - { - title: "About Us", - description: "Meet and learn about our dedication", - icon: UserGroupIcon, - }, - { - title: "Blog", - description: "Find the perfect solution for your needs.", - icon: Bars4Icon, - }, - { - title: "Services", - description: "Learn how we can help you achieve your goals.", - icon: SunIcon, - }, - { - title: "Support", - description: "Reach out to us for assistance or inquiries", - icon: GlobeAmericasIcon, - }, - { - title: "Contact", - description: "Find the perfect solution for your needs.", - icon: PhoneIcon, - }, - { - title: "News", - description: "Read insightful articles, tips, and expert opinions.", - icon: NewspaperIcon, - }, - { - title: "Products", - description: "Find the perfect solution for your needs.", - icon: RectangleGroupIcon, - }, - { - title: "Special Offers", - description: "Explore limited-time deals and bundles", - icon: TagIcon, - }, -]; - -function NavListMenu() { - const [isMenuOpen, setIsMenuOpen] = React.useState(false); - const [isMobileMenuOpen, setIsMobileMenuOpen] = React.useState(false); - const renderItems = navListMenuItems.map( - ({ icon, title, description }, key) => ( - - -
+```html +<> + + + ``` From ab4d3887f26db57dfec1a91b932c9338ef79a372 Mon Sep 17 00:00:00 2001 From: sajadevo Date: Wed, 20 Dec 2023 13:15:10 +0430 Subject: [PATCH 31/38] update the content --- docs-content/html/plugins/index.ts | 1 + docs-content/html/plugins/text-editor.tsx | 421 +++++++ .../react/plugins/text-editor-react.tsx | 10 +- documentation/html/plugins/text-editor.mdx | 486 ++++++++ documentation/react/plugins/text-editor.mdx | 12 +- package.json | 25 +- pages/_app.tsx | 28 +- pages/docs/[...slug].tsx | 8 +- pages/test.tsx | 1058 ----------------- styles/globals.css | 9 + widgets/code-preview.tsx | 28 +- widgets/layout/docs-navbar.tsx | 51 +- widgets/layout/page-map.tsx | 16 +- widgets/layout/sidenav.tsx | 19 +- 14 files changed, 1014 insertions(+), 1158 deletions(-) create mode 100644 docs-content/html/plugins/text-editor.tsx create mode 100644 documentation/html/plugins/text-editor.mdx delete mode 100644 pages/test.tsx diff --git a/docs-content/html/plugins/index.ts b/docs-content/html/plugins/index.ts index f72c351c8..9e751f884 100644 --- a/docs-content/html/plugins/index.ts +++ b/docs-content/html/plugins/index.ts @@ -1,2 +1,3 @@ export * from "./date-picker"; +export * from "./text-editor"; export * from "./clipboard/clipboard-default"; diff --git a/docs-content/html/plugins/text-editor.tsx b/docs-content/html/plugins/text-editor.tsx new file mode 100644 index 000000000..f6de613e3 --- /dev/null +++ b/docs-content/html/plugins/text-editor.tsx @@ -0,0 +1,421 @@ +import React from "react"; +import { Editor } from "@tiptap/core"; +import Placeholder from "@tiptap/extension-placeholder"; +import StarterKit from "@tiptap/starter-kit"; +import Paragraph from "@tiptap/extension-paragraph"; +import Bold from "@tiptap/extension-bold"; +import Underline from "@tiptap/extension-underline"; +import Link from "@tiptap/extension-link"; +import BulletList from "@tiptap/extension-bullet-list"; +import OrderedList from "@tiptap/extension-ordered-list"; +import Blockquote from "@tiptap/extension-blockquote"; + +export function TextEditor() { + React.useEffect(() => { + const editor = new Editor({ + element: document.querySelector( + "#hs-editor-tiptap [data-hs-editor-field]", + ), + extensions: [ + Placeholder.configure({ + placeholder: "Play around with the editor...", + emptyNodeClass: "text-gray-600", + }), + StarterKit, + Paragraph.configure({ + HTMLAttributes: { + class: "text-gray-600", + }, + }), + Bold.configure({ + HTMLAttributes: { + class: "font-bold", + }, + }), + Underline, + Link.configure({ + HTMLAttributes: { + class: + "inline-flex items-center gap-x-1 text-blue-500 decoration-2 hover:underline font-medium", + }, + }), + BulletList.configure({ + HTMLAttributes: { + class: "list-disc list-inside text-gray-800", + }, + }), + OrderedList.configure({ + HTMLAttributes: { + class: "list-decimal list-inside text-gray-800", + }, + }), + Blockquote.configure({ + HTMLAttributes: { + class: "text-gray-800 sm:text-xl", + }, + }), + ], + }); + const actions = [ + { + id: "#hs-editor-tiptap [data-hs-editor-bold]", + fn: () => editor.chain().focus().toggleBold().run(), + }, + { + id: "#hs-editor-tiptap [data-hs-editor-italic]", + fn: () => editor.chain().focus().toggleItalic().run(), + }, + { + id: "#hs-editor-tiptap [data-hs-editor-underline]", + fn: () => editor.chain().focus().toggleUnderline().run(), + }, + { + id: "#hs-editor-tiptap [data-hs-editor-strike]", + fn: () => editor.chain().focus().toggleStrike().run(), + }, + { + id: "#hs-editor-tiptap [data-hs-editor-link]", + fn: () => { + const url = window.prompt("URL"); + editor + .chain() + .focus() + .extendMarkRange("link") + .setLink({ href: url }) + .run(); + }, + }, + { + id: "#hs-editor-tiptap [data-hs-editor-ol]", + fn: () => editor.chain().focus().toggleOrderedList().run(), + }, + { + id: "#hs-editor-tiptap [data-hs-editor-ul]", + fn: () => editor.chain().focus().toggleBulletList().run(), + }, + { + id: "#hs-editor-tiptap [data-hs-editor-blockquote]", + fn: () => editor.chain().focus().toggleBlockquote().run(), + }, + { + id: "#hs-editor-tiptap [data-hs-editor-code]", + fn: () => editor.chain().focus().toggleCode().run(), + }, + ]; + + actions.forEach(({ id, fn }) => { + const action = document.querySelector(id); + + if (action === null) return; + + action.addEventListener("click", fn); + }); + }, []); + + return ( +
+
+
+ + + + + + + + +
+
+
+
+ ); +} diff --git a/docs-content/react/plugins/text-editor-react.tsx b/docs-content/react/plugins/text-editor-react.tsx index cff72bf53..7c63a74cf 100644 --- a/docs-content/react/plugins/text-editor-react.tsx +++ b/docs-content/react/plugins/text-editor-react.tsx @@ -719,7 +719,6 @@ function FloatingLinkEditor({ editor }) { {linkUrl} event.preventDefault()} @@ -847,13 +846,12 @@ function ToolbarPlugin() { return (
{supportedBlockTypes.has(blockType) && ( <> + + + + + + + +
+
+
+
+ + +``` + + +
+
+ + +## Adding Styles + + +You need to put the below code to your tailwind css stylesheet file, this will add the styles for elements and formatters of the editor. + +```css +.tiptap ul p, +.tiptap ol p { + @apply inline; +} + +.tiptap p.is-editor-empty:first-child::before { + @apply pointer-events-none float-left h-0 text-sm; +} +``` \ No newline at end of file diff --git a/documentation/react/plugins/text-editor.mdx b/documentation/react/plugins/text-editor.mdx index 0337b0bad..d87f9247b 100644 --- a/documentation/react/plugins/text-editor.mdx +++ b/documentation/react/plugins/text-editor.mdx @@ -763,7 +763,6 @@ function FloatingLinkEditor({ editor }) { {linkUrl} event.preventDefault()} @@ -891,13 +890,12 @@ function ToolbarPlugin() { return (
{supportedBlockTypes.has(blockType) && ( <> - {showBlockOptionsDropDown && - createPortal( - , - document.body, - )} - - - )} - {blockType === "code" ? ( - <> - -
- - - ⌘ - - K - +
+ + + ⌘ + + K +
- - ab + + ab
@@ -143,7 +143,7 @@ export function DocsNavbar({ slug, setMobileNav }: DocsNavbar) { /> } - className="items-center gap-2 bg-white border py-1 !border-blue-gray-100 !pr-2 text-xs text-blue-gray-900" + className="items-center gap-2 border !border-blue-gray-100 bg-white py-1 !pr-2 text-xs text-blue-gray-900" /> @@ -159,7 +159,12 @@ export function DocsNavbar({ slug, setMobileNav }: DocsNavbar) { - +
@@ -185,7 +190,11 @@ export function DocsNavbar({ slug, setMobileNav }: DocsNavbar) { Material
Tailwind diff --git a/widgets/layout/page-map.tsx b/widgets/layout/page-map.tsx index 862877b0b..ef07da045 100644 --- a/widgets/layout/page-map.tsx +++ b/widgets/layout/page-map.tsx @@ -17,14 +17,14 @@ import { CardHeader, } from "@material-tailwind/react"; import Link from "next/link"; -import { useRouter } from "next/router"; +import { usePathname } from "next/navigation"; export function PageMap({ type, frontMatter }) { - const { query } = useRouter(); + const pathname = usePathname(); const [open, setOpen] = React.useState(false); const [hash, setHash] = React.useState(frontMatter[0]); const [feedbackType, setFeedbackType] = React.useState("issue"); - const frameWorkType = query?.slug?.[0]; + const frameWorkType = pathname.includes("/docs/react") ? "react" : "html"; const handleOpen = () => setOpen(!open); @@ -43,7 +43,7 @@ export function PageMap({ type, frontMatter }) { }, []); return ( -