mirror of
https://github.com/grafana/grafana.git
synced 2025-07-31 16:02:46 +08:00
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
This commit is contained in:
@ -153,7 +153,7 @@ export const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
|
||||
|
||||
Button.displayName = 'Button';
|
||||
|
||||
type ButtonLinkProps = CommonProps & AnchorHTMLAttributes<HTMLAnchorElement>;
|
||||
type ButtonLinkProps = CommonProps & ButtonHTMLAttributes<HTMLButtonElement> & AnchorHTMLAttributes<HTMLAnchorElement>;
|
||||
export const LinkButton = React.forwardRef<HTMLAnchorElement, ButtonLinkProps>(
|
||||
({ variant, icon, children, className, ...otherProps }, ref) => {
|
||||
const theme = useContext(ThemeContext);
|
||||
|
59
packages/grafana-ui/src/components/InfoBox/InfoBox.story.tsx
Normal file
59
packages/grafana-ui/src/components/InfoBox/InfoBox.story.tsx
Normal file
@ -0,0 +1,59 @@
|
||||
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 & 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>
|
||||
);
|
||||
};
|
77
packages/grafana-ui/src/components/InfoBox/InfoBox.tsx
Normal file
77
packages/grafana-ui/src/components/InfoBox/InfoBox.tsx
Normal file
@ -0,0 +1,77 @@
|
||||
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> {
|
||||
href={link.href}
|
||||
target={'_blank'}
|
||||
onClick={
|
||||
link.onClick
|
||||
? event => {
|
||||
if (!(event.ctrlKey || event.metaKey || event.shiftKey) && link.onClick) {
|
||||
event.preventDefault();
|
||||
link.onClick(event);
|
||||
}
|
||||
}
|
||||
: undefined
|
||||
link.onClick &&
|
||||
((event: any) => {
|
||||
if (!(event.ctrlKey || event.metaKey || event.shiftKey) && link.onClick) {
|
||||
event.preventDefault();
|
||||
link.onClick(event);
|
||||
}
|
||||
})
|
||||
}
|
||||
/>
|
||||
</>
|
||||
|
@ -97,6 +97,7 @@ export { DataLinksInlineEditor } from './DataLinks/DataLinksInlineEditor/DataLin
|
||||
export { DataLinkInput } from './DataLinks/DataLinkInput';
|
||||
export { DataLinksContextMenu } from './DataLinks/DataLinksContextMenu';
|
||||
export { SeriesIcon } from './Legend/SeriesIcon';
|
||||
export { InfoBox } from './InfoBox/InfoBox';
|
||||
|
||||
export { JSONFormatter } from './JSONFormatter/JSONFormatter';
|
||||
export { JsonExplorer } from './JSONFormatter/json_explorer/json_explorer';
|
||||
|
Reference in New Issue
Block a user