Chore: Unskip some a11y story checks and fix any associated issues (#108613)
* fix some a11y issues with the stories * fix lockfile * fix tests * put aria-label on <Icon> * add aria-describedby * undo changes to VizLegendTable * use useID for image id
This commit is contained in:
@@ -4229,36 +4229,12 @@ exports[`no skipping a11y tests in stories`] = {
|
||||
"packages/grafana-alerting/src/grafana/contactPoints/components/ContactPointSelector/ContactPointSelector.story.tsx:5381": [
|
||||
[0, 0, 0, "No skipping of a11y tests in stories. Please fix the component or story instead.", "5381"]
|
||||
],
|
||||
"packages/grafana-ui/src/components/AutoSaveField/AutoSaveField.story.tsx:5381": [
|
||||
[0, 0, 0, "No skipping of a11y tests in stories. Please fix the component or story instead.", "5381"]
|
||||
],
|
||||
"packages/grafana-ui/src/components/Button/Button.story.tsx:5381": [
|
||||
[0, 0, 0, "No skipping of a11y tests in stories. Please fix the component or story instead.", "5381"]
|
||||
],
|
||||
"packages/grafana-ui/src/components/Carousel/Carousel.story.tsx:5381": [
|
||||
[0, 0, 0, "No skipping of a11y tests in stories. Please fix the component or story instead.", "5381"]
|
||||
],
|
||||
"packages/grafana-ui/src/components/Cascader/Cascader.story.tsx:5381": [
|
||||
[0, 0, 0, "No skipping of a11y tests in stories. Please fix the component or story instead.", "5381"]
|
||||
],
|
||||
"packages/grafana-ui/src/components/ColorPicker/ColorPicker.story.tsx:5381": [
|
||||
[0, 0, 0, "No skipping of a11y tests in stories. Please fix the component or story instead.", "5381"]
|
||||
],
|
||||
"packages/grafana-ui/src/components/ColorPicker/ColorPickerInput.story.tsx:5381": [
|
||||
[0, 0, 0, "No skipping of a11y tests in stories. Please fix the component or story instead.", "5381"]
|
||||
],
|
||||
"packages/grafana-ui/src/components/Combobox/MultiCombobox.story.tsx:5381": [
|
||||
[0, 0, 0, "No skipping of a11y tests in stories. Please fix the component or story instead.", "5381"]
|
||||
],
|
||||
"packages/grafana-ui/src/components/ConfirmButton/ConfirmButton.story.tsx:5381": [
|
||||
[0, 0, 0, "No skipping of a11y tests in stories. Please fix the component or story instead.", "5381"]
|
||||
],
|
||||
"packages/grafana-ui/src/components/ContextMenu/ContextMenu.story.tsx:5381": [
|
||||
[0, 0, 0, "No skipping of a11y tests in stories. Please fix the component or story instead.", "5381"]
|
||||
],
|
||||
"packages/grafana-ui/src/components/DateTimePickers/TimeOfDayPicker.story.tsx:5381": [
|
||||
[0, 0, 0, "No skipping of a11y tests in stories. Please fix the component or story instead.", "5381"]
|
||||
],
|
||||
"packages/grafana-ui/src/components/FileDropzone/FileDropzone.story.tsx:5381": [
|
||||
[0, 0, 0, "No skipping of a11y tests in stories. Please fix the component or story instead.", "5381"]
|
||||
],
|
||||
@@ -4268,45 +4244,21 @@ exports[`no skipping a11y tests in stories`] = {
|
||||
"packages/grafana-ui/src/components/Forms/Checkbox.story.tsx:5381": [
|
||||
[0, 0, 0, "No skipping of a11y tests in stories. Please fix the component or story instead.", "5381"]
|
||||
],
|
||||
"packages/grafana-ui/src/components/Forms/Field.story.tsx:5381": [
|
||||
[0, 0, 0, "No skipping of a11y tests in stories. Please fix the component or story instead.", "5381"]
|
||||
],
|
||||
"packages/grafana-ui/src/components/Forms/FieldArray.story.tsx:5381": [
|
||||
[0, 0, 0, "No skipping of a11y tests in stories. Please fix the component or story instead.", "5381"]
|
||||
],
|
||||
"packages/grafana-ui/src/components/Forms/FieldSet.story.tsx:5381": [
|
||||
[0, 0, 0, "No skipping of a11y tests in stories. Please fix the component or story instead.", "5381"]
|
||||
],
|
||||
"packages/grafana-ui/src/components/Forms/Form.story.tsx:5381": [
|
||||
[0, 0, 0, "No skipping of a11y tests in stories. Please fix the component or story instead.", "5381"]
|
||||
],
|
||||
"packages/grafana-ui/src/components/Forms/InlineField.story.tsx:5381": [
|
||||
[0, 0, 0, "No skipping of a11y tests in stories. Please fix the component or story instead.", "5381"]
|
||||
],
|
||||
"packages/grafana-ui/src/components/Forms/RadioButtonGroup/RadioButtonGroup.story.tsx:5381": [
|
||||
[0, 0, 0, "No skipping of a11y tests in stories. Please fix the component or story instead.", "5381"]
|
||||
],
|
||||
"packages/grafana-ui/src/components/InlineToast/InlineToast.story.tsx:5381": [
|
||||
[0, 0, 0, "No skipping of a11y tests in stories. Please fix the component or story instead.", "5381"]
|
||||
],
|
||||
"packages/grafana-ui/src/components/Input/Input.story.tsx:5381": [
|
||||
[0, 0, 0, "No skipping of a11y tests in stories. Please fix the component or story instead.", "5381"]
|
||||
],
|
||||
"packages/grafana-ui/src/components/InteractiveTable/InteractiveTable.story.tsx:5381": [
|
||||
[0, 0, 0, "No skipping of a11y tests in stories. Please fix the component or story instead.", "5381"]
|
||||
],
|
||||
"packages/grafana-ui/src/components/Layout/Grid/Grid.story.tsx:5381": [
|
||||
[0, 0, 0, "No skipping of a11y tests in stories. Please fix the component or story instead.", "5381"]
|
||||
],
|
||||
"packages/grafana-ui/src/components/Layout/Stack/Stack.story.tsx:5381": [
|
||||
[0, 0, 0, "No skipping of a11y tests in stories. Please fix the component or story instead.", "5381"]
|
||||
],
|
||||
"packages/grafana-ui/src/components/Link/TextLink.story.tsx:5381": [
|
||||
[0, 0, 0, "No skipping of a11y tests in stories. Please fix the component or story instead.", "5381"]
|
||||
],
|
||||
"packages/grafana-ui/src/components/LoadingBar/LoadingBar.story.tsx:5381": [
|
||||
[0, 0, 0, "No skipping of a11y tests in stories. Please fix the component or story instead.", "5381"]
|
||||
],
|
||||
"packages/grafana-ui/src/components/Menu/Menu.story.tsx:5381": [
|
||||
[0, 0, 0, "No skipping of a11y tests in stories. Please fix the component or story instead.", "5381"]
|
||||
],
|
||||
@@ -4325,54 +4277,18 @@ exports[`no skipping a11y tests in stories`] = {
|
||||
"packages/grafana-ui/src/components/ScrollContainer/ScrollContainer.story.tsx:5381": [
|
||||
[0, 0, 0, "No skipping of a11y tests in stories. Please fix the component or story instead.", "5381"]
|
||||
],
|
||||
"packages/grafana-ui/src/components/Segment/Segment.story.tsx:5381": [
|
||||
[0, 0, 0, "No skipping of a11y tests in stories. Please fix the component or story instead.", "5381"]
|
||||
],
|
||||
"packages/grafana-ui/src/components/Segment/SegmentAsync.story.tsx:5381": [
|
||||
[0, 0, 0, "No skipping of a11y tests in stories. Please fix the component or story instead.", "5381"]
|
||||
],
|
||||
"packages/grafana-ui/src/components/Segment/SegmentInput.story.tsx:5381": [
|
||||
[0, 0, 0, "No skipping of a11y tests in stories. Please fix the component or story instead.", "5381"]
|
||||
],
|
||||
"packages/grafana-ui/src/components/Select/Select.story.tsx:5381": [
|
||||
[0, 0, 0, "No skipping of a11y tests in stories. Please fix the component or story instead.", "5381"]
|
||||
],
|
||||
"packages/grafana-ui/src/components/Select/SelectPerf.story.tsx:5381": [
|
||||
[0, 0, 0, "No skipping of a11y tests in stories. Please fix the component or story instead.", "5381"]
|
||||
],
|
||||
"packages/grafana-ui/src/components/Slider/RangeSlider.story.tsx:5381": [
|
||||
[0, 0, 0, "No skipping of a11y tests in stories. Please fix the component or story instead.", "5381"]
|
||||
],
|
||||
"packages/grafana-ui/src/components/Slider/Slider.story.tsx:5381": [
|
||||
[0, 0, 0, "No skipping of a11y tests in stories. Please fix the component or story instead.", "5381"]
|
||||
],
|
||||
"packages/grafana-ui/src/components/StatsPicker/StatsPicker.story.tsx:5381": [
|
||||
[0, 0, 0, "No skipping of a11y tests in stories. Please fix the component or story instead.", "5381"]
|
||||
],
|
||||
"packages/grafana-ui/src/components/Switch/Switch.story.tsx:5381": [
|
||||
[0, 0, 0, "No skipping of a11y tests in stories. Please fix the component or story instead.", "5381"]
|
||||
],
|
||||
"packages/grafana-ui/src/components/Table/Table.story.tsx:5381": [
|
||||
[0, 0, 0, "No skipping of a11y tests in stories. Please fix the component or story instead.", "5381"]
|
||||
],
|
||||
"packages/grafana-ui/src/components/TableInputCSV/TableInputCSV.story.tsx:5381": [
|
||||
[0, 0, 0, "No skipping of a11y tests in stories. Please fix the component or story instead.", "5381"]
|
||||
],
|
||||
"packages/grafana-ui/src/components/Tags/TagList.story.tsx:5381": [
|
||||
[0, 0, 0, "No skipping of a11y tests in stories. Please fix the component or story instead.", "5381"]
|
||||
],
|
||||
"packages/grafana-ui/src/components/Text/Text.story.tsx:5381": [
|
||||
[0, 0, 0, "No skipping of a11y tests in stories. Please fix the component or story instead.", "5381"]
|
||||
],
|
||||
"packages/grafana-ui/src/components/ThemeDemos/ThemeDemo.story.tsx:5381": [
|
||||
[0, 0, 0, "No skipping of a11y tests in stories. Please fix the component or story instead.", "5381"]
|
||||
],
|
||||
"packages/grafana-ui/src/components/ThemeDemos/Typography.story.tsx:5381": [
|
||||
[0, 0, 0, "No skipping of a11y tests in stories. Please fix the component or story instead.", "5381"]
|
||||
],
|
||||
"packages/grafana-ui/src/components/ToolbarButton/ToolbarButton.story.tsx:5381": [
|
||||
[0, 0, 0, "No skipping of a11y tests in stories. Please fix the component or story instead.", "5381"]
|
||||
],
|
||||
"packages/grafana-ui/src/components/VizLayout/VizLayout.story.tsx:5381": [
|
||||
[0, 0, 0, "No skipping of a11y tests in stories. Please fix the component or story instead.", "5381"]
|
||||
],
|
||||
|
||||
@@ -186,7 +186,7 @@ class LightColors implements ThemeColorsBase<Partial<ThemeRichColor>> {
|
||||
text = {
|
||||
primary: `rgba(${this.blackBase}, 1)`,
|
||||
secondary: `rgba(${this.blackBase}, 0.75)`,
|
||||
disabled: `rgba(${this.blackBase}, 0.64)`,
|
||||
disabled: `rgba(${this.blackBase}, 0.65)`,
|
||||
link: this.primary.text,
|
||||
maxContrast: palette.black,
|
||||
};
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { StoryFn, Meta } from '@storybook/react';
|
||||
import { useState } from 'react';
|
||||
import { useId, useState } from 'react';
|
||||
|
||||
import { Combobox } from '../Combobox/Combobox';
|
||||
import { Checkbox } from '../Forms/Checkbox';
|
||||
@@ -35,8 +35,6 @@ const meta: Meta = {
|
||||
'validationMessageHorizontalOverflow',
|
||||
],
|
||||
},
|
||||
// TODO fix a11y issue in story and remove this
|
||||
a11y: { test: 'off' },
|
||||
},
|
||||
argTypes: {
|
||||
saveErrorMessage: { control: 'text' },
|
||||
@@ -76,10 +74,12 @@ const themeOptions = [
|
||||
|
||||
export const Basic: StoryFn = (args) => {
|
||||
const [inputValue, setInputValue] = useState('');
|
||||
const id = useId();
|
||||
return (
|
||||
<AutoSaveField onFinishChange={args.inputSuccessful ? getSuccess : getError} {...args}>
|
||||
{(onChange) => (
|
||||
<Input
|
||||
id={id}
|
||||
value={inputValue}
|
||||
onChange={(e) => {
|
||||
const value = e.currentTarget.value;
|
||||
@@ -105,12 +105,19 @@ export const AllComponents: StoryFn = (args) => {
|
||||
const [checkBoxValue, setCheckBoxValue] = useState(false);
|
||||
const [textAreaValue, setTextAreaValue] = useState('');
|
||||
const [switchValue, setSwitchValue] = useState(false);
|
||||
const textId = useId();
|
||||
const comboboxId = useId();
|
||||
const radioButtonId = useId();
|
||||
const checkBoxId = useId();
|
||||
const textAreaId = useId();
|
||||
const switchId = useId();
|
||||
|
||||
return (
|
||||
<div>
|
||||
<AutoSaveField onFinishChange={args.inputSuccessful ? getSuccess : getError} label="Text as a child" {...args}>
|
||||
{(onChange) => (
|
||||
<Input
|
||||
id={textId}
|
||||
value={inputTextValue}
|
||||
onChange={(e) => {
|
||||
const value = e.currentTarget.value;
|
||||
@@ -123,6 +130,7 @@ export const AllComponents: StoryFn = (args) => {
|
||||
<AutoSaveField onFinishChange={args.inputSuccessful ? getSuccess : getError} label="Combobox as child" {...args}>
|
||||
{(onChange) => (
|
||||
<Combobox
|
||||
id={comboboxId}
|
||||
options={themeOptions}
|
||||
value={comoboboxValue}
|
||||
onChange={(v) => {
|
||||
@@ -139,6 +147,7 @@ export const AllComponents: StoryFn = (args) => {
|
||||
>
|
||||
{(onChange) => (
|
||||
<RadioButtonGroup
|
||||
id={radioButtonId}
|
||||
options={themeOptions}
|
||||
value={radioButtonValue}
|
||||
onChange={(themeOption) => {
|
||||
@@ -155,6 +164,7 @@ export const AllComponents: StoryFn = (args) => {
|
||||
>
|
||||
{(onChange) => (
|
||||
<Checkbox
|
||||
id={checkBoxId}
|
||||
label="Checkbox test"
|
||||
description="This is a checkbox input"
|
||||
name="checkbox-test"
|
||||
@@ -174,6 +184,7 @@ export const AllComponents: StoryFn = (args) => {
|
||||
>
|
||||
{(onChange) => (
|
||||
<TextArea
|
||||
id={textAreaId}
|
||||
value={textAreaValue}
|
||||
onChange={(e) => {
|
||||
const value = e.currentTarget.value;
|
||||
@@ -190,6 +201,7 @@ export const AllComponents: StoryFn = (args) => {
|
||||
>
|
||||
{(onChange) => (
|
||||
<Switch
|
||||
id={switchId}
|
||||
label="Switch test"
|
||||
name="switch-test"
|
||||
value={switchValue}
|
||||
|
||||
@@ -18,8 +18,6 @@ export default {
|
||||
docs: {
|
||||
page: mdx,
|
||||
},
|
||||
// TODO fix a11y issue in story and remove this
|
||||
a11y: { test: 'off' },
|
||||
},
|
||||
argTypes: {
|
||||
size: {
|
||||
@@ -81,25 +79,25 @@ export const Examples: StoryFn<typeof Button> = () => {
|
||||
<div>Inside ButtonGroup</div>
|
||||
<ButtonGroup>
|
||||
<Button icon="sync">Run query</Button>
|
||||
<Button icon="angle-down" />
|
||||
<Button icon="angle-down" aria-label="Expand menu" />
|
||||
</ButtonGroup>
|
||||
<ButtonGroup>
|
||||
<Button variant="destructive" icon="sync">
|
||||
Run query
|
||||
</Button>
|
||||
<Button variant="destructive" icon="angle-down" />
|
||||
<Button variant="destructive" icon="angle-down" aria-label="Expand menu" />
|
||||
</ButtonGroup>
|
||||
<ButtonGroup>
|
||||
<Button variant="success" icon="sync">
|
||||
Run query
|
||||
</Button>
|
||||
<Button variant="success" icon="angle-down" />
|
||||
<Button variant="success" icon="angle-down" aria-label="Expand menu" />
|
||||
</ButtonGroup>
|
||||
<ButtonGroup>
|
||||
<Button variant="secondary" icon="sync">
|
||||
Run query
|
||||
</Button>
|
||||
<Button variant="secondary" icon="angle-down" />
|
||||
<Button variant="secondary" icon="angle-down" aria-label="Expand menu" />
|
||||
</ButtonGroup>
|
||||
</Stack>
|
||||
<Card noMargin>
|
||||
|
||||
@@ -19,8 +19,6 @@ const meta: Meta<typeof Carousel> = {
|
||||
component: Carousel,
|
||||
parameters: {
|
||||
docs: { page: mdx },
|
||||
// TODO fix a11y issue in story and remove this
|
||||
a11y: { test: 'off' },
|
||||
},
|
||||
argTypes: {
|
||||
images: {
|
||||
|
||||
@@ -24,9 +24,10 @@ describe('Carousel', () => {
|
||||
render(<Carousel images={testImages} />);
|
||||
|
||||
testImages.forEach((image) => {
|
||||
const imgElement = screen.getByAltText(image.name);
|
||||
expect(imgElement).toBeInTheDocument();
|
||||
expect(imgElement).toHaveAttribute('src', image.path);
|
||||
const name = screen.getByText(image.name);
|
||||
expect(name).toBeInTheDocument();
|
||||
const imageElement = document.querySelector(`img[src="${image.path}"]`);
|
||||
expect(imageElement).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -140,7 +141,7 @@ describe('Carousel', () => {
|
||||
|
||||
render(<Carousel images={testImages} />);
|
||||
|
||||
const images = screen.getAllByRole('img');
|
||||
const images = screen.getAllByRole('presentation');
|
||||
images.forEach((img) => {
|
||||
fireEvent.error(img);
|
||||
});
|
||||
|
||||
@@ -2,7 +2,7 @@ import { css, cx } from '@emotion/css';
|
||||
import { useDialog } from '@react-aria/dialog';
|
||||
import { FocusScope } from '@react-aria/focus';
|
||||
import { OverlayContainer, useOverlay } from '@react-aria/overlays';
|
||||
import { useState, useEffect, useRef } from 'react';
|
||||
import { useState, useEffect, useRef, useId } from 'react';
|
||||
|
||||
import { GrafanaTheme2 } from '@grafana/data';
|
||||
import { t } from '@grafana/i18n';
|
||||
@@ -26,6 +26,7 @@ export const Carousel: React.FC<CarouselProps> = ({ images }) => {
|
||||
const [selectedIndex, setSelectedIndex] = useState<number | null>(null);
|
||||
const [imageErrors, setImageErrors] = useState<Record<string, boolean>>({});
|
||||
const [validImages, setValidImages] = useState<CarouselImage[]>(images);
|
||||
const id = useId();
|
||||
|
||||
const styles = useStyles2(getStyles);
|
||||
const resetButtonStyles = useStyles2(clearButtonStyles);
|
||||
@@ -100,17 +101,22 @@ export const Carousel: React.FC<CarouselProps> = ({ images }) => {
|
||||
return (
|
||||
<>
|
||||
<div className={cx(styles.imageGrid)}>
|
||||
{validImages.map((image, index) => (
|
||||
<button
|
||||
type="button"
|
||||
key={image.path}
|
||||
onClick={() => openPreview(index)}
|
||||
className={cx(resetButtonStyles, styles.imageButton)}
|
||||
>
|
||||
<img src={image.path} alt={image.name} onError={() => handleImageError(image.path)} />
|
||||
<p>{image.name}</p>
|
||||
</button>
|
||||
))}
|
||||
{validImages.map((image, index) => {
|
||||
const imageNameId = `${id}-carousel-image-${index}`;
|
||||
return (
|
||||
<button
|
||||
aria-label={t('grafana-ui.carousel.aria-label-open-image', 'Open image preview')}
|
||||
aria-describedby={imageNameId}
|
||||
type="button"
|
||||
key={image.path}
|
||||
onClick={() => openPreview(index)}
|
||||
className={cx(resetButtonStyles, styles.imageButton)}
|
||||
>
|
||||
<img src={image.path} alt="" onError={() => handleImageError(image.path)} />
|
||||
<p id={imageNameId}>{image.name}</p>
|
||||
</button>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
|
||||
{selectedIndex !== null && (
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import { StoryFn, Meta } from '@storybook/react';
|
||||
import { useState } from 'react';
|
||||
import { useId, useState } from 'react';
|
||||
|
||||
import { Field } from '../Forms/Field';
|
||||
|
||||
import { Cascader, CascaderOption } from './Cascader';
|
||||
import mdx from './Cascader.mdx';
|
||||
@@ -49,8 +51,6 @@ const meta: Meta<typeof Cascader> = {
|
||||
'formatCreateLabel',
|
||||
],
|
||||
},
|
||||
// TODO fix a11y issue in story and remove this
|
||||
a11y: { test: 'off' },
|
||||
},
|
||||
args: {
|
||||
onSelect,
|
||||
@@ -61,7 +61,14 @@ const meta: Meta<typeof Cascader> = {
|
||||
},
|
||||
};
|
||||
|
||||
const Template: StoryFn<typeof Cascader> = (args) => <Cascader {...args} />;
|
||||
const Template: StoryFn<typeof Cascader> = (args) => {
|
||||
const id = useId();
|
||||
return (
|
||||
<Field label="Cascader field">
|
||||
<Cascader {...args} id={id} />
|
||||
</Field>
|
||||
);
|
||||
};
|
||||
|
||||
export const Simple = Template.bind({});
|
||||
Simple.args = {
|
||||
@@ -93,10 +100,15 @@ export const WithOptionsStateUpdate = () => {
|
||||
value: 'initial',
|
||||
},
|
||||
]);
|
||||
const id = useId();
|
||||
|
||||
setTimeout(() => setOptions(options), 2000);
|
||||
|
||||
return <Cascader options={updatedOptions} onSelect={onSelect} />;
|
||||
return (
|
||||
<Field label="Cascader field with updated options">
|
||||
<Cascader options={updatedOptions} onSelect={onSelect} id={id} />
|
||||
</Field>
|
||||
);
|
||||
};
|
||||
|
||||
export default meta;
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
import { action } from '@storybook/addon-actions';
|
||||
import { useArgs } from '@storybook/preview-api';
|
||||
import { Meta, StoryFn } from '@storybook/react';
|
||||
import { useId } from 'react';
|
||||
|
||||
import { Field } from '../Forms/Field';
|
||||
|
||||
import { ColorPickerInput } from './ColorPickerInput';
|
||||
|
||||
@@ -11,22 +14,24 @@ const meta: Meta<typeof ColorPickerInput> = {
|
||||
controls: {
|
||||
exclude: ['onChange', 'onColorChange'],
|
||||
},
|
||||
// TODO fix a11y issue in story and remove this
|
||||
a11y: { test: 'off' },
|
||||
},
|
||||
};
|
||||
|
||||
export const Basic: StoryFn<typeof ColorPickerInput> = ({ color }) => {
|
||||
const [, updateArgs] = useArgs();
|
||||
const id = useId();
|
||||
return (
|
||||
<div style={{ minHeight: '100dvh', display: 'grid', placeContent: 'center' }}>
|
||||
<ColorPickerInput
|
||||
value={color}
|
||||
onChange={(color) => {
|
||||
action('Color changed')(color);
|
||||
updateArgs({ color });
|
||||
}}
|
||||
/>
|
||||
<Field label="Select color">
|
||||
<ColorPickerInput
|
||||
id={id}
|
||||
value={color}
|
||||
onChange={(color) => {
|
||||
action('Color changed')(color);
|
||||
updateArgs({ color });
|
||||
}}
|
||||
/>
|
||||
</Field>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -21,8 +21,6 @@ const meta: Meta = {
|
||||
controls: {
|
||||
exclude: ['className', 'onClick', 'onCancel', 'onConfirm'],
|
||||
},
|
||||
// TODO fix a11y issue in story and remove this
|
||||
a11y: { test: 'off' },
|
||||
},
|
||||
args: {
|
||||
buttonText: 'Edit',
|
||||
|
||||
@@ -27,7 +27,12 @@ export const DeleteButton = ({ size, disabled, onConfirm, 'aria-label': ariaLabe
|
||||
onConfirm={onConfirm}
|
||||
closeOnConfirm={closeOnConfirm}
|
||||
>
|
||||
<Button aria-label={ariaLabel} variant="destructive" icon="times" size={size || 'sm'} />
|
||||
<Button
|
||||
aria-label={ariaLabel ?? t('grafana-ui.confirm-button.aria-label-delete', 'Delete')}
|
||||
variant="destructive"
|
||||
icon="times"
|
||||
size={size || 'sm'}
|
||||
/>
|
||||
</ConfirmButton>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -3,6 +3,7 @@ import { StoryFn, Meta } from '@storybook/react';
|
||||
import * as React from 'react';
|
||||
|
||||
import { IconButton } from '../IconButton/IconButton';
|
||||
import { Text } from '../Text/Text';
|
||||
|
||||
import { ContextMenu, ContextMenuProps } from './ContextMenu';
|
||||
import mdx from './ContextMenu.mdx';
|
||||
@@ -19,8 +20,6 @@ const meta: Meta<typeof ContextMenu> = {
|
||||
controls: {
|
||||
exclude: ['renderMenuItems', 'renderHeader', 'onClose', 'children'],
|
||||
},
|
||||
// TODO fix a11y issue in story and remove this
|
||||
a11y: { test: 'off' },
|
||||
},
|
||||
args: {
|
||||
x: 200,
|
||||
@@ -31,7 +30,7 @@ const meta: Meta<typeof ContextMenu> = {
|
||||
};
|
||||
|
||||
const renderHeader = (): React.ReactNode => {
|
||||
return <h6>Menu</h6>;
|
||||
return <Text variant="h6">Menu</Text>;
|
||||
};
|
||||
|
||||
export const Basic: StoryFn<typeof ContextMenu> = (args: ContextMenuProps) => {
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
import { action } from '@storybook/addon-actions';
|
||||
import { useArgs } from '@storybook/preview-api';
|
||||
import { Meta, StoryFn } from '@storybook/react';
|
||||
import { useId } from 'react';
|
||||
|
||||
import { dateTime } from '@grafana/data';
|
||||
|
||||
import { Field } from '../Forms/Field';
|
||||
|
||||
import { TimeOfDayPicker } from './TimeOfDayPicker';
|
||||
|
||||
const meta: Meta<typeof TimeOfDayPicker> = {
|
||||
@@ -13,8 +16,6 @@ const meta: Meta<typeof TimeOfDayPicker> = {
|
||||
controls: {
|
||||
exclude: ['onChange'],
|
||||
},
|
||||
// TODO fix a11y issue in story and remove this
|
||||
a11y: { test: 'off' },
|
||||
},
|
||||
args: {
|
||||
value: dateTime(Date.now()),
|
||||
@@ -24,14 +25,18 @@ const meta: Meta<typeof TimeOfDayPicker> = {
|
||||
|
||||
export const Basic: StoryFn<typeof TimeOfDayPicker> = (args) => {
|
||||
const [, updateArgs] = useArgs();
|
||||
const id = useId();
|
||||
return (
|
||||
<TimeOfDayPicker
|
||||
{...args}
|
||||
onChange={(newValue?) => {
|
||||
action('on selected')(newValue);
|
||||
updateArgs({ value: newValue });
|
||||
}}
|
||||
/>
|
||||
<Field label="Select a time">
|
||||
<TimeOfDayPicker
|
||||
{...args}
|
||||
id={id}
|
||||
onChange={(newValue?) => {
|
||||
action('on selected')(newValue);
|
||||
updateArgs({ value: newValue });
|
||||
}}
|
||||
/>
|
||||
</Field>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@ interface BaseProps {
|
||||
disabledSeconds?: () => number[];
|
||||
placeholder?: string;
|
||||
allowEmpty?: boolean;
|
||||
id?: string;
|
||||
}
|
||||
|
||||
interface AllowEmptyProps extends BaseProps {
|
||||
@@ -52,6 +53,7 @@ export const TimeOfDayPicker = ({
|
||||
disabledHours,
|
||||
disabledMinutes,
|
||||
disabledSeconds,
|
||||
id,
|
||||
placeholder,
|
||||
// note: we can't destructure allowEmpty/onChange here
|
||||
// in order to discriminate the types properly later in the onChange handler
|
||||
@@ -62,6 +64,7 @@ export const TimeOfDayPicker = ({
|
||||
|
||||
return (
|
||||
<RcPicker<Moment>
|
||||
id={id}
|
||||
generateConfig={generateConfig}
|
||||
locale={locale}
|
||||
allowClear={
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Meta, StoryFn } from '@storybook/react';
|
||||
import { useState, useCallback } from 'react';
|
||||
import { useState, useCallback, useId } from 'react';
|
||||
import * as React from 'react';
|
||||
|
||||
import { Input } from '../Input/Input';
|
||||
@@ -26,18 +26,19 @@ const meta: Meta<typeof Field> = {
|
||||
controls: {
|
||||
exclude: ['children', 'className'],
|
||||
},
|
||||
// TODO fix a11y issue in story and remove this
|
||||
a11y: { test: 'off' },
|
||||
},
|
||||
};
|
||||
|
||||
export const Simple: StoryFn<typeof Field> = (args) => (
|
||||
<div>
|
||||
<Field {...args}>
|
||||
<Input id="thisField" />
|
||||
</Field>
|
||||
</div>
|
||||
);
|
||||
export const Simple: StoryFn<typeof Field> = (args) => {
|
||||
const id = useId();
|
||||
return (
|
||||
<div>
|
||||
<Field {...args}>
|
||||
<Input id={id} />
|
||||
</Field>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
Simple.args = {
|
||||
label: 'Graphite API key',
|
||||
@@ -50,6 +51,7 @@ Simple.args = {
|
||||
};
|
||||
|
||||
export const HorizontalLayout: StoryFn<typeof Field> = (args) => {
|
||||
const id = useId();
|
||||
const [checked, setChecked] = useState(false);
|
||||
const onChange = useCallback(
|
||||
(e: React.FormEvent<HTMLInputElement>) => setChecked(e.currentTarget.checked),
|
||||
@@ -58,7 +60,7 @@ export const HorizontalLayout: StoryFn<typeof Field> = (args) => {
|
||||
return (
|
||||
<div>
|
||||
<Field {...args}>
|
||||
<Switch checked={checked} onChange={onChange} />
|
||||
<Switch checked={checked} onChange={onChange} id={id} />
|
||||
</Field>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { Meta, StoryFn } from '@storybook/react';
|
||||
import { useId } from 'react';
|
||||
|
||||
import { Button } from '../Button/Button';
|
||||
import { Input } from '../Input/Input';
|
||||
@@ -21,8 +22,6 @@ const meta: Meta<typeof FieldSet> = {
|
||||
controls: {
|
||||
exclude: ['children'],
|
||||
},
|
||||
// TODO fix a11y issue in story and remove this
|
||||
a11y: { test: 'off' },
|
||||
},
|
||||
argTypes: {
|
||||
label: { control: 'text' },
|
||||
@@ -30,22 +29,26 @@ const meta: Meta<typeof FieldSet> = {
|
||||
};
|
||||
|
||||
export const Basic: StoryFn<typeof FieldSet> = (args: Props) => {
|
||||
const nameId = useId();
|
||||
const emailId = useId();
|
||||
const colorId = useId();
|
||||
const fontSizeId = useId();
|
||||
return (
|
||||
<Form onSubmit={() => console.log('Submit')}>
|
||||
{() => (
|
||||
<>
|
||||
<FieldSet {...args}>
|
||||
<Field label="Name">
|
||||
<Input name="name" />
|
||||
<Input name="name" id={nameId} />
|
||||
</Field>
|
||||
<Field label="Email">
|
||||
<Input name="email" />
|
||||
<Input name="email" id={emailId} />
|
||||
</Field>
|
||||
<Field label="Color">
|
||||
<Input name="color" />
|
||||
<Input name="color" id={colorId} />
|
||||
</Field>
|
||||
<Field label="Font size">
|
||||
<Input name="fontsize" />
|
||||
<Input name="fontsize" id={fontSizeId} />
|
||||
</Field>
|
||||
</FieldSet>
|
||||
<Button variant="primary">Save</Button>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { StoryFn } from '@storybook/react';
|
||||
import { useId } from 'react';
|
||||
import { ValidateResult } from 'react-hook-form';
|
||||
|
||||
import { withStoryContainer } from '../../utils/storybook/withStoryContainer';
|
||||
@@ -23,8 +24,6 @@ export default {
|
||||
docs: {
|
||||
page: mdx,
|
||||
},
|
||||
// TODO fix a11y issue in story and remove this
|
||||
a11y: { test: 'off' },
|
||||
},
|
||||
};
|
||||
|
||||
@@ -57,71 +56,82 @@ interface FormDTO {
|
||||
};
|
||||
}
|
||||
|
||||
const renderForm = (defaultValues?: FormDTO) => (
|
||||
<Form
|
||||
defaultValues={defaultValues}
|
||||
onSubmit={(data: FormDTO) => {
|
||||
console.log(data);
|
||||
}}
|
||||
>
|
||||
{({ register, control, errors }) => {
|
||||
console.log(errors);
|
||||
return (
|
||||
<>
|
||||
<Legend>Edit user</Legend>
|
||||
const renderForm = (defaultValues?: FormDTO) => {
|
||||
const nameId = useId();
|
||||
const emailId = useId();
|
||||
const usernameId = useId();
|
||||
const nestedPathId = useId();
|
||||
const textId = useId();
|
||||
const checkboxId = useId();
|
||||
const switchId = useId();
|
||||
const radioId = useId();
|
||||
const selectId = useId();
|
||||
return (
|
||||
<Form
|
||||
defaultValues={defaultValues}
|
||||
onSubmit={(data: FormDTO) => {
|
||||
console.log(data);
|
||||
}}
|
||||
>
|
||||
{({ register, control, errors }) => {
|
||||
console.log(errors);
|
||||
return (
|
||||
<>
|
||||
<Legend>Edit user</Legend>
|
||||
|
||||
<Field label="Name" invalid={!!errors.name} error="Name is required">
|
||||
<Input {...register('name', { required: true })} placeholder="Roger Waters" />
|
||||
</Field>
|
||||
<Field label="Name" invalid={!!errors.name} error="Name is required">
|
||||
<Input {...register('name', { required: true })} placeholder="Roger Waters" id={nameId} />
|
||||
</Field>
|
||||
|
||||
<Field label="Email" invalid={!!errors.email} error="E-mail is required">
|
||||
<Input {...register('email', { required: true })} id="email" placeholder="roger.waters@grafana.com" />
|
||||
</Field>
|
||||
<Field label="Email" invalid={!!errors.email} error="E-mail is required">
|
||||
<Input {...register('email', { required: true })} id={emailId} placeholder="roger.waters@grafana.com" />
|
||||
</Field>
|
||||
|
||||
<Field label="Username">
|
||||
<Input {...register('username')} placeholder="mr.waters" />
|
||||
</Field>
|
||||
<Field label="Nested object">
|
||||
<Input {...register('nested.path')} placeholder="Nested path" />
|
||||
</Field>
|
||||
<Field label="Username">
|
||||
<Input {...register('username')} placeholder="mr.waters" id={usernameId} />
|
||||
</Field>
|
||||
<Field label="Nested object">
|
||||
<Input {...register('nested.path')} placeholder="Nested path" id={nestedPathId} />
|
||||
</Field>
|
||||
|
||||
<Field label="Textarea" invalid={!!errors.text} error="Text is required">
|
||||
<TextArea {...register('text', { required: true })} placeholder="Long text" />
|
||||
</Field>
|
||||
<Field label="Textarea" invalid={!!errors.text} error="Text is required">
|
||||
<TextArea {...register('text', { required: true })} placeholder="Long text" id={textId} />
|
||||
</Field>
|
||||
|
||||
<Field label="Checkbox" invalid={!!errors.checkbox} error="We need your consent">
|
||||
<Checkbox {...register('checkbox', { required: true })} label="Do you consent?" />
|
||||
</Field>
|
||||
<Field label="Checkbox" invalid={!!errors.checkbox} error="We need your consent">
|
||||
<Checkbox {...register('checkbox', { required: true })} label="Do you consent?" id={checkboxId} />
|
||||
</Field>
|
||||
|
||||
<Field label="Switch">
|
||||
<Switch name="switch" {...register} />
|
||||
</Field>
|
||||
<Field label="Switch">
|
||||
<Switch name="switch" {...register} id={switchId} />
|
||||
</Field>
|
||||
|
||||
<Field label="RadioButton">
|
||||
<InputControl
|
||||
name="radio"
|
||||
control={control}
|
||||
render={({ field }) => <RadioButtonGroup {...field} options={selectOptions} />}
|
||||
/>
|
||||
</Field>
|
||||
<Field label="RadioButton" htmlFor={radioId}>
|
||||
<InputControl
|
||||
name="radio"
|
||||
control={control}
|
||||
render={({ field }) => <RadioButtonGroup {...field} options={selectOptions} id={radioId} />}
|
||||
/>
|
||||
</Field>
|
||||
|
||||
<Field label="Select" invalid={!!errors.select} error="Select is required">
|
||||
<InputControl
|
||||
name="select"
|
||||
control={control}
|
||||
rules={{
|
||||
required: true,
|
||||
}}
|
||||
render={({ field }) => <Select {...field} options={selectOptions} />}
|
||||
/>
|
||||
</Field>
|
||||
<Field label="Select" invalid={!!errors.select} error="Select is required" htmlFor={selectId}>
|
||||
<InputControl
|
||||
name="select"
|
||||
control={control}
|
||||
rules={{
|
||||
required: true,
|
||||
}}
|
||||
render={({ field }) => <Select {...field} options={selectOptions} inputId={selectId} />}
|
||||
/>
|
||||
</Field>
|
||||
|
||||
<Button type="submit">Update</Button>
|
||||
</>
|
||||
);
|
||||
}}
|
||||
</Form>
|
||||
);
|
||||
<Button type="submit">Update</Button>
|
||||
</>
|
||||
);
|
||||
}}
|
||||
</Form>
|
||||
);
|
||||
};
|
||||
|
||||
export const Basic = () => {
|
||||
return <>{renderForm()}</>;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Meta, StoryFn } from '@storybook/react';
|
||||
import { useState } from 'react';
|
||||
import { useId, useState } from 'react';
|
||||
|
||||
import { Combobox } from '../Combobox/Combobox';
|
||||
import { Input } from '../Input/Input';
|
||||
@@ -23,15 +23,14 @@ const meta: Meta<typeof InlineField> = {
|
||||
controls: {
|
||||
exclude: ['htmlFor', 'className', 'children'],
|
||||
},
|
||||
// TODO fix a11y issue in story and remove this
|
||||
a11y: { test: 'off' },
|
||||
},
|
||||
};
|
||||
|
||||
export const basic: StoryFn<typeof InlineField> = (args) => {
|
||||
const id = useId();
|
||||
return (
|
||||
<InlineField {...args}>
|
||||
<Input placeholder="Inline input" />
|
||||
<Input placeholder="Inline input" id={id} />
|
||||
</InlineField>
|
||||
);
|
||||
};
|
||||
@@ -50,9 +49,10 @@ basic.args = {
|
||||
};
|
||||
|
||||
export const withTooltip: StoryFn<typeof InlineField> = (args) => {
|
||||
const id = useId();
|
||||
return (
|
||||
<InlineField {...args}>
|
||||
<Input placeholder="Inline input" />
|
||||
<Input placeholder="Inline input" id={id} />
|
||||
</InlineField>
|
||||
);
|
||||
};
|
||||
@@ -64,9 +64,10 @@ withTooltip.args = {
|
||||
};
|
||||
|
||||
export const grow: StoryFn<typeof InlineField> = (args) => {
|
||||
const id = useId();
|
||||
return (
|
||||
<InlineField {...args}>
|
||||
<Input placeholder="Inline input" />
|
||||
<Input placeholder="Inline input" id={id} />
|
||||
</InlineField>
|
||||
);
|
||||
};
|
||||
@@ -83,9 +84,10 @@ export const withCombobox: StoryFn<typeof InlineField> = (args) => {
|
||||
{ value: 2, label: 'Two' },
|
||||
];
|
||||
const [selected, setSelected] = useState(1);
|
||||
const id = useId();
|
||||
return (
|
||||
<InlineField {...args}>
|
||||
<Combobox width={16} onChange={(v) => setSelected(v.value)} options={comboboxOptions} value={selected} />
|
||||
<Combobox width={16} onChange={(v) => setSelected(v.value)} options={comboboxOptions} value={selected} id={id} />
|
||||
</InlineField>
|
||||
);
|
||||
};
|
||||
@@ -96,25 +98,29 @@ withCombobox.args = {
|
||||
};
|
||||
|
||||
export const multiple: StoryFn<typeof InlineField> = () => {
|
||||
const id1 = useId();
|
||||
const id2 = useId();
|
||||
const id3 = useId();
|
||||
return (
|
||||
<>
|
||||
<InlineField label="Field 1">
|
||||
<Input placeholder="Inline input" />
|
||||
<Input placeholder="Inline input" id={id1} />
|
||||
</InlineField>
|
||||
<InlineField label="Field 2">
|
||||
<Input placeholder="Inline input" />
|
||||
<Input placeholder="Inline input" id={id2} />
|
||||
</InlineField>
|
||||
<InlineField label="Field 3">
|
||||
<Input placeholder="Inline input" />
|
||||
<Input placeholder="Inline input" id={id3} />
|
||||
</InlineField>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export const error: StoryFn<typeof InlineField> = (args) => {
|
||||
const id = useId();
|
||||
return (
|
||||
<InlineField {...args}>
|
||||
<Input placeholder="Inline input" />
|
||||
<Input placeholder="Inline input" id={id} />
|
||||
</InlineField>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { Meta, StoryFn } from '@storybook/react';
|
||||
import { useState } from 'react';
|
||||
import { useId, useState } from 'react';
|
||||
|
||||
import { ClipboardButton } from '../ClipboardButton/ClipboardButton';
|
||||
import { Field } from '../Forms/Field';
|
||||
import { Input } from '../Input/Input';
|
||||
|
||||
import { InlineToast as InlineToastImpl, InlineToastProps } from './InlineToast';
|
||||
@@ -14,8 +15,6 @@ const story: Meta = {
|
||||
docs: {
|
||||
page: mdx,
|
||||
},
|
||||
// TODO fix a11y issue in story and remove this
|
||||
a11y: { test: 'off' },
|
||||
},
|
||||
argTypes: {
|
||||
referenceElement: {
|
||||
@@ -30,13 +29,16 @@ export default story;
|
||||
|
||||
export const InlineToast: StoryFn<InlineToastProps> = (args) => {
|
||||
const [el, setEl] = useState<null | HTMLInputElement>(null);
|
||||
const id = useId();
|
||||
|
||||
return (
|
||||
<div style={{ maxWidth: 500, width: `calc(100% - 100px)` }}>
|
||||
<InlineToastImpl {...args} referenceElement={el}>
|
||||
Saved
|
||||
</InlineToastImpl>
|
||||
<Input ref={setEl} />
|
||||
<Field label="Input with InlineToast">
|
||||
<Input ref={setEl} id={id} />
|
||||
</Field>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { StoryFn, Meta } from '@storybook/react';
|
||||
import { useState } from 'react';
|
||||
import { useId, useState } from 'react';
|
||||
|
||||
import { KeyValue } from '@grafana/data';
|
||||
|
||||
@@ -31,8 +31,6 @@ const meta: Meta = {
|
||||
controls: {
|
||||
exclude: ['prefix', 'suffix', 'addonBefore', 'addonAfter'],
|
||||
},
|
||||
// TODO fix a11y issue in story and remove this
|
||||
a11y: { test: 'off' },
|
||||
},
|
||||
args: {
|
||||
type: 'text',
|
||||
@@ -73,20 +71,24 @@ export const Simple: StoryFn = (args) => {
|
||||
const addonBefore = <div style={{ display: 'flex', alignItems: 'center', padding: '5px' }}>Input</div>;
|
||||
const prefix = parseAccessory(args.prefixVisible);
|
||||
const suffix = parseAccessory(args.suffixVisible);
|
||||
const id = useId();
|
||||
|
||||
return (
|
||||
<Input
|
||||
disabled={args.disabled}
|
||||
width={args.width}
|
||||
prefix={prefix}
|
||||
invalid={args.invalid}
|
||||
suffix={suffix}
|
||||
loading={args.loading}
|
||||
addonBefore={args.before && addonBefore}
|
||||
addonAfter={args.after && addonAfter}
|
||||
type={args.type}
|
||||
placeholder={args.placeholder}
|
||||
/>
|
||||
<Field label="Simple input">
|
||||
<Input
|
||||
id={id}
|
||||
disabled={args.disabled}
|
||||
width={args.width}
|
||||
prefix={prefix}
|
||||
invalid={args.invalid}
|
||||
suffix={suffix}
|
||||
loading={args.loading}
|
||||
addonBefore={args.before && addonBefore}
|
||||
addonAfter={args.after && addonAfter}
|
||||
type={args.type}
|
||||
placeholder={args.placeholder}
|
||||
/>
|
||||
</Field>
|
||||
);
|
||||
};
|
||||
Simple.args = {
|
||||
@@ -98,11 +100,12 @@ Simple.args = {
|
||||
|
||||
export const WithFieldValidation: StoryFn = (args) => {
|
||||
const [value, setValue] = useState('');
|
||||
const id = useId();
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Field invalid={value === ''} error={value === '' ? 'This input is required' : ''}>
|
||||
<Input value={value} onChange={(e) => setValue(e.currentTarget.value)} {...args} />
|
||||
<Field invalid={value === ''} error={value === '' ? 'This input is required' : ''} label="Input with validation">
|
||||
<Input id={id} value={value} onChange={(e) => setValue(e.currentTarget.value)} {...args} />
|
||||
</Field>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Meta, StoryFn } from '@storybook/react';
|
||||
|
||||
import { useTheme2 } from '../../../themes/ThemeContext';
|
||||
import { SpacingTokenControl } from '../../../utils/storybook/themeStorybookControls';
|
||||
import { Card } from '../../Card/Card';
|
||||
|
||||
import { Grid } from './Grid';
|
||||
import mdx from './Grid.mdx';
|
||||
@@ -17,8 +17,6 @@ const meta: Meta<typeof Grid> = {
|
||||
docs: {
|
||||
page: mdx,
|
||||
},
|
||||
// TODO fix a11y issue in story and remove this
|
||||
a11y: { test: 'off' },
|
||||
},
|
||||
args: {
|
||||
gap: 1,
|
||||
@@ -26,13 +24,12 @@ const meta: Meta<typeof Grid> = {
|
||||
};
|
||||
|
||||
export const ColumnsNumber: StoryFn<typeof Grid> = (args) => {
|
||||
const theme = useTheme2();
|
||||
return (
|
||||
<Grid {...args}>
|
||||
{Array.from({ length: 9 }).map((_, i) => (
|
||||
<div key={i} style={{ background: theme.colors.background.secondary, textAlign: 'center', ...dimensions[i] }}>
|
||||
N# {i}
|
||||
</div>
|
||||
<Card key={i} style={dimensions[i]}>
|
||||
<Card.Heading>N# {i}</Card.Heading>
|
||||
</Card>
|
||||
))}
|
||||
</Grid>
|
||||
);
|
||||
@@ -56,13 +53,12 @@ ColumnsNumber.parameters = {
|
||||
};
|
||||
|
||||
export const ColumnsMinWidth: StoryFn<typeof Grid> = (args) => {
|
||||
const theme = useTheme2();
|
||||
return (
|
||||
<Grid {...args}>
|
||||
{Array.from({ length: 9 }).map((_, i) => (
|
||||
<div key={i} style={{ background: theme.colors.background.secondary, textAlign: 'center' }}>
|
||||
N# {i}
|
||||
</div>
|
||||
<Card key={i}>
|
||||
<Card.Heading>N# {i}</Card.Heading>
|
||||
</Card>
|
||||
))}
|
||||
</Grid>
|
||||
);
|
||||
|
||||
@@ -17,8 +17,6 @@ const meta: Meta<typeof LoadingBar> = {
|
||||
docs: {
|
||||
page: mdx,
|
||||
},
|
||||
// TODO fix a11y issue in story and remove this
|
||||
a11y: { test: 'off' },
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ export function LoadingBar({ width, delay = DEFAULT_ANIMATION_DELAY, ariaLabel =
|
||||
|
||||
return (
|
||||
<div style={containerStyles}>
|
||||
<div aria-label={ariaLabel} className={styles.bar} />
|
||||
<div aria-label={ariaLabel} role="status" className={styles.bar} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -223,7 +223,7 @@ export const Examples = () => {
|
||||
<Button size="sm" variant="secondary" key="A">
|
||||
Breakdown
|
||||
</Button>,
|
||||
<Button size="sm" variant="secondary" icon="times" key="B" />,
|
||||
<Button aria-label="Close" size="sm" variant="secondary" icon="times" key="B" />,
|
||||
],
|
||||
})}
|
||||
{renderPanel('With radio button', {
|
||||
|
||||
@@ -12,7 +12,7 @@ import { SegmentSection } from './SegmentSection';
|
||||
|
||||
const AddButton = (
|
||||
<span className="gf-form-label query-part">
|
||||
<Icon name="plus-circle" />
|
||||
<Icon aria-label="Add" name="plus-circle" />
|
||||
</span>
|
||||
);
|
||||
|
||||
@@ -62,10 +62,6 @@ export const ArrayOptions = () => {
|
||||
const meta: Meta<typeof Segment> = {
|
||||
title: 'Inputs/Segment',
|
||||
component: Segment,
|
||||
parameters: {
|
||||
// TODO fix a11y issue in story and remove this
|
||||
a11y: { test: 'off' },
|
||||
},
|
||||
};
|
||||
|
||||
export const ArrayOptionsWithPrimitiveValue = () => {
|
||||
|
||||
@@ -13,7 +13,7 @@ import { SegmentSection } from './SegmentSection';
|
||||
|
||||
const AddButton = (
|
||||
<span className="gf-form-label query-part">
|
||||
<Icon name="plus" />
|
||||
<Icon aria-label="Add" name="plus" />
|
||||
</span>
|
||||
);
|
||||
|
||||
@@ -63,10 +63,6 @@ export const ArrayOptions = () => {
|
||||
const meta: Meta<typeof SegmentAsync> = {
|
||||
title: 'Inputs/SegmentAsync',
|
||||
component: SegmentAsync,
|
||||
parameters: {
|
||||
// TODO fix a11y issue in story and remove this
|
||||
a11y: { test: 'off' },
|
||||
},
|
||||
};
|
||||
|
||||
export const ArrayOptionsWithPrimitiveValue = () => {
|
||||
|
||||
@@ -32,10 +32,6 @@ export const BasicInput = () => {
|
||||
const meta: Meta<typeof SegmentInput> = {
|
||||
title: 'Inputs/SegmentInput',
|
||||
component: SegmentInput,
|
||||
parameters: {
|
||||
// TODO fix a11y issue in story and remove this
|
||||
a11y: { test: 'off' },
|
||||
},
|
||||
};
|
||||
|
||||
export const BasicInputWithPlaceholder = () => {
|
||||
@@ -98,6 +94,7 @@ export const InputWithAutoFocus = () => {
|
||||
<InputComponent initialValue="test" key={i} />
|
||||
))}
|
||||
<button
|
||||
aria-label="Add"
|
||||
type="button"
|
||||
className="gf-form-label query-part"
|
||||
onClick={() => {
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
import { css } from '@emotion/css';
|
||||
|
||||
import { GrafanaTheme, GrafanaTheme2 } from '@grafana/data';
|
||||
|
||||
export const getSegmentStyles = (theme: GrafanaTheme | GrafanaTheme2) => {
|
||||
const palette = 'v1' in theme ? theme.v1.palette : theme.palette;
|
||||
import { GrafanaTheme2 } from '@grafana/data';
|
||||
|
||||
export const getSegmentStyles = (theme: GrafanaTheme2) => {
|
||||
return {
|
||||
segment: css({
|
||||
cursor: 'pointer',
|
||||
@@ -12,7 +10,7 @@ export const getSegmentStyles = (theme: GrafanaTheme | GrafanaTheme2) => {
|
||||
}),
|
||||
|
||||
queryPlaceholder: css({
|
||||
color: palette.gray2,
|
||||
color: theme.colors.text.disabled,
|
||||
}),
|
||||
|
||||
disabled: css({
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { Meta } from '@storybook/react';
|
||||
import { useMemo } from 'react';
|
||||
import { useId, useMemo } from 'react';
|
||||
import ReactSelect, { createFilter } from 'react-select';
|
||||
|
||||
import { SelectableValue } from '@grafana/data';
|
||||
|
||||
import { Label } from '../Forms/Label';
|
||||
import { Field } from '../Forms/Field';
|
||||
|
||||
import { Select, VirtualizedSelect } from './Select';
|
||||
|
||||
@@ -16,10 +16,6 @@ const meta: Meta = {
|
||||
control: { type: 'number' },
|
||||
},
|
||||
},
|
||||
parameters: {
|
||||
// TODO fix a11y issue in story and remove this
|
||||
a11y: { test: 'off' },
|
||||
},
|
||||
};
|
||||
|
||||
export default meta;
|
||||
@@ -37,6 +33,10 @@ function customFilter(opt: SelectableValue, searchQuery: string) {
|
||||
}
|
||||
|
||||
export function PerformanceScenarios({ numberOfOptions }: { numberOfOptions: number }) {
|
||||
const virtualId = useId();
|
||||
const virtualIgnoreAccentsId = useId();
|
||||
const normalId = useId();
|
||||
const standardId = useId();
|
||||
const options = useMemo(() => {
|
||||
const opts: SelectableValue[] = [];
|
||||
const ALPHABET = 'qwertyuiopasdfghjklzxcvbnm'.split('');
|
||||
@@ -51,20 +51,29 @@ export function PerformanceScenarios({ numberOfOptions }: { numberOfOptions: num
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Label>Virtual:</Label>
|
||||
<VirtualizedSelect options={options} onChange={() => {}} />
|
||||
<Field label="Virtual:">
|
||||
<VirtualizedSelect inputId={virtualId} options={options} onChange={() => {}} />
|
||||
</Field>
|
||||
<br />
|
||||
|
||||
<Label>Virtual with ignoreAccents false:</Label>
|
||||
<VirtualizedSelect filterOption={customFilter} options={options} onChange={() => {}} />
|
||||
<Field label="Virtual with ignoreAccents false:">
|
||||
<VirtualizedSelect
|
||||
inputId={virtualIgnoreAccentsId}
|
||||
filterOption={customFilter}
|
||||
options={options}
|
||||
onChange={() => {}}
|
||||
/>
|
||||
</Field>
|
||||
<br />
|
||||
|
||||
<Label>Normal:</Label>
|
||||
<Select options={options} onChange={() => {}} />
|
||||
<Field label="Normal:">
|
||||
<Select inputId={normalId} options={options} onChange={() => {}} />
|
||||
</Field>
|
||||
<br />
|
||||
|
||||
<Label>Standard react-select</Label>
|
||||
<ReactSelect options={options} onChange={() => {}} />
|
||||
<Field label="Standard react-select">
|
||||
<ReactSelect inputId={standardId} options={options} onChange={() => {}} />
|
||||
</Field>
|
||||
<br />
|
||||
|
||||
<p>Rendered with {options.length.toLocaleString()} options</p>
|
||||
|
||||
@@ -2,6 +2,8 @@ import { action } from '@storybook/addon-actions';
|
||||
import { Meta, StoryFn } from '@storybook/react';
|
||||
import { PureComponent } from 'react';
|
||||
|
||||
import { Field } from '../Forms/Field';
|
||||
|
||||
import { Props, StatsPicker } from './StatsPicker';
|
||||
|
||||
interface State {
|
||||
@@ -21,17 +23,20 @@ class WrapperWithState extends PureComponent<Props, State> {
|
||||
const { stats } = this.state;
|
||||
|
||||
return (
|
||||
<StatsPicker
|
||||
placeholder={placeholder}
|
||||
allowMultiple={allowMultiple}
|
||||
stats={stats}
|
||||
onChange={(stats: string[]) => {
|
||||
action('Picked:')(stats);
|
||||
this.setState({ stats });
|
||||
}}
|
||||
menuPlacement={menuPlacement}
|
||||
width={width}
|
||||
/>
|
||||
<Field label="Pick stats">
|
||||
<StatsPicker
|
||||
inputId="stats-picker"
|
||||
placeholder={placeholder}
|
||||
allowMultiple={allowMultiple}
|
||||
stats={stats}
|
||||
onChange={(stats: string[]) => {
|
||||
action('Picked:')(stats);
|
||||
this.setState({ stats });
|
||||
}}
|
||||
menuPlacement={menuPlacement}
|
||||
width={width}
|
||||
/>
|
||||
</Field>
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -43,8 +48,6 @@ const meta: Meta<typeof StatsPicker> = {
|
||||
controls: {
|
||||
exclude: ['onChange', 'stats', 'defaultStat', 'className'],
|
||||
},
|
||||
// TODO fix a11y issue in story and remove this
|
||||
a11y: { test: 'off' },
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Meta, StoryFn } from '@storybook/react';
|
||||
import { useState, useCallback } from 'react';
|
||||
import { useState, useCallback, useId } from 'react';
|
||||
import * as React from 'react';
|
||||
|
||||
import { Field } from '../Forms/Field';
|
||||
@@ -16,8 +16,6 @@ const meta: Meta<typeof Switch> = {
|
||||
docs: {
|
||||
page: mdx,
|
||||
},
|
||||
// TODO fix a11y issue in story and remove this
|
||||
a11y: { test: 'off' },
|
||||
},
|
||||
args: {
|
||||
disabled: false,
|
||||
@@ -63,7 +61,12 @@ export const Uncontrolled: StoryFn<typeof Switch> = (args) => {
|
||||
(e: React.FormEvent<HTMLInputElement>) => setChecked(e.currentTarget.checked),
|
||||
[setChecked]
|
||||
);
|
||||
return <Switch value={checked} disabled={args.disabled} onChange={onChange} invalid={args.invalid} />;
|
||||
const id = useId();
|
||||
return (
|
||||
<Field label="Uncontrolled switch" disabled={args.disabled} invalid={args.invalid}>
|
||||
<Switch id={id} value={checked} onChange={onChange} />
|
||||
</Field>
|
||||
);
|
||||
};
|
||||
|
||||
export default meta;
|
||||
|
||||
@@ -8,10 +8,6 @@ import { TableInputCSV } from './TableInputCSV';
|
||||
const meta: Meta<typeof TableInputCSV> = {
|
||||
title: 'Inputs/Deprecated/TableInputCSV',
|
||||
component: TableInputCSV,
|
||||
parameters: {
|
||||
// TODO fix a11y issue in story and remove this
|
||||
a11y: { test: 'off' },
|
||||
},
|
||||
};
|
||||
|
||||
export const basic: StoryFn<typeof TableInputCSV> = () => {
|
||||
|
||||
@@ -118,8 +118,9 @@ const getStyles = stylesFactory((theme: GrafanaTheme2) => {
|
||||
position: 'absolute',
|
||||
bottom: '15px',
|
||||
right: '15px',
|
||||
border: '1px solid #222',
|
||||
border: `1px solid ${theme.colors.success.border}`,
|
||||
background: theme.colors.success.main,
|
||||
color: theme.colors.success.contrastText,
|
||||
padding: `1px ${theme.spacing(0.5)}`,
|
||||
fontSize: '80%',
|
||||
}),
|
||||
|
||||
@@ -14,8 +14,6 @@ const meta: Meta<typeof TagList> = {
|
||||
controls: {
|
||||
exclude: ['className', 'onClick', 'getAriaLabel'],
|
||||
},
|
||||
// TODO fix a11y issue in story and remove this
|
||||
a11y: { test: 'off' },
|
||||
},
|
||||
args: {
|
||||
displayMax: 3,
|
||||
|
||||
@@ -49,10 +49,12 @@ const TagListComponent = memo(
|
||||
</li>
|
||||
))}
|
||||
{displayMax && displayMax > 0 && numTags - displayMax > 0 && (
|
||||
<span className={styles.moreTagsLabel}>
|
||||
{'+ '}
|
||||
{numTags - displayMax}
|
||||
</span>
|
||||
<li className={styles.li}>
|
||||
<span className={styles.moreTagsLabel}>
|
||||
{'+ '}
|
||||
{numTags - displayMax}
|
||||
</span>
|
||||
</li>
|
||||
)}
|
||||
</ul>
|
||||
);
|
||||
|
||||
@@ -13,8 +13,6 @@ const meta: Meta = {
|
||||
docs: {
|
||||
page: mdx,
|
||||
},
|
||||
// TODO fix a11y issue in story and remove this
|
||||
a11y: { test: 'off' },
|
||||
},
|
||||
argTypes: {
|
||||
variant: {
|
||||
|
||||
@@ -11,8 +11,6 @@ const meta: Meta = {
|
||||
showPanel: false,
|
||||
},
|
||||
docs: {},
|
||||
// TODO fix a11y issue in story and remove this
|
||||
a11y: { test: 'off' },
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
/* eslint-disable @grafana/i18n/no-untranslated-strings */
|
||||
import { css, cx } from '@emotion/css';
|
||||
import { useState } from 'react';
|
||||
import { useId, useState } from 'react';
|
||||
import * as React from 'react';
|
||||
import tinycolor from 'tinycolor2';
|
||||
|
||||
import { GrafanaTheme2, ThemeRichColor, ThemeVizHue } from '@grafana/data';
|
||||
import { colorManipulator, GrafanaTheme2, ThemeRichColor, ThemeVizHue } from '@grafana/data';
|
||||
|
||||
import { useTheme2 } from '../../themes/ThemeContext';
|
||||
import { allButtonVariants, Button } from '../Button/Button';
|
||||
@@ -65,6 +64,15 @@ export const ThemeDemo = () => {
|
||||
const [boolValue, setBoolValue] = useState(false);
|
||||
const [selectValue, setSelectValue] = useState('Item 2');
|
||||
const t = useTheme2();
|
||||
const inputId = useId();
|
||||
const disabledInputId = useId();
|
||||
const comboboxId = useId();
|
||||
const radioId = useId();
|
||||
const switchId = useId();
|
||||
const switchTrueId = useId();
|
||||
const switchDisabledId = useId();
|
||||
const inlineId = useId();
|
||||
const inlineDisabledId = useId();
|
||||
|
||||
const richColors = [
|
||||
t.colors.primary,
|
||||
@@ -169,36 +177,41 @@ export const ThemeDemo = () => {
|
||||
<CollapsableSection label="Forms" isOpen={true}>
|
||||
<DemoBox bg="primary">
|
||||
<Field label="Input label" description="Field description">
|
||||
<Input placeholder="Placeholder" />
|
||||
<Input id={inputId} placeholder="Placeholder" />
|
||||
</Field>
|
||||
<Field label="Input disabled" disabled>
|
||||
<Input placeholder="Placeholder" value="Disabled value" />
|
||||
<Input id={disabledInputId} placeholder="Placeholder" value="Disabled value" />
|
||||
</Field>
|
||||
<Field label="Combobox">
|
||||
<Combobox options={selectOptions} value={selectValue} onChange={(v) => setSelectValue(v?.value!)} />
|
||||
<Combobox
|
||||
id={comboboxId}
|
||||
options={selectOptions}
|
||||
value={selectValue}
|
||||
onChange={(v) => setSelectValue(v?.value!)}
|
||||
/>
|
||||
</Field>
|
||||
<Field label="Radio label">
|
||||
<RadioButtonGroup options={radioOptions} value={radioValue} onChange={setRadioValue} />
|
||||
<RadioButtonGroup id={radioId} options={radioOptions} value={radioValue} onChange={setRadioValue} />
|
||||
</Field>
|
||||
<Stack>
|
||||
<Field label="Switch">
|
||||
<Switch value={boolValue} onChange={(e) => setBoolValue(e.currentTarget.checked)} />
|
||||
<Switch id={switchId} value={boolValue} onChange={(e) => setBoolValue(e.currentTarget.checked)} />
|
||||
</Field>
|
||||
<Field label="Switch true">
|
||||
<Switch value={true} />
|
||||
<Switch id={switchTrueId} value={true} />
|
||||
</Field>
|
||||
<Field label="Switch false disabled" disabled={true}>
|
||||
<Switch value={false} />
|
||||
<Switch id={switchDisabledId} value={false} />
|
||||
</Field>
|
||||
</Stack>
|
||||
<Stack direction="column">
|
||||
<div>Inline forms</div>
|
||||
<InlineFieldRow>
|
||||
<InlineField label="Label">
|
||||
<Input placeholder="Placeholder" />
|
||||
<Input id={inlineId} placeholder="Placeholder" />
|
||||
</InlineField>
|
||||
<InlineField label="Another Label" disabled>
|
||||
<Input placeholder="Disabled" />
|
||||
<Input id={inlineDisabledId} placeholder="Disabled" />
|
||||
</InlineField>
|
||||
</InlineFieldRow>
|
||||
</Stack>
|
||||
@@ -265,7 +278,7 @@ export function VizHuesDemo({ theme, color }: VizHuesDemoProps) {
|
||||
className={css({
|
||||
background: shade.color,
|
||||
borderRadius: theme.shape.radius.default,
|
||||
color: tinycolor(shade.color).isLight() ? 'black' : 'white',
|
||||
color: colorManipulator.getContrastRatio('#FFFFFF', shade.color) >= 4.5 ? '#FFFFFF' : '#000000',
|
||||
padding: theme.spacing(1),
|
||||
})}
|
||||
>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Meta, StoryFn } from '@storybook/react';
|
||||
import { useState } from 'react';
|
||||
import { useId, useState } from 'react';
|
||||
import * as React from 'react';
|
||||
|
||||
import { Divider } from '../Divider/Divider';
|
||||
@@ -9,10 +9,6 @@ import { Text } from '../Text/Text';
|
||||
|
||||
const meta: Meta = {
|
||||
title: 'Developers/Typography',
|
||||
parameters: {
|
||||
// TODO fix a11y issue in story and remove this
|
||||
a11y: { test: 'off' },
|
||||
},
|
||||
};
|
||||
|
||||
const FONT_WEIGHTS = [/*100, 200, 300, */ 400, 500 /*600, 700, 800, 900*/];
|
||||
@@ -20,6 +16,8 @@ const FONT_WEIGHTS = [/*100, 200, 300, */ 400, 500 /*600, 700, 800, 900*/];
|
||||
export const TypographySamples: StoryFn = () => {
|
||||
const [fontWeight, setFontWeight] = useState(400);
|
||||
const [fontSize, setFontSize] = useState(30);
|
||||
const fontWeightId = useId();
|
||||
const fontSizeId = useId();
|
||||
|
||||
const handleFontWeightChange = (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
setFontWeight(Number(event.target.value));
|
||||
@@ -33,6 +31,7 @@ export const TypographySamples: StoryFn = () => {
|
||||
<div style={{ fontSynthesis: 'none' }}>
|
||||
<Field label={`Font weight - ${fontWeight}`}>
|
||||
<input
|
||||
id={fontWeightId}
|
||||
type="range"
|
||||
min={100}
|
||||
max={900}
|
||||
@@ -45,6 +44,7 @@ export const TypographySamples: StoryFn = () => {
|
||||
|
||||
<Field label={`Font size - ${fontSize}`}>
|
||||
<input
|
||||
id={fontSizeId}
|
||||
type="range"
|
||||
min={8}
|
||||
max={100}
|
||||
|
||||
@@ -18,8 +18,6 @@ const meta: Meta<typeof ToolbarButton> = {
|
||||
controls: {
|
||||
exclude: ['imgSrc', 'imgAlt', 'narrow'],
|
||||
},
|
||||
// TODO fix a11y issue in story and remove this
|
||||
a11y: { test: 'off' },
|
||||
},
|
||||
args: {
|
||||
variant: 'default',
|
||||
@@ -132,12 +130,12 @@ export const Examples: StoryFn<typeof ToolbarButton> = (args) => {
|
||||
<ToolbarButton variant="active" icon="clock-nine" tooltip="Time picker">
|
||||
2020-10-02
|
||||
</ToolbarButton>
|
||||
<ToolbarButton variant="active" icon="search-minus" />
|
||||
<ToolbarButton aria-label="Zoom out" variant="active" icon="search-minus" />
|
||||
</ButtonGroup>
|
||||
<br />
|
||||
<ButtonGroup>
|
||||
<ToolbarButton variant="canvas" icon="sync" />
|
||||
<ToolbarButton variant="canvas" isOpen={false} narrow />
|
||||
<ToolbarButton aria-label="Refresh" variant="canvas" icon="sync" />
|
||||
<ToolbarButton aria-label="Open menu" variant="canvas" isOpen={false} narrow />
|
||||
</ButtonGroup>
|
||||
<br />
|
||||
Inside button group
|
||||
@@ -146,13 +144,13 @@ export const Examples: StoryFn<typeof ToolbarButton> = (args) => {
|
||||
<ToolbarButton variant="primary" icon="sync">
|
||||
Run query
|
||||
</ToolbarButton>
|
||||
<ToolbarButton isOpen={false} narrow variant="primary" />
|
||||
<ToolbarButton aria-label="Open menu" isOpen={false} narrow variant="primary" />
|
||||
</ButtonGroup>
|
||||
<ButtonGroup>
|
||||
<ToolbarButton variant="destructive" icon="sync">
|
||||
Run query
|
||||
</ToolbarButton>
|
||||
<ToolbarButton isOpen={false} narrow variant="destructive" />
|
||||
<ToolbarButton aria-label="Open menu" isOpen={false} narrow variant="destructive" />
|
||||
</ButtonGroup>
|
||||
</Stack>
|
||||
</Stack>
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { css } from '@emotion/css';
|
||||
import * as React from 'react';
|
||||
|
||||
import { useTheme2 } from '../../themes/ThemeContext';
|
||||
import { Stack } from '../../components/Layout/Stack/Stack';
|
||||
import { Text } from '../../components/Text/Text';
|
||||
|
||||
export interface Props {
|
||||
name: string;
|
||||
@@ -9,20 +10,17 @@ export interface Props {
|
||||
}
|
||||
|
||||
export const StoryExample = ({ name, children }: Props) => {
|
||||
const theme = useTheme2();
|
||||
const style = css({
|
||||
width: '100%',
|
||||
padding: '16px',
|
||||
});
|
||||
const heading = css({
|
||||
color: theme.colors.text.secondary,
|
||||
marginBottom: '16px',
|
||||
});
|
||||
|
||||
return (
|
||||
<div className={style}>
|
||||
<h5 className={heading}>{name}</h5>
|
||||
{children}
|
||||
<Stack gap={2} direction="column">
|
||||
<Text variant="h5">{name}</Text>
|
||||
{children}
|
||||
</Stack>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -8272,6 +8272,9 @@
|
||||
"card": {
|
||||
"option": "option"
|
||||
},
|
||||
"carousel": {
|
||||
"aria-label-open-image": "Open image preview"
|
||||
},
|
||||
"cascader": {
|
||||
"clear-button": "Clear selection"
|
||||
},
|
||||
@@ -8284,6 +8287,7 @@
|
||||
"aria-label-selected-color": "{{colorLabel}} color"
|
||||
},
|
||||
"confirm-button": {
|
||||
"aria-label-delete": "Delete",
|
||||
"cancel": "Cancel",
|
||||
"confirmText-delete": "Delete"
|
||||
},
|
||||
|
||||
@@ -55,7 +55,7 @@ $text-color-emphasis: #000000;
|
||||
// Links
|
||||
// -------------------------
|
||||
$link-color: rgba(36, 41, 46, 1);
|
||||
$link-color-disabled: rgba(36, 41, 46, 0.64);
|
||||
$link-color-disabled: rgba(36, 41, 46, 0.65);
|
||||
$link-hover-color: #000000;
|
||||
|
||||
// Typography
|
||||
|
||||
Reference in New Issue
Block a user