Commit e8f4b46a by Alexander Zobnin Committed by GitHub

UI: add InfoBox component (#23701)

* UI: inherit LinkButton props from ButtonHTMLAttributes

* Chore: fix implicit any

* UI: add InfoBox component

* UI: fix InfoBox border color

* Chore: use new style for defining stories

* Chore: InfoBox refactor

* Chore: inherit className attribute from HTMLDivElement
parent a9032f91
...@@ -153,7 +153,7 @@ export const Button = React.forwardRef<HTMLButtonElement, ButtonProps>( ...@@ -153,7 +153,7 @@ export const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
Button.displayName = 'Button'; Button.displayName = 'Button';
type ButtonLinkProps = CommonProps & AnchorHTMLAttributes<HTMLAnchorElement>; type ButtonLinkProps = CommonProps & ButtonHTMLAttributes<HTMLButtonElement> & AnchorHTMLAttributes<HTMLAnchorElement>;
export const LinkButton = React.forwardRef<HTMLAnchorElement, ButtonLinkProps>( export const LinkButton = React.forwardRef<HTMLAnchorElement, ButtonLinkProps>(
({ variant, icon, children, className, ...otherProps }, ref) => { ({ variant, icon, children, className, ...otherProps }, ref) => {
const theme = useContext(ThemeContext); const theme = useContext(ThemeContext);
......
import React from 'react';
import { number } from '@storybook/addon-knobs';
import { InfoBox } from './InfoBox';
export default {
title: 'General/InfoBox',
component: InfoBox,
decorators: [],
parameters: {
docs: {},
},
};
const getKnobs = () => {
const CONTAINER_GROUP = 'Container options';
// ---
const containerWidth = number(
'Container width',
800,
{
range: true,
min: 100,
max: 1500,
step: 100,
},
CONTAINER_GROUP
);
return { containerWidth };
};
export const basic = () => {
const { containerWidth } = getKnobs();
return (
<div style={{ width: containerWidth }}>
<InfoBox
header="User Permission"
footer={
<>
Checkout the{' '}
<a className="external-link" target="_blank" href="http://docs.grafana.org/features/datasources/mysql/">
MySQL Data Source Docs
</a>{' '}
for more information.,
</>
}
>
<p>
The database user should only be granted SELECT permissions on the specified database &amp; tables you want to
query. Grafana does not validate that queries are safe so queries can contain any SQL statement. For example,
statements like <code>USE otherdb;</code> and <code>DROP TABLE user;</code> would be executed. To protect
against this we <strong>Highly</strong> recommmend you create a specific MySQL user with restricted
permissions.
</p>
</InfoBox>
</div>
);
};
import React from 'react';
import { css, cx } from 'emotion';
import { GrafanaTheme } from '@grafana/data';
import { stylesFactory, useTheme } from '../../themes';
export interface Props extends React.HTMLAttributes<HTMLDivElement> {
header?: string | JSX.Element;
footer?: string | JSX.Element;
}
/**
* This is a simple InfoBox component, the api is not considered stable yet and will likely see breaking changes
* in future minor releases.
* @Alpha
*/
export const InfoBox = React.memo(
React.forwardRef<HTMLDivElement, Props>(({ header, footer, className, children, ...otherProps }, ref) => {
const theme = useTheme();
const css = getInfoBoxStyles(theme);
return (
<div className={cx([css.wrapper, className])} {...otherProps} ref={ref}>
{header && (
<div className={css.header}>
<h5>{header}</h5>
</div>
)}
{children}
{footer && <div className={css.footer}>{footer}</div>}
</div>
);
})
);
const getInfoBoxStyles = stylesFactory((theme: GrafanaTheme) => ({
wrapper: css`
position: relative;
padding: ${theme.spacing.lg};
background-color: ${theme.colors.bg2};
border-top: 3px solid ${theme.palette.blue80};
margin-bottom: ${theme.spacing.md};
margin-right: ${theme.spacing.xs};
box-shadow: ${theme.shadows.listItem};
flex-grow: 1;
ul {
padding-left: ${theme.spacing.lg};
}
code {
@include font-family-monospace();
font-size: ${theme.typography.size.sm};
background-color: ${theme.colors.bg1};
color: ${theme.colors.text};
border: 1px solid ${theme.colors.border2};
border-radius: 4px;
}
p:last-child {
margin-bottom: 0;
}
a {
@extend .external-link;
}
&--max-lg {
max-width: ${theme.breakpoints.lg};
}
`,
header: css`
margin-bottom: ${theme.spacing.d};
`,
footer: css`
margin-top: ${theme.spacing.d};
`,
}));
...@@ -126,14 +126,13 @@ class UnThemedLogDetailsRow extends PureComponent<Props, State> { ...@@ -126,14 +126,13 @@ class UnThemedLogDetailsRow extends PureComponent<Props, State> {
href={link.href} href={link.href}
target={'_blank'} target={'_blank'}
onClick={ onClick={
link.onClick link.onClick &&
? event => { ((event: any) => {
if (!(event.ctrlKey || event.metaKey || event.shiftKey) && link.onClick) { if (!(event.ctrlKey || event.metaKey || event.shiftKey) && link.onClick) {
event.preventDefault(); event.preventDefault();
link.onClick(event); link.onClick(event);
} }
} })
: undefined
} }
/> />
</> </>
......
...@@ -97,6 +97,7 @@ export { DataLinksInlineEditor } from './DataLinks/DataLinksInlineEditor/DataLin ...@@ -97,6 +97,7 @@ export { DataLinksInlineEditor } from './DataLinks/DataLinksInlineEditor/DataLin
export { DataLinkInput } from './DataLinks/DataLinkInput'; export { DataLinkInput } from './DataLinks/DataLinkInput';
export { DataLinksContextMenu } from './DataLinks/DataLinksContextMenu'; export { DataLinksContextMenu } from './DataLinks/DataLinksContextMenu';
export { SeriesIcon } from './Legend/SeriesIcon'; export { SeriesIcon } from './Legend/SeriesIcon';
export { InfoBox } from './InfoBox/InfoBox';
export { JSONFormatter } from './JSONFormatter/JSONFormatter'; export { JSONFormatter } from './JSONFormatter/JSONFormatter';
export { JsonExplorer } from './JSONFormatter/json_explorer/json_explorer'; export { JsonExplorer } from './JSONFormatter/json_explorer/json_explorer';
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment