Skip to content

Commit

Permalink
fix(TreeView): prevent disabled node selection and expansion (#11520)
Browse files Browse the repository at this point in the history
* refactor(treeview): unnest styles

* fix(TreeView): prevent disabled node selection on ctrl+a

* fix(TreeView): prevent disabled node selection on ctrl+shift+home/end

* fix(TreeNode): prevent disabled node expansion

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
  • Loading branch information
emyarod and kodiakhq[bot] committed Jun 2, 2022
1 parent e785ba7 commit a7964cd
Show file tree
Hide file tree
Showing 3 changed files with 138 additions and 120 deletions.
6 changes: 6 additions & 0 deletions packages/react/src/components/TreeView/TreeNode.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,9 @@ export default function TreeNode({
[`${prefix}--tree-parent-node__toggle-icon--expanded`]: expanded,
});
function handleToggleClick(event) {
if (disabled) {
return;
}
onToggle?.(event, { id, isExpanded: !expanded, label, value });
setExpanded(!expanded);
}
Expand All @@ -73,6 +76,9 @@ export default function TreeNode({
}
}
function handleKeyDown(event) {
if (disabled) {
return;
}
if (matches(event, [keys.ArrowLeft, keys.ArrowRight, keys.Enter])) {
event.stopPropagation();
}
Expand Down
18 changes: 15 additions & 3 deletions packages/react/src/components/TreeView/TreeView.js
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,12 @@ export default function TreeView({
const nodeIds = [];

if (matches(event, [keys.Home, keys.End])) {
if (multiselect && event.shiftKey && event.ctrlKey) {
if (
multiselect &&
event.shiftKey &&
event.ctrlKey &&
!treeWalker.current.currentNode.getAttribute('aria-disabled')
) {
nodeIds.push(treeWalker.current.currentNode?.id);
}
while (
Expand All @@ -137,7 +142,12 @@ export default function TreeView({
) {
nextFocusNode = treeWalker.current.currentNode;

if (multiselect && event.shiftKey && event.ctrlKey) {
if (
multiselect &&
event.shiftKey &&
event.ctrlKey &&
!nextFocusNode.getAttribute('aria-disabled')
) {
nodeIds.push(nextFocusNode?.id);
}
}
Expand All @@ -146,7 +156,9 @@ export default function TreeView({
treeWalker.current.currentNode = treeWalker.current.root;

while (treeWalker.current.nextNode()) {
nodeIds.push(treeWalker.current.currentNode?.id);
if (!treeWalker.current.currentNode.getAttribute('aria-disabled')) {
nodeIds.push(treeWalker.current.currentNode?.id);
}
}
}
setSelected(selected.concat(nodeIds));
Expand Down
234 changes: 117 additions & 117 deletions packages/styles/scss/components/treeview/_treeview.scss
Original file line number Diff line number Diff line change
Expand Up @@ -20,154 +20,154 @@
@mixin treeview {
.#{$prefix}--tree {
overflow: hidden;
}

.#{$prefix}--tree-node {
padding-left: $spacing-05;
background-color: $layer-01;
color: $text-secondary;

&:focus {
outline: none;
}
}
.#{$prefix}--tree-node {
padding-left: $spacing-05;
background-color: $layer-01;
color: $text-secondary;

.#{$prefix}--tree-node:focus > .#{$prefix}--tree-node__label {
@include focus-outline('outline');
}

.#{$prefix}--tree-node--disabled:focus > .#{$prefix}--tree-node__label {
&:focus {
outline: none;
}
}

.#{$prefix}--tree-node--disabled,
.#{$prefix}--tree-node--disabled .#{$prefix}--tree-node__label:hover,
.#{$prefix}--tree-node--disabled
.#{$prefix}--tree-node__label:hover
.#{$prefix}--tree-node__label__details {
background-color: $field-01;
color: $text-disabled;
}
.#{$prefix}--tree-node:focus > .#{$prefix}--tree-node__label {
@include focus-outline('outline');
}

.#{$prefix}--tree-node--disabled .#{$prefix}--tree-parent-node__toggle-icon,
.#{$prefix}--tree-node--disabled .#{$prefix}--tree-node__icon,
.#{$prefix}--tree-node--disabled
.#{$prefix}--tree-node__label:hover
.#{$prefix}--tree-parent-node__toggle-icon,
.#{$prefix}--tree-node--disabled
.#{$prefix}--tree-node__label:hover
.#{$prefix}--tree-node__icon {
fill: $icon-disabled;
}
.#{$prefix}--tree-node--disabled:focus > .#{$prefix}--tree-node__label {
outline: none;
}

.#{$prefix}--tree-node--disabled,
.#{$prefix}--tree-node--disabled
.#{$prefix}--tree-parent-node__toggle-icon:hover {
cursor: not-allowed;
}
.#{$prefix}--tree-node--disabled,
.#{$prefix}--tree-node--disabled .#{$prefix}--tree-node__label:hover,
.#{$prefix}--tree-node--disabled
.#{$prefix}--tree-node__label:hover
.#{$prefix}--tree-node__label__details {
background-color: $field-01;
color: $text-disabled;
}

.#{$prefix}--tree-node--disabled .#{$prefix}--tree-parent-node__toggle-icon,
.#{$prefix}--tree-node--disabled .#{$prefix}--tree-node__icon,
.#{$prefix}--tree-node--disabled
.#{$prefix}--tree-node__label:hover
.#{$prefix}--tree-parent-node__toggle-icon,
.#{$prefix}--tree-node--disabled
.#{$prefix}--tree-node__label:hover
.#{$prefix}--tree-node__icon {
fill: $icon-disabled;
}

.#{$prefix}--tree-node__label {
@include type-style('body-compact-01');
.#{$prefix}--tree-node--disabled,
.#{$prefix}--tree-node--disabled
.#{$prefix}--tree-parent-node__toggle-icon:hover {
cursor: not-allowed;
}

display: flex;
min-height: rem(32px);
flex: 1;
align-items: center;
.#{$prefix}--tree-node__label {
@include type-style('body-compact-01');

&:hover {
background-color: $layer-hover-01;
color: $text-primary;
}
}
display: flex;
min-height: rem(32px);
flex: 1;
align-items: center;

.#{$prefix}--tree-node__label:hover .#{$prefix}--tree-node__label__details {
&:hover {
background-color: $layer-hover-01;
color: $text-primary;
}
}

.#{$prefix}--tree-node__label:hover
.#{$prefix}--tree-parent-node__toggle-icon,
.#{$prefix}--tree-node__label:hover .#{$prefix}--tree-node__icon {
fill: $icon-primary;
}
.#{$prefix}--tree-node__label:hover .#{$prefix}--tree-node__label__details {
color: $text-primary;
}

.#{$prefix}--tree-leaf-node {
display: flex;
padding-left: $spacing-08;
}
.#{$prefix}--tree-node__label:hover
.#{$prefix}--tree-parent-node__toggle-icon,
.#{$prefix}--tree-node__label:hover .#{$prefix}--tree-node__icon {
fill: $icon-primary;
}

.#{$prefix}--tree-leaf-node.#{$prefix}--tree-node--with-icon {
padding-left: $spacing-07;
}
.#{$prefix}--tree-leaf-node {
display: flex;
padding-left: $spacing-08;
}

.#{$prefix}--tree-node__label__details {
display: flex;
align-items: center;
}
.#{$prefix}--tree-leaf-node.#{$prefix}--tree-node--with-icon {
padding-left: $spacing-07;
}

.#{$prefix}--tree-node--with-icon .#{$prefix}--tree-parent-node__toggle {
margin-right: 0;
}
.#{$prefix}--tree-node__label__details {
display: flex;
align-items: center;
}

.#{$prefix}--tree-parent-node__toggle {
padding: 0;
border: 0;
margin-right: $spacing-03;
.#{$prefix}--tree-node--with-icon .#{$prefix}--tree-parent-node__toggle {
margin-right: 0;
}

&:hover {
cursor: pointer;
}
.#{$prefix}--tree-parent-node__toggle {
padding: 0;
border: 0;
margin-right: $spacing-03;

&:focus {
outline: none;
}
&:hover {
cursor: pointer;
}

.#{$prefix}--tree-parent-node__toggle-icon {
fill: $icon-secondary;
transform: rotate(-90deg);
transition: all $duration-fast-02 motion(standard, productive);
&:focus {
outline: none;
}
}

.#{$prefix}--tree-parent-node__toggle-icon--expanded {
transform: rotate(0);
}
.#{$prefix}--tree-parent-node__toggle-icon {
fill: $icon-secondary;
transform: rotate(-90deg);
transition: all $duration-fast-02 motion(standard, productive);
}

.#{$prefix}--tree-node__icon {
min-width: 1rem;
min-height: 1rem;
margin-right: $spacing-03;
fill: $icon-secondary;
}
.#{$prefix}--tree-parent-node__toggle-icon--expanded {
transform: rotate(0);
}

.#{$prefix}--tree-node--selected > .#{$prefix}--tree-node__label {
background-color: $layer-selected-01;
color: $text-primary;
.#{$prefix}--tree-node__icon {
min-width: 1rem;
min-height: 1rem;
margin-right: $spacing-03;
fill: $icon-secondary;
}

&:hover {
background-color: $layer-selected-hover-01;
}
}
.#{$prefix}--tree-node--selected > .#{$prefix}--tree-node__label {
background-color: $layer-selected-01;
color: $text-primary;

.#{$prefix}--tree-node--selected
> .#{$prefix}--tree-node__label
.#{$prefix}--tree-parent-node__toggle-icon,
.#{$prefix}--tree-node--selected
> .#{$prefix}--tree-node__label
.#{$prefix}--tree-node__icon {
fill: $icon-primary;
&:hover {
background-color: $layer-selected-hover-01;
}
}

.#{$prefix}--tree-node--selected
> .#{$prefix}--tree-node__label
.#{$prefix}--tree-parent-node__toggle-icon,
.#{$prefix}--tree-node--selected
> .#{$prefix}--tree-node__label
.#{$prefix}--tree-node__icon {
fill: $icon-primary;
}

.#{$prefix}--tree-node--active > .#{$prefix}--tree-node__label {
position: relative;

&::before {
position: absolute;
top: 0;
left: 0;
width: rem(4px);
height: 100%;
background-color: $interactive;
content: '';
}
.#{$prefix}--tree-node--active > .#{$prefix}--tree-node__label {
position: relative;

&::before {
position: absolute;
top: 0;
left: 0;
width: rem(4px);
height: 100%;
background-color: $interactive;
content: '';
}
}

Expand Down

0 comments on commit a7964cd

Please sign in to comment.