mirror of https://github.com/grafana/grafana
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 HTMLDivElementpull/23695/head
parent
a9032f9188
commit
e8f4b46aae
@ -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> |
||||
); |
||||
}; |
||||
@ -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}; |
||||
`,
|
||||
})); |
||||
Loading…
Reference in new issue