GettingStarted: Improve styling and add tracking (#80410)

* refactor: remove icons and related styling

* refactor: remove cut off on the left side

* fix: aria-labels

* feat: add tracking

* refactor: adjust button position

* refactor: move previous button back

* refactor: use emotion object syntax

* feat: add tracking

* refactor: remove console.log()
This commit is contained in:
Laura Benz 2024-01-19 10:50:56 +01:00 committed by GitHub
parent ed196e67a8
commit 0e4c6742c8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 95 additions and 118 deletions

View File

@ -6051,19 +6051,6 @@ exports[`better eslint`] = {
"public/app/plugins/panel/geomap/utils/tooltip.ts:5381": [ "public/app/plugins/panel/geomap/utils/tooltip.ts:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"] [0, 0, 0, "Do not use any type assertions.", "0"]
], ],
"public/app/plugins/panel/gettingstarted/GettingStarted.tsx:5381": [
[0, 0, 0, "Styles should be written using objects.", "0"],
[0, 0, 0, "Styles should be written using objects.", "1"],
[0, 0, 0, "Styles should be written using objects.", "2"],
[0, 0, 0, "Styles should be written using objects.", "3"],
[0, 0, 0, "Styles should be written using objects.", "4"],
[0, 0, 0, "Styles should be written using objects.", "5"],
[0, 0, 0, "Styles should be written using objects.", "6"],
[0, 0, 0, "Styles should be written using objects.", "7"],
[0, 0, 0, "Styles should be written using objects.", "8"],
[0, 0, 0, "Styles should be written using objects.", "9"],
[0, 0, 0, "Styles should be written using objects.", "10"]
],
"public/app/plugins/panel/gettingstarted/components/DocsCard.tsx:5381": [ "public/app/plugins/panel/gettingstarted/components/DocsCard.tsx:5381": [
[0, 0, 0, "Styles should be written using objects.", "0"], [0, 0, 0, "Styles should be written using objects.", "0"],
[0, 0, 0, "Styles should be written using objects.", "1"], [0, 0, 0, "Styles should be written using objects.", "1"],
@ -6086,8 +6073,7 @@ exports[`better eslint`] = {
[0, 0, 0, "Styles should be written using objects.", "5"] [0, 0, 0, "Styles should be written using objects.", "5"]
], ],
"public/app/plugins/panel/gettingstarted/components/sharedStyles.ts:5381": [ "public/app/plugins/panel/gettingstarted/components/sharedStyles.ts:5381": [
[0, 0, 0, "Styles should be written using objects.", "0"], [0, 0, 0, "Styles should be written using objects.", "0"]
[0, 0, 0, "Styles should be written using objects.", "1"]
], ],
"public/app/plugins/panel/heatmap/HeatmapPanel.tsx:5381": [ "public/app/plugins/panel/heatmap/HeatmapPanel.tsx:5381": [
[0, 0, 0, "Do not use any type assertions.", "0"], [0, 0, 0, "Do not use any type assertions.", "0"],

View File

@ -3,7 +3,7 @@ import { css, cx } from '@emotion/css';
import React, { PureComponent } from 'react'; import React, { PureComponent } from 'react';
import { PanelProps } from '@grafana/data'; import { PanelProps } from '@grafana/data';
import { config } from '@grafana/runtime'; import { config, reportInteraction } from '@grafana/runtime';
import { Button, Spinner, stylesFactory } from '@grafana/ui'; import { Button, Spinner, stylesFactory } from '@grafana/ui';
import { contextSrv } from 'app/core/core'; import { contextSrv } from 'app/core/core';
import { backendSrv } from 'app/core/services/backend_srv'; import { backendSrv } from 'app/core/services/backend_srv';
@ -53,12 +53,14 @@ export class GettingStarted extends PureComponent<PanelProps, State> {
} }
onForwardClick = () => { onForwardClick = () => {
reportInteraction('grafana_getting_started_button_to_advanced_tutorials');
this.setState((prevState) => ({ this.setState((prevState) => ({
currentStep: prevState.currentStep + 1, currentStep: prevState.currentStep + 1,
})); }));
}; };
onPreviousClick = () => { onPreviousClick = () => {
reportInteraction('grafana_getting_started_button_to_basic_tutorials');
this.setState((prevState) => ({ this.setState((prevState) => ({
currentStep: prevState.currentStep - 1, currentStep: prevState.currentStep - 1,
})); }));
@ -69,6 +71,8 @@ export class GettingStarted extends PureComponent<PanelProps, State> {
const dashboard = getDashboardSrv().getCurrent(); const dashboard = getDashboardSrv().getCurrent();
const panel = dashboard?.getPanelById(id); const panel = dashboard?.getPanelById(id);
reportInteraction('grafana_getting_started_remove_panel');
dashboard?.removePanel(panel!); dashboard?.removePanel(panel!);
backendSrv.put('/api/user/helpflags/1', undefined, { showSuccessAlert: false }).then((res) => { backendSrv.put('/api/user/helpflags/1', undefined, { showSuccessAlert: false }).then((res) => {
@ -97,7 +101,7 @@ export class GettingStarted extends PureComponent<PanelProps, State> {
<Button <Button
className={cx(styles.backForwardButtons, styles.previous)} className={cx(styles.backForwardButtons, styles.previous)}
onClick={this.onPreviousClick} onClick={this.onPreviousClick}
aria-label="To advanced tutorials" aria-label="To basic tutorials"
icon="angle-left" icon="angle-left"
variant="secondary" variant="secondary"
/> />
@ -109,7 +113,7 @@ export class GettingStarted extends PureComponent<PanelProps, State> {
<Button <Button
className={cx(styles.backForwardButtons, styles.forward)} className={cx(styles.backForwardButtons, styles.forward)}
onClick={this.onForwardClick} onClick={this.onForwardClick}
aria-label="To basic tutorials" aria-label="To advanced tutorials"
icon="angle-right" icon="angle-right"
variant="secondary" variant="secondary"
/> />
@ -124,86 +128,83 @@ export class GettingStarted extends PureComponent<PanelProps, State> {
const getStyles = stylesFactory(() => { const getStyles = stylesFactory(() => {
const theme = config.theme2; const theme = config.theme2;
return { return {
container: css` container: css({
display: flex; display: 'flex',
flex-direction: column; flexDirection: 'column',
height: 100%; height: '100%',
// background: url(public/img/getting_started_bg_${theme.colors.mode}.svg) no-repeat; backgroundSize: 'cover',
background-size: cover; padding: `${theme.spacing(4)} ${theme.spacing(2)} 0`,
padding: ${theme.spacing(4)} ${theme.spacing(2)} 0; }),
`, content: css({
content: css` label: 'content',
label: content; display: 'flex',
display: flex; justifyContent: 'center',
justify-content: center;
${theme.breakpoints.down('xxl')} { [theme.breakpoints.down('xxl')]: {
margin-left: ${theme.spacing(3)}; marginLeft: theme.spacing(3),
justify-content: flex-start; justifyContent: 'flex-start',
} },
`, }),
header: css` header: css({
label: header; label: 'header',
margin-bottom: ${theme.spacing(3)}; marginBottom: theme.spacing(3),
display: flex; display: 'flex',
flex-direction: column; flexDirection: 'column',
${theme.breakpoints.down('lg')} { [theme.breakpoints.down('lg')]: {
flex-direction: row; flexDirection: 'row',
} },
`, }),
headerLogo: css` headerLogo: css({
height: 58px; height: '58px',
padding-right: ${theme.spacing(2)}; paddingRight: theme.spacing(2),
display: none; display: 'none',
${theme.breakpoints.up('md')} { [theme.breakpoints.up('md')]: {
display: block; display: 'block',
} },
`, }),
heading: css` heading: css({
label: heading; label: 'heading',
margin-right: ${theme.spacing(3)}; marginRight: theme.spacing(3),
margin-bottom: ${theme.spacing(3)}; marginBottom: theme.spacing(3),
flex-grow: 1; flexGrow: 1,
display: flex; display: 'flex',
${theme.breakpoints.up('md')} { [theme.breakpoints.up('md')]: {
margin-bottom: 0; marginBottom: 0,
} },
`, }),
backForwardButtons: css` backForwardButtons: css({
position: absolute; position: 'absolute',
top: 50%; top: '50%',
transform: translateY(-50%); transform: 'translateY(-50%)',
`, }),
previous: css` previous: css({
left: 10px; left: '10px',
[theme.breakpoints.down('md')]: {
${theme.breakpoints.down('md')} { left: 0,
left: 0; },
} }),
`, forward: css({
forward: css` right: '10px',
right: 10px; [theme.breakpoints.down('md')]: {
right: 0,
${theme.breakpoints.down('md')} { },
right: 0; }),
} dismiss: css({
`, alignSelf: 'flex-end',
dismiss: css` textDecoration: 'underline',
align-self: flex-end; marginBottom: theme.spacing(1),
text-decoration: underline; }),
margin-bottom: ${theme.spacing(1)}; loading: css({
`, display: 'flex',
loading: css` justifyContent: 'center',
display: flex; alignItems: 'center',
justify-content: center; height: '100%',
align-items: center; }),
height: 100%; loadingText: css({
`, marginRight: theme.spacing(1),
loadingText: css` }),
margin-right: ${theme.spacing(1)};
`,
}; };
}); });

View File

@ -2,11 +2,12 @@ import { css } from '@emotion/css';
import React from 'react'; import React from 'react';
import { GrafanaTheme2 } from '@grafana/data'; import { GrafanaTheme2 } from '@grafana/data';
import { reportInteraction } from '@grafana/runtime';
import { Icon, useStyles2 } from '@grafana/ui'; import { Icon, useStyles2 } from '@grafana/ui';
import { Card } from '../types'; import { Card } from '../types';
import { cardContent, cardStyle, iconStyle } from './sharedStyles'; import { cardContent, cardStyle } from './sharedStyles';
interface Props { interface Props {
card: Card; card: Card;
@ -14,17 +15,17 @@ interface Props {
export const DocsCard = ({ card }: Props) => { export const DocsCard = ({ card }: Props) => {
const styles = useStyles2(getStyles, card.done); const styles = useStyles2(getStyles, card.done);
const iconStyles = useStyles2(iconStyle, card.done);
return ( return (
<div className={styles.card}> <div className={styles.card}>
<div className={cardContent}> <div className={cardContent}>
<a href={`${card.href}?utm_source=grafana_gettingstarted`} className={styles.url}> <a
href={`${card.href}?utm_source=grafana_gettingstarted`}
className={styles.url}
onClick={() => reportInteraction('grafana_getting_started_docs', { title: card.title, link: card.href })}
>
<div className={styles.heading}>{card.done ? 'complete' : card.heading}</div> <div className={styles.heading}>{card.done ? 'complete' : card.heading}</div>
<h4 className={styles.title}>{card.title}</h4> <h4 className={styles.title}>{card.title}</h4>
<div>
<Icon className={iconStyles} name={card.icon} size="xxl" />
</div>
</a> </a>
</div> </div>
<a <a
@ -32,6 +33,7 @@ export const DocsCard = ({ card }: Props) => {
className={styles.learnUrl} className={styles.learnUrl}
target="_blank" target="_blank"
rel="noreferrer" rel="noreferrer"
onClick={() => reportInteraction('grafana_getting_started_docs', { title: card.title, link: card.learnHref })}
> >
Learn how in the docs <Icon name="external-link-alt" /> Learn how in the docs <Icon name="external-link-alt" />
</a> </a>

View File

@ -60,11 +60,7 @@ const getStyles = (theme: GrafanaTheme2) => {
overflow-y: hidden; overflow-y: hidden;
width: 100%; width: 100%;
display: flex; display: flex;
justify-content: center; justify-content: flex-start;
${theme.breakpoints.down('xxl')} {
justify-content: flex-start;
}
`, `,
}; };
}; };

View File

@ -2,12 +2,13 @@ import { css } from '@emotion/css';
import React, { MouseEvent } from 'react'; import React, { MouseEvent } from 'react';
import { GrafanaTheme2 } from '@grafana/data'; import { GrafanaTheme2 } from '@grafana/data';
import { Icon, useStyles2 } from '@grafana/ui'; import { reportInteraction } from '@grafana/runtime';
import { useStyles2 } from '@grafana/ui';
import store from 'app/core/store'; import store from 'app/core/store';
import { TutorialCardType } from '../types'; import { TutorialCardType } from '../types';
import { cardContent, cardStyle, iconStyle } from './sharedStyles'; import { cardContent, cardStyle } from './sharedStyles';
interface Props { interface Props {
card: TutorialCardType; card: TutorialCardType;
@ -15,7 +16,6 @@ interface Props {
export const TutorialCard = ({ card }: Props) => { export const TutorialCard = ({ card }: Props) => {
const styles = useStyles2(getStyles, card.done); const styles = useStyles2(getStyles, card.done);
const iconStyles = useStyles2(iconStyle, card.done);
return ( return (
<a <a
@ -30,7 +30,6 @@ export const TutorialCard = ({ card }: Props) => {
<div className={styles.heading}>{card.done ? 'complete' : card.heading}</div> <div className={styles.heading}>{card.done ? 'complete' : card.heading}</div>
<h4 className={styles.cardTitle}>{card.title}</h4> <h4 className={styles.cardTitle}>{card.title}</h4>
<div className={styles.info}>{card.info}</div> <div className={styles.info}>{card.info}</div>
<Icon className={iconStyles} name={card.icon} size="xxl" />
</div> </div>
</a> </a>
); );
@ -42,6 +41,7 @@ const handleTutorialClick = (event: MouseEvent<HTMLAnchorElement>, card: Tutoria
if (!isSet) { if (!isSet) {
store.set(card.key, true); store.set(card.key, true);
} }
reportInteraction('grafana_getting_started_tutorial', { title: card.title });
}; };
const getStyles = (theme: GrafanaTheme2, complete: boolean) => { const getStyles = (theme: GrafanaTheme2, complete: boolean) => {

View File

@ -34,14 +34,6 @@ export const cardStyle = (theme: GrafanaTheme2, complete: boolean) => {
`; `;
}; };
export const iconStyle = (theme: GrafanaTheme2, complete: boolean) => css`
color: ${complete ? theme.v1.palette.blue95 : theme.colors.text.secondary};
${theme.breakpoints.down('sm')} {
display: none;
}
`;
export const cardContent = css` export const cardContent = css`
padding: 16px; padding: 16px;
`; `;