mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Storybook: Fixes theming of the padded story (that makes stories use primary background by default) (#33166)
This commit is contained in:
parent
bad048b7ba
commit
dc6d134276
@ -9,7 +9,6 @@ import '../../../public/vendor/flot/jquery.flot.crosshair';
|
||||
import '../../../public/vendor/flot/jquery.flot.dashes';
|
||||
import '../../../public/vendor/flot/jquery.flot.gauge';
|
||||
import { withTheme } from '../src/utils/storybook/withTheme';
|
||||
import { withPaddedStory } from '../src/utils/storybook/withPaddedStory';
|
||||
// @ts-ignore
|
||||
import lightTheme from '../../../public/sass/grafana.light.scss';
|
||||
// @ts-ignore
|
||||
@ -33,7 +32,7 @@ addons.setConfig({
|
||||
theme: GrafanaDark,
|
||||
});
|
||||
|
||||
export const decorators = [withTheme(handleThemeChange), withPaddedStory];
|
||||
export const decorators = [withTheme(handleThemeChange)];
|
||||
|
||||
export const parameters = {
|
||||
docs: {
|
||||
|
@ -1,5 +1,4 @@
|
||||
import React from 'react';
|
||||
import { renderComponentWithTheme } from '../../utils/storybook/withTheme';
|
||||
import { CallToActionCard, CallToActionCardProps } from './CallToActionCard';
|
||||
import { Story, Meta } from '@storybook/react';
|
||||
import { Button } from '../Button/Button';
|
||||
@ -37,11 +36,9 @@ export const Basic: Story<StoryProps> = (args) => {
|
||||
),
|
||||
};
|
||||
|
||||
return renderComponentWithTheme(CallToActionCard, {
|
||||
message: args.message,
|
||||
callToActionElement: ctaElements[args.Element],
|
||||
footer: args.footer,
|
||||
});
|
||||
return (
|
||||
<CallToActionCard message={args.message} callToActionElement={ctaElements[args.Element]} footer={args.footer} />
|
||||
);
|
||||
};
|
||||
|
||||
Basic.args = {
|
||||
|
@ -1,32 +1,27 @@
|
||||
import React, { useContext } from 'react';
|
||||
import React 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} />;
|
||||
};
|
||||
import { CallToActionCard } from './CallToActionCard';
|
||||
|
||||
describe('CallToActionCard', () => {
|
||||
describe('rendering', () => {
|
||||
it('when no message and footer provided', () => {
|
||||
const tree = render(<TestRenderer callToActionElement={<a href="http://dummy.link">Click me</a>} />);
|
||||
const tree = render(<CallToActionCard 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>} />
|
||||
<CallToActionCard
|
||||
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
|
||||
<CallToActionCard
|
||||
message="Click button bellow"
|
||||
footer="footer content"
|
||||
callToActionElement={<a href="http://dummy.link">Click me</a>}
|
||||
|
@ -1,17 +1,33 @@
|
||||
import React from 'react';
|
||||
import { Themeable } from '../../types/theme';
|
||||
import { GrafanaTheme } from '@grafana/data';
|
||||
import { css, cx } from '@emotion/css';
|
||||
import { stylesFactory } from '../../themes';
|
||||
import { useStyles } from '../../themes/ThemeContext';
|
||||
|
||||
export interface CallToActionCardProps extends Themeable {
|
||||
export interface CallToActionCardProps {
|
||||
message?: string | JSX.Element;
|
||||
callToActionElement: JSX.Element;
|
||||
footer?: string | JSX.Element;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
const getCallToActionCardStyles = stylesFactory((theme: GrafanaTheme) => ({
|
||||
export const CallToActionCard: React.FunctionComponent<CallToActionCardProps> = ({
|
||||
message,
|
||||
callToActionElement,
|
||||
footer,
|
||||
className,
|
||||
}) => {
|
||||
const css = useStyles(getStyles);
|
||||
|
||||
return (
|
||||
<div className={cx([css.wrapper, className])}>
|
||||
{message && <div className={css.message}>{message}</div>}
|
||||
{callToActionElement}
|
||||
{footer && <div className={css.footer}>{footer}</div>}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const getStyles = (theme: GrafanaTheme) => ({
|
||||
wrapper: css`
|
||||
label: call-to-action-card;
|
||||
padding: ${theme.spacing.lg};
|
||||
@ -30,22 +46,4 @@ const getCallToActionCardStyles = stylesFactory((theme: GrafanaTheme) => ({
|
||||
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>
|
||||
);
|
||||
};
|
||||
});
|
||||
|
@ -1,24 +0,0 @@
|
||||
import React from 'react';
|
||||
import { GlobalStyles, useTheme } from '../../themes';
|
||||
import { RenderFunction } from '../../types';
|
||||
|
||||
const PaddedStory: React.FunctionComponent<{}> = ({ children }) => {
|
||||
const theme = useTheme();
|
||||
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
width: '100%',
|
||||
padding: '20px',
|
||||
display: 'flex',
|
||||
minHeight: '80vh',
|
||||
background: `${theme.v2.palette.background.primary}`,
|
||||
}}
|
||||
>
|
||||
<GlobalStyles />
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export const withPaddedStory = (story: RenderFunction) => <PaddedStory>{story()}</PaddedStory>;
|
@ -1,20 +1,38 @@
|
||||
import React from 'react';
|
||||
import { ThemeContext } from '../../themes/ThemeContext';
|
||||
import { getTheme } from '../../themes/index';
|
||||
import { getTheme, GlobalStyles } from '../../themes/index';
|
||||
import { GrafanaThemeType } from '@grafana/data';
|
||||
import { RenderFunction } from '../../types';
|
||||
import { useDarkMode } from 'storybook-dark-mode';
|
||||
|
||||
type SassThemeChangeHandler = (theme: GrafanaThemeType) => void;
|
||||
|
||||
const ThemeableStory: React.FunctionComponent<{ handleSassThemeChange: SassThemeChangeHandler }> = ({
|
||||
children,
|
||||
handleSassThemeChange,
|
||||
}) => {
|
||||
const theme = useDarkMode() ? GrafanaThemeType.Dark : GrafanaThemeType.Light;
|
||||
const themeType = useDarkMode() ? GrafanaThemeType.Dark : GrafanaThemeType.Light;
|
||||
|
||||
handleSassThemeChange(theme);
|
||||
handleSassThemeChange(themeType);
|
||||
|
||||
return <ThemeContext.Provider value={getTheme(theme)}>{children}</ThemeContext.Provider>;
|
||||
const theme = getTheme(themeType);
|
||||
|
||||
return (
|
||||
<ThemeContext.Provider value={theme}>
|
||||
<div
|
||||
style={{
|
||||
width: '100%',
|
||||
padding: '20px',
|
||||
display: 'flex',
|
||||
minHeight: '80vh',
|
||||
background: `${theme.v2.palette.background.primary}`,
|
||||
}}
|
||||
>
|
||||
<GlobalStyles />
|
||||
{children}
|
||||
</div>
|
||||
</ThemeContext.Provider>
|
||||
);
|
||||
};
|
||||
|
||||
// Temporary solution. When we update to Storybook V5 we will be able to pass data from decorator to story
|
||||
|
@ -1,6 +1,6 @@
|
||||
import React, { MouseEvent, useContext } from 'react';
|
||||
import React, { MouseEvent } from 'react';
|
||||
import { css } from '@emotion/css';
|
||||
import { CallToActionCard, Icon, IconName, LinkButton, ThemeContext } from '@grafana/ui';
|
||||
import { CallToActionCard, Icon, IconName, LinkButton } from '@grafana/ui';
|
||||
import { selectors } from '@grafana/e2e-selectors';
|
||||
|
||||
export interface Props {
|
||||
@ -39,8 +39,6 @@ const EmptyListCTA: React.FunctionComponent<Props> = ({
|
||||
infoBox,
|
||||
infoBoxTitle,
|
||||
}) => {
|
||||
const theme = useContext(ThemeContext);
|
||||
|
||||
const footer = () => {
|
||||
return (
|
||||
<>
|
||||
@ -86,15 +84,7 @@ const EmptyListCTA: React.FunctionComponent<Props> = ({
|
||||
</LinkButton>
|
||||
);
|
||||
|
||||
return (
|
||||
<CallToActionCard
|
||||
className={ctaStyle}
|
||||
message={title}
|
||||
footer={footer()}
|
||||
callToActionElement={ctaElement}
|
||||
theme={theme}
|
||||
/>
|
||||
);
|
||||
return <CallToActionCard className={ctaStyle} message={title} footer={footer()} callToActionElement={ctaElement} />;
|
||||
};
|
||||
|
||||
export default EmptyListCTA;
|
||||
|
@ -35,12 +35,6 @@ export const NoDataSourceCallToAction = () => {
|
||||
`;
|
||||
|
||||
return (
|
||||
<CallToActionCard
|
||||
callToActionElement={ctaElement}
|
||||
className={cardClassName}
|
||||
footer={footer}
|
||||
message={message}
|
||||
theme={theme}
|
||||
/>
|
||||
<CallToActionCard callToActionElement={ctaElement} className={cardClassName} footer={footer} message={message} />
|
||||
);
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user