Dashboards: A11y improvements for edit experience (#106321)

* Dashboards: A11y improvements for edit experience

* Pass descriptor to render function
pull/106210/head
kay delaney 3 weeks ago committed by GitHub
parent 5137995830
commit c30765bbea
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 11
      public/app/features/dashboard-scene/edit-pane/VizPanelEditableElement.tsx
  2. 34
      public/app/features/dashboard-scene/panel-edit/getPanelFrameOptions.tsx
  3. 7
      public/app/features/dashboard-scene/scene/layout-auto-grid/AutoGridItemEditor.tsx
  4. 7
      public/app/features/dashboard-scene/scene/layout-default/DashboardGridItemEditor.tsx
  5. 6
      public/app/features/dashboard/components/PanelEditor/OptionsPaneItemDescriptor.tsx
  6. 20
      public/app/features/dashboard/components/PanelEditor/getPanelFrameOptions.tsx

@ -55,22 +55,27 @@ export class VizPanelEditableElement implements EditableDashboardElement, BulkAc
.addItem(
new OptionsPaneItemDescriptor({
title: t('dashboard.viz-panel.options.title-option', 'Title'),
id: 'PanelFrameTitle',
value: panel.state.title,
popularRank: 1,
render: () => <PanelFrameTitleInput panel={panel} isNewElement={isNewElement} />,
render: (descriptor) => (
<PanelFrameTitleInput id={descriptor.props.id} panel={panel} isNewElement={isNewElement} />
),
})
)
.addItem(
new OptionsPaneItemDescriptor({
title: t('dashboard.viz-panel.options.description', 'Description'),
id: 'description-text-area',
value: panel.state.description,
render: () => <PanelDescriptionTextArea panel={panel} />,
render: (descriptor) => <PanelDescriptionTextArea id={descriptor.props.id} panel={panel} />,
})
)
.addItem(
new OptionsPaneItemDescriptor({
title: t('dashboard.viz-panel.options.transparent-background', 'Transparent background'),
render: () => <PanelBackgroundSwitch panel={panel} />,
id: 'transparent-background',
render: (descriptor) => <PanelBackgroundSwitch id={descriptor.props.id} panel={panel} />,
})
);
}, [panel, isNewElement]);

@ -37,10 +37,11 @@ export function getPanelFrameOptions(panel: VizPanel): OptionsPaneCategoryDescri
.addItem(
new OptionsPaneItemDescriptor({
title: t('dashboard-scene.get-panel-frame-options.title.title', 'Title'),
id: 'PanelFrameTitle',
value: panel.state.title,
popularRank: 1,
render: function renderTitle() {
return <PanelFrameTitleInput panel={panel} />;
render: function renderTitle(descriptor) {
return <PanelFrameTitleInput id={descriptor.props.id} panel={panel} />;
},
addon: config.featureToggles.dashgpt && (
<GenAIPanelTitleButton
@ -54,9 +55,10 @@ export function getPanelFrameOptions(panel: VizPanel): OptionsPaneCategoryDescri
.addItem(
new OptionsPaneItemDescriptor({
title: t('dashboard-scene.get-panel-frame-options.title.description', 'Description'),
id: 'description-text-area',
value: panel.state.description,
render: function renderDescription() {
return <PanelDescriptionTextArea panel={panel} />;
render: function renderDescription(descriptor) {
return <PanelDescriptionTextArea id={descriptor.props.id} panel={panel} />;
},
addon: config.featureToggles.dashgpt && (
<GenAIPanelDescriptionButton
@ -69,8 +71,9 @@ export function getPanelFrameOptions(panel: VizPanel): OptionsPaneCategoryDescri
.addItem(
new OptionsPaneItemDescriptor({
title: t('dashboard-scene.get-panel-frame-options.title.transparent-background', 'Transparent background'),
render: function renderTransparent() {
return <PanelBackgroundSwitch panel={panel} />;
id: 'transparent-background',
render: function renderTransparent(descriptor) {
return <PanelBackgroundSwitch id={descriptor.props.id} panel={panel} />;
},
})
)
@ -112,7 +115,15 @@ function ScenePanelLinksEditor({ panelLinks }: ScenePanelLinksEditorProps) {
);
}
export function PanelFrameTitleInput({ panel, isNewElement }: { panel: VizPanel; isNewElement?: boolean }) {
export function PanelFrameTitleInput({
panel,
isNewElement,
id,
}: {
panel: VizPanel;
isNewElement?: boolean;
id?: string;
}) {
const { title } = panel.useState();
const notInPanelEdit = panel.getPanelContext().app !== CoreApp.PanelEditor;
const [prevTitle, setPrevTitle] = React.useState(panel.state.title);
@ -125,6 +136,7 @@ export function PanelFrameTitleInput({ panel, isNewElement }: { panel: VizPanel;
<Input
ref={ref}
data-testid={selectors.components.PanelEditor.OptionsPane.fieldInput('Title')}
id={id}
value={title}
onFocus={() => setPrevTitle(title)}
onBlur={() => editPanelTitleAction(panel, title, prevTitle)}
@ -135,13 +147,13 @@ export function PanelFrameTitleInput({ panel, isNewElement }: { panel: VizPanel;
);
}
export function PanelDescriptionTextArea({ panel }: { panel: VizPanel }) {
export function PanelDescriptionTextArea({ panel, id }: { panel: VizPanel; id?: string }) {
const { description } = panel.useState();
const [prevDescription, setPrevDescription] = React.useState(panel.state.description);
return (
<TextArea
id="description-text-area"
id={id}
value={description}
onChange={(evt) => panel.setState({ description: evt.currentTarget.value })}
onFocus={() => setPrevDescription(panel.state.description)}
@ -157,7 +169,7 @@ export function PanelDescriptionTextArea({ panel }: { panel: VizPanel }) {
);
}
export function PanelBackgroundSwitch({ panel }: { panel: VizPanel }) {
export function PanelBackgroundSwitch({ panel, id }: { panel: VizPanel; id?: string }) {
const { displayMode = 'default' } = panel.useState();
const onChange = () => {
@ -171,7 +183,7 @@ export function PanelBackgroundSwitch({ panel }: { panel: VizPanel }) {
});
};
return <Switch value={displayMode === 'transparent'} id="transparent-background" onChange={onChange} />;
return <Switch value={displayMode === 'transparent'} id={id} onChange={onChange} />;
}
function updatePanelTitleState(panel: VizPanel, title: string) {

@ -15,11 +15,12 @@ export function getOptions(model: AutoGridItem): OptionsPaneCategoryDescriptor[]
}).addItem(
new OptionsPaneItemDescriptor({
title: t('dashboard.auto-grid.item-options.repeat.variable.title', 'Repeat by variable'),
id: 'repeat-by-variable-select',
description: t(
'dashboard.auto-grid.item-options.repeat.variable.description',
'Repeat this panel for each value in the selected variable. This is not visible while in edit mode. You need to go back to dashboard and then update the variable or reload the dashboard.'
),
render: () => <RepeatByOption item={model} />,
render: (descriptor) => <RepeatByOption id={descriptor.props.id} item={model} />,
})
);
@ -28,12 +29,12 @@ export function getOptions(model: AutoGridItem): OptionsPaneCategoryDescriptor[]
return [repeatCategory, conditionalRenderingCategory];
}
function RepeatByOption({ item }: { item: AutoGridItem }) {
function RepeatByOption({ item, id }: { item: AutoGridItem; id?: string }) {
const { variableName } = item.useState();
return (
<RepeatRowSelect2
id="repeat-by-variable-select"
id={id}
sceneContext={item}
repeat={variableName}
onChange={(value?: string) => item.setRepeatByVariable(value)}

@ -18,11 +18,12 @@ export function getDashboardGridItemOptions(gridItem: DashboardGridItem): Option
.addItem(
new OptionsPaneItemDescriptor({
title: t('dashboard.default-layout.item-options.repeat.variable.title', 'Repeat by variable'),
id: 'repeat-by-variable-select',
description: t(
'dashboard.default-layout.item-options.repeat.variable.description',
'Repeat this panel for each value in the selected variable. This is not visible while in edit mode. You need to go back to dashboard and then update the variable or reload the dashboard.'
),
render: () => <RepeatByOption gridItem={gridItem} />,
render: (descriptor) => <RepeatByOption id={descriptor.props.id} gridItem={gridItem} />,
})
)
.addItem(
@ -86,12 +87,12 @@ function MaxPerRowOption({ gridItem }: OptionComponentProps) {
);
}
function RepeatByOption({ gridItem }: OptionComponentProps) {
function RepeatByOption({ gridItem, id }: OptionComponentProps & { id?: string }) {
const { variableName, width } = gridItem.useState();
return (
<RepeatRowSelect2
id="repeat-by-variable-select"
id={id}
sceneContext={gridItem}
repeat={variableName}
onChange={(value?: string) => {

@ -16,7 +16,7 @@ export interface OptionsPaneItemInfo {
value?: any;
description?: string;
popularRank?: number;
render: () => React.ReactElement;
render: (descriptor: OptionsPaneItemDescriptor) => React.ReactElement;
skipField?: boolean;
showIf?: () => boolean;
/** Hook for controlling visibility */
@ -66,7 +66,7 @@ function OptionsPaneItem({ itemDescriptor, searchQuery }: OptionsPaneItemProps)
}
if (skipField) {
return render();
return render(itemDescriptor);
}
return (
@ -77,7 +77,7 @@ function OptionsPaneItem({ itemDescriptor, searchQuery }: OptionsPaneItemProps)
aria-label={selectors.components.PanelEditor.OptionsPane.fieldLabel(key)}
htmlFor={id}
>
{render()}
{render(itemDescriptor)}
</Field>
);
}

@ -40,13 +40,14 @@ export function getPanelFrameCategory(props: OptionPaneRenderProps): OptionsPane
.addItem(
new OptionsPaneItemDescriptor({
title: t('dashboard.get-panel-frame-category.title.title', 'Title'),
id: 'PanelFrameTitle',
value: panel.title,
popularRank: 1,
render: function renderTitle() {
render: function renderTitle(descriptor) {
return (
<Input
data-testid={selectors.components.PanelEditor.OptionsPane.fieldInput('Title')}
id="PanelFrameTitle"
id={descriptor.props.id}
defaultValue={panel.title}
onBlur={(e) => onPanelConfigChange('title', e.currentTarget.value)}
/>
@ -64,13 +65,14 @@ export function getPanelFrameCategory(props: OptionPaneRenderProps): OptionsPane
.addItem(
new OptionsPaneItemDescriptor({
title: t('dashboard.get-panel-frame-category.title.description', 'Description'),
id: 'description-text-area',
description: panel.description,
value: panel.description,
render: function renderDescription() {
render: function renderDescription(descriptor) {
return (
<TextArea
data-testid={selectors.components.PanelEditor.OptionsPane.fieldInput('Description')}
id="description-text-area"
id={descriptor.props.id}
defaultValue={panel.description}
onBlur={(e) => onPanelConfigChange('description', e.currentTarget.value)}
/>
@ -84,12 +86,13 @@ export function getPanelFrameCategory(props: OptionPaneRenderProps): OptionsPane
.addItem(
new OptionsPaneItemDescriptor({
title: t('dashboard.get-panel-frame-category.title.transparent-background', 'Transparent background'),
render: function renderTransparent() {
id: 'transparent-background',
render: function renderTransparent(descriptor) {
return (
<Switch
data-testid={selectors.components.PanelEditor.OptionsPane.fieldInput('Transparent background')}
value={panel.transparent}
id="transparent-background"
id={descriptor.props.id}
onChange={(e) => onPanelConfigChange('transparent', e.currentTarget.checked)}
/>
);
@ -127,12 +130,13 @@ export function getPanelFrameCategory(props: OptionPaneRenderProps): OptionsPane
.addItem(
new OptionsPaneItemDescriptor({
title: t('dashboard.get-panel-frame-category.title.repeat-by-variable', 'Repeat by variable'),
id: 'repeat-by-variable-select',
description:
'Repeat this panel for each value in the selected variable. This is not visible while in edit mode. You need to go back to dashboard and then update the variable or reload the dashboard.',
render: function renderRepeatOptions() {
render: function renderRepeatOptions(descriptor) {
return (
<RepeatRowSelect
id="repeat-by-variable-select"
id={descriptor.props.id}
repeat={panel.repeat}
onChange={(value?: string) => {
onPanelConfigChange('repeat', value);

Loading…
Cancel
Save