mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Feature: Introduced CallToActionCard to @grafana/ui (#16237)
CallToActionCard is an abstraction to display a card with message, call to action element and a footer. It is used i.e. on datasource add page.
This commit is contained in:
@@ -0,0 +1,34 @@
|
||||
import React from 'react';
|
||||
import { storiesOf } from '@storybook/react';
|
||||
import { renderComponentWithTheme } from '../../utils/storybook/withTheme';
|
||||
import { CallToActionCard } from './CallToActionCard';
|
||||
import { select, text } from '@storybook/addon-knobs';
|
||||
import { LargeButton } from '../Button/Button';
|
||||
import { action } from '@storybook/addon-actions';
|
||||
|
||||
const CallToActionCardStories = storiesOf('UI/CallToActionCard', module);
|
||||
|
||||
CallToActionCardStories.add('default', () => {
|
||||
const ctaElements: { [key: string]: JSX.Element } = {
|
||||
custom: <h1>This is just H1 tag, you can any component as CTA element</h1>,
|
||||
button: (
|
||||
<LargeButton icon="fa fa-plus" onClick={action('cta button clicked')}>
|
||||
Add datasource
|
||||
</LargeButton>
|
||||
),
|
||||
};
|
||||
const ctaElement = select(
|
||||
'Call to action element',
|
||||
{
|
||||
Custom: 'custom',
|
||||
Button: 'button',
|
||||
},
|
||||
'custom'
|
||||
);
|
||||
|
||||
return renderComponentWithTheme(CallToActionCard, {
|
||||
message: text('Call to action message', 'Renders message prop content'),
|
||||
callToActionElement: ctaElements[ctaElement],
|
||||
footer: text('Call to action footer', 'Renders footer prop content'),
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,38 @@
|
||||
import React, { useContext } from 'react';
|
||||
import { render } from 'enzyme';
|
||||
import { CallToActionCard, CallToActionCardProps } from './CallToActionCard';
|
||||
import { ThemeContext } from '../../themes';
|
||||
|
||||
type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>;
|
||||
|
||||
const TestRenderer = (props: Omit<CallToActionCardProps, 'theme'>) => {
|
||||
const theme = useContext(ThemeContext);
|
||||
return <CallToActionCard theme={theme} {...props} />;
|
||||
};
|
||||
|
||||
describe('CallToActionCard', () => {
|
||||
describe('rendering', () => {
|
||||
it('when no message and footer provided', () => {
|
||||
const tree = render(<TestRenderer callToActionElement={<a href="http://dummy.link">Click me</a>} />);
|
||||
expect(tree).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('when message and no footer provided', () => {
|
||||
const tree = render(
|
||||
<TestRenderer message="Click button bellow" callToActionElement={<a href="http://dummy.link">Click me</a>} />
|
||||
);
|
||||
expect(tree).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('when message and footer provided', () => {
|
||||
const tree = render(
|
||||
<TestRenderer
|
||||
message="Click button bellow"
|
||||
footer="footer content"
|
||||
callToActionElement={<a href="http://dummy.link">Click me</a>}
|
||||
/>
|
||||
);
|
||||
expect(tree).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,49 @@
|
||||
import React from 'react';
|
||||
import { Themeable, GrafanaTheme } from '../../types/theme';
|
||||
import { selectThemeVariant } from '../../themes/selectThemeVariant';
|
||||
import { css, cx } from 'emotion';
|
||||
|
||||
export interface CallToActionCardProps extends Themeable {
|
||||
message?: string | JSX.Element;
|
||||
callToActionElement: JSX.Element;
|
||||
footer?: string | JSX.Element;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
const getCallToActionCardStyles = (theme: GrafanaTheme) => ({
|
||||
wrapper: css`
|
||||
label: call-to-action-card;
|
||||
padding: ${theme.spacing.lg};
|
||||
background: ${selectThemeVariant({ light: theme.colors.gray6, dark: theme.colors.grayBlue }, theme.type)};
|
||||
border-radius: ${theme.border.radius.md};
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
`,
|
||||
message: css`
|
||||
margin-bottom: ${theme.spacing.lg};
|
||||
font-style: italic;
|
||||
`,
|
||||
footer: css`
|
||||
margin-top: ${theme.spacing.lg};
|
||||
`,
|
||||
});
|
||||
|
||||
export const CallToActionCard: React.FunctionComponent<CallToActionCardProps> = ({
|
||||
message,
|
||||
callToActionElement,
|
||||
footer,
|
||||
theme,
|
||||
className,
|
||||
}) => {
|
||||
const css = getCallToActionCardStyles(theme);
|
||||
|
||||
return (
|
||||
<div className={cx([css.wrapper, className])}>
|
||||
{message && <div className={css.message}>{message}</div>}
|
||||
{callToActionElement}
|
||||
{footer && <div className={css.footer}>{footer}</div>}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,52 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`CallToActionCard rendering when message and footer provided 1`] = `
|
||||
<div
|
||||
class="css-1ph0cdx-call-to-action-card"
|
||||
>
|
||||
<div
|
||||
class="css-m2iibx"
|
||||
>
|
||||
Click button bellow
|
||||
</div>
|
||||
<a
|
||||
href="http://dummy.link"
|
||||
>
|
||||
Click me
|
||||
</a>
|
||||
<div
|
||||
class="css-1sg2huk"
|
||||
>
|
||||
footer content
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`CallToActionCard rendering when message and no footer provided 1`] = `
|
||||
<div
|
||||
class="css-1ph0cdx-call-to-action-card"
|
||||
>
|
||||
<div
|
||||
class="css-m2iibx"
|
||||
>
|
||||
Click button bellow
|
||||
</div>
|
||||
<a
|
||||
href="http://dummy.link"
|
||||
>
|
||||
Click me
|
||||
</a>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`CallToActionCard rendering when no message and footer provided 1`] = `
|
||||
<div
|
||||
class="css-1ph0cdx-call-to-action-card"
|
||||
>
|
||||
<a
|
||||
href="http://dummy.link"
|
||||
>
|
||||
Click me
|
||||
</a>
|
||||
</div>
|
||||
`;
|
||||
@@ -37,3 +37,5 @@ export { Gauge } from './Gauge/Gauge';
|
||||
export { Graph } from './Graph/Graph';
|
||||
export { BarGauge } from './BarGauge/BarGauge';
|
||||
export { VizRepeater } from './VizRepeater/VizRepeater';
|
||||
|
||||
export { CallToActionCard } from './CallToActionCard/CallToActionCard';
|
||||
|
||||
Reference in New Issue
Block a user