From 014e7d92611739344458f8ac4cc66f986553f443 Mon Sep 17 00:00:00 2001 From: Alex Khomenko Date: Tue, 24 Mar 2020 13:52:20 +0200 Subject: [PATCH] Granfana ui/tag components (#22964) * Add Tag component * Add Tag story * Add TagList * Group Tab and TabList * Fix typechecks * Remove Meta * Use forwardRef for the Tag * Add actions instead of console.log * Add previews --- .../grafana-ui/src/components/Tags/Tag.mdx | 23 ++++++++ .../src/components/Tags/Tag.story.tsx | 20 +++++++ .../grafana-ui/src/components/Tags/Tag.tsx | 52 +++++++++++++++++++ .../src/components/Tags/TagList.mdx | 22 ++++++++ .../src/components/Tags/TagList.story.tsx | 26 ++++++++++ .../src/components/Tags/TagList.tsx | 38 ++++++++++++++ packages/grafana-ui/src/components/index.ts | 2 + 7 files changed, 183 insertions(+) create mode 100644 packages/grafana-ui/src/components/Tags/Tag.mdx create mode 100644 packages/grafana-ui/src/components/Tags/Tag.story.tsx create mode 100644 packages/grafana-ui/src/components/Tags/Tag.tsx create mode 100644 packages/grafana-ui/src/components/Tags/TagList.mdx create mode 100644 packages/grafana-ui/src/components/Tags/TagList.story.tsx create mode 100644 packages/grafana-ui/src/components/Tags/TagList.tsx diff --git a/packages/grafana-ui/src/components/Tags/Tag.mdx b/packages/grafana-ui/src/components/Tags/Tag.mdx new file mode 100644 index 00000000000..4c4a0db3f83 --- /dev/null +++ b/packages/grafana-ui/src/components/Tags/Tag.mdx @@ -0,0 +1,23 @@ +import { Story, Preview, Props } from '@storybook/addon-docs/blocks'; +import { Tag } from './Tag'; + +# Tag + +Used for displaying metadata, for example to add more details to search results. Background and border colors are generated from the tag name. + + +
+ console.log(name)} /> +
+
+ +### Usage + +```jsx +import { Tag } from '@grafana/ui'; + + console.log(name)} /> +``` + +### Props + diff --git a/packages/grafana-ui/src/components/Tags/Tag.story.tsx b/packages/grafana-ui/src/components/Tags/Tag.story.tsx new file mode 100644 index 00000000000..aeeb124efda --- /dev/null +++ b/packages/grafana-ui/src/components/Tags/Tag.story.tsx @@ -0,0 +1,20 @@ +import React from 'react'; +import { action } from '@storybook/addon-actions'; +import { Tag } from './Tag'; +import { withCenteredStory } from '../../utils/storybook/withCenteredStory'; +import mdx from './Tag.mdx'; + +export default { + title: 'General/Tags/Tag', + component: Tag, + decorators: [withCenteredStory], + parameters: { + docs: { + page: mdx, + }, + }, +}; + +export const single = () => { + return ; +}; diff --git a/packages/grafana-ui/src/components/Tags/Tag.tsx b/packages/grafana-ui/src/components/Tags/Tag.tsx new file mode 100644 index 00000000000..611646ba665 --- /dev/null +++ b/packages/grafana-ui/src/components/Tags/Tag.tsx @@ -0,0 +1,52 @@ +import React, { forwardRef, HTMLAttributes } from 'react'; +import { cx, css } from 'emotion'; +import { GrafanaTheme } from '@grafana/data'; +import { useTheme } from '../../themes'; +import { getTagColorsFromName } from '../../utils'; + +export interface Props extends Omit, 'onClick'> { + /** Name of the tag to display */ + name: string; + onClick?: (name: string) => any; +} + +export const Tag = forwardRef(({ name, onClick, className, ...rest }, ref) => { + const theme = useTheme(); + const styles = getTagStyles(theme, name); + + const onTagClick = () => { + if (onClick) { + onClick(name); + } + }; + + return ( + + {name} + + ); +}); + +const getTagStyles = (theme: GrafanaTheme, name: string) => { + const { borderColor, color } = getTagColorsFromName(name); + return { + wrapper: css` + font-weight: ${theme.typography.weight.semibold}; + font-size: ${theme.typography.size.sm}; + line-height: ${theme.typography.lineHeight.xs}; + vertical-align: baseline; + background-color: ${color}; + color: ${theme.colors.white}; + white-space: nowrap; + text-shadow: none; + padding: 3px 6px; + border: 1px solid ${borderColor}; + border-radius: ${theme.border.radius.md}; + + :hover { + opacity: 0.85; + cursor: pointer; + } + `, + }; +}; diff --git a/packages/grafana-ui/src/components/Tags/TagList.mdx b/packages/grafana-ui/src/components/Tags/TagList.mdx new file mode 100644 index 00000000000..99597e62d15 --- /dev/null +++ b/packages/grafana-ui/src/components/Tags/TagList.mdx @@ -0,0 +1,22 @@ +import { Story, Preview, Props } from '@storybook/addon-docs/blocks'; +import { TagList } from './TagList'; + +# TagList + +List of tags with predefined margins and positioning. + + + + + +### Usage + +```jsx +import { TagList } from '@grafana/ui'; +const tags = ['datasource-test', 'gdev', 'mysql', 'mssql']; + + console.log(tag)} /> +``` + +### Props + diff --git a/packages/grafana-ui/src/components/Tags/TagList.story.tsx b/packages/grafana-ui/src/components/Tags/TagList.story.tsx new file mode 100644 index 00000000000..dfecbb0ea57 --- /dev/null +++ b/packages/grafana-ui/src/components/Tags/TagList.story.tsx @@ -0,0 +1,26 @@ +import React from 'react'; +import { action } from '@storybook/addon-actions'; +import { TagList } from './TagList'; +import { withCenteredStory } from '../../utils/storybook/withCenteredStory'; +import mdx from './TagList.mdx'; + +export default { + title: 'General/Tags/TagList', + component: TagList, + decorators: [withCenteredStory], + parameters: { + docs: { + page: mdx, + }, + }, +}; + +const tags = ['datasource-test', 'gdev', 'mysql', 'mssql']; + +export const list = () => { + return ( +
+ +
+ ); +}; diff --git a/packages/grafana-ui/src/components/Tags/TagList.tsx b/packages/grafana-ui/src/components/Tags/TagList.tsx new file mode 100644 index 00000000000..da62227b53f --- /dev/null +++ b/packages/grafana-ui/src/components/Tags/TagList.tsx @@ -0,0 +1,38 @@ +import React, { FC } from 'react'; +import { cx, css } from 'emotion'; +import { Tag } from './Tag'; + +export interface Props { + tags: string[]; + onClick?: (name: string) => any; + /** Custom styles for the wrapper component */ + className?: string; +} + +export const TagList: FC = ({ tags, onClick, className }) => { + const styles = getStyles(); + + return ( + + {tags.map(tag => ( + + ))} + + ); +}; + +const getStyles = () => { + return { + wrapper: css` + display: flex; + flex: 1 1 auto; + flex-wrap: wrap; + padding: 10px; + `, + tag: css` + margin-left: 6px; + font-size: 11px; + padding: 2px 6px; + `, + }; +}; diff --git a/packages/grafana-ui/src/components/index.ts b/packages/grafana-ui/src/components/index.ts index 3476fdd95e3..c20c00d092e 100644 --- a/packages/grafana-ui/src/components/index.ts +++ b/packages/grafana-ui/src/components/index.ts @@ -41,6 +41,8 @@ export { TimeOfDayPicker } from './TimePicker/TimeOfDayPicker'; export { List } from './List/List'; export { TagsInput } from './TagsInput/TagsInput'; export { Pagination } from './Pagination/Pagination'; +export { Tag } from './Tags/Tag'; +export { TagList } from './Tags/TagList'; export { ConfirmModal } from './ConfirmModal/ConfirmModal'; export { QueryField } from './QueryField/QueryField';