diff --git a/packages/grafana-ui/src/components/Button/Button.mdx b/packages/grafana-ui/src/components/Button/Button.mdx index e4e64d11380..cce79cbf3bd 100644 --- a/packages/grafana-ui/src/components/Button/Button.mdx +++ b/packages/grafana-ui/src/components/Button/Button.mdx @@ -1,10 +1,17 @@ import { Meta, Preview, ArgTypes } from '@storybook/blocks'; import { Button, LinkButton } from './Button'; +import { Alert } from '../Alert/Alert'; # Button + + After reviewing this component we are asking you to use the IconButton when you require a button with only an icon. + + +When using a button please always follow a11y rules (e.g. W3C Recommendation [3.3.2 Labels or instructions](https://www.w3.org/TR/WCAG21/#labels-or-instructions)) and make sure the context in which the button is located is also communicated by screen readers. + ## Primary Used for "call to action", i.e. triggering the main action. There should never be more than one on a page. If you need multiple buttons for different actions, decide which action is the most important and make that the primary `Button`. All other `Button` components should be secondary. diff --git a/packages/grafana-ui/src/components/Button/Button.story.tsx b/packages/grafana-ui/src/components/Button/Button.story.tsx index 336304028df..64e7362fb34 100644 --- a/packages/grafana-ui/src/components/Button/Button.story.tsx +++ b/packages/grafana-ui/src/components/Button/Button.story.tsx @@ -1,7 +1,7 @@ import { StoryFn } from '@storybook/react'; import React from 'react'; -import { ComponentSize } from '../../types/size'; +import { ComponentSize } from '../../types'; import { withCenteredStory } from '../../utils/storybook/withCenteredStory'; import { Card } from '../Card/Card'; import { HorizontalGroup, VerticalGroup } from '../Layout/Layout'; @@ -69,12 +69,6 @@ export const Examples: StoryFn = () => {
- -
With icon only
- ); @@ -69,9 +81,11 @@ export const IconButton = React.forwardRef( IconButton.displayName = 'IconButton'; -const getStyles = stylesFactory((theme: GrafanaTheme2, size: IconSize, variant: IconButtonVariant) => { - const pixelSize = getSvgSize(size); - const hoverSize = Math.max(pixelSize / 3, 8); +const getStyles = stylesFactory((theme: GrafanaTheme2, size, variant: IconButtonVariant) => { + // overall size of the IconButton on hover + // theme.spacing.gridSize originates from 2*4px for padding and letting the IconSize generally decide on the hoverSize + const hoverSize = getSvgSize(size) + theme.spacing.gridSize; + let iconColor = theme.colors.text.primary; if (variant === 'primary') { @@ -82,47 +96,34 @@ const getStyles = stylesFactory((theme: GrafanaTheme2, size: IconSize, variant: return { button: css` - width: ${pixelSize}px; - height: ${pixelSize}px; - background: transparent; - border: none; - color: ${iconColor}; - padding: 0; - margin: 0; - outline: none; - box-shadow: none; - display: inline-flex; - align-items: center; - justify-content: center; - position: relative; - border-radius: ${theme.shape.borderRadius()}; z-index: 0; - margin-right: ${theme.spacing(0.5)}; + position: relative; + margin: 0 ${theme.spacing(0.5)} 0 0; + box-shadow: none; + border: none; + display: inline-flex; + background: transparent; + justify-content: center; + align-items: center; + padding: 0; + color: ${iconColor}; &[disabled], &:disabled { cursor: not-allowed; color: ${theme.colors.action.disabledText}; opacity: 0.65; - box-shadow: none; } &:before { - content: ''; - display: block; - opacity: 1; + z-index: -1; position: absolute; + width: ${hoverSize}px; + height: ${hoverSize}px; + border-radius: ${theme.shape.radius.default}; + content: ''; transition-duration: 0.2s; transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); - z-index: -1; - bottom: -${hoverSize}px; - left: -${hoverSize}px; - right: -${hoverSize}px; - top: -${hoverSize}px; - background: none; - border-radius: 50%; - box-sizing: border-box; - transform: scale(0); transition-property: transform, opacity; } @@ -136,22 +137,15 @@ const getStyles = stylesFactory((theme: GrafanaTheme2, size: IconSize, variant: } &:hover { - color: ${iconColor}; - &:before { background-color: ${variant === 'secondary' ? theme.colors.action.hover : colorManipulator.alpha(iconColor, 0.12)}; - border: none; - box-shadow: none; - opacity: 1; - transform: scale(0.8); } } `, icon: css` vertical-align: baseline; - display: flex; `, }; }); diff --git a/packages/grafana-ui/src/components/PanelChrome/PanelChrome.mdx b/packages/grafana-ui/src/components/PanelChrome/PanelChrome.mdx index ad804c4c65e..b06139a6bd6 100644 --- a/packages/grafana-ui/src/components/PanelChrome/PanelChrome.mdx +++ b/packages/grafana-ui/src/components/PanelChrome/PanelChrome.mdx @@ -1,13 +1,13 @@ -import { Meta, Preview, ArgTypes } from '@storybook/blocks'; +import { css } from '@emotion/css'; +import { Meta } from '@storybook/addon-docs/blocks'; import { PanelChrome } from './PanelChrome'; -import { LoadingIndicator } from './LoadingIndicator'; import { action } from '@storybook/addon-actions'; -import { DashboardStoryCanvas } from '../../utils/storybook/DashboardStoryCanvas'; import { HorizontalGroup } from '../Layout/Layout'; import { LoadingState } from '@grafana/data'; -import { Button } from '../Button/Button.tsx'; +import { Button } from '../Button'; import { Menu } from '../Menu/Menu'; +import { IconButton } from '../IconButton/IconButton'; @@ -306,10 +306,17 @@ Component used for rendering content wrapped in the same style as grafana panels -
+ <> + + + } actions={ + ); ``` diff --git a/public/app/features/alerting/unified/components/DynamicTable.tsx b/public/app/features/alerting/unified/components/DynamicTable.tsx index 29ee2eeac96..3e99d226239 100644 --- a/public/app/features/alerting/unified/components/DynamicTable.tsx +++ b/public/app/features/alerting/unified/components/DynamicTable.tsx @@ -125,9 +125,8 @@ export const DynamicTable = ({
toggleExpanded(item)} type="button" @@ -278,9 +277,5 @@ const getStyles = ( padding: ${theme.spacing(1)} 0 0 0; } `, - expandButton: css` - margin-right: 0; - display: block; - `, }); };