Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { Meta, StoryObj } from "@storybook/react";
import { IconButton } from ".";
import { JiraLogoIcon } from "../../../../common/icons/16px/JiraLogoIcon";

// More on how to set up stories at: https://storybook.js.org/docs/react/writing-stories/introduction
const meta: Meta<typeof IconButton> = {
title: "Insights/common/InsightCard/IconButton",
component: IconButton,
parameters: {
// More on how to position stories at: https://storybook.js.org/docs/react/configure/story-layout
layout: "fullscreen"
}
};

export default meta;

type Story = StoryObj<typeof meta>;

export const Default: Story = {
args: {
icon: {
component: JiraLogoIcon
}
}
};

export const Disabled: Story = {
args: {
icon: {
component: JiraLogoIcon
},
isDisabled: true
}
};
22 changes: 22 additions & 0 deletions src/components/Insights/common/InsightCard/IconButton/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { ForwardedRef, forwardRef } from "react";
import * as s from "./styles";
import { IconButtonProps } from "./types";

export const IconButtonComponent = (
props: IconButtonProps,
ref: ForwardedRef<HTMLButtonElement>
) => (
<s.Button
ref={ref}
disabled={props.isDisabled}
onClick={props.onClick}
className={props.className}
>
<props.icon.component
size={props.icon.size || 16}
color={props.icon.color || "currentColor"}
/>
</s.Button>
);

export const IconButton = forwardRef(IconButtonComponent);
22 changes: 22 additions & 0 deletions src/components/Insights/common/InsightCard/IconButton/styles.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import styled from "styled-components";

export const Button = styled.button`
display: flex;
border-radius: 2px;
margin: 0;
cursor: pointer;
padding: 4px;
border: none;
background: none;
color: ${({ theme }) => theme.colors.v3.icon.disabled};

&:disabled {
cursor: initial;
}

&:hover:enabled,
&:focus:enabled,
&:active:enabled {
background: ${({ theme }) => theme.colors.v3.surface.highlight};
}
`;
14 changes: 14 additions & 0 deletions src/components/Insights/common/InsightCard/IconButton/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { ComponentType } from "react";
import { IconProps } from "../../../../common/icons/types";

export interface IconButtonProps {
icon: {
component: ComponentType<IconProps>;
color?: string;
size?: number;
};
title?: string;
onClick?: () => void;
isDisabled?: boolean;
className?: string;
}
Original file line number Diff line number Diff line change
@@ -1,18 +1,12 @@
import { ForwardedRef, forwardRef } from "react";
import * as s from "./styles";
import { AnimatedCodeButtonProps } from "./types";

export const AnimatedCodeButtonComponent = (
props: AnimatedCodeButtonProps,
ref: ForwardedRef<HTMLButtonElement>
) => (
<s.Button onClick={props.onClick} ref={ref}>
export const AnimatedCodeButton = (props: AnimatedCodeButtonProps) => (
<s.Button onClick={props.onClick}>
<s.BorderContainer />
<s.Background>
<s.InitialMask />
<s.EndMask />
</s.Background>
</s.Button>
);

export const AnimatedCodeButton = forwardRef(AnimatedCodeButtonComponent);
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
export interface AnimatedCodeButtonProps {
onClick: () => void;
onClick?: () => void;
}
12 changes: 3 additions & 9 deletions src/components/Navigation/CodeButton/GlowingIconButton/index.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,8 @@
import { ForwardedRef, forwardRef } from "react";
import * as s from "./styles";
import { GlowingIconButtonProps } from "./types";

export const GlowingIconButtonComponent = (
props: GlowingIconButtonProps,
ref: ForwardedRef<HTMLDivElement>
) => (
<s.BorderContainer $type={props.type} ref={ref}>
<s.BorderlessIconButton icon={props.icon} onClick={props.onClick} />
export const GlowingIconButton = (props: GlowingIconButtonProps) => (
<s.BorderContainer $type={props.type} onClick={props.onClick}>
<s.BorderlessIconButton icon={props.icon} />
</s.BorderContainer>
);

export const GlowingIconButton = forwardRef(GlowingIconButtonComponent);
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ type GlowingIconButtonType = "default" | "error";

export interface GlowingIconButtonProps {
icon: React.ReactNode;
onClick: () => void;
onClick?: () => void;
type?: GlowingIconButtonType;
}

Expand Down
124 changes: 78 additions & 46 deletions src/components/Navigation/CodeButton/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { ForwardedRef, forwardRef } from "react";
import { ForwardedRef, forwardRef, useEffect, useState } from "react";
import { usePrevious } from "../../../hooks/usePrevious";
import { isBoolean } from "../../../typeGuards/isBoolean";
import { ClockWithTicksIcon } from "../../common/icons/20px/ClockWithTicksIcon";
import { CodeIcon } from "../../common/icons/20px/CodeIcon";
import { OpenTelemetryLogoIcon } from "../../common/icons/20px/OpenTelemetryLogoIcon";
Expand All @@ -8,57 +10,87 @@ import * as s from "./styles";
import { CodeButtonProps } from "./types";

const CodeButtonComponent = (
props: CodeButtonProps,
ref: ForwardedRef<HTMLDivElement | HTMLButtonElement>
{
hasData,
hasErrors,
hasObservability,
isDisabled,
isAlreadyAtScope,
onClick,
onMouseEnter,
onMouseLeave
}: CodeButtonProps,
ref: ForwardedRef<HTMLDivElement>
) => {
if (props.isDisabled || props.isAlreadyAtScope) {
return (
<s.ExtendedIconButton
ref={ref as ForwardedRef<HTMLButtonElement>}
icon={<CodeIcon color={"currentColor"} size={20} />}
isDisabled={props.isDisabled}
onClick={props.onClick}
isActive={props.isAlreadyAtScope}
/>
);
}
const [isHovered, setIsHovered] = useState(false);
const previousIsHovered = usePrevious(isHovered);

if (props.hasErrors) {
return (
<GlowingIconButton
ref={ref as ForwardedRef<HTMLDivElement>}
icon={<CodeIcon color={"currentColor"} size={20} />}
onClick={props.onClick}
type={"error"}
/>
);
}
const handleMouseEnter = () => {
setIsHovered(true);
};

if (!props.hasObservability) {
return (
<GlowingIconButton
ref={ref as ForwardedRef<HTMLDivElement>}
icon={<OpenTelemetryLogoIcon color={"currentColor"} size={20} />}
onClick={props.onClick}
/>
);
}
const handleMouseLeave = () => {
setIsHovered(false);
};

if (!props.hasData) {
return (
<GlowingIconButton
ref={ref as ForwardedRef<HTMLDivElement>}
icon={<ClockWithTicksIcon color={"currentColor"} size={20} />}
onClick={props.onClick}
/>
);
}
useEffect(() => {
if (isBoolean(previousIsHovered) && previousIsHovered !== isHovered) {
if (isHovered) {
onMouseEnter();
} else {
onMouseLeave();
}
}
}, [onMouseEnter, onMouseLeave, previousIsHovered, isHovered]);

const getButtonComponent = () => {
if (isDisabled || isAlreadyAtScope) {
return (
<s.ExtendedIconButton
icon={<CodeIcon color={"currentColor"} size={20} />}
isDisabled={isDisabled}
isActive={isAlreadyAtScope}
/>
);
}

if (hasErrors) {
return (
<GlowingIconButton
icon={<CodeIcon color={"currentColor"} size={20} />}
type={"error"}
/>
);
}

if (!hasObservability) {
return (
<GlowingIconButton
icon={<OpenTelemetryLogoIcon color={"currentColor"} size={20} />}
/>
);
}

if (!hasData) {
return (
<GlowingIconButton
icon={<ClockWithTicksIcon color={"currentColor"} size={20} />}
/>
);
}

return <AnimatedCodeButton />;
};

return (
<AnimatedCodeButton
ref={ref as ForwardedRef<HTMLButtonElement>}
onClick={props.onClick}
/>
<s.Container
ref={ref}
onClick={onClick}
onMouseEnter={handleMouseEnter}
onMouseLeave={handleMouseLeave}
>
{getButtonComponent()}
</s.Container>
);
};

Expand Down
4 changes: 4 additions & 0 deletions src/components/Navigation/CodeButton/styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@ import styled from "styled-components";
import { IconButton } from "../common/IconButton";
import { ExtendedIconButtonProps } from "./types";

export const Container = styled.div`
display: flex;
`;

export const ExtendedIconButton = styled(IconButton)<ExtendedIconButtonProps>`
color: ${({ theme, isActive }) =>
isActive
Expand Down
2 changes: 2 additions & 0 deletions src/components/Navigation/CodeButton/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,6 @@ export interface CodeButtonProps {
hasData: boolean;
isAlreadyAtScope: boolean;
hasErrors: boolean;
onMouseEnter: () => void;
onMouseLeave: () => void;
}
4 changes: 3 additions & 1 deletion src/components/Navigation/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,7 @@ export const actions = addPrefix(ACTION_PREFIX, {
SET_AUTOFIX_MISSING_DEPENDENCY_RESULT:
"SET_AUTOFIX_MISSING_DEPENDENCY_RESULT",
ADD_ANNOTATION: "ADD_ANNOTATION",
SET_ADD_ANNOTATION_RESULT: "SET_ADD_ANNOTATION_RESULT"
SET_ADD_ANNOTATION_RESULT: "SET_ADD_ANNOTATION_RESULT",
HIGHLIGHT_METHOD_IN_EDITOR: "HIGHLIGHT_METHOD_IN_EDITOR",
CLEAR_HIGHLIGHTS_IN_EDITOR: "CLEAR_HIGHLIGHTS_IN_EDITOR"
});
2 changes: 2 additions & 0 deletions src/components/Navigation/common/IconButton/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ export const IconButtonComponent = (
className={props.className}
onClick={props.onClick}
disabled={props.isDisabled}
onMouseEnter={props.onMouseEnter}
onMouseLeave={props.onMouseLeave}
>
{props.icon}
</s.Button>
Expand Down
4 changes: 3 additions & 1 deletion src/components/Navigation/common/IconButton/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,7 @@ export interface IconButtonProps {
icon: React.ReactNode;
isDisabled?: boolean;
className?: string;
onClick: () => void;
onClick?: () => void;
onMouseEnter?: () => void;
onMouseLeave?: () => void;
}
22 changes: 22 additions & 0 deletions src/components/Navigation/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import {
ChangeScopePayload,
ChangeViewPayload,
CodeContext,
HighlightMethodInEditorPayload,
OpenDashboardPayload,
SetViewsPayload,
TabData
Expand Down Expand Up @@ -242,6 +243,23 @@ export const Navigation = () => {
}
};

const handleCodeButtonMouseEnter = () => {
if (codeContext && codeContext.methodId) {
window.sendMessageToDigma<HighlightMethodInEditorPayload>({
action: actions.HIGHLIGHT_METHOD_IN_EDITOR,
payload: {
methodId: codeContext.methodId
}
});
}
};

const handleCodeButtonMouseLeave = () => {
window.sendMessageToDigma({
action: actions.CLEAR_HIGHLIGHTS_IN_EDITOR
});
};

const handleEnvironmentChange = (environment: Environment) => {
sendTrackingEvent(trackingEvents.ENVIRONMENT_SELECTED);
setIsEnvironmentMenuOpen(false);
Expand Down Expand Up @@ -393,6 +411,8 @@ export const Navigation = () => {
onClick={handleCodeButtonClick}
isAlreadyAtScope={isAlreadyAtScope(codeContext, config.scope)}
hasErrors={false}
onMouseEnter={handleCodeButtonMouseEnter}
onMouseLeave={handleCodeButtonMouseLeave}
/>
</NewPopover>
</div>
Expand All @@ -404,6 +424,8 @@ export const Navigation = () => {
onClick={handleCodeButtonClick}
isAlreadyAtScope={isAlreadyAtScope(codeContext, config.scope)}
hasErrors={false}
onMouseEnter={handleCodeButtonMouseEnter}
onMouseLeave={handleCodeButtonMouseLeave}
/>
)}
</Tooltip>
Expand Down
4 changes: 4 additions & 0 deletions src/components/Navigation/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,10 @@ export interface AddAnnotationPayload {
methodId: string;
}

export interface HighlightMethodInEditorPayload {
methodId: string;
}

export interface CodeContext {
spans: {
assets: {
Expand Down
Loading