feat: Keyboard accessible property pane header (#11339)
This commit is contained in:
parent
bd9636f514
commit
2ad121a092
|
|
@ -378,7 +378,8 @@ const ButtonStyles = css<ThemeProp & ButtonProps>`
|
|||
fill: ${(props) => btnColorStyles(props, "main").txtColor};
|
||||
}
|
||||
}
|
||||
&:hover {
|
||||
&:hover,
|
||||
&:focus {
|
||||
text-decoration: none;
|
||||
background-color: ${(props) => btnColorStyles(props, "hover").bgColor};
|
||||
color: ${(props) => btnColorStyles(props, "hover").txtColor};
|
||||
|
|
|
|||
|
|
@ -687,14 +687,6 @@ export function RenderDropdownOptions(props: DropdownOptionsProps) {
|
|||
maxHeight={props.dropdownMaxHeight || "auto"}
|
||||
>
|
||||
{options.map((option: DropdownOption, index: number) => {
|
||||
if (renderOption) {
|
||||
return renderOption({
|
||||
option,
|
||||
index,
|
||||
optionClickHandler,
|
||||
optionWidth,
|
||||
});
|
||||
}
|
||||
let isSelected = false;
|
||||
if (
|
||||
props.isMultiSelect &&
|
||||
|
|
@ -708,6 +700,15 @@ export function RenderDropdownOptions(props: DropdownOptionsProps) {
|
|||
isSelected =
|
||||
(props.selected as DropdownOption).value === option.value;
|
||||
}
|
||||
if (renderOption) {
|
||||
return renderOption({
|
||||
option,
|
||||
index,
|
||||
optionClickHandler,
|
||||
optionWidth,
|
||||
isSelectedNode: isSelected,
|
||||
});
|
||||
}
|
||||
return !option.isSectionHeader ? (
|
||||
<OptionWrapper
|
||||
aria-selected={isSelected}
|
||||
|
|
|
|||
|
|
@ -30,10 +30,11 @@ const StyledDiv = styled.div`
|
|||
props.theme.spaces[7]}px;
|
||||
margin: ${(props) => props.theme.spaces[2]}px 0px;
|
||||
|
||||
a:first-child {
|
||||
button:first-child {
|
||||
margin-top: ${(props) => props.theme.spaces[2]}px;
|
||||
width: 100%;
|
||||
}
|
||||
a:nth-child(2) {
|
||||
button:nth-child(2) {
|
||||
border: none;
|
||||
background-color: transparent;
|
||||
text-transform: none;
|
||||
|
|
@ -43,7 +44,7 @@ const StyledDiv = styled.div`
|
|||
${(props) => getTypographyByKey(props, "p3")}
|
||||
margin-top: ${(props) => props.theme.spaces[2]}px;
|
||||
|
||||
:hover {
|
||||
:hover, :focus {
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
|
|
@ -95,11 +96,15 @@ function ConnectDataCTA(props: ConnectDataCTAProps) {
|
|||
category={Category.primary}
|
||||
onClick={onClick}
|
||||
size={Size.large}
|
||||
tabIndex={0}
|
||||
tag="button"
|
||||
text="CONNECT DATA"
|
||||
/>
|
||||
<Button
|
||||
category={Category.tertiary}
|
||||
onClick={openHelpModal}
|
||||
tabIndex={0}
|
||||
tag="button"
|
||||
text="Learn more"
|
||||
/>
|
||||
</StyledDiv>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import React, { memo, useMemo, useCallback } from "react";
|
||||
import React, { memo, useMemo, useCallback, useEffect } from "react";
|
||||
import styled from "styled-components";
|
||||
import Icon, { IconSize } from "components/ads/Icon";
|
||||
import Dropdown, {
|
||||
|
|
@ -125,6 +125,7 @@ const OptionWrapper = styled.div<{ hasError: boolean; fillIconColor: boolean }>`
|
|||
|
||||
const OptionContentWrapper = styled.div<{
|
||||
hasError: boolean;
|
||||
isSelected: boolean;
|
||||
}>`
|
||||
padding: ${(props) => props.theme.spaces[2] + 1}px
|
||||
${(props) => props.theme.spaces[5]}px;
|
||||
|
|
@ -134,6 +135,10 @@ const OptionContentWrapper = styled.div<{
|
|||
line-height: 8px;
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
background-color: ${(props) =>
|
||||
props.isSelected &&
|
||||
!props.hasError &&
|
||||
props.theme.colors.dropdown.hovered.bg};
|
||||
|
||||
span:first-child {
|
||||
font-size: 10px;
|
||||
|
|
@ -210,7 +215,7 @@ const useDependencyList = (name: string) => {
|
|||
const dependencyOptions =
|
||||
entityDependencies?.directDependencies.map((e) => ({
|
||||
label: e,
|
||||
value: getEntityId(e),
|
||||
value: getEntityId(e) ?? e,
|
||||
})) ?? [];
|
||||
const inverseDependencyOptions =
|
||||
entityDependencies?.inverseDependencies.map((e) => ({
|
||||
|
|
@ -245,12 +250,28 @@ function OptionNode(props: any) {
|
|||
});
|
||||
};
|
||||
|
||||
const handleKeyDown = (e: KeyboardEvent) => {
|
||||
if (!props.isSelectedNode) return;
|
||||
if (e.key === " " || e.key === "Enter") onClick();
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
document.addEventListener("keydown", handleKeyDown);
|
||||
return () => {
|
||||
document.removeEventListener("keydown", handleKeyDown);
|
||||
};
|
||||
}, [props.isSelectedNode]);
|
||||
|
||||
return (
|
||||
<OptionWrapper
|
||||
fillIconColor={!entityInfo?.datasourceName}
|
||||
hasError={!!entityInfo?.hasError}
|
||||
>
|
||||
<OptionContentWrapper hasError={!!entityInfo?.hasError} onClick={onClick}>
|
||||
<OptionContentWrapper
|
||||
hasError={!!entityInfo?.hasError}
|
||||
isSelected={props.isSelectedNode}
|
||||
onClick={onClick}
|
||||
>
|
||||
<span>{entityInfo?.icon}</span>
|
||||
<Text type={TextType.H6}>
|
||||
{props.option.label}{" "}
|
||||
|
|
@ -297,6 +318,7 @@ const TriggerNode = memo((props: TriggerNodeProps) => {
|
|||
<Tooltip
|
||||
content={tooltipText}
|
||||
disabled={props.isOpen}
|
||||
openOnTargetFocus={false}
|
||||
position={props.tooltipPosition}
|
||||
>
|
||||
{props.entityCount ? `${props.entityCount} ${ENTITY}` : "No Entity"}
|
||||
|
|
@ -360,7 +382,12 @@ function PropertyPaneConnections(props: PropertyPaneConnectionsProps) {
|
|||
height={`${CONNECTION_HEIGHT}px`}
|
||||
options={dependencies.dependencyOptions}
|
||||
renderOption={(optionProps) => {
|
||||
return <OptionNode option={optionProps.option} />;
|
||||
return (
|
||||
<OptionNode
|
||||
isSelectedNode={optionProps.isSelectedNode}
|
||||
option={optionProps.option}
|
||||
/>
|
||||
);
|
||||
}}
|
||||
selected={selectedOption}
|
||||
showDropIcon={false}
|
||||
|
|
|
|||
|
|
@ -73,7 +73,7 @@ function PropertyPaneView(
|
|||
tooltipPosition: "bottom-right",
|
||||
icon: (
|
||||
<button
|
||||
className="p-1 hover:bg-warmGray-100 group t--copy-widget"
|
||||
className="p-1 hover:bg-warmGray-100 focus:bg-warmGray-100 group t--copy-widget"
|
||||
onClick={onCopy}
|
||||
>
|
||||
<CopyIcon className="w-4 h-4 text-gray-500" />
|
||||
|
|
@ -85,7 +85,7 @@ function PropertyPaneView(
|
|||
tooltipPosition: "bottom-right",
|
||||
icon: (
|
||||
<button
|
||||
className="p-1 hover:bg-warmGray-100 group t--delete-widget"
|
||||
className="p-1 hover:bg-warmGray-100 focus:bg-warmGray-100 group t--delete-widget"
|
||||
onClick={onDelete}
|
||||
>
|
||||
<DeleteIcon className="w-4 h-4 text-gray-500" />
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user