diff --git a/packages/components/docs/sass.md b/packages/components/docs/sass.md
index 33b0ad3bab92..0b294bcf9e26 100644
--- a/packages/components/docs/sass.md
+++ b/packages/components/docs/sass.md
@@ -22387,8 +22387,6 @@ Tag styles
// tags used for filtering
.#{$prefix}--tag--filter {
@include tag-theme($inverse-02, $inverse-01);
-
- cursor: pointer;
padding-right: rem(2px);
&:focus,
@@ -22397,28 +22395,34 @@ Tag styles
}
}
- .#{$prefix}--tag--filter > svg {
+ .#{$prefix}--tag__close-icon {
flex-shrink: 0;
width: rem(20px);
height: rem(20px);
margin: 0 0 0 rem(4px);
padding: rem(2px);
border: 0;
- fill: $inverse-01;
background-color: transparent;
border-radius: 50%;
+ cursor: pointer;
&:hover {
background-color: $inverse-hover-ui;
}
}
- .#{$prefix}--tag--filter:focus > svg {
+ .#{$prefix}--tag__close-icon svg {
+ fill: $inverse-01;
+ }
+
+ .#{$prefix}--tag__close-icon:focus {
+ outline: none;
box-shadow: inset 0 0 0 2px $inverse-focus-ui;
border-radius: 50%;
}
- .#{$prefix}--tag--filter.#{$prefix}--tag--disabled svg:hover {
+ .#{$prefix}--tag--filter.#{$prefix}--tag--disabled
+ .#{$prefix}--tag__close-icon:hover {
background-color: transparent;
}
diff --git a/packages/components/src/components/tag/_tag.scss b/packages/components/src/components/tag/_tag.scss
index 218e6928f20d..0c44bdd2aa61 100644
--- a/packages/components/src/components/tag/_tag.scss
+++ b/packages/components/src/components/tag/_tag.scss
@@ -98,8 +98,6 @@
// tags used for filtering
.#{$prefix}--tag--filter {
@include tag-theme($inverse-02, $inverse-01);
-
- cursor: pointer;
padding-right: rem(2px);
&:focus,
@@ -108,28 +106,34 @@
}
}
- .#{$prefix}--tag--filter > svg {
+ .#{$prefix}--tag__close-icon {
flex-shrink: 0;
width: rem(20px);
height: rem(20px);
margin: 0 0 0 rem(4px);
padding: rem(2px);
border: 0;
- fill: $inverse-01;
background-color: transparent;
border-radius: 50%;
+ cursor: pointer;
&:hover {
background-color: $inverse-hover-ui;
}
}
- .#{$prefix}--tag--filter:focus > svg {
+ .#{$prefix}--tag__close-icon svg {
+ fill: $inverse-01;
+ }
+
+ .#{$prefix}--tag__close-icon:focus {
+ outline: none;
box-shadow: inset 0 0 0 2px $inverse-focus-ui;
border-radius: 50%;
}
- .#{$prefix}--tag--filter.#{$prefix}--tag--disabled svg:hover {
+ .#{$prefix}--tag--filter.#{$prefix}--tag--disabled
+ .#{$prefix}--tag__close-icon:hover {
background-color: transparent;
}
diff --git a/packages/components/src/components/tag/tag.hbs b/packages/components/src/components/tag/tag.hbs
index 7b413dc22b00..75336ce92c62 100644
--- a/packages/components/src/components/tag/tag.hbs
+++ b/packages/components/src/components/tag/tag.hbs
@@ -15,9 +15,11 @@
{{#if filter}}
-
diff --git a/packages/components/src/components/ui-shell/_side-nav.scss b/packages/components/src/components/ui-shell/_side-nav.scss
index c3879da74ca4..397b8286b358 100644
--- a/packages/components/src/components/ui-shell/_side-nav.scss
+++ b/packages/components/src/components/ui-shell/_side-nav.scss
@@ -110,7 +110,7 @@
width: 0;
}
- .#{$prefix}--side-nav:not(.#{$prefix}--side-nav--fixed):hover,
+ .#{$prefix}--side-nav.bx--side-nav--rail:not(.#{$prefix}--side-nav--fixed):hover,
.#{$prefix}--side-nav--expanded {
width: mini-units(32);
}
diff --git a/packages/react/__tests__/__snapshots__/PublicAPI-test.js.snap b/packages/react/__tests__/__snapshots__/PublicAPI-test.js.snap
index 22c75d47d08d..d6f026cd816a 100644
--- a/packages/react/__tests__/__snapshots__/PublicAPI-test.js.snap
+++ b/packages/react/__tests__/__snapshots__/PublicAPI-test.js.snap
@@ -4721,6 +4721,9 @@ Map {
"filter": Object {
"type": "bool",
},
+ "onClose": Object {
+ "type": "func",
+ },
"title": Object {
"type": "string",
},
diff --git a/packages/react/src/components/Tag/Tag-story.js b/packages/react/src/components/Tag/Tag-story.js
index 1b9ddcf8971a..7a3e2c261fb2 100644
--- a/packages/react/src/components/Tag/Tag-story.js
+++ b/packages/react/src/components/Tag/Tag-story.js
@@ -29,7 +29,11 @@ const props = {
title: 'Clear Filter',
}),
filter() {
- return { ...this.regular(), onClick: action('onClick') };
+ return {
+ ...this.regular(),
+ onClick: action('onClick'),
+ onClose: action('onClose'),
+ };
},
};
diff --git a/packages/react/src/components/Tag/Tag.js b/packages/react/src/components/Tag/Tag.js
index 2b484c81b6b8..60c54f0daf5f 100644
--- a/packages/react/src/components/Tag/Tag.js
+++ b/packages/react/src/components/Tag/Tag.js
@@ -10,9 +10,10 @@ import React from 'react';
import classNames from 'classnames';
import { settings } from 'carbon-components';
import { Close16 } from '@carbon/icons-react';
+import setupGetInstanceId from '../../tools/setupGetInstanceId';
const { prefix } = settings;
-
+const getInstanceId = setupGetInstanceId();
const TYPES = {
red: 'Red',
magenta: 'Magenta',
@@ -29,32 +30,45 @@ const TYPES = {
const Tag = ({
children,
className,
+ id,
type,
filter,
title,
disabled,
+ onClose,
...other
}) => {
+ const tagId = id || `tag-${getInstanceId()}`;
const tagClass = `${prefix}--tag--${type}`;
const tagClasses = classNames(`${prefix}--tag`, tagClass, className, {
[`${prefix}--tag--disabled`]: disabled,
[`${prefix}--tag--filter`]: filter,
});
+ const handleClose = event => {
+ event.stopPropagation();
+ onClose(event);
+ };
return filter ? (
-
{children !== null && children !== undefined ? children : TYPES[type]}
-
-
+
+
+
+
) : (
{children !== null && children !== undefined ? children : TYPES[type]}
@@ -92,6 +106,11 @@ Tag.propTypes = {
* Text to show on clear filters
*/
title: PropTypes.string,
+
+ /**
+ * Click handler for filter tag close button.
+ */
+ onClose: PropTypes.func,
};
export const types = Object.keys(TYPES);
diff --git a/packages/react/src/components/UIShell/SideNav.js b/packages/react/src/components/UIShell/SideNav.js
index 6c566763e50e..066f2d3ba816 100644
--- a/packages/react/src/components/UIShell/SideNav.js
+++ b/packages/react/src/components/UIShell/SideNav.js
@@ -99,7 +99,7 @@ const SideNav = React.forwardRef(function SideNav(props, ref) {
eventHandlers.onBlur = event => handleToggle(event, false);
}
- if (addMouseListeners) {
+ if (addMouseListeners && isRail) {
eventHandlers.onMouseEnter = () => handleToggle(true, true);
eventHandlers.onMouseLeave = () => handleToggle(false, false);
}
diff --git a/packages/react/src/components/UIShell/__tests__/SideNav-test.js b/packages/react/src/components/UIShell/__tests__/SideNav-test.js
index 9c92bbb94580..4799ae27c89d 100644
--- a/packages/react/src/components/UIShell/__tests__/SideNav-test.js
+++ b/packages/react/src/components/UIShell/__tests__/SideNav-test.js
@@ -8,6 +8,7 @@
import React from 'react';
import { mount } from 'enzyme';
import SideNav from '../SideNav';
+import SideNavLink from '../SideNavLink';
describe('SideNav', () => {
let mockProps, wrapper;
@@ -15,7 +16,7 @@ describe('SideNav', () => {
beforeEach(() => {
mockProps = {
'aria-label': 'Navigation',
- children: Navigation
,
+ children: Navigation,
};
});
@@ -28,12 +29,18 @@ describe('SideNav', () => {
expect(wrapper).toMatchSnapshot();
});
- it('by default, all event listeners are added', () => {
+ it('by default, focus event listeners are added', () => {
wrapper = mount();
expect(wrapper.find('nav').props().onFocus).toBeDefined();
expect(wrapper.find('nav').props().onBlur).toBeDefined();
- expect(wrapper.find('nav').props().onMouseEnter).toBeDefined();
- expect(wrapper.find('nav').props().onMouseLeave).toBeDefined();
+ });
+
+ it('by default, mouse event listeners are not added', () => {
+ wrapper = mount();
+ expect(wrapper.find('nav').props().onFocus).toBeDefined();
+ expect(wrapper.find('nav').props().onBlur).toBeDefined();
+ expect(wrapper.find('nav').props().onMouseEnter).not.toBeDefined();
+ expect(wrapper.find('nav').props().onMouseLeave).not.toBeDefined();
});
it('if addFocusListeners is specified as false, no focus event listeners props are added', () => {
@@ -41,6 +48,15 @@ describe('SideNav', () => {
wrapper.setProps({ addFocusListeners: false });
expect(wrapper.find('nav').props().onFocus).not.toBeDefined();
expect(wrapper.find('nav').props().onBlur).not.toBeDefined();
+ expect(wrapper.find('nav').props().onMouseEnter).not.toBeDefined();
+ expect(wrapper.find('nav').props().onMouseLeave).not.toBeDefined();
+ });
+
+ it('if addFocusListeners is specified as false in rail SideNav, no event listeners props are added', () => {
+ wrapper = mount();
+ wrapper.setProps({ addFocusListeners: false });
+ expect(wrapper.find('nav').props().onFocus).not.toBeDefined();
+ expect(wrapper.find('nav').props().onBlur).not.toBeDefined();
expect(wrapper.find('nav').props().onMouseEnter).toBeDefined();
expect(wrapper.find('nav').props().onMouseLeave).toBeDefined();
});
diff --git a/packages/react/src/components/UIShell/__tests__/__snapshots__/SideNav-test.js.snap b/packages/react/src/components/UIShell/__tests__/__snapshots__/SideNav-test.js.snap
index 895d20bd1db4..df53d1e1b86d 100644
--- a/packages/react/src/components/UIShell/__tests__/__snapshots__/SideNav-test.js.snap
+++ b/packages/react/src/components/UIShell/__tests__/__snapshots__/SideNav-test.js.snap
@@ -19,12 +19,39 @@ exports[`SideNav should render 1`] = `
className="bx--side-nav__navigation bx--side-nav bx--side-nav--ux"
onBlur={[Function]}
onFocus={[Function]}
- onMouseEnter={[Function]}
- onMouseLeave={[Function]}
>
-
- Navigation
-
+
+
+
+
+
+
+
+ Navigation
+
+
+
+
+
+
+
`;