From 7bba9b39cf184e392c3cca0547099eb80abe568c Mon Sep 17 00:00:00 2001 From: olehp Date: Tue, 20 Feb 2024 17:16:21 +0200 Subject: [PATCH 1/2] init --- src/components/common/v3/Tag/Tag.stories.tsx | 100 +++++++++++++++++++ src/components/common/v3/Tag/index.tsx | 30 ++++++ src/components/common/v3/Tag/styles.ts | 66 ++++++++++++ src/components/common/v3/Tag/types.ts | 21 ++++ 4 files changed, 217 insertions(+) create mode 100644 src/components/common/v3/Tag/Tag.stories.tsx create mode 100644 src/components/common/v3/Tag/index.tsx create mode 100644 src/components/common/v3/Tag/styles.ts create mode 100644 src/components/common/v3/Tag/types.ts diff --git a/src/components/common/v3/Tag/Tag.stories.tsx b/src/components/common/v3/Tag/Tag.stories.tsx new file mode 100644 index 000000000..2a124e5ef --- /dev/null +++ b/src/components/common/v3/Tag/Tag.stories.tsx @@ -0,0 +1,100 @@ +import { Meta, StoryObj } from "@storybook/react"; +import { Tag } from "."; +import { BottleneckIcon } from "../../icons/BottleneckIcon"; + +// More on how to set up stories at: https://storybook.js.org/docs/react/writing-stories/introduction +const meta: Meta = { + title: "common/v3/Tag", + component: Tag, + 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: { + icon: BottleneckIcon + }, + parameters: { + design: { + type: "figma" + } + } +}; + +export const HighlighNumber: Story = { + args: { + type: "highlight", + value: 30 + }, + parameters: { + design: { + type: "figma" + } + } +}; + +export const HighlightString: Story = { + args: { + type: "highlight", + value: "~30ms" + }, + parameters: { + design: { + type: "figma" + } + } +}; + +export const HighSeverity: Story = { + args: { + type: "highSeverity", + value: "Input" + }, + parameters: { + design: { + type: "figma" + } + } +}; + +export const MediumSeverity: Story = { + args: { + type: "mediumSeverity", + value: "Input" + }, + parameters: { + design: { + type: "figma" + } + } +}; + +export const LowSeverity: Story = { + args: { + type: "lowSeverity", + value: "Input" + }, + parameters: { + design: { + type: "figma" + } + } +}; + +export const Success: Story = { + args: { + type: "success", + value: "100ms" + }, + parameters: { + design: { + type: "figma" + } + } +}; diff --git a/src/components/common/v3/Tag/index.tsx b/src/components/common/v3/Tag/index.tsx new file mode 100644 index 000000000..87fc3b6fa --- /dev/null +++ b/src/components/common/v3/Tag/index.tsx @@ -0,0 +1,30 @@ +import { isString } from "../../../../typeGuards/isString"; +import { isUndefined } from "../../../../typeGuards/isUndefined"; +import { Tooltip } from "../../Tooltip"; +import * as s from "./styles"; +import { TagProps } from "./types"; + +const renderValue = (value: TagProps["value"]) => { + switch (typeof value) { + case "string": + return {value}; + case "number": + return value; + default: + return null; + } +}; + +export const Tag = (props: TagProps) => { + const title = isString(props.title) ? props.title : props.value; + return ( + + + {props.icon && } + {!isUndefined(props.value) && ( + {renderValue(props.value)} + )} + + + ); +}; diff --git a/src/components/common/v3/Tag/styles.ts b/src/components/common/v3/Tag/styles.ts new file mode 100644 index 000000000..a58fea4f6 --- /dev/null +++ b/src/components/common/v3/Tag/styles.ts @@ -0,0 +1,66 @@ +import styled from "styled-components"; +import { DefaultTheme } from "styled-components/dist/types"; +import { ContainerProps, TagType } from "./types"; + +const getTagTheme = ( + theme: DefaultTheme, + type?: TagType +): { text: string; background: string } => { + const typeMap = { + default: { + text: theme.colors.v3.text.secondary, + background: theme.colors.v3.surface.primary + }, + highlight: { + text: theme.colors.v3.text.secondary, + background: theme.colors.v3.surface.highlight + }, + highSeverity: { + text: theme.colors.v3.status.high, + background: theme.colors.v3.status.backgroundHigh + }, + mediumSeverity: { + text: theme.colors.v3.status.medium, + background: theme.colors.v3.status.backgroundMedium + }, + lowSeverity: { + text: theme.colors.v3.status.low, + background: theme.colors.v3.status.backgroundLow + }, + success: { + text: theme.colors.v3.status.success, + background: theme.colors.v3.status.backgroundSuccess + } + }; + + if (!type) { + return typeMap.default; + } + + return typeMap[type]; +}; + +export const Container = styled.div` + font-size: 14px; + font-weight: normal; + display: flex; + min-width: 24px; + padding: 4px 0; + justify-content: center; + align-items: center; + gap: 4px; + border-radius: 4px; + max-width: fit-content; + color: ${({ theme, $type }) => getTagTheme(theme, $type).text}; + background: ${({ theme, $type }) => getTagTheme(theme, $type).background}; +`; + +export const ValueContainer = styled.span` + white-space: nowrap; + text-overflow: ellipsis; + overflow: hidden; +`; + +export const TextContainer = styled.span` + padding: 0 4px; +`; diff --git a/src/components/common/v3/Tag/types.ts b/src/components/common/v3/Tag/types.ts new file mode 100644 index 000000000..13311dbeb --- /dev/null +++ b/src/components/common/v3/Tag/types.ts @@ -0,0 +1,21 @@ +import { MemoExoticComponent } from "react"; +import { IconProps } from "../../icons/types"; + +export type TagType = + | "highSeverity" + | "mediumSeverity" + | "lowSeverity" + | "success" + | "highlight" + | "default"; + +export interface TagProps { + icon?: MemoExoticComponent<(props: IconProps) => JSX.Element>; + value?: string | number; + type?: TagType; + title?: string; +} + +export interface ContainerProps { + $type?: TagType; +} From 7a4808211e873b1067a8232d702fa536eb1666c4 Mon Sep 17 00:00:00 2001 From: olehp Date: Tue, 20 Feb 2024 17:44:49 +0200 Subject: [PATCH 2/2] Simplify tag --- src/components/common/v3/Tag/Tag.stories.tsx | 24 +++++------------- src/components/common/v3/Tag/index.tsx | 26 +++----------------- src/components/common/v3/Tag/styles.ts | 10 +++----- src/components/common/v3/Tag/types.ts | 7 ++---- 4 files changed, 14 insertions(+), 53 deletions(-) diff --git a/src/components/common/v3/Tag/Tag.stories.tsx b/src/components/common/v3/Tag/Tag.stories.tsx index 2a124e5ef..4954e6877 100644 --- a/src/components/common/v3/Tag/Tag.stories.tsx +++ b/src/components/common/v3/Tag/Tag.stories.tsx @@ -18,19 +18,7 @@ type Story = StoryObj; export const Default: Story = { args: { - icon: BottleneckIcon - }, - parameters: { - design: { - type: "figma" - } - } -}; - -export const HighlighNumber: Story = { - args: { - type: "highlight", - value: 30 + content: }, parameters: { design: { @@ -42,7 +30,7 @@ export const HighlighNumber: Story = { export const HighlightString: Story = { args: { type: "highlight", - value: "~30ms" + content: ~30ms }, parameters: { design: { @@ -54,7 +42,7 @@ export const HighlightString: Story = { export const HighSeverity: Story = { args: { type: "highSeverity", - value: "Input" + content: input }, parameters: { design: { @@ -66,7 +54,7 @@ export const HighSeverity: Story = { export const MediumSeverity: Story = { args: { type: "mediumSeverity", - value: "Input" + content: input }, parameters: { design: { @@ -78,7 +66,7 @@ export const MediumSeverity: Story = { export const LowSeverity: Story = { args: { type: "lowSeverity", - value: "Input" + content: Input }, parameters: { design: { @@ -90,7 +78,7 @@ export const LowSeverity: Story = { export const Success: Story = { args: { type: "success", - value: "100ms" + content: 10ms }, parameters: { design: { diff --git a/src/components/common/v3/Tag/index.tsx b/src/components/common/v3/Tag/index.tsx index 87fc3b6fa..0d43d9ea0 100644 --- a/src/components/common/v3/Tag/index.tsx +++ b/src/components/common/v3/Tag/index.tsx @@ -1,30 +1,10 @@ -import { isString } from "../../../../typeGuards/isString"; -import { isUndefined } from "../../../../typeGuards/isUndefined"; -import { Tooltip } from "../../Tooltip"; import * as s from "./styles"; import { TagProps } from "./types"; -const renderValue = (value: TagProps["value"]) => { - switch (typeof value) { - case "string": - return {value}; - case "number": - return value; - default: - return null; - } -}; - export const Tag = (props: TagProps) => { - const title = isString(props.title) ? props.title : props.value; return ( - - - {props.icon && } - {!isUndefined(props.value) && ( - {renderValue(props.value)} - )} - - + + {props.content} + ); }; diff --git a/src/components/common/v3/Tag/styles.ts b/src/components/common/v3/Tag/styles.ts index a58fea4f6..e5c918596 100644 --- a/src/components/common/v3/Tag/styles.ts +++ b/src/components/common/v3/Tag/styles.ts @@ -44,23 +44,19 @@ export const Container = styled.div` font-size: 14px; font-weight: normal; display: flex; - min-width: 24px; - padding: 4px 0; justify-content: center; align-items: center; - gap: 4px; border-radius: 4px; + min-width: 24px; max-width: fit-content; color: ${({ theme, $type }) => getTagTheme(theme, $type).text}; background: ${({ theme, $type }) => getTagTheme(theme, $type).background}; `; export const ValueContainer = styled.span` + display: flex; white-space: nowrap; text-overflow: ellipsis; overflow: hidden; -`; - -export const TextContainer = styled.span` - padding: 0 4px; + padding: 4px; `; diff --git a/src/components/common/v3/Tag/types.ts b/src/components/common/v3/Tag/types.ts index 13311dbeb..ccc288a31 100644 --- a/src/components/common/v3/Tag/types.ts +++ b/src/components/common/v3/Tag/types.ts @@ -1,5 +1,4 @@ -import { MemoExoticComponent } from "react"; -import { IconProps } from "../../icons/types"; +import React from "react"; export type TagType = | "highSeverity" @@ -10,10 +9,8 @@ export type TagType = | "default"; export interface TagProps { - icon?: MemoExoticComponent<(props: IconProps) => JSX.Element>; - value?: string | number; + content: React.ReactNode; type?: TagType; - title?: string; } export interface ContainerProps {