diff --git a/packages/grafana-ui/src/components/Drawer/Drawer.tsx b/packages/grafana-ui/src/components/Drawer/Drawer.tsx
index 7171caac2e8..265fff11e97 100644
--- a/packages/grafana-ui/src/components/Drawer/Drawer.tsx
+++ b/packages/grafana-ui/src/components/Drawer/Drawer.tsx
@@ -125,7 +125,7 @@ export function Drawer({
/>
-
+
{title}
{subtitle && {subtitle}
}
diff --git a/packages/grafana-ui/src/components/Link/TextLink.story.tsx b/packages/grafana-ui/src/components/Link/TextLink.story.tsx
index d6d826e2274..a4dcdc74a31 100644
--- a/packages/grafana-ui/src/components/Link/TextLink.story.tsx
+++ b/packages/grafana-ui/src/components/Link/TextLink.story.tsx
@@ -3,7 +3,7 @@ import React from 'react';
import { StoryExample } from '../../utils/storybook/StoryExample';
import { VerticalGroup } from '../Layout/Layout';
-import { P } from '../Text/TextElements';
+import { Text } from '../Text/Text';
import { TextLink } from './TextLink';
import mdx from './TextLink.mdx';
@@ -44,13 +44,13 @@ export const Example: StoryFn = (args) => {
return (
-
+
To get started with a forever free Grafana Cloud account, sign up at
grafana.com
.
-
+
@@ -58,7 +58,9 @@ export const Example: StoryFn = (args) => {
-
*The examples cannot contemplate an internal link due to conflicts between Storybook and React Router
+
+ *The examples cannot contemplate an internal link due to conflicts between Storybook and React Router
+
);
};
diff --git a/packages/grafana-ui/src/components/Text/Text.internal.story.tsx b/packages/grafana-ui/src/components/Text/Text.internal.story.tsx
index 14367f713df..e3ea5b5eea9 100644
--- a/packages/grafana-ui/src/components/Text/Text.internal.story.tsx
+++ b/packages/grafana-ui/src/components/Text/Text.internal.story.tsx
@@ -6,7 +6,6 @@ import { VerticalGroup } from '../Layout/Layout';
import { Text } from './Text';
import mdx from './Text.mdx';
-import { H1, H2, H3, H4, H5, H6, Span, P, Legend, TextModifier } from './TextElements';
const meta: Meta = {
title: 'General/Text',
@@ -15,7 +14,6 @@ const meta: Meta = {
docs: {
page: mdx,
},
- controls: { exclude: ['as'] },
},
argTypes: {
variant: { control: 'select', options: ['h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'body', 'bodySmall', undefined] },
@@ -39,93 +37,73 @@ const meta: Meta = {
],
},
truncate: { control: 'boolean' },
+ italic: { control: 'boolean' },
textAlignment: {
control: 'select',
options: ['inherit', 'initial', 'left', 'right', 'center', 'justify', undefined],
},
},
+ args: {
+ element: 'h1',
+ variant: undefined,
+ weight: 'light',
+ textAlignment: 'left',
+ truncate: false,
+ italic: false,
+ color: 'primary',
+ children: `This is an example of a Text component`,
+ },
};
-export const Example: StoryFn = () => {
+export const Example: StoryFn = (args) => {
return (
-
- h1. Heading
- h2. Heading
- h3. Heading
- h4. Heading
- h5. Heading
- h6. Heading
- This is a paragraph
-
- This is a span
+
+
+ This is a header
+
+
+ This is a paragraph that contains
+
+ {' '}
+ a span element with different color and style{' '}
+
+ but is comprised within the same block text
+
+
+
+
+ This is a paragraph that contains
+
+ {' '}
+ a span element{' '}
+
+ but has truncate set to true
+
);
};
Example.parameters = {
controls: {
- exclude: ['variant', 'weight', 'textAlignment', 'truncate', 'color', 'children'],
+ exclude: ['element', 'variant', 'weight', 'textAlignment', 'truncate', 'italic', 'color', 'children'],
},
};
-export const HeadingComponent: StoryFn = (args) => {
+export const Basic: StoryFn = (args) => {
return (
-
+
{args.children}
-
+
);
};
-HeadingComponent.args = {
- variant: undefined,
- weight: 'light',
- textAlignment: 'center',
- truncate: false,
- color: 'primary',
- children: 'This is a H1 component',
-};
-
-export const LegendComponent: StoryFn = (args) => {
- return (
-
-
-
- );
-};
-
-LegendComponent.args = {
- variant: undefined,
- weight: 'bold',
- textAlignment: 'center',
- truncate: false,
- color: 'error',
- children: 'This is a lengend component',
-};
-
-export const TextModifierComponent: StoryFn = (args) => {
- return (
-
-
- {args.children}{' '}
-
- {' '}
- with a part of its text modified{' '}
-
-
-
- );
-};
-TextModifierComponent.args = {
- variant: undefined,
- weight: 'light',
- textAlignment: 'center',
- truncate: false,
- color: 'maxContrast',
- children: 'This is a H6 component',
-};
export default meta;
diff --git a/packages/grafana-ui/src/components/Text/Text.test.tsx b/packages/grafana-ui/src/components/Text/Text.test.tsx
index 591211db265..f05d37d06a6 100644
--- a/packages/grafana-ui/src/components/Text/Text.test.tsx
+++ b/packages/grafana-ui/src/components/Text/Text.test.tsx
@@ -7,13 +7,13 @@ import { Text } from './Text';
describe('Text', () => {
it('renders correctly', () => {
- render(
This is a text component);
+ render(
This is a text component);
expect(screen.getByText('This is a text component')).toBeInTheDocument();
});
it('keeps the element type but changes its styles', () => {
const customVariant: keyof ThemeTypographyVariantTypes = 'body';
render(
-
+
This is a text component
);
@@ -26,7 +26,7 @@ describe('Text', () => {
const customColor = 'info';
const theme = createTheme();
render(
-
+
This is a text component
);
diff --git a/packages/grafana-ui/src/components/Text/Text.tsx b/packages/grafana-ui/src/components/Text/Text.tsx
index d8e7d460c4f..ffcc98fc090 100644
--- a/packages/grafana-ui/src/components/Text/Text.tsx
+++ b/packages/grafana-ui/src/components/Text/Text.tsx
@@ -5,11 +5,11 @@ import { GrafanaTheme2, ThemeTypographyVariantTypes } from '@grafana/data';
import { useStyles2 } from '../../themes';
-import { customWeight, customColor } from './utils';
+import { customWeight, customColor, customVariant } from './utils';
export interface TextProps {
- /** Defines what HTML element is defined underneath */
- as: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' | 'span' | 'p' | 'legend';
+ /** Defines what HTML element is defined underneath. "span" by default */
+ element?: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' | 'span' | 'p';
/** What typograpy variant should be used for the component. Only use if default variant for the defined element is not what is needed */
variant?: keyof ThemeTypographyVariantTypes;
/** Override the default weight for the used variant */
@@ -18,22 +18,24 @@ export interface TextProps {
color?: keyof GrafanaTheme2['colors']['text'] | 'error' | 'success' | 'warning' | 'info';
/** Use to cut the text off with ellipsis if there isn't space to show all of it. On hover shows the rest of the text */
truncate?: boolean;
+ /** If true, show the text as italic. False by default */
+ italic?: boolean;
/** Whether to align the text to left, center or right */
textAlignment?: CSSProperties['textAlign'];
children: React.ReactNode;
}
export const Text = React.forwardRef(
- ({ as, variant, weight, color, truncate, textAlignment, children }, ref) => {
+ ({ element = 'span', variant, weight, color, truncate, italic, textAlignment, children }, ref) => {
const styles = useStyles2(
useCallback(
- (theme) => getTextStyles(theme, variant, color, weight, truncate, textAlignment),
- [color, textAlignment, truncate, weight, variant]
+ (theme) => getTextStyles(theme, element, variant, color, weight, truncate, italic, textAlignment),
+ [color, textAlignment, truncate, italic, weight, variant, element]
)
);
return createElement(
- as,
+ element,
{
className: styles,
ref,
@@ -47,19 +49,22 @@ Text.displayName = 'Text';
const getTextStyles = (
theme: GrafanaTheme2,
+ element?: TextProps['element'],
variant?: keyof ThemeTypographyVariantTypes,
color?: TextProps['color'],
weight?: TextProps['weight'],
truncate?: TextProps['truncate'],
+ italic?: TextProps['italic'],
textAlignment?: TextProps['textAlignment']
) => {
return css([
- variant && {
- ...theme.typography[variant],
- },
{
margin: 0,
padding: 0,
+ ...customVariant(theme, element, variant),
+ },
+ variant && {
+ ...theme.typography[variant],
},
color && {
color: customColor(color, theme),
@@ -72,6 +77,9 @@ const getTextStyles = (
textOverflow: 'ellipsis',
whiteSpace: 'nowrap',
},
+ italic && {
+ fontStyle: 'italic',
+ },
textAlignment && {
textAlign: textAlignment,
},
diff --git a/packages/grafana-ui/src/components/Text/TextElements.tsx b/packages/grafana-ui/src/components/Text/TextElements.tsx
deleted file mode 100644
index f0569f9b376..00000000000
--- a/packages/grafana-ui/src/components/Text/TextElements.tsx
+++ /dev/null
@@ -1,75 +0,0 @@
-import React from 'react';
-
-import { GrafanaTheme2 } from '@grafana/data';
-
-import { Text, TextProps } from './Text';
-
-interface TextElementsProps extends Omit {}
-
-interface TextModifierProps {
- /** Override the default weight for the used variant */
- weight?: 'light' | 'regular' | 'medium' | 'bold';
- /** Color to use for text */
- color?: keyof GrafanaTheme2['colors']['text'] | 'error' | 'success' | 'warning' | 'info';
- children: React.ReactNode;
-}
-
-export const H1 = React.forwardRef((props, ref) => {
- return ;
-});
-
-H1.displayName = 'H1';
-
-export const H2 = React.forwardRef((props, ref) => {
- return ;
-});
-
-H2.displayName = 'H2';
-
-export const H3 = React.forwardRef((props, ref) => {
- return ;
-});
-
-H3.displayName = 'H3';
-
-export const H4 = React.forwardRef((props, ref) => {
- return ;
-});
-
-H4.displayName = 'H4';
-
-export const H5 = React.forwardRef((props, ref) => {
- return ;
-});
-
-H5.displayName = 'H5';
-
-export const H6 = React.forwardRef((props, ref) => {
- return ;
-});
-
-H6.displayName = 'H6';
-
-export const P = React.forwardRef((props, ref) => {
- return ;
-});
-
-P.displayName = 'P';
-
-export const Span = React.forwardRef((props, ref) => {
- return ;
-});
-
-Span.displayName = 'Span';
-
-export const Legend = React.forwardRef((props, ref) => {
- return ;
-});
-
-Legend.displayName = 'Legend';
-
-export const TextModifier = React.forwardRef((props, ref) => {
- return ;
-});
-
-TextModifier.displayName = 'TextModifier';
diff --git a/packages/grafana-ui/src/components/Text/utils.ts b/packages/grafana-ui/src/components/Text/utils.ts
index 650e6ecae74..5e28195e1a9 100644
--- a/packages/grafana-ui/src/components/Text/utils.ts
+++ b/packages/grafana-ui/src/components/Text/utils.ts
@@ -1,4 +1,4 @@
-import { GrafanaTheme2 } from '@grafana/data';
+import { GrafanaTheme2, ThemeTypographyVariantTypes } from '@grafana/data';
import { TextProps } from './Text';
@@ -30,3 +30,32 @@ export const customColor = (color: TextProps['color'], theme: GrafanaTheme2): st
return color ? theme.colors.text[color] : undefined;
}
};
+
+export const customVariant = (
+ theme: GrafanaTheme2,
+ element: TextProps['element'],
+ variant?: keyof ThemeTypographyVariantTypes
+) => {
+ if (variant) {
+ return theme.typography[variant];
+ }
+ switch (element) {
+ //Span elements does not have a default variant to be able to take the parents style
+ case 'span':
+ return;
+ case 'h1':
+ return theme.typography.h1;
+ case 'h2':
+ return theme.typography.h2;
+ case 'h3':
+ return theme.typography.h3;
+ case 'h4':
+ return theme.typography.h4;
+ case 'h5':
+ return theme.typography.h5;
+ case 'h6':
+ return theme.typography.h6;
+ default:
+ return theme.typography.body;
+ }
+};
diff --git a/packages/grafana-ui/src/unstable.ts b/packages/grafana-ui/src/unstable.ts
index 7941d6a0e6d..3a2dd5f6632 100644
--- a/packages/grafana-ui/src/unstable.ts
+++ b/packages/grafana-ui/src/unstable.ts
@@ -9,4 +9,4 @@
* be subject to the standard policies
*/
-export * from './components/Text/TextElements';
+export * from './components/Text/Text';
diff --git a/public/app/core/components/AppChrome/News/NewsContainer.tsx b/public/app/core/components/AppChrome/News/NewsContainer.tsx
index da7c096702b..56227837b09 100644
--- a/public/app/core/components/AppChrome/News/NewsContainer.tsx
+++ b/public/app/core/components/AppChrome/News/NewsContainer.tsx
@@ -5,7 +5,7 @@ import { useToggle } from 'react-use';
import { GrafanaTheme2 } from '@grafana/data';
import { selectors } from '@grafana/e2e-selectors';
import { Button, Drawer, ToolbarButton, useStyles2 } from '@grafana/ui';
-import { H3 } from '@grafana/ui/src/unstable';
+import { Text } from '@grafana/ui/src/unstable';
import { t } from 'app/core/internationalization';
import { DEFAULT_FEED_URL } from 'app/plugins/panel/news/constants';
@@ -26,7 +26,7 @@ export function NewsContainer({ className }: NewsContainerProps) {
- {t('news.title', 'Latest from the blog')}
+ {t('news.title', 'Latest from the blog')}
-
- {item.title}
-
+ {/* TODO: text is not truncated properly, it still overflows the container */}
+ {item.title}
diff --git a/public/app/core/components/NestedFolderPicker/NestedFolderPicker.tsx b/public/app/core/components/NestedFolderPicker/NestedFolderPicker.tsx
index 1ba8b3fbd75..eaa737f69e6 100644
--- a/public/app/core/components/NestedFolderPicker/NestedFolderPicker.tsx
+++ b/public/app/core/components/NestedFolderPicker/NestedFolderPicker.tsx
@@ -7,7 +7,7 @@ import { useAsync } from 'react-use';
import { GrafanaTheme2 } from '@grafana/data';
import { Alert, Button, Icon, Input, LoadingBar, useStyles2 } from '@grafana/ui';
import { Text } from '@grafana/ui/src/components/Text/Text';
-import { Trans, t } from 'app/core/internationalization';
+import { t, Trans } from 'app/core/internationalization';
import { skipToken, useGetFolderQuery } from 'app/features/browse-dashboards/api/browseDashboardsAPI';
import { PAGE_SIZE } from 'app/features/browse-dashboards/api/services';
import {
@@ -209,7 +209,7 @@ export function NestedFolderPicker({ value, onChange }: NestedFolderPickerProps)
{selectedFolder.isLoading ? (