From 7a6efabad944953e3c828d81975a0182e042ac19 Mon Sep 17 00:00:00 2001 From: Dhaval Vira Date: Sun, 2 Jun 2024 15:06:40 +0530 Subject: [PATCH 01/10] feat(components): add Clipboard --- .changeset/poor-tools-hide.md | 5 ++ .../web/content/docs/components/clipboard.mdx | 42 +++++++++++ apps/web/data/docs-sidebar.ts | 1 + .../web/examples/clipboard/clipboard.root.tsx | 57 +++++++++++++++ .../examples/clipboard/clipboard.withIcon.tsx | 57 +++++++++++++++ .../clipboard/clipboard.withIconText.tsx | 57 +++++++++++++++ apps/web/examples/clipboard/index.ts | 3 + apps/web/examples/index.ts | 1 + .../Clipboard/Clipboard.stories.tsx | 72 +++++++++++++++++++ .../ui/src/components/Clipboard/Clipboard.tsx | 56 +++++++++++++++ .../Clipboard/ClipboardWithIcon.tsx | 44 ++++++++++++ .../Clipboard/ClipboardWithIconText.tsx | 56 +++++++++++++++ packages/ui/src/components/Clipboard/index.ts | 8 +++ .../ui/src/components/Clipboard/theme.tsx | 28 ++++++++ .../src/components/Flowbite/FlowbiteTheme.ts | 2 + packages/ui/src/index.ts | 1 + packages/ui/src/theme.ts | 2 + 17 files changed, 492 insertions(+) create mode 100644 .changeset/poor-tools-hide.md create mode 100644 apps/web/content/docs/components/clipboard.mdx create mode 100644 apps/web/examples/clipboard/clipboard.root.tsx create mode 100644 apps/web/examples/clipboard/clipboard.withIcon.tsx create mode 100644 apps/web/examples/clipboard/clipboard.withIconText.tsx create mode 100644 apps/web/examples/clipboard/index.ts create mode 100644 packages/ui/src/components/Clipboard/Clipboard.stories.tsx create mode 100644 packages/ui/src/components/Clipboard/Clipboard.tsx create mode 100644 packages/ui/src/components/Clipboard/ClipboardWithIcon.tsx create mode 100644 packages/ui/src/components/Clipboard/ClipboardWithIconText.tsx create mode 100644 packages/ui/src/components/Clipboard/index.ts create mode 100644 packages/ui/src/components/Clipboard/theme.tsx diff --git a/.changeset/poor-tools-hide.md b/.changeset/poor-tools-hide.md new file mode 100644 index 000000000..69a7f7542 --- /dev/null +++ b/.changeset/poor-tools-hide.md @@ -0,0 +1,5 @@ +--- +"flowbite-react": patch +--- + +feat(components): add "Clipboard" diff --git a/apps/web/content/docs/components/clipboard.mdx b/apps/web/content/docs/components/clipboard.mdx new file mode 100644 index 000000000..60c510027 --- /dev/null +++ b/apps/web/content/docs/components/clipboard.mdx @@ -0,0 +1,42 @@ +--- +title: React Clipboard - Flowbite +description: Use the clipboard component to copy text, data or lines of code to the clipboard with a single click based on various styles and examples coded with Tailwind CSS and Flowbite +--- + +The copy to clipboard component allows you to copy text, lines of code, contact details or any other data to the clipboard with a single click on a trigger element such as a button. This component can be used to copy text from an input field, textarea, code block or even address fields in a form element. + +These components are built with Tailwind CSS and Flowbite React and can be found on the internet on websites such as Bitly, Cloudflare, Amazon AWS and almost all open-source projects and documentations. + +Import the component from `flowbite-react` to use the clipboard element: + +```jsx +import { Clipboard } from "flowbite-react"; + +## Default copy to clipboard + +Use this example to copy the content of an input text field by clicking on a button and update the button text. + + + +## Input with copy button + +This example can be used to copy the content of an input field by clicking on a button with an icon positioned inside the form element and also show a tooltip with a message when the text has been copied. + + + +## Copy button with text + +Use this example to show a copy button inside the input field with a text label and icon that updates to a success state when the text has been copied. + + + +## Theme + +To learn more about how to customize the appearance of components, please see the [Theme docs](/docs/customize/theme). + + + +## References + +- [Flowbite Datepicker](https://flowbite.com/docs/components/clipboard/) +``` diff --git a/apps/web/data/docs-sidebar.ts b/apps/web/data/docs-sidebar.ts index 73af25d81..933eaf146 100644 --- a/apps/web/data/docs-sidebar.ts +++ b/apps/web/data/docs-sidebar.ts @@ -63,6 +63,7 @@ export const DOCS_SIDEBAR: DocsSidebarSection[] = [ { title: "Button group", href: "/docs/components/button-group" }, { title: "Card", href: "/docs/components/card" }, { title: "Carousel", href: "/docs/components/carousel" }, + { title: "Clipboard", href: "/docs/components/clipboard", isNew: true }, { title: "Datepicker", href: "/docs/components/datepicker", isNew: true }, { title: "Drawer", href: "/docs/components/drawer", isNew: true }, { title: "Dropdown", href: "/docs/components/dropdown" }, diff --git a/apps/web/examples/clipboard/clipboard.root.tsx b/apps/web/examples/clipboard/clipboard.root.tsx new file mode 100644 index 000000000..0cedf60f3 --- /dev/null +++ b/apps/web/examples/clipboard/clipboard.root.tsx @@ -0,0 +1,57 @@ +import { Clipboard } from "flowbite-react"; +import type { CodeData } from "~/components/code-demo"; + +const code = ` +"use client"; + +import { Clipboard } from "flowbite-react" + +export function Component() { + return ( +
+ + + +
+ ) +} +`; + +export function Component() { + return ( +
+ + + +
+ ); +} + +export const root: CodeData = { + type: "single", + code: [ + { + fileName: "client", + language: "tsx", + code, + }, + ], + githubSlug: "clipboard/clipboard.root.tsx", + component: , +}; diff --git a/apps/web/examples/clipboard/clipboard.withIcon.tsx b/apps/web/examples/clipboard/clipboard.withIcon.tsx new file mode 100644 index 000000000..819d23fb1 --- /dev/null +++ b/apps/web/examples/clipboard/clipboard.withIcon.tsx @@ -0,0 +1,57 @@ +import { Clipboard } from "flowbite-react"; +import type { CodeData } from "~/components/code-demo"; + +const code = ` +"use client"; + +import { Clipboard } from "flowbite-react" + +export function Component() { + return ( +
+ + + +
+ ) +} +`; + +export function Component() { + return ( +
+ + + +
+ ); +} + +export const withIcon: CodeData = { + type: "single", + code: [ + { + fileName: "client", + language: "tsx", + code, + }, + ], + githubSlug: "clipboard/clipboard.withIcon.tsx", + component: , +}; diff --git a/apps/web/examples/clipboard/clipboard.withIconText.tsx b/apps/web/examples/clipboard/clipboard.withIconText.tsx new file mode 100644 index 000000000..b16eb6750 --- /dev/null +++ b/apps/web/examples/clipboard/clipboard.withIconText.tsx @@ -0,0 +1,57 @@ +import { Clipboard } from "flowbite-react"; +import type { CodeData } from "~/components/code-demo"; + +const code = ` +"use client"; + +import { Clipboard } from "flowbite-react" + +export function Component() { + return ( +
+ + + +
+ ) +} +`; + +export function Component() { + return ( +
+ + + +
+ ); +} + +export const withIconText: CodeData = { + type: "single", + code: [ + { + fileName: "client", + language: "tsx", + code, + }, + ], + githubSlug: "clipboard/clipboard.withIconText.tsx", + component: , +}; diff --git a/apps/web/examples/clipboard/index.ts b/apps/web/examples/clipboard/index.ts new file mode 100644 index 000000000..176b081e7 --- /dev/null +++ b/apps/web/examples/clipboard/index.ts @@ -0,0 +1,3 @@ +export { root } from "./clipboard.root"; +export { withIcon } from "./clipboard.withIcon"; +export { withIconText } from "./clipboard.withIconText"; diff --git a/apps/web/examples/index.ts b/apps/web/examples/index.ts index 8f1c4575d..8491bc69b 100644 --- a/apps/web/examples/index.ts +++ b/apps/web/examples/index.ts @@ -9,6 +9,7 @@ export * as button from "./button"; export * as buttonGroup from "./buttonGroup"; export * as card from "./card"; export * as carousel from "./carousel"; +export * as clipboard from "./clipboard"; export * as datepicker from "./datepicker"; export * as drawer from "./drawer"; export * as dropdown from "./dropdown"; diff --git a/packages/ui/src/components/Clipboard/Clipboard.stories.tsx b/packages/ui/src/components/Clipboard/Clipboard.stories.tsx new file mode 100644 index 000000000..abc7dac35 --- /dev/null +++ b/packages/ui/src/components/Clipboard/Clipboard.stories.tsx @@ -0,0 +1,72 @@ +import type { Meta, StoryFn } from "@storybook/react"; +// import { FaClipboardList } from "react-icons/fa6"; +import type { ClipboardProps } from "./Clipboard"; +import { Clipboard } from "./Clipboard"; +import { ClipboardWithIcon } from "./ClipboardWithIcon"; +import { ClipboardWithIconText } from "./ClipboardWithIconText"; + +export default { + title: "Components/Clipboard", + component: Clipboard, +} as Meta; + +const DefaultTemplate: StoryFn = () => ( +
+ + + +
+); + +export const Default = DefaultTemplate.bind({}); + +const CopyIconTemplate: StoryFn = () => ( +
+
+ + + +
+
+); + +export const CopyIcon = CopyIconTemplate.bind({}); + +const CopyIconTextTemplate: StoryFn = () => ( +
+
+ + + +
+
+); + +export const CopyIconText = CopyIconTextTemplate.bind({}); diff --git a/packages/ui/src/components/Clipboard/Clipboard.tsx b/packages/ui/src/components/Clipboard/Clipboard.tsx new file mode 100644 index 000000000..33b1e396f --- /dev/null +++ b/packages/ui/src/components/Clipboard/Clipboard.tsx @@ -0,0 +1,56 @@ +import { forwardRef, useState, type ComponentProps, type ReactNode } from "react"; +import { twMerge } from "tailwind-merge"; +import { mergeDeep } from "../../helpers/merge-deep"; +import { getTheme } from "../../theme-store"; +import type { DeepPartial } from "../../types"; +import { Tooltip } from "../Tooltip"; +import { ClipboardWithIcon } from "./ClipboardWithIcon"; +import type { FlowbiteClipboardWithIconTheme } from "./ClipboardWithIcon"; +import { ClipboardWithIconText } from "./ClipboardWithIconText"; +import type { FlowbiteClipboardWithIconTextTheme } from "./ClipboardWithIconText"; + +export interface FlowbiteClipboardTheme { + button: { + base: string; + label: string; + }; + withIcon: FlowbiteClipboardWithIconTheme; + withIconText: FlowbiteClipboardWithIconTextTheme; +} + +export interface ClipboardProps extends ComponentProps<"button"> { + valueToCopy: string; + label?: ReactNode; + theme?: DeepPartial; +} + +const ClipboardComponent = forwardRef( + ({ className, valueToCopy, label, theme: customTheme = {}, ...rest }, ref) => { + const [isJustCopied, setIsJustCopied] = useState(false); + + const theme = mergeDeep(getTheme().clipboard.button, customTheme); + + const copyToClipboard = () => { + setIsJustCopied(true); + navigator?.clipboard?.writeText(valueToCopy); + setTimeout(() => setIsJustCopied(false), 4000); + }; + + return ( + + + + ); + }, +); + +ClipboardComponent.displayName = "Clipboard"; +ClipboardWithIcon.displayName = "ClipboardWithIcon"; +ClipboardWithIconText.displayName = "ClipboardWithIconText"; + +export const Clipboard = Object.assign(ClipboardComponent, { + WithIcon: ClipboardWithIcon, + WithIconText: ClipboardWithIconText, +}); diff --git a/packages/ui/src/components/Clipboard/ClipboardWithIcon.tsx b/packages/ui/src/components/Clipboard/ClipboardWithIcon.tsx new file mode 100644 index 000000000..a7e6a1d57 --- /dev/null +++ b/packages/ui/src/components/Clipboard/ClipboardWithIcon.tsx @@ -0,0 +1,44 @@ +import { forwardRef, useState, type ComponentProps, type FC } from "react"; +import { FaCheck, FaClipboardList } from "react-icons/fa6"; +import { twMerge } from "tailwind-merge"; +import { mergeDeep } from "../../helpers/merge-deep"; +import { getTheme } from "../../theme-store"; +import type { DeepPartial } from "../../types"; + +export interface FlowbiteClipboardWithIconTheme { + base: string; + icon: { + defaultIcon: string; + successIcon: string; + }; +} + +export interface ClipboardWithIconProps extends ComponentProps<"button"> { + valueToCopy: string; + icon?: FC>; + theme?: DeepPartial; +} + +export const ClipboardWithIcon = forwardRef( + ({ valueToCopy, icon: Icon = FaClipboardList, theme: customTheme = {}, className, ...rest }, ref) => { + const [isJustCopied, setIsJustCopied] = useState(false); + + const theme = mergeDeep(getTheme().clipboard.withIcon, customTheme); + + const copyToClipboard = () => { + setIsJustCopied(true); + navigator?.clipboard?.writeText(valueToCopy); + setTimeout(() => setIsJustCopied(false), 4000); + }; + + return ( + + ); + }, +); diff --git a/packages/ui/src/components/Clipboard/ClipboardWithIconText.tsx b/packages/ui/src/components/Clipboard/ClipboardWithIconText.tsx new file mode 100644 index 000000000..f3d97b687 --- /dev/null +++ b/packages/ui/src/components/Clipboard/ClipboardWithIconText.tsx @@ -0,0 +1,56 @@ +import { forwardRef, useState, type ComponentProps, type FC } from "react"; +import { FaCheck, FaClipboardList } from "react-icons/fa6"; +import { twMerge } from "tailwind-merge"; +import { mergeDeep } from "../../helpers/merge-deep"; +import { getTheme } from "../../theme-store"; +import type { DeepPartial } from "../../types"; + +export interface FlowbiteClipboardWithIconTextTheme { + base: string; + label: { + base: string; + defaultText: string; + successText: string; + }; + icon: { + defaultIcon: string; + successIcon: string; + }; +} + +export interface ClipboardWithIconTextProps extends ComponentProps<"button"> { + valueToCopy: string; + label?: string; + icon?: FC>; + theme?: DeepPartial; +} + +export const ClipboardWithIconText = forwardRef( + ({ valueToCopy, icon: Icon = FaClipboardList, label = "Copy", theme: customTheme = {}, className, ...rest }, ref) => { + const [isJustCopied, setIsJustCopied] = useState(false); + + const theme = mergeDeep(getTheme().clipboard.withIconText, customTheme); + + const copyToClipboard = () => { + setIsJustCopied(true); + navigator?.clipboard?.writeText(valueToCopy); + setTimeout(() => setIsJustCopied(false), 4000); + }; + + return ( + + ); + }, +); diff --git a/packages/ui/src/components/Clipboard/index.ts b/packages/ui/src/components/Clipboard/index.ts new file mode 100644 index 000000000..b87b42b3b --- /dev/null +++ b/packages/ui/src/components/Clipboard/index.ts @@ -0,0 +1,8 @@ +export { Clipboard } from "./Clipboard"; +export type { ClipboardProps, FlowbiteClipboardTheme } from "./Clipboard"; + +export { ClipboardWithIcon } from "./ClipboardWithIcon"; +export type { ClipboardWithIconProps, FlowbiteClipboardWithIconTheme } from "./ClipboardWithIcon"; + +export { ClipboardWithIconText } from "./ClipboardWithIconText"; +export type { ClipboardWithIconTextProps, FlowbiteClipboardWithIconTextTheme } from "./ClipboardWithIconText"; diff --git a/packages/ui/src/components/Clipboard/theme.tsx b/packages/ui/src/components/Clipboard/theme.tsx new file mode 100644 index 000000000..216dfb72f --- /dev/null +++ b/packages/ui/src/components/Clipboard/theme.tsx @@ -0,0 +1,28 @@ +import { createTheme } from "../../helpers/create-theme"; +import type { FlowbiteClipboardTheme } from "./Clipboard"; + +export const clipboardTheme: FlowbiteClipboardTheme = createTheme({ + button: { + base: "inline-flex w-full items-center justify-center rounded-lg bg-blue-700 px-5 py-3 hover:bg-blue-800 focus:outline-none focus:ring-4 focus:ring-blue-300 dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800", + label: "text-center text-sm font-medium text-white sm:w-auto", + }, + withIcon: { + base: "absolute end-2 top-1/2 inline-flex -translate-y-1/2 items-center justify-center rounded-lg p-2 text-gray-500 hover:bg-gray-100 dark:text-gray-400 dark:hover:bg-gray-800", + icon: { + defaultIcon: "h-4 w-4", + successIcon: "h-4 w-4 text-blue-700 dark:text-blue-500", + }, + }, + withIconText: { + base: "absolute end-2.5 top-1/2 inline-flex -translate-y-1/2 items-center justify-center rounded-lg border border-gray-200 bg-white px-2.5 py-2 text-gray-900 hover:bg-gray-100 dark:border-gray-600 dark:bg-gray-800 dark:text-gray-400 dark:hover:bg-gray-700", + icon: { + defaultIcon: "me-1.5 h-3 w-3", + successIcon: "me-1.5 h-3 w-3 text-blue-700 dark:text-blue-500", + }, + label: { + base: "inline-flex items-center", + defaultText: "text-xs font-semibold", + successText: "text-xs font-semibold text-blue-700 dark:text-blue-500", + }, + }, +}); diff --git a/packages/ui/src/components/Flowbite/FlowbiteTheme.ts b/packages/ui/src/components/Flowbite/FlowbiteTheme.ts index 3da3a6d32..8489755ce 100644 --- a/packages/ui/src/components/Flowbite/FlowbiteTheme.ts +++ b/packages/ui/src/components/Flowbite/FlowbiteTheme.ts @@ -9,6 +9,7 @@ import type { FlowbiteButtonGroupTheme, FlowbiteButtonTheme } from "../Button"; import type { FlowbiteCardTheme } from "../Card"; import type { FlowbiteCarouselTheme } from "../Carousel"; import type { FlowbiteCheckboxTheme } from "../Checkbox"; +import type { FlowbiteClipboardTheme } from "../Clipboard"; import type { FlowbiteDarkThemeToggleTheme } from "../DarkThemeToggle"; import type { FlowbiteDatepickerTheme } from "../Datepicker"; import type { FlowbiteDrawerTheme } from "../Drawer"; @@ -56,6 +57,7 @@ export interface FlowbiteTheme { card: FlowbiteCardTheme; carousel: FlowbiteCarouselTheme; checkbox: FlowbiteCheckboxTheme; + clipboard: FlowbiteClipboardTheme; darkThemeToggle: FlowbiteDarkThemeToggleTheme; datepicker: FlowbiteDatepickerTheme; drawer: FlowbiteDrawerTheme; diff --git a/packages/ui/src/index.ts b/packages/ui/src/index.ts index ac9ade2cd..f3a0ec786 100644 --- a/packages/ui/src/index.ts +++ b/packages/ui/src/index.ts @@ -10,6 +10,7 @@ export * from "./components/Button"; export * from "./components/Card"; export * from "./components/Carousel"; export * from "./components/Checkbox"; +export * from "./components/Clipboard"; export * from "./components/DarkThemeToggle"; export * from "./components/Datepicker"; export * from "./components/Drawer"; diff --git a/packages/ui/src/theme.ts b/packages/ui/src/theme.ts index 73d563ae3..1697b4b94 100644 --- a/packages/ui/src/theme.ts +++ b/packages/ui/src/theme.ts @@ -9,6 +9,7 @@ import { buttonGroupTheme, buttonTheme } from "./components/Button/theme"; import { cardTheme } from "./components/Card/theme"; import { carouselTheme } from "./components/Carousel/theme"; import { checkboxTheme } from "./components/Checkbox/theme"; +import { clipboardTheme } from "./components/Clipboard/theme"; import { darkThemeToggleTheme } from "./components/DarkThemeToggle/theme"; import { datePickerTheme } from "./components/Datepicker/theme"; import { drawerTheme } from "./components/Drawer/theme"; @@ -54,6 +55,7 @@ export const theme: FlowbiteTheme = { card: cardTheme, carousel: carouselTheme, checkbox: checkboxTheme, + clipboard: clipboardTheme, datepicker: datePickerTheme, darkThemeToggle: darkThemeToggleTheme, drawer: drawerTheme, From c2d193fd9581a54d3c05153c6b93a4ef2a6764c2 Mon Sep 17 00:00:00 2001 From: Dhaval Vira Date: Sun, 2 Jun 2024 15:35:00 +0530 Subject: [PATCH 02/10] PR Build error fixed --- apps/web/examples/clipboard/clipboard.withIcon.tsx | 4 ++-- apps/web/examples/clipboard/clipboard.withIconText.tsx | 4 ++-- packages/ui/src/components/Clipboard/Clipboard.tsx | 2 ++ packages/ui/src/components/Clipboard/ClipboardWithIcon.tsx | 2 ++ .../ui/src/components/Clipboard/ClipboardWithIconText.tsx | 2 ++ 5 files changed, 10 insertions(+), 4 deletions(-) diff --git a/apps/web/examples/clipboard/clipboard.withIcon.tsx b/apps/web/examples/clipboard/clipboard.withIcon.tsx index 819d23fb1..4b4cce69c 100644 --- a/apps/web/examples/clipboard/clipboard.withIcon.tsx +++ b/apps/web/examples/clipboard/clipboard.withIcon.tsx @@ -18,7 +18,7 @@ export function Component() { disabled readOnly /> - + ) } @@ -38,7 +38,7 @@ export function Component() { disabled readOnly /> - + ); } diff --git a/apps/web/examples/clipboard/clipboard.withIconText.tsx b/apps/web/examples/clipboard/clipboard.withIconText.tsx index b16eb6750..9f0e6a678 100644 --- a/apps/web/examples/clipboard/clipboard.withIconText.tsx +++ b/apps/web/examples/clipboard/clipboard.withIconText.tsx @@ -18,7 +18,7 @@ export function Component() { disabled readOnly /> - + ) } @@ -38,7 +38,7 @@ export function Component() { disabled readOnly /> - + ); } diff --git a/packages/ui/src/components/Clipboard/Clipboard.tsx b/packages/ui/src/components/Clipboard/Clipboard.tsx index 33b1e396f..39a2a80aa 100644 --- a/packages/ui/src/components/Clipboard/Clipboard.tsx +++ b/packages/ui/src/components/Clipboard/Clipboard.tsx @@ -1,3 +1,5 @@ +"use client"; + import { forwardRef, useState, type ComponentProps, type ReactNode } from "react"; import { twMerge } from "tailwind-merge"; import { mergeDeep } from "../../helpers/merge-deep"; diff --git a/packages/ui/src/components/Clipboard/ClipboardWithIcon.tsx b/packages/ui/src/components/Clipboard/ClipboardWithIcon.tsx index a7e6a1d57..184550109 100644 --- a/packages/ui/src/components/Clipboard/ClipboardWithIcon.tsx +++ b/packages/ui/src/components/Clipboard/ClipboardWithIcon.tsx @@ -1,3 +1,5 @@ +"use client"; + import { forwardRef, useState, type ComponentProps, type FC } from "react"; import { FaCheck, FaClipboardList } from "react-icons/fa6"; import { twMerge } from "tailwind-merge"; diff --git a/packages/ui/src/components/Clipboard/ClipboardWithIconText.tsx b/packages/ui/src/components/Clipboard/ClipboardWithIconText.tsx index f3d97b687..bbb87cfe8 100644 --- a/packages/ui/src/components/Clipboard/ClipboardWithIconText.tsx +++ b/packages/ui/src/components/Clipboard/ClipboardWithIconText.tsx @@ -1,3 +1,5 @@ +"use client"; + import { forwardRef, useState, type ComponentProps, type FC } from "react"; import { FaCheck, FaClipboardList } from "react-icons/fa6"; import { twMerge } from "tailwind-merge"; From de00e28c767de6dc399ec4feee718e6dedf4389f Mon Sep 17 00:00:00 2001 From: Dhaval Vira Date: Sun, 2 Jun 2024 15:39:48 +0530 Subject: [PATCH 03/10] docs typo mistake --- apps/web/content/docs/components/clipboard.mdx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/apps/web/content/docs/components/clipboard.mdx b/apps/web/content/docs/components/clipboard.mdx index 60c510027..c1cf920a2 100644 --- a/apps/web/content/docs/components/clipboard.mdx +++ b/apps/web/content/docs/components/clipboard.mdx @@ -11,6 +11,7 @@ Import the component from `flowbite-react` to use the clipboard element: ```jsx import { Clipboard } from "flowbite-react"; +``` ## Default copy to clipboard @@ -39,4 +40,7 @@ To learn more about how to customize the appearance of components, please see th ## References - [Flowbite Datepicker](https://flowbite.com/docs/components/clipboard/) + +``` + ``` From 3d73490de92f369a42d535a340c46f1337b275d3 Mon Sep 17 00:00:00 2001 From: Dhaval Vira Date: Sun, 2 Jun 2024 15:42:09 +0530 Subject: [PATCH 04/10] docs typo mistake --- apps/web/content/docs/components/clipboard.mdx | 4 ---- 1 file changed, 4 deletions(-) diff --git a/apps/web/content/docs/components/clipboard.mdx b/apps/web/content/docs/components/clipboard.mdx index c1cf920a2..447ac9b4c 100644 --- a/apps/web/content/docs/components/clipboard.mdx +++ b/apps/web/content/docs/components/clipboard.mdx @@ -40,7 +40,3 @@ To learn more about how to customize the appearance of components, please see th ## References - [Flowbite Datepicker](https://flowbite.com/docs/components/clipboard/) - -``` - -``` From b0bf04720e4624f0b9196fdd8b0e014e471823c6 Mon Sep 17 00:00:00 2001 From: Dhaval Vira Date: Sun, 2 Jun 2024 15:49:12 +0530 Subject: [PATCH 05/10] added missing use client in example --- apps/web/examples/clipboard/clipboard.root.tsx | 2 ++ apps/web/examples/clipboard/clipboard.withIcon.tsx | 2 ++ apps/web/examples/clipboard/clipboard.withIconText.tsx | 2 ++ 3 files changed, 6 insertions(+) diff --git a/apps/web/examples/clipboard/clipboard.root.tsx b/apps/web/examples/clipboard/clipboard.root.tsx index 0cedf60f3..d48ddc09c 100644 --- a/apps/web/examples/clipboard/clipboard.root.tsx +++ b/apps/web/examples/clipboard/clipboard.root.tsx @@ -1,3 +1,5 @@ +"use client"; + import { Clipboard } from "flowbite-react"; import type { CodeData } from "~/components/code-demo"; diff --git a/apps/web/examples/clipboard/clipboard.withIcon.tsx b/apps/web/examples/clipboard/clipboard.withIcon.tsx index 4b4cce69c..f34c0d97b 100644 --- a/apps/web/examples/clipboard/clipboard.withIcon.tsx +++ b/apps/web/examples/clipboard/clipboard.withIcon.tsx @@ -1,3 +1,5 @@ +"use client"; + import { Clipboard } from "flowbite-react"; import type { CodeData } from "~/components/code-demo"; diff --git a/apps/web/examples/clipboard/clipboard.withIconText.tsx b/apps/web/examples/clipboard/clipboard.withIconText.tsx index 9f0e6a678..6e740b2f2 100644 --- a/apps/web/examples/clipboard/clipboard.withIconText.tsx +++ b/apps/web/examples/clipboard/clipboard.withIconText.tsx @@ -1,3 +1,5 @@ +"use client"; + import { Clipboard } from "flowbite-react"; import type { CodeData } from "~/components/code-demo"; From ca4554f1f915e0c77b386100008ad7232b6f7629 Mon Sep 17 00:00:00 2001 From: Dhaval Vira Date: Sun, 2 Jun 2024 15:58:34 +0530 Subject: [PATCH 06/10] export naming fix --- packages/ui/src/components/Clipboard/Clipboard.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/ui/src/components/Clipboard/Clipboard.tsx b/packages/ui/src/components/Clipboard/Clipboard.tsx index 39a2a80aa..941629c8d 100644 --- a/packages/ui/src/components/Clipboard/Clipboard.tsx +++ b/packages/ui/src/components/Clipboard/Clipboard.tsx @@ -49,8 +49,8 @@ const ClipboardComponent = forwardRef( ); ClipboardComponent.displayName = "Clipboard"; -ClipboardWithIcon.displayName = "ClipboardWithIcon"; -ClipboardWithIconText.displayName = "ClipboardWithIconText"; +ClipboardWithIcon.displayName = "Clipboard.WithIcon"; +ClipboardWithIconText.displayName = "Clipboard.WithIconText"; export const Clipboard = Object.assign(ClipboardComponent, { WithIcon: ClipboardWithIcon, From cbc4b5843bc101008871229c95b46e5735aa06c7 Mon Sep 17 00:00:00 2001 From: Dhaval Vira Date: Sun, 2 Jun 2024 16:10:03 +0530 Subject: [PATCH 07/10] small change --- .../src/components/Clipboard/Clipboard.stories.tsx | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/ui/src/components/Clipboard/Clipboard.stories.tsx b/packages/ui/src/components/Clipboard/Clipboard.stories.tsx index abc7dac35..7374f0f54 100644 --- a/packages/ui/src/components/Clipboard/Clipboard.stories.tsx +++ b/packages/ui/src/components/Clipboard/Clipboard.stories.tsx @@ -2,8 +2,8 @@ import type { Meta, StoryFn } from "@storybook/react"; // import { FaClipboardList } from "react-icons/fa6"; import type { ClipboardProps } from "./Clipboard"; import { Clipboard } from "./Clipboard"; -import { ClipboardWithIcon } from "./ClipboardWithIcon"; -import { ClipboardWithIconText } from "./ClipboardWithIconText"; +import type { ClipboardWithIconProps } from "./ClipboardWithIcon"; +import type { ClipboardWithIconTextProps } from "./ClipboardWithIconText"; export default { title: "Components/Clipboard", @@ -29,7 +29,7 @@ const DefaultTemplate: StoryFn = () => ( export const Default = DefaultTemplate.bind({}); -const CopyIconTemplate: StoryFn = () => ( +const CopyIconTemplate: StoryFn = () => (
); export const CopyIcon = CopyIconTemplate.bind({}); -const CopyIconTextTemplate: StoryFn = () => ( +const CopyIconTextTemplate: StoryFn = () => (
); From 0b44dc27a8582b3485aa675fb3f7e8898ad6495c Mon Sep 17 00:00:00 2001 From: Dhaval Vira Date: Mon, 3 Jun 2024 06:31:16 +0530 Subject: [PATCH 08/10] Example updated --- .../examples/clipboard/clipboard.withIcon.tsx | 50 +++++++++++-------- .../clipboard/clipboard.withIconText.tsx | 50 +++++++++++-------- 2 files changed, 56 insertions(+), 44 deletions(-) diff --git a/apps/web/examples/clipboard/clipboard.withIcon.tsx b/apps/web/examples/clipboard/clipboard.withIcon.tsx index f34c0d97b..4e7c51d10 100644 --- a/apps/web/examples/clipboard/clipboard.withIcon.tsx +++ b/apps/web/examples/clipboard/clipboard.withIcon.tsx @@ -10,17 +10,21 @@ import { Clipboard } from "flowbite-react" export function Component() { return ( -
+
+
- - + + +
) } @@ -28,19 +32,21 @@ export function Component() { export function Component() { return ( -
- - - +
+
+ + + +
); } diff --git a/apps/web/examples/clipboard/clipboard.withIconText.tsx b/apps/web/examples/clipboard/clipboard.withIconText.tsx index 6e740b2f2..e8640398c 100644 --- a/apps/web/examples/clipboard/clipboard.withIconText.tsx +++ b/apps/web/examples/clipboard/clipboard.withIconText.tsx @@ -10,17 +10,21 @@ import { Clipboard } from "flowbite-react" export function Component() { return ( -
+
+
- - + + +
) } @@ -28,19 +32,21 @@ export function Component() { export function Component() { return ( -
- - - +
+
+ + + +
); } From b7c379219261aa015caecae3a310c3b724a39085 Mon Sep 17 00:00:00 2001 From: Dhaval Vira Date: Mon, 3 Jun 2024 06:50:53 +0530 Subject: [PATCH 09/10] moved copyToClipboard function to helpers for the reusability (DRY) --- .changeset/poor-tools-hide.md | 2 +- packages/ui/src/components/Clipboard/Clipboard.tsx | 14 +++++++------- .../src/components/Clipboard/ClipboardWithIcon.tsx | 14 +++++++------- .../components/Clipboard/ClipboardWithIconText.tsx | 14 +++++++------- packages/ui/src/components/Clipboard/helpers.ts | 7 +++++++ 5 files changed, 29 insertions(+), 22 deletions(-) create mode 100644 packages/ui/src/components/Clipboard/helpers.ts diff --git a/.changeset/poor-tools-hide.md b/.changeset/poor-tools-hide.md index 69a7f7542..ac2d1bf43 100644 --- a/.changeset/poor-tools-hide.md +++ b/.changeset/poor-tools-hide.md @@ -1,5 +1,5 @@ --- -"flowbite-react": patch +"flowbite-react": minor --- feat(components): add "Clipboard" diff --git a/packages/ui/src/components/Clipboard/Clipboard.tsx b/packages/ui/src/components/Clipboard/Clipboard.tsx index 941629c8d..a32914e83 100644 --- a/packages/ui/src/components/Clipboard/Clipboard.tsx +++ b/packages/ui/src/components/Clipboard/Clipboard.tsx @@ -10,6 +10,7 @@ import { ClipboardWithIcon } from "./ClipboardWithIcon"; import type { FlowbiteClipboardWithIconTheme } from "./ClipboardWithIcon"; import { ClipboardWithIconText } from "./ClipboardWithIconText"; import type { FlowbiteClipboardWithIconTextTheme } from "./ClipboardWithIconText"; +import { copyToClipboard } from "./helpers"; export interface FlowbiteClipboardTheme { button: { @@ -32,15 +33,14 @@ const ClipboardComponent = forwardRef( const theme = mergeDeep(getTheme().clipboard.button, customTheme); - const copyToClipboard = () => { - setIsJustCopied(true); - navigator?.clipboard?.writeText(valueToCopy); - setTimeout(() => setIsJustCopied(false), 4000); - }; - return ( - diff --git a/packages/ui/src/components/Clipboard/ClipboardWithIcon.tsx b/packages/ui/src/components/Clipboard/ClipboardWithIcon.tsx index 184550109..574c8fa66 100644 --- a/packages/ui/src/components/Clipboard/ClipboardWithIcon.tsx +++ b/packages/ui/src/components/Clipboard/ClipboardWithIcon.tsx @@ -6,6 +6,7 @@ import { twMerge } from "tailwind-merge"; import { mergeDeep } from "../../helpers/merge-deep"; import { getTheme } from "../../theme-store"; import type { DeepPartial } from "../../types"; +import { copyToClipboard } from "./helpers"; export interface FlowbiteClipboardWithIconTheme { base: string; @@ -27,14 +28,13 @@ export const ClipboardWithIcon = forwardRef { - setIsJustCopied(true); - navigator?.clipboard?.writeText(valueToCopy); - setTimeout(() => setIsJustCopied(false), 4000); - }; - return ( -