Skip to content

Commit

Permalink
feat(dashboard): Highlight selected step with border (#6869)
Browse files Browse the repository at this point in the history
  • Loading branch information
desiprisg authored Nov 6, 2024
1 parent 6b79915 commit 2415da8
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 27 deletions.
11 changes: 8 additions & 3 deletions apps/dashboard/src/components/workflow-editor/base-node.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ export const NODE_WIDTH = 300;
export const NODE_HEIGHT = 86;

const nodeVariants = cva(
`relative border-neutral-alpha-200 bg-foreground-0 flex w-[300px] flex-col gap-1 border p-1 shadow-xs`,
`relative border-neutral-alpha-200 transition-colors aria-selected:border-primary bg-foreground-0 flex w-[300px] flex-col gap-1 border p-1 shadow-xs`,
{
variants: {
variant: {
Expand All @@ -108,6 +108,11 @@ const nodeVariants = cva(

export interface BaseNodeProps extends React.HTMLAttributes<HTMLDivElement>, VariantProps<typeof nodeVariants> {}

export const Node = ({ children, variant, className }: BaseNodeProps) => {
return <div className={nodeVariants({ variant, className })}>{children}</div>;
export const Node = (props: BaseNodeProps) => {
const { children, variant, className, ...rest } = props;
return (
<div className={nodeVariants({ variant, className })} {...rest}>
{children}
</div>
);
};
67 changes: 43 additions & 24 deletions apps/dashboard/src/components/workflow-editor/nodes.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
import { Handle, Node as FlowNode, NodeProps, Position } from '@xyflow/react';
import { RiPlayCircleLine } from 'react-icons/ri';
import { Link } from 'react-router-dom';
import { Link, useParams } from 'react-router-dom';
import { STEP_TYPE_TO_COLOR } from '@/utils/color';
import { STEP_TYPE_TO_ICON } from '../icons/utils';
import { AddStepMenu } from './add-step-menu';
import { Node, NodeBody, NodeError, NodeHeader, NodeIcon, NodeName } from './base-node';
import { StepTypeEnum } from '@/utils/enums';
import { useWorkflowEditorContext } from './hooks';
import { buildRoute, ROUTES } from '@/utils/routes';
import { ComponentProps } from 'react';
import { cn } from '@/utils/ui';

export type NodeData = {
name?: string;
Expand Down Expand Up @@ -41,12 +43,22 @@ export const TriggerNode = (_props: NodeProps) => {
);
};

type StepNodeProps = ComponentProps<typeof Node> & { data: NodeData };
const StepNode = (props: StepNodeProps) => {
const { className, data, ...rest } = props;
const { stepSlug } = useParams<{
stepSlug: string;
}>();

return <Node aria-selected={stepSlug === data.stepSlug} className={cn('group', className)} {...rest} />;
};

export const EmailNode = ({ data }: NodeProps<NodeType>) => {
const Icon = STEP_TYPE_TO_ICON[StepTypeEnum.EMAIL];

return (
<Link to={`step/${data.stepSlug}`}>
<Node>
<StepNode data={data}>
<NodeHeader type={StepTypeEnum.EMAIL}>
<NodeIcon variant={STEP_TYPE_TO_COLOR[StepTypeEnum.EMAIL]}>
<Icon />
Expand All @@ -57,17 +69,18 @@ export const EmailNode = ({ data }: NodeProps<NodeType>) => {
{data.error && <NodeError>{data.error}</NodeError>}
<Handle isConnectable={false} className={handleClassName} type="target" position={Position.Top} id="a" />
<Handle isConnectable={false} className={handleClassName} type="source" position={Position.Bottom} id="b" />
</Node>
</StepNode>
</Link>
);
};

export const SmsNode = ({ data }: NodeProps<NodeType>) => {
export const SmsNode = (props: NodeProps<NodeType>) => {
const { data } = props;
const Icon = STEP_TYPE_TO_ICON[StepTypeEnum.SMS];

return (
<Link to={`step/${data.stepSlug}`}>
<Node>
<StepNode data={data}>
<NodeHeader type={StepTypeEnum.SMS}>
<NodeIcon variant={STEP_TYPE_TO_COLOR[StepTypeEnum.SMS]}>
<Icon />
Expand All @@ -78,17 +91,18 @@ export const SmsNode = ({ data }: NodeProps<NodeType>) => {
{data.error && <NodeError>{data.error}</NodeError>}
<Handle isConnectable={false} className={handleClassName} type="target" position={Position.Top} id="a" />
<Handle isConnectable={false} className={handleClassName} type="source" position={Position.Bottom} id="b" />
</Node>
</StepNode>
</Link>
);
};

export const InAppNode = ({ data }: NodeProps<NodeType>) => {
export const InAppNode = (props: NodeProps<NodeType>) => {
const { data } = props;
const Icon = STEP_TYPE_TO_ICON[StepTypeEnum.IN_APP];

return (
<Link to={buildRoute(ROUTES.CONFIGURE_STEP, { stepSlug: data.stepSlug ?? '' })}>
<Node>
<StepNode data={data}>
<NodeHeader type={StepTypeEnum.IN_APP}>
<NodeIcon variant={STEP_TYPE_TO_COLOR[StepTypeEnum.IN_APP]}>
<Icon />
Expand All @@ -99,17 +113,18 @@ export const InAppNode = ({ data }: NodeProps<NodeType>) => {
{data.error && <NodeError>{data.error}</NodeError>}
<Handle isConnectable={false} className={handleClassName} type="target" position={Position.Top} id="a" />
<Handle isConnectable={false} className={handleClassName} type="source" position={Position.Bottom} id="b" />
</Node>
</StepNode>
</Link>
);
};

export const PushNode = ({ data }: NodeProps<NodeType>) => {
export const PushNode = (props: NodeProps<NodeType>) => {
const { data } = props;
const Icon = STEP_TYPE_TO_ICON[StepTypeEnum.PUSH];

return (
<Link to={`step/${data.stepSlug}`}>
<Node>
<StepNode data={data}>
<NodeHeader type={StepTypeEnum.PUSH}>
<NodeIcon variant={STEP_TYPE_TO_COLOR[StepTypeEnum.PUSH]}>
<Icon />
Expand All @@ -120,17 +135,18 @@ export const PushNode = ({ data }: NodeProps<NodeType>) => {
{data.error && <NodeError>{data.error}</NodeError>}
<Handle isConnectable={false} className={handleClassName} type="target" position={Position.Top} id="a" />
<Handle isConnectable={false} className={handleClassName} type="source" position={Position.Bottom} id="b" />
</Node>
</StepNode>
</Link>
);
};

export const ChatNode = ({ data }: NodeProps<NodeType>) => {
export const ChatNode = (props: NodeProps<NodeType>) => {
const { data } = props;
const Icon = STEP_TYPE_TO_ICON[StepTypeEnum.CHAT];

return (
<Link to={`step/${data.stepSlug}`}>
<Node>
<StepNode data={data}>
<NodeHeader type={StepTypeEnum.CHAT}>
<NodeIcon variant={STEP_TYPE_TO_COLOR[StepTypeEnum.CHAT]}>
<Icon />
Expand All @@ -141,16 +157,17 @@ export const ChatNode = ({ data }: NodeProps<NodeType>) => {
{data.error && <NodeError>{data.error}</NodeError>}
<Handle isConnectable={false} className={handleClassName} type="target" position={Position.Top} id="a" />
<Handle isConnectable={false} className={handleClassName} type="source" position={Position.Bottom} id="b" />
</Node>
</StepNode>
</Link>
);
};

export const DelayNode = ({ data }: NodeProps<NodeType>) => {
export const DelayNode = (props: NodeProps<NodeType>) => {
const { data } = props;
const Icon = STEP_TYPE_TO_ICON[StepTypeEnum.DELAY];

return (
<Node>
<StepNode data={data}>
<NodeHeader type={StepTypeEnum.DELAY}>
<NodeIcon variant={STEP_TYPE_TO_COLOR[StepTypeEnum.DELAY]}>
<Icon />
Expand All @@ -160,15 +177,16 @@ export const DelayNode = ({ data }: NodeProps<NodeType>) => {
<NodeBody>{data.content || 'You have been invited to the Novu party on "commentSnippet"'}</NodeBody>
<Handle isConnectable={false} className={handleClassName} type="target" position={Position.Top} id="a" />
<Handle isConnectable={false} className={handleClassName} type="source" position={Position.Bottom} id="b" />
</Node>
</StepNode>
);
};

export const DigestNode = ({ data }: NodeProps<NodeType>) => {
export const DigestNode = (props: NodeProps<NodeType>) => {
const { data } = props;
const Icon = STEP_TYPE_TO_ICON[StepTypeEnum.DIGEST];

return (
<Node>
<StepNode data={data}>
<NodeHeader type={StepTypeEnum.DIGEST}>
<NodeIcon variant={STEP_TYPE_TO_COLOR[StepTypeEnum.DIGEST]}>
<Icon />
Expand All @@ -180,15 +198,16 @@ export const DigestNode = ({ data }: NodeProps<NodeType>) => {
</NodeBody>
<Handle isConnectable={false} className={handleClassName} type="target" position={Position.Top} id="a" />
<Handle isConnectable={false} className={handleClassName} type="source" position={Position.Bottom} id="b" />
</Node>
</StepNode>
);
};

export const CustomNode = ({ data }: NodeProps<NodeType>) => {
export const CustomNode = (props: NodeProps<NodeType>) => {
const { data } = props;
const Icon = STEP_TYPE_TO_ICON[StepTypeEnum.CUSTOM];

return (
<Node>
<StepNode data={data}>
<NodeHeader type={StepTypeEnum.CUSTOM}>
<NodeIcon variant={STEP_TYPE_TO_COLOR[StepTypeEnum.CUSTOM]}>
<Icon />
Expand All @@ -198,7 +217,7 @@ export const CustomNode = ({ data }: NodeProps<NodeType>) => {
<NodeBody>Executes the business logic in your bridge application</NodeBody>
<Handle isConnectable={false} className={handleClassName} type="target" position={Position.Top} id="a" />
<Handle isConnectable={false} className={handleClassName} type="source" position={Position.Bottom} id="b" />
</Node>
</StepNode>
);
};

Expand Down

0 comments on commit 2415da8

Please sign in to comment.