diff --git a/apps/dashboard/src/components/activity/components/overview-item.tsx b/apps/dashboard/src/components/activity/components/overview-item.tsx index 16297ddba88..f33b14949a7 100644 --- a/apps/dashboard/src/components/activity/components/overview-item.tsx +++ b/apps/dashboard/src/components/activity/components/overview-item.tsx @@ -1,7 +1,6 @@ -import { Copy } from 'lucide-react'; -import { ReactNode } from 'react'; -import { cn } from '@/utils/ui'; import { CopyButton } from '@/components/primitives/copy-button'; +import { cn } from '@/utils/ui'; +import { ReactNode } from 'react'; interface OverviewItemProps { label: string; @@ -28,11 +27,9 @@ export function OverviewItem({ - - + > )} {children || {value}} diff --git a/apps/dashboard/src/components/primitives/button.tsx b/apps/dashboard/src/components/primitives/button.tsx index 1708b6c1cc6..34872987a91 100644 --- a/apps/dashboard/src/components/primitives/button.tsx +++ b/apps/dashboard/src/components/primitives/button.tsx @@ -24,7 +24,8 @@ export const buttonVariants = tv({ ], icon: [ // base - 'flex size-5 shrink-0 items-center justify-center', + 'flex size-5 shrink-0 items-center justify-center transition-transform duration-200', + '[&.arrow-right-hover-animation]:group-hover:translate-x-0.5', ], }, variants: { @@ -353,17 +354,20 @@ export type ButtonProps = React.ComponentPropsWithoutRef & { trailingIcon?: IconType; }; -const Button = React.forwardRef( - ({ children, leadingIcon: LeadingIcon, trailingIcon: TrailingIcon, ...rest }, forwardedRef) => { - return ( - - {LeadingIcon && } - {children} - {TrailingIcon && } - - ); - } -); +const Button = ({ leadingIcon: LeadingIcon, trailingIcon: TrailingIcon, children, ...rest }: ButtonProps) => { + const isArrowRight = TrailingIcon?.name === 'RiArrowRightSLine'; + + return ( + + {LeadingIcon && } + {children} + {TrailingIcon && ( + + )} + + ); +}; + Button.displayName = 'Button'; function ButtonIcon({ @@ -381,4 +385,4 @@ function ButtonIcon({ } ButtonIcon.displayName = BUTTON_ICON_NAME; -export { Button, ButtonIcon as ButtonIcon, ButtonRoot as Root }; +export { Button, ButtonIcon, ButtonRoot }; diff --git a/apps/dashboard/src/components/primitives/copy-button.tsx b/apps/dashboard/src/components/primitives/copy-button.tsx index 80a1dfc64d5..7d13d1057de 100644 --- a/apps/dashboard/src/components/primitives/copy-button.tsx +++ b/apps/dashboard/src/components/primitives/copy-button.tsx @@ -1,20 +1,77 @@ -import { HoverToCopy } from '@/components/primitives/hover-to-copy'; -import { cn } from '@/utils/ui'; -import { RiFileCopyLine } from 'react-icons/ri'; +import { AnimatePresence, motion } from 'motion/react'; +import { useState } from 'react'; +import { RiCheckLine, RiFileCopyLine } from 'react-icons/ri'; +import { cn } from '../../utils/ui'; import { Button, ButtonProps } from './button'; +import { Tooltip, TooltipContent, TooltipTrigger } from './tooltip'; type CopyButtonProps = ButtonProps & { valueToCopy: string; + inputGroup?: boolean; }; export const CopyButton = (props: CopyButtonProps) => { - const { className, valueToCopy, children, ...rest } = props; + const { className, valueToCopy, inputGroup, children, ...rest } = props; + + const [copied, setCopied] = useState(false); + + const handleCopy = async () => { + try { + await navigator.clipboard.writeText(valueToCopy); + setCopied(true); + setTimeout(() => setCopied(false), 1500); + } catch (err) { + console.error('Failed to copy text: ', err); + } + }; + + const sizeClass = props.size === '2xs' ? 'size-3' : 'size-4'; return ( - - - {children || } - - + + + + {children} + + + {copied ? ( + + + + ) : ( + + + + )} + + + + + + {copied ? 'Copied!' : 'Click to copy'} + + ); }; diff --git a/apps/dashboard/src/components/primitives/hover-to-copy.tsx b/apps/dashboard/src/components/primitives/hover-to-copy.tsx deleted file mode 100644 index cace094279b..00000000000 --- a/apps/dashboard/src/components/primitives/hover-to-copy.tsx +++ /dev/null @@ -1,37 +0,0 @@ -import { ComponentProps, useState } from 'react'; -import { Tooltip, TooltipContent, TooltipTrigger } from './tooltip'; - -type HoverToCopyProps = ComponentProps & { - valueToCopy: string; -}; - -export const HoverToCopy = (props: HoverToCopyProps) => { - const { valueToCopy, ...rest } = props; - const [isCopied, setIsCopied] = useState(false); - - const copyToClipboard = async (e: React.MouseEvent) => { - e.preventDefault(); - try { - await navigator.clipboard.writeText(valueToCopy); - setIsCopied(true); - const timeout = setTimeout(() => setIsCopied(false), 1500); - return () => clearTimeout(timeout); - } catch (err) { - console.error('Failed to copy text: ', err); - } - }; - - return ( - - - { - e.preventDefault(); - }} - > - {isCopied ? 'Copied!' : 'Click to copy'} - - - ); -}; diff --git a/apps/dashboard/src/components/workflow-editor/configure-workflow-form.tsx b/apps/dashboard/src/components/workflow-editor/configure-workflow-form.tsx index b59bc54b3a5..a241457001f 100644 --- a/apps/dashboard/src/components/workflow-editor/configure-workflow-form.tsx +++ b/apps/dashboard/src/components/workflow-editor/configure-workflow-form.tsx @@ -298,10 +298,7 @@ export const ConfigureWorkflowForm = (props: ConfigureWorkflowFormProps) => { - + @@ -364,8 +361,10 @@ export const ConfigureWorkflowForm = (props: ConfigureWorkflowFormProps) => { leadingIcon={RiSettingsLine} className="flex w-full justify-start gap-1.5 p-1.5 text-xs font-medium" type="button" + trailingIcon={RiArrowRightSLine} > - Configure channel preferences + Configure channel preferences + diff --git a/apps/dashboard/src/components/workflow-editor/steps/configure-step-form.tsx b/apps/dashboard/src/components/workflow-editor/steps/configure-step-form.tsx index 5260c783ab2..1caee6d6621 100644 --- a/apps/dashboard/src/components/workflow-editor/steps/configure-step-form.tsx +++ b/apps/dashboard/src/components/workflow-editor/steps/configure-step-form.tsx @@ -255,11 +255,7 @@ export const ConfigureStepForm = (props: ConfigureStepFormProps) => { - + diff --git a/apps/dashboard/src/components/workflow-editor/test-workflow/test-workflow-form.tsx b/apps/dashboard/src/components/workflow-editor/test-workflow/test-workflow-form.tsx index e7d6cff999b..deb0875e174 100644 --- a/apps/dashboard/src/components/workflow-editor/test-workflow/test-workflow-form.tsx +++ b/apps/dashboard/src/components/workflow-editor/test-workflow/test-workflow-form.tsx @@ -14,7 +14,7 @@ import type { WorkflowResponseDto } from '@novu/shared'; import { loadLanguage } from '@uiw/codemirror-extensions-langs'; import { useMemo, useState } from 'react'; import { useFormContext, useWatch } from 'react-hook-form'; -import { RiFileCopyLine, RiSendPlaneFill } from 'react-icons/ri'; +import { RiSendPlaneFill } from 'react-icons/ri'; import { Code2 } from '../../icons/code-2'; import { CopyButton } from '../../primitives/copy-button'; import { FormControl, FormField, FormItem, FormLabel, FormMessage } from '../../primitives/form/form'; @@ -133,13 +133,7 @@ export const TestWorkflowForm = ({ workflow }: { workflow?: WorkflowResponseDto Python - + Copy code diff --git a/apps/dashboard/src/components/workflow-row.tsx b/apps/dashboard/src/components/workflow-row.tsx index 3df3a1890f1..ccb96964d40 100644 --- a/apps/dashboard/src/components/workflow-row.tsx +++ b/apps/dashboard/src/components/workflow-row.tsx @@ -8,7 +8,6 @@ import { DropdownMenuSeparator, DropdownMenuTrigger, } from '@/components/primitives/dropdown-menu'; -import { HoverToCopy } from '@/components/primitives/hover-to-copy'; import { TableCell, TableRow } from '@/components/primitives/table'; import { Tooltip, TooltipContent, TooltipPortal, TooltipTrigger } from '@/components/primitives/tooltip'; import TruncatedText from '@/components/truncated-text'; @@ -27,7 +26,6 @@ import { ComponentProps, useState } from 'react'; import { FaCode } from 'react-icons/fa6'; import { RiDeleteBin2Line, - RiFileCopyLine, RiFlashlightLine, RiGitPullRequestFill, RiMore2Fill, @@ -40,6 +38,7 @@ import { type ExternalToast } from 'sonner'; import { ConfirmationModal } from './confirmation-modal'; import { DeleteWorkflowDialog } from './delete-workflow-dialog'; import { CompactButton } from './primitives/button-compact'; +import { CopyButton } from './primitives/copy-button'; import { ToastIcon } from './primitives/sonner'; import { showToast } from './primitives/sonner-helpers'; import { TimeDisplayHoverCard } from './time-display-hover-card'; @@ -191,10 +190,16 @@ export const WorkflowRow = ({ workflow }: WorkflowRowProps) => { )} {workflow.name} - + {workflow.workflowId} - - + + +