mirror of https://github.com/grafana/grafana
Buttons: Refactor & use new theme (#32767)
* WIP button styles refactoring * Starting to work * Tweak form disabled color * Emotion performance tests * More benchmarks * added classnames prop * Button class names refactor test * revert to old style generation * Wrapping up * Updates * Updated testspull/32568/head
parent
33a4cfde51
commit
2f3ef69b30
@ -0,0 +1,195 @@ |
|||||||
|
/** @jsxImportSource @emotion/react */ |
||||||
|
|
||||||
|
import { Profiler, ProfilerOnRenderCallback, useState, FC } from 'react'; |
||||||
|
import { GrafanaTheme } from '@grafana/data'; |
||||||
|
import { css, cx } from '@emotion/css'; |
||||||
|
import { useStyles, useTheme } from '../../themes'; |
||||||
|
import { Button } from '../Button'; |
||||||
|
import { VerticalGroup } from '../Layout/Layout'; |
||||||
|
import classnames from 'classnames'; |
||||||
|
|
||||||
|
export function EmotionPerfTest() { |
||||||
|
console.log('process.env.NODE_ENV', process.env.NODE_ENV); |
||||||
|
|
||||||
|
return ( |
||||||
|
<VerticalGroup> |
||||||
|
<div>Emotion performance tests</div> |
||||||
|
<TestScenario name="No styles" Component={NoStyles} /> |
||||||
|
<TestScenario name="inline emotion/css" Component={InlineEmotionCSS} /> |
||||||
|
<TestScenario name="useStyles no cx" Component={UseStylesNoCX} /> |
||||||
|
<TestScenario name="useStyles with conditional cx styles" Component={UseStylesWithConditionalCX} /> |
||||||
|
<TestScenario name="useStyles with css prop" Component={UseStylesWithCSSProp} /> |
||||||
|
<TestScenario name="useStyles with conditional css prop" Component={UseStylesWithConditionalCSS} /> |
||||||
|
<TestScenario name="useStyles with conditional classnames" Component={UseStylesWithConditionalClassNames} /> |
||||||
|
</VerticalGroup> |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
export const TestScenario: FC<{ name: string; Component: FC<TestComponentProps> }> = ({ name, Component }) => { |
||||||
|
const [render, setRender] = useState(0); |
||||||
|
|
||||||
|
return ( |
||||||
|
<div> |
||||||
|
<Button onClick={() => setRender(render > 2 ? 0 : render + 1)}>{name}</Button> |
||||||
|
{render > 0 && <MeasureRender id={name}>{renderManyComponents(Component)}</MeasureRender>} |
||||||
|
</div> |
||||||
|
); |
||||||
|
}; |
||||||
|
|
||||||
|
TestScenario.displayName = 'TestScenario'; |
||||||
|
|
||||||
|
function renderManyComponents(Component: FC<TestComponentProps>) { |
||||||
|
const elements: React.ReactNode[] = []; |
||||||
|
|
||||||
|
for (let i = 0; i < 5000; i++) { |
||||||
|
elements.push(<Component index={i} key={i.toString()} />); |
||||||
|
} |
||||||
|
|
||||||
|
return <div style={{ display: 'flex', flexWrap: 'wrap' }}>{elements}</div>; |
||||||
|
} |
||||||
|
|
||||||
|
interface TestComponentProps { |
||||||
|
index: number; |
||||||
|
} |
||||||
|
|
||||||
|
function UseStylesNoCX({ index }: TestComponentProps) { |
||||||
|
const styles = useStyles(getStyles); |
||||||
|
return ( |
||||||
|
<div className={styles.main}> |
||||||
|
<div className={styles.child}>{index}</div> |
||||||
|
</div> |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
function UseStylesWithConditionalCX({ index }: TestComponentProps) { |
||||||
|
const styles = useStyles(getStyles); |
||||||
|
const mainStyles = cx(styles.main, { [styles.large]: index > 10, [styles.disabed]: index % 10 === 0 }); |
||||||
|
|
||||||
|
return ( |
||||||
|
<div className={mainStyles}> |
||||||
|
<div className={styles.child}>{index}</div> |
||||||
|
</div> |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
function UseStylesWithConditionalClassNames({ index }: TestComponentProps) { |
||||||
|
const styles = useStyles(getStyles); |
||||||
|
const mainStyles = classnames(styles.main, { [styles.large]: index > 10, [styles.disabed]: index % 10 === 0 }); |
||||||
|
|
||||||
|
return ( |
||||||
|
<div className={mainStyles}> |
||||||
|
<div className={styles.child}>{index}</div> |
||||||
|
</div> |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
function UseStylesWithCSSProp({ index }: TestComponentProps) { |
||||||
|
const styles = useStyles(getStylesObjects); |
||||||
|
|
||||||
|
return ( |
||||||
|
<div css={styles.main}> |
||||||
|
<div css={styles.child}>{index}</div> |
||||||
|
</div> |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
function UseStylesWithConditionalCSS({ index }: TestComponentProps) { |
||||||
|
const styles = useStyles(getStylesObjects); |
||||||
|
const mainStyles = [styles.main, index > 10 && styles.large, index % 10 === 0 && styles.disabed]; |
||||||
|
return ( |
||||||
|
<div css={mainStyles}> |
||||||
|
<div css={styles.child}>{index}</div> |
||||||
|
</div> |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
function InlineEmotionCSS({ index }: TestComponentProps) { |
||||||
|
const theme = useTheme(); |
||||||
|
const styles = getStyles(theme); |
||||||
|
|
||||||
|
return ( |
||||||
|
<div className={styles.main}> |
||||||
|
<div className={styles.child}>{index}</div> |
||||||
|
</div> |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
function NoStyles({ index }: TestComponentProps) { |
||||||
|
return ( |
||||||
|
<div className="no-styles-main"> |
||||||
|
<div className="no-styles-child">{index}</div> |
||||||
|
</div> |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
function MeasureRender({ children, id }: { children: React.ReactNode; id: string }) { |
||||||
|
const onRender: ProfilerOnRenderCallback = ( |
||||||
|
id: string, |
||||||
|
phase: 'mount' | 'update', |
||||||
|
actualDuration: number, |
||||||
|
baseDuration: number, |
||||||
|
startTime: number, |
||||||
|
commitTime: number |
||||||
|
) => { |
||||||
|
console.log('Profile ' + id, actualDuration); |
||||||
|
}; |
||||||
|
|
||||||
|
return ( |
||||||
|
<Profiler id={id} onRender={onRender}> |
||||||
|
{children} |
||||||
|
</Profiler> |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
const getStyles = (theme: GrafanaTheme) => { |
||||||
|
return { |
||||||
|
main: css(getStylesObjectMain(theme)), |
||||||
|
large: css({ |
||||||
|
fontSize: '20px', |
||||||
|
color: 'red', |
||||||
|
}), |
||||||
|
disabed: css({ |
||||||
|
fontSize: '10px', |
||||||
|
color: 'gray', |
||||||
|
}), |
||||||
|
child: css(getStylesObjectChild(theme)), |
||||||
|
}; |
||||||
|
}; |
||||||
|
|
||||||
|
const getStylesObjects = (theme: GrafanaTheme) => { |
||||||
|
return { |
||||||
|
main: getStylesObjectMain(theme), |
||||||
|
large: { |
||||||
|
fontSize: '20px', |
||||||
|
color: 'red', |
||||||
|
}, |
||||||
|
disabed: { |
||||||
|
fontSize: '10px', |
||||||
|
color: 'gray', |
||||||
|
}, |
||||||
|
child: getStylesObjectChild(theme), |
||||||
|
}; |
||||||
|
}; |
||||||
|
|
||||||
|
function getStylesObjectMain(theme: GrafanaTheme): any { |
||||||
|
return { |
||||||
|
background: 'blue', |
||||||
|
border: '1px solid red', |
||||||
|
color: 'white', |
||||||
|
padding: theme.v2.spacing(1), |
||||||
|
shadow: theme.v2.shadows.z1, |
||||||
|
':hover': { |
||||||
|
background: theme.colors.bg1, |
||||||
|
}, |
||||||
|
}; |
||||||
|
} |
||||||
|
|
||||||
|
function getStylesObjectChild(theme: GrafanaTheme): any { |
||||||
|
return { |
||||||
|
padding: '2px', |
||||||
|
fontSize: '10px', |
||||||
|
boxShadow: 'none', |
||||||
|
textAlign: 'center', |
||||||
|
textDecoration: 'none', |
||||||
|
}; |
||||||
|
} |
@ -0,0 +1,12 @@ |
|||||||
|
import { EmotionPerfTest, VerticalGroup } from '@grafana/ui'; |
||||||
|
import React, { FC } from 'react'; |
||||||
|
|
||||||
|
export const BenchmarksPage: FC = () => { |
||||||
|
return ( |
||||||
|
<VerticalGroup> |
||||||
|
<EmotionPerfTest /> |
||||||
|
</VerticalGroup> |
||||||
|
); |
||||||
|
}; |
||||||
|
|
||||||
|
export default BenchmarksPage; |
Loading…
Reference in new issue