diff --git a/packages/grafana-ui/src/components/Card/Card.mdx b/packages/grafana-ui/src/components/Card/Card.mdx index 2e604d527f7..b6b1445de7f 100644 --- a/packages/grafana-ui/src/components/Card/Card.mdx +++ b/packages/grafana-ui/src/components/Card/Card.mdx @@ -445,6 +445,24 @@ Card can have a disabled state, effectively making it and its actions non-clicka +### With overline + +```jsx + + Filter option + Filter by name + Filter data by query. + +``` + + + + Filter option + Filter by name + Filter data by query. + + + ### Props diff --git a/packages/grafana-ui/src/components/Card/Card.story.tsx b/packages/grafana-ui/src/components/Card/Card.story.tsx index f6904421394..4d4f8367b17 100644 --- a/packages/grafana-ui/src/components/Card/Card.story.tsx +++ b/packages/grafana-ui/src/components/Card/Card.story.tsx @@ -24,9 +24,9 @@ const meta: Meta = { }, }; -export const Basic: StoryFn = ({ disabled }) => { +export const Basic: StoryFn = (args) => { return ( - + Filter by name Filter data by query. This is useful if you are sharing the results from a different panel that has many queries @@ -36,24 +36,24 @@ export const Basic: StoryFn = ({ disabled }) => { ); }; -export const AsLink: StoryFn = ({ disabled }) => { +export const AsLink: StoryFn = (args) => { return ( - + Filter by name Filter data by query. This is useful if you are sharing the results from a different panel that has many queries and you want to only visualize a subset of that in this panel. - + Filter by name2 Filter data by query. This is useful if you are sharing the results from a different panel that has many queries and you want to only visualize a subset of that in this panel. - + Production system overview Meta tags @@ -61,9 +61,9 @@ export const AsLink: StoryFn = ({ disabled }) => { ); }; -export const WithTags: StoryFn = ({ disabled }) => { +export const WithTags: StoryFn = (args) => { return ( - + Elasticsearch – Custom Templated Query Elastic Search @@ -73,9 +73,9 @@ export const WithTags: StoryFn = ({ disabled }) => { ); }; -export const WithMedia: StoryFn = ({ disabled }) => { +export const WithMedia: StoryFn = (args) => { return ( - + 1-ops-tools1-fallback Prometheus @@ -89,9 +89,9 @@ export const WithMedia: StoryFn = ({ disabled }) => { ); }; -export const WithActions: StoryFn = ({ disabled }) => { +export const WithActions: StoryFn = (args) => { return ( - + 1-ops-tools1-fallback Prometheus @@ -118,9 +118,9 @@ export const WithActions: StoryFn = ({ disabled }) => { ); }; -export const Full: StoryFn = ({ disabled }) => { +export const Full: StoryFn = (args) => { return ( - + Card title Description, body text. Greetings! Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod @@ -179,4 +179,18 @@ export const NotSelected: StoryFn = () => { ); }; +export const WithOverline: StoryFn = (args) => { + return ( + + Overline text above the title + Card title + + Description, body text. Greetings! Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod + tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco + laboris nisi ut aliquip ex ea commodo consequat. + + + ); +}; + export default meta; diff --git a/packages/grafana-ui/src/components/Card/Card.tsx b/packages/grafana-ui/src/components/Card/Card.tsx index 4ebb077f1fa..be178a25c29 100644 --- a/packages/grafana-ui/src/components/Card/Card.tsx +++ b/packages/grafana-ui/src/components/Card/Card.tsx @@ -5,6 +5,7 @@ import { GrafanaTheme2 } from '@grafana/data'; import { useStyles2 } from '../../themes'; import { getFocusStyles } from '../../themes/mixins'; +import { Text } from '../Text/Text'; import { CardContainer, CardContainerProps, getCardContainerStyles } from './CardContainer'; @@ -23,9 +24,12 @@ export interface Props extends Omit { + Overline: typeof Overline; Heading: typeof Heading; Tags: typeof Tags; Figure: typeof Figure; @@ -47,7 +51,16 @@ const CardContext = React.createContext<{ * * @public */ -export const Card: CardInterface = ({ disabled, href, onClick, children, isSelected, className, ...htmlProps }) => { +export const Card: CardInterface = ({ + disabled, + href, + onClick, + children, + isSelected, + isCompact, + className, + ...htmlProps +}) => { const hasHeadingComponent = useMemo( () => React.Children.toArray(children).some((c) => React.isValidElement(c) && c.type === Heading), [children] @@ -55,7 +68,7 @@ export const Card: CardInterface = ({ disabled, href, onClick, children, isSelec const disableHover = disabled || (!onClick && !href); const onCardClick = onClick && !disabled ? onClick : undefined; - const styles = useStyles2(getCardContainerStyles, disabled, disableHover, isSelected); + const styles = useStyles2(getCardContainerStyles, disabled, disableHover, isSelected, isCompact); return ( ({ }), }); +/** Card text to be displayed above title */ +const Overline = ({ children, className }: ChildProps) => { + const styles = useStyles2(getOverlineStyles); + return ( +
+ {children && ( + + {children} + + )} +
+ ); +}; +Overline.displayName = 'Overline'; + +const getOverlineStyles = (theme: GrafanaTheme2) => ({ + overline: css({ + gridArea: 'Overline', + marginBottom: theme.spacing(0.5), + }), +}); + const Tags = ({ children, className }: ChildProps) => { const styles = useStyles2(getTagStyles); return
{children}
; @@ -349,6 +384,7 @@ export const getCardStyles = (theme: GrafanaTheme2) => { }; }; +Card.Overline = Overline; Card.Heading = Heading; Card.Tags = Tags; Card.Figure = Figure; diff --git a/packages/grafana-ui/src/components/Card/CardContainer.tsx b/packages/grafana-ui/src/components/Card/CardContainer.tsx index e4a52c9f1f2..430634f9ba7 100644 --- a/packages/grafana-ui/src/components/Card/CardContainer.tsx +++ b/packages/grafana-ui/src/components/Card/CardContainer.tsx @@ -70,7 +70,8 @@ export const getCardContainerStyles = ( theme: GrafanaTheme2, disabled = false, disableHover = false, - isSelected?: boolean + isSelected?: boolean, + isCompact?: boolean ) => { const isSelectable = isSelected !== undefined; @@ -79,16 +80,17 @@ export const getCardContainerStyles = ( display: 'grid', position: 'relative', gridTemplateColumns: 'auto 1fr auto', - gridTemplateRows: '1fr auto auto auto', + gridTemplateRows: 'auto 1fr auto auto auto', gridAutoColumns: '1fr', gridAutoFlow: 'row', gridTemplateAreas: ` + "Figure Overline Tags" "Figure Heading Tags" "Figure Meta Tags" "Figure Description Tags" "Figure Actions Secondary"`, width: '100%', - padding: theme.spacing(2), + padding: theme.spacing(isCompact ? 1 : 2), background: theme.colors.background.secondary, borderRadius: theme.shape.radius.default, marginBottom: '8px',