diff --git a/src/components/Insights/SpanNexusInsight/index.tsx b/src/components/Insights/SpanNexusInsight/index.tsx index 1f3a8dbe0..233838d40 100644 --- a/src/components/Insights/SpanNexusInsight/index.tsx +++ b/src/components/Insights/SpanNexusInsight/index.tsx @@ -7,7 +7,6 @@ import { SpanNexusInsightProps } from "./types"; const getTagType = (isHigh: boolean) => { return isHigh ? "mediumSeverity" : "default"; }; - export const SpanNexusInsight = (props: SpanNexusInsightProps) => { const { insight } = props; const { diff --git a/src/components/Insights/SpanNexusInsight/mockData.ts b/src/components/Insights/SpanNexusInsight/mockData.ts index 97d15330c..0dc1395b6 100644 --- a/src/components/Insights/SpanNexusInsight/mockData.ts +++ b/src/components/Insights/SpanNexusInsight/mockData.ts @@ -53,7 +53,6 @@ export const mockedSpanNexusInsight: SpanNexusInsight = { actualStartTime: "2023-08-10T08:04:00Z", flows: 4, services: 3, - usage: "High", entries: 5, isEntriesHigh: false, isFlowsHigh: true, diff --git a/src/components/Insights/common/insights/SpanNexusInsight/SpanNexusInsight.stories.tsx b/src/components/Insights/common/insights/SpanNexusInsight/SpanNexusInsight.stories.tsx new file mode 100644 index 000000000..1678f09b0 --- /dev/null +++ b/src/components/Insights/common/insights/SpanNexusInsight/SpanNexusInsight.stories.tsx @@ -0,0 +1,23 @@ +import { Meta, StoryObj } from "@storybook/react"; +import { SpanNexusInsight } from "."; +import { mockedSpanNexusInsight } from "./mockData"; + +// More on how to set up stories at: https://storybook.js.org/docs/react/writing-stories/introduction +const meta: Meta = { + title: "Insights/Common/Insights/SpanNexusInsight", + component: SpanNexusInsight, + 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; + +export const Default: Story = { + args: { + insight: mockedSpanNexusInsight + } +}; diff --git a/src/components/Insights/common/insights/SpanNexusInsight/index.tsx b/src/components/Insights/common/insights/SpanNexusInsight/index.tsx new file mode 100644 index 000000000..5f2afd47c --- /dev/null +++ b/src/components/Insights/common/insights/SpanNexusInsight/index.tsx @@ -0,0 +1,55 @@ +import { InsightCard } from "../../../../common/v3/InsightCard"; +import { + KeyValue, + KeyValueContainer +} from "../../../../common/v3/KeyValueContainer"; +import { Tag } from "../../../../common/v3/Tag"; +import * as s from "./styles"; +import { SpanNexusInsightProps } from "./types"; + +const getTagType = (isHigh: boolean) => { + return isHigh ? "mediumSeverity" : "default"; +}; + +export const SpanNexusInsight = (props: SpanNexusInsightProps) => { + const { insight } = props; + const { + entries, + flows, + usage, + services, + isEntriesHigh, + isFlowsHigh, + isServicesHigh + } = insight; + return ( + + + Multiple code flows depend on this location + + + + + + + + + + + + {usage && ( + + + + )} + + + } + onRecalculate={props.onRecalculate} + onRefresh={props.onRefresh} + /> + ); +}; diff --git a/src/components/Insights/common/insights/SpanNexusInsight/mockData.ts b/src/components/Insights/common/insights/SpanNexusInsight/mockData.ts new file mode 100644 index 000000000..c872748d7 --- /dev/null +++ b/src/components/Insights/common/insights/SpanNexusInsight/mockData.ts @@ -0,0 +1,64 @@ +import { InsightType } from "../../../../../types"; +import { + InsightCategory, + InsightScope, + SpanNexusInsight +} from "../../../types"; + +export const mockedSpanNexusInsight: SpanNexusInsight = { + id: "60b54792-8262-4c5d-9628-7cce7979ad6d", + firstDetected: "2023-12-05T17:25:47.010Z", + lastDetected: "2024-01-05T13:14:47.010Z", + criticality: 0, + impact: 0, + firstCommitId: "b3f7b3f", + lastCommitId: "a1b2c3d", + deactivatedCommitId: null, + reopenCount: 0, + ticketLink: null, + name: "Code Nexus Point", + category: InsightCategory.Usage, + specifity: 2, + importance: 3, + scope: InsightScope.Span, + spanInfo: { + name: "HTTP POST /owners/{ownerId}/pets/new", + displayName: "HTTP POST /owners/{ownerId}/pets/new", + instrumentationLibrary: "io.opentelemetry.tomcat-10.0", + spanCodeObjectId: + "span:io.opentelemetry.tomcat-10.0$_$HTTP POST /owners/{ownerId}/pets/new", + methodCodeObjectId: + "method:org.springframework.samples.petclinic.owner.PetController$_$processCreationForm", + kind: "Server", + codeObjectId: + "org.springframework.samples.petclinic.owner.PetController$_$processCreationForm" + }, + shortDisplayInfo: { + title: "", + targetDisplayName: "", + subtitle: "", + description: "" + }, + codeObjectId: + "org.springframework.samples.petclinic.owner.PetController$_$processCreationForm", + decorators: [ + { + title: "Excessive HTTP Calls", + description: "Numerous Http calls to the same endpoint detected " + } + ], + environment: "BOB-LAPTOP[LOCAL]", + severity: 0.0, + isRecalculateEnabled: false, + prefixedCodeObjectId: + "method:org.springframework.samples.petclinic.owner.PetController$_$processCreationForm", + customStartTime: null, + actualStartTime: "2023-08-10T08:04:00Z", + flows: 4, + services: 3, + entries: 5, + isEntriesHigh: false, + isFlowsHigh: true, + isServicesHigh: false, + type: InsightType.SpanNexus +}; diff --git a/src/components/Insights/common/insights/SpanNexusInsight/styles.ts b/src/components/Insights/common/insights/SpanNexusInsight/styles.ts new file mode 100644 index 000000000..4fccda7c7 --- /dev/null +++ b/src/components/Insights/common/insights/SpanNexusInsight/styles.ts @@ -0,0 +1,14 @@ +import styled from "styled-components"; + +export const ContentContainer = styled.div` + gap: 8px; + display: flex; + flex-direction: column; +`; + +export const Description = styled.div` + display: flex; + gap: 8px; + font-size: 13px; + color: ${({ theme }) => theme.colors.v3.text.primary}; +`; diff --git a/src/components/Insights/common/insights/SpanNexusInsight/types.ts b/src/components/Insights/common/insights/SpanNexusInsight/types.ts new file mode 100644 index 000000000..b0ab27d55 --- /dev/null +++ b/src/components/Insights/common/insights/SpanNexusInsight/types.ts @@ -0,0 +1,5 @@ +import { InsightProps, SpanNexusInsight } from "../../../types"; + +export interface SpanNexusInsightProps extends InsightProps { + insight: SpanNexusInsight; +} diff --git a/src/components/Insights/types.ts b/src/components/Insights/types.ts index a640373df..edbd71710 100644 --- a/src/components/Insights/types.ts +++ b/src/components/Insights/types.ts @@ -746,3 +746,5 @@ export interface InsightsQuery { export interface ScopedInsightsQuery extends InsightsQuery { scopedSpanCodeObjectId: string | null; } + +export { InsightType }; diff --git a/src/components/common/App/themes/darkTheme.ts b/src/components/common/App/themes/darkTheme.ts index 88400d6ea..3a13a73c7 100644 --- a/src/components/common/App/themes/darkTheme.ts +++ b/src/components/common/App/themes/darkTheme.ts @@ -234,7 +234,8 @@ export const darkTheme: ThemeColors = { brandPrimary: v3colors.primary[500], brandSecondary: v3colors.primary[300], brandDark: v3colors.primary[900], - sidePanelHeader: v3colors.gray[1200] + sidePanelHeader: v3colors.gray[1200], + asyncTag: v3colors.blue[400] }, text: { primary: v3colors.gray[0], diff --git a/src/components/common/App/themes/lightTheme.ts b/src/components/common/App/themes/lightTheme.ts index 2f8fda305..5d1922146 100644 --- a/src/components/common/App/themes/lightTheme.ts +++ b/src/components/common/App/themes/lightTheme.ts @@ -232,7 +232,8 @@ export const lightTheme: ThemeColors = { brandPrimary: v3colors.primary[500], brandSecondary: v3colors.primary[300], brandDark: v3colors.primary[150], - sidePanelHeader: v3colors.gray[300] + sidePanelHeader: v3colors.gray[300], + asyncTag: v3colors.blue[100] }, text: { primary: v3colors.gray[1200], diff --git a/src/components/common/icons/16px/HistogramIcon.tsx b/src/components/common/icons/16px/HistogramIcon.tsx new file mode 100644 index 000000000..5b3ce45fc --- /dev/null +++ b/src/components/common/icons/16px/HistogramIcon.tsx @@ -0,0 +1,24 @@ +import React from "react"; +import { useIconProps } from "../hooks"; +import { IconProps } from "../types"; + +const HistogramIconComponent = (props: IconProps) => { + const { size, color } = useIconProps(props); + + return ( + + + + + + + ); +}; + +export const HistogramIcon = React.memo(HistogramIconComponent); diff --git a/src/components/common/icons/16px/LiveIcon.tsx b/src/components/common/icons/16px/LiveIcon.tsx new file mode 100644 index 000000000..2a947306e --- /dev/null +++ b/src/components/common/icons/16px/LiveIcon.tsx @@ -0,0 +1,34 @@ +import React from "react"; +import { useIconProps } from "../hooks"; +import { IconProps } from "../types"; + +const LiveIconComponent = (props: IconProps) => { + const { size, color } = useIconProps(props); + + return ( + + + + + + + + + + + + ); +}; + +export const LiveIcon = React.memo(LiveIconComponent); diff --git a/src/components/common/icons/16px/PinIcon.tsx b/src/components/common/icons/16px/PinIcon.tsx new file mode 100644 index 000000000..c5753e754 --- /dev/null +++ b/src/components/common/icons/16px/PinIcon.tsx @@ -0,0 +1,33 @@ +import React from "react"; +import { useIconProps } from "../hooks"; +import { IconProps } from "../types"; + +const PinIconComponent = (props: IconProps) => { + const { size, color } = useIconProps(props); + + return ( + + + + + + + + + + + ); +}; + +export const PinIcon = React.memo(PinIconComponent); diff --git a/src/components/common/icons/16px/RecalculateIcon.tsx b/src/components/common/icons/16px/RecalculateIcon.tsx new file mode 100644 index 000000000..837d13ff8 --- /dev/null +++ b/src/components/common/icons/16px/RecalculateIcon.tsx @@ -0,0 +1,35 @@ +import React from "react"; +import { useIconProps } from "../hooks"; +import { IconProps } from "../types"; + +const RecalculateComponent = (props: IconProps) => { + const { size, color } = useIconProps(props); + + return ( + + + + + + + + + + + + + ); +}; + +export const RecalculateIcon = React.memo(RecalculateComponent); diff --git a/src/components/common/v3/AsyncTag/AsyncTag.stories.tsx b/src/components/common/v3/AsyncTag/AsyncTag.stories.tsx new file mode 100644 index 000000000..5a508ea73 --- /dev/null +++ b/src/components/common/v3/AsyncTag/AsyncTag.stories.tsx @@ -0,0 +1,20 @@ +import { Meta, StoryObj } from "@storybook/react"; +import { AsyncTag } from "."; + +// More on how to set up stories at: https://storybook.js.org/docs/react/writing-stories/introduction +const meta: Meta = { + title: "common/v3/AsyncTag", + component: AsyncTag, + 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; + +export const Default: Story = { + args: {} +}; diff --git a/src/components/common/v3/AsyncTag/index.tsx b/src/components/common/v3/AsyncTag/index.tsx new file mode 100644 index 000000000..12f22bdc7 --- /dev/null +++ b/src/components/common/v3/AsyncTag/index.tsx @@ -0,0 +1,5 @@ +import * as s from "./styles"; + +export const AsyncTag = () => { + return ; +}; diff --git a/src/components/common/v3/AsyncTag/styles.ts b/src/components/common/v3/AsyncTag/styles.ts new file mode 100644 index 000000000..507738aa6 --- /dev/null +++ b/src/components/common/v3/AsyncTag/styles.ts @@ -0,0 +1,8 @@ +import styled from "styled-components"; +import { Tag as TagCommon } from "../Tag"; + +export const AsyncTag = styled(TagCommon)` + color: ${({ theme }) => theme.colors.v3.text.primary}; + background: ${({ theme }) => theme.colors.v3.surface.asyncTag}; + font-size: 12px; +`; diff --git a/src/components/common/v3/Card/styles.ts b/src/components/common/v3/Card/styles.ts index 9c096661c..51a0a2290 100644 --- a/src/components/common/v3/Card/styles.ts +++ b/src/components/common/v3/Card/styles.ts @@ -5,7 +5,7 @@ export const Container = styled.div` flex-direction: column; border-radius: 4px; border: 1px solid ${({ theme }) => theme.colors.v3.stroke.primary}; - background: ${({ theme }) => theme.colors.v3.surface.primary}; + background: ${({ theme }) => theme.colors.v3.surface.secondary}; `; const Section = styled.div` diff --git a/src/components/common/v3/InsightCard/InsightCard.stories.tsx b/src/components/common/v3/InsightCard/InsightCard.stories.tsx new file mode 100644 index 000000000..6e90721f2 --- /dev/null +++ b/src/components/common/v3/InsightCard/InsightCard.stories.tsx @@ -0,0 +1,30 @@ +import { Meta, StoryObj } from "@storybook/react"; +import { InsightCard } from "."; +import { mockedEndpointNPlusOneInsight } from "../../../Insights/EndpointNPlusOneInsight/mockData"; + +// More on how to set up stories at: https://storybook.js.org/docs/react/writing-stories/introduction +const meta: Meta = { + title: "Common/v3/InsightCard", + component: InsightCard, + 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; + +export const Default: Story = { + args: { + isAsync: true, + insight: mockedEndpointNPlusOneInsight + } +}; + +export const OnlyContent: Story = { + args: { + content:
Hover me
+ } +}; diff --git a/src/components/common/v3/InsightCard/InsightFooter/index.tsx b/src/components/common/v3/InsightCard/InsightFooter/index.tsx new file mode 100644 index 000000000..e69de29bb diff --git a/src/components/common/v3/InsightCard/index.tsx b/src/components/common/v3/InsightCard/index.tsx new file mode 100644 index 000000000..c232a6621 --- /dev/null +++ b/src/components/common/v3/InsightCard/index.tsx @@ -0,0 +1,151 @@ +import { useState } from "react"; +import { isString } from "../../../../typeGuards/isString"; +import { formatTimeDistance } from "../../../../utils/formatTimeDistance"; +import { Link } from "../../Link"; +import { NewButton } from "../../NewButton"; +import { TraceIcon } from "../../icons/12px/TraceIcon"; +import { HistogramIcon } from "../../icons/16px/HistogramIcon"; +import { JiraLogoIcon } from "../../icons/16px/JiraLogoIcon"; +import { LiveIcon } from "../../icons/16px/LiveIcon"; +import { PinIcon } from "../../icons/16px/PinIcon"; +import { RecalculateIcon } from "../../icons/16px/RecalculateIcon"; +import { CrossIcon } from "../../icons/CrossIcon"; +import { Card } from "../Card"; +import { InsightHeader } from "../InsightHeader"; +import { Tooltip } from "../Tooltip"; +import * as s from "./styles"; +import { InsightCardProps } from "./types"; + +const IS_NEW_TIME_LIMIT = 1000 * 60 * 10; // in milliseconds + +export const InsightCard = (props: InsightCardProps) => { + const [isRecalculatingStarted, setIsRecalculatingStarted] = useState(false); + const handleRefreshLinkClick = () => { + props.onRefresh && props.onRefresh(props.insight.type); + }; + + const handleRecalculateClick = () => { + props.insight.prefixedCodeObjectId && + props.onRecalculate && + props.onRecalculate( + props.insight.prefixedCodeObjectId, + props.insight.type + ); + setIsRecalculatingStarted(true); + }; + + const renderRecalculationBlock = ( + actualStartTime: string, + customStartTime: string | null, + isRecalculatingStarted: boolean + ) => { + if (!props.insight.customStartTime && !isRecalculatingStarted) { + return; + } + + if ( + isRecalculatingStarted || + (customStartTime && customStartTime > actualStartTime) + ) { + return ( + + + Applying the new time filter. Wait a few minutes and then refresh. + + + Refresh + + + ); + } + + const areStartTimesEqual = + customStartTime && + new Date(actualStartTime).valueOf() - + new Date(customStartTime).valueOf() === + 0; + + if (areStartTimesEqual) { + const title = new Date(actualStartTime).toString(); + return ( + + Data from:{" "} + + {formatTimeDistance(actualStartTime)} + + + ); + } + }; + + const isNew = isString(props.insight.firstDetected) + ? Date.now() - new Date(props.insight.firstDetected).valueOf() < + IS_NEW_TIME_LIMIT + : false; + return ( + + } + content={ + + {props.insight.actualStartTime && + renderRecalculationBlock( + props.insight.actualStartTime, + props.insight.customStartTime, + isRecalculatingStarted + )} + {props.content} + + } + footer={ + + + + {props.onOpenHistogram && ( + + )} + {props.onRecalculate && ( + + )} + {props.onOpenJiraTicket && ( + + )} + {props.onPin && } + + {props.onGoToTrace && ( + props.onGoToTrace && props.onGoToTrace()} + /> + )} + {props.onGoToLive && ( + props.onGoToLive && props.onGoToLive()} + /> + )} + + + + } + /> + ); +}; diff --git a/src/components/common/v3/InsightCard/styles.ts b/src/components/common/v3/InsightCard/styles.ts new file mode 100644 index 000000000..776d40f11 --- /dev/null +++ b/src/components/common/v3/InsightCard/styles.ts @@ -0,0 +1,43 @@ +import styled from "styled-components"; +import { NewButton } from "../../NewButton"; + +export const InsightFooter = styled.div` + display: flex; + justify-content: space-between; +`; + +export const Description = styled.div` + display: flex; + gap: 8px; + font-size: 13px; + color: ${({ theme }) => theme.colors.v3.text.secondary}; +`; + +export const RefreshContainer = styled.div` + display: flex; + flex-direction: column; + gap: 4px; +`; + +export const DismissButton = styled(NewButton)` + &:hover { + color: ${({ theme }) => theme.colors.v3.text.link}; + } + + font-size: 12px; +`; + +export const Actions = styled.div` + display: flex; +`; + +export const MainActions = styled(Actions)` + padding-left: 4px; + gap: 4px; +`; + +export const ContentContainer = styled.div` + display: flex; + flex-direction: column; + gap: 8px; +`; diff --git a/src/components/common/v3/InsightCard/types.ts b/src/components/common/v3/InsightCard/types.ts new file mode 100644 index 000000000..423347a2d --- /dev/null +++ b/src/components/common/v3/InsightCard/types.ts @@ -0,0 +1,27 @@ +import { ReactNode } from "react"; +import { InsightType } from "../../../../types"; +import { GenericCodeObjectInsight } from "../../../Insights/types"; + +export interface InsightCardProps { + insight: GenericCodeObjectInsight; + content?: ReactNode; + isAsync?: boolean; + isActive?: boolean; + onDismiss?: (insightId: string) => void; + onOpenHistogram?: ( + insightType: InsightType, + spanCodeObjectId: string + ) => void; + onRecalculate?: ( + prefixedCodeObjectId: string, + insightType: InsightType + ) => void; + onRefresh?: (insightType: InsightType, spanCodeObjectId?: string) => void; + onOpenJiraTicket?: ( + insight: GenericCodeObjectInsight, + spanCodeObjectId?: string + ) => void; + onPin?: (insightId: string) => void; + onGoToLive?: () => void; + onGoToTrace?: () => void; +} diff --git a/src/components/common/v3/InsightHeader/InisghtHeader.stories.tsx b/src/components/common/v3/InsightHeader/InisghtHeader.stories.tsx new file mode 100644 index 000000000..bb9884162 --- /dev/null +++ b/src/components/common/v3/InsightHeader/InisghtHeader.stories.tsx @@ -0,0 +1,26 @@ +import { Meta, StoryObj } from "@storybook/react"; +import { InsightHeader } from "."; + +// More on how to set up stories at: https://storybook.js.org/docs/react/writing-stories/introduction +const meta: Meta = { + title: "Common/v3/InsightsHeader", + component: InsightHeader, + 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; + +export const Default: Story = { + args: { + importance: 3, + insightType: "HotSpot", + isNew: true, + isAsync: true, + isActive: true + } +}; diff --git a/src/components/common/v3/InsightHeader/index.tsx b/src/components/common/v3/InsightHeader/index.tsx new file mode 100644 index 000000000..2e215aed0 --- /dev/null +++ b/src/components/common/v3/InsightHeader/index.tsx @@ -0,0 +1,58 @@ +import { getInsightTypeInfo } from "../../../../utils/getInsightTypeInfo"; +import { InfoCircleIcon } from "../../icons/InfoCircleIcon"; +import { AsyncTag } from "../AsyncTag"; +import { NewTag } from "../NewTag"; +import { Tag } from "../Tag"; +import { TagType } from "../Tag/types"; +import { Tooltip } from "../Tooltip"; +import * as s from "./styles"; +import { InsightHeaderProps } from "./types"; + +export const getTagType = (importance: number): TagType => { + if (importance === 0) { + return "default"; + } + if (importance < 3) { + return "highSeverity"; + } + if (importance < 7) { + return "mediumSeverity"; + } + return "lowSeverity"; +}; + +export const InsightHeader = (props: InsightHeaderProps) => { + const insightTypeInfo = getInsightTypeInfo(props.insightType); + const tagType = getTagType(props.importance); + + return ( + + {insightTypeInfo && ( + } + /> + )} + + {insightTypeInfo?.label} + {insightTypeInfo?.description && ( + }> + + + + + )} + + + {props.isAsync && } + {props.isNew && } + {props.isActive && ( + + + Active + + )} + + + ); +}; diff --git a/src/components/common/v3/InsightHeader/styles.ts b/src/components/common/v3/InsightHeader/styles.ts new file mode 100644 index 000000000..d7df95f10 --- /dev/null +++ b/src/components/common/v3/InsightHeader/styles.ts @@ -0,0 +1,44 @@ +import styled from "styled-components"; + +export const Container = styled.div` + display: flex; + align-items: center; + gap: 8px; +`; + +export const InfoContainer = styled.div` + display: flex; +`; + +export const Label = styled.div` + display: flex; + gap: 4px; + line-height: 18px; + align-items: center; + font-size: 14px; + font-weight: 600; +`; + +export const Tags = styled.div` + margin-left: auto; + display: flex; + gap: 8px; + height: 24px; + font-size: 12px; + line-height: 16px; +`; + +export const Active = styled.div` + display: flex; + align-items: center; + gap: 4px; + color: ${({ theme }) => theme.colors.v3.text.secondary}; + padding: 4px; +`; + +export const Indicator = styled.div` + border-radius: 50%; + width: 6px; + height: 6px; + background: ${({ theme }) => theme.colors.v3.status.success}; +`; diff --git a/src/components/common/v3/InsightHeader/types.ts b/src/components/common/v3/InsightHeader/types.ts new file mode 100644 index 000000000..1520ffd21 --- /dev/null +++ b/src/components/common/v3/InsightHeader/types.ts @@ -0,0 +1,8 @@ +export interface InsightHeaderProps { + insightType: string; + isActive?: boolean; + tags?: []; + importance: number; + isAsync?: boolean; + isNew?: boolean; +} diff --git a/src/components/common/v3/KeyValueContainer/KeyValue/styles.ts b/src/components/common/v3/KeyValueContainer/KeyValue/styles.ts index 78ba455c2..4820bb075 100644 --- a/src/components/common/v3/KeyValueContainer/KeyValue/styles.ts +++ b/src/components/common/v3/KeyValueContainer/KeyValue/styles.ts @@ -9,6 +9,7 @@ export const Container = styled.div` export const Key = styled.div` color: ${({ theme }) => theme.colors.v3.text.secondary}; + font-size: 11px; `; export const Value = styled.div` diff --git a/src/components/common/v3/KeyValueContainer/styles.ts b/src/components/common/v3/KeyValueContainer/styles.ts index 970dbdbad..2fae92a6d 100644 --- a/src/components/common/v3/KeyValueContainer/styles.ts +++ b/src/components/common/v3/KeyValueContainer/styles.ts @@ -4,7 +4,6 @@ export const Container = styled.div` display: flex; align-items: flex-start; gap: 8px; - padding: 8px; justify-content: space-between; align-self: stretch; `; diff --git a/src/components/common/v3/NewTag/NewTag.stories.tsx b/src/components/common/v3/NewTag/NewTag.stories.tsx new file mode 100644 index 000000000..b539d7cbf --- /dev/null +++ b/src/components/common/v3/NewTag/NewTag.stories.tsx @@ -0,0 +1,20 @@ +import { Meta, StoryObj } from "@storybook/react"; +import { NewTag } from "."; + +// More on how to set up stories at: https://storybook.js.org/docs/react/writing-stories/introduction +const meta: Meta = { + title: "common/v3/NewTag", + component: NewTag, + 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; + +export const Default: Story = { + args: {} +}; diff --git a/src/components/common/v3/NewTag/index.tsx b/src/components/common/v3/NewTag/index.tsx new file mode 100644 index 000000000..1b9e4c605 --- /dev/null +++ b/src/components/common/v3/NewTag/index.tsx @@ -0,0 +1,5 @@ +import { Tag } from "../Tag"; + +export const NewTag = () => { + return ; +}; diff --git a/src/components/common/v3/Tag/index.tsx b/src/components/common/v3/Tag/index.tsx index dd3055985..6cd595ffc 100644 --- a/src/components/common/v3/Tag/index.tsx +++ b/src/components/common/v3/Tag/index.tsx @@ -1,8 +1,10 @@ import * as s from "./styles"; import { TagProps } from "./types"; -export const Tag = (props: TagProps) => ( - - {props.content} - -); +export const Tag = (props: TagProps) => { + return ( + + {props.content} + + ); +}; diff --git a/src/components/common/v3/Tag/styles.ts b/src/components/common/v3/Tag/styles.ts index e5c918596..a3e606e50 100644 --- a/src/components/common/v3/Tag/styles.ts +++ b/src/components/common/v3/Tag/styles.ts @@ -41,8 +41,6 @@ const getTagTheme = ( }; export const Container = styled.div` - font-size: 14px; - font-weight: normal; display: flex; justify-content: center; align-items: center; @@ -53,7 +51,7 @@ export const Container = styled.div` background: ${({ theme, $type }) => getTagTheme(theme, $type).background}; `; -export const ValueContainer = styled.span` +export const ValueContainer = styled.div` display: flex; white-space: nowrap; text-overflow: ellipsis; diff --git a/src/components/common/v3/Tag/types.ts b/src/components/common/v3/Tag/types.ts index ccc288a31..6b233ede5 100644 --- a/src/components/common/v3/Tag/types.ts +++ b/src/components/common/v3/Tag/types.ts @@ -11,6 +11,7 @@ export type TagType = export interface TagProps { content: React.ReactNode; type?: TagType; + className?: string; } export interface ContainerProps { diff --git a/src/styled.d.ts b/src/styled.d.ts index edeb2b8c8..d9961638a 100644 --- a/src/styled.d.ts +++ b/src/styled.d.ts @@ -72,6 +72,7 @@ export interface ThemeColors { brandSecondary: string; brandDark: string; sidePanelHeader: string; + asyncTag: string; }; text: { primary: string;