Skip to content

Commit

Permalink
[New Nav Feature] EuiPinnableListGroup (#3061)
Browse files Browse the repository at this point in the history
* Added EuiCollapsibleNavGroupList component

* Added content to EuiCollapsibleNavList

* Update to use latest props from EuiListGroup

* Passing `color` to EuiListGroup

* Added active link to examples

* Better docs for nav list and added snippets

* cleanup

* Renamed `EuiCollapsibleList` to `EuiPinnableListGroup` and moved to `list_group`

Also made `onPinClick` required

* i18n

* Fix focus and focus-within states

With IE fallback

* Allowing pin icon title/aria-labels to be custom

Co-authored-by: Greg Thompson <thompson.glowe@gmail.com>
  • Loading branch information
2 people authored and cchaos committed Mar 17, 2020
1 parent 988cffc commit 6d62843
Show file tree
Hide file tree
Showing 17 changed files with 701 additions and 12 deletions.
59 changes: 59 additions & 0 deletions src-docs/src/views/list_group/list_group_example.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import React from 'react';
import { Link } from 'react-router';

import { renderToHtml } from '../../services';

Expand All @@ -7,8 +8,10 @@ import { GuideSectionTypes } from '../../components';
import {
EuiListGroup,
EuiListGroupItem,
EuiPinnableListGroup,
EuiCode,
} from '../../../../src/components';
import { EuiPinnableListGroupItem } from './props';

import ListGroup from './list_group';
const listGroupSource = require('!!raw-loader!./list_group');
Expand All @@ -30,6 +33,10 @@ import ListGroupItemColor from './list_group_item_color';
const listGroupItemColorSource = require('!!raw-loader!./list_group_item_color');
const listGroupItemColorHtml = renderToHtml(ListGroupItemColor);

import PinnableListGroup from './pinnable_list_group';
const pinnableListGroupSource = require('!!raw-loader!./pinnable_list_group');
const pinnableListGroupHtml = renderToHtml(PinnableListGroup);

export const ListGroupExample = {
title: 'List group',
sections: [
Expand Down Expand Up @@ -205,6 +212,58 @@ export const ListGroupExample = {
label="Primary"
color="primary"
size="s"
/>`,
},
{
title: 'Pinnable list group',
source: [
{
type: GuideSectionTypes.JS,
code: pinnableListGroupSource,
},
{
type: GuideSectionTypes.HTML,
code: pinnableListGroupHtml,
},
],
text: (
<>
<p>
<strong>EuiPinnableListGroup</strong> is simply an extra wrapper
around an{' '}
<Link to="/display/list-group">
<strong>EuiListGroup</strong>
</Link>{' '}
that provides visual indicators for <strong>pinning</strong>.
</p>
<p>
Pinning is the concept that users can click a pin icon and add it to
a subset of links (most likely shown in different list group). By
providing an <EuiCode>onPinClick</EuiCode> handler, the component
will automatically add the pin action to the item. However, the
consuming application must manage the <EuiCode>listItem</EuiCode>s
and their <EuiCode>pinned</EuiCode> state.
</p>
<p>
In order to get the full benefit of using{' '}
<strong>EuiPinnableListGroup</strong>, the component only supports
providing list items via the <EuiCode>listItem</EuiCode> prop and
does not support <EuiCode>children</EuiCode>.
</p>
</>
),
props: { EuiPinnableListGroup, EuiPinnableListGroupItem },
demo: <PinnableListGroup />,
snippet: `<EuiPinnableListGroup
onPinClick={item => {}}
listItems={[
{
label: 'A link',
href: '#',
pinned: true,
isActive: true,
},
]}
/>`,
},
],
Expand Down
8 changes: 4 additions & 4 deletions src-docs/src/views/list_group/list_group_link_actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ export default class extends Component {
extraAction={{
color: 'subdued',
onClick: this.link1Clicked,
iconType: favorite1 === 'link1' ? 'pinFilled' : 'pin',
iconType: favorite1 === 'link1' ? 'starFilled' : 'starEmpty',
iconSize: 's',
'aria-label': 'Favorite link1',
alwaysShow: favorite1 === 'link1',
Expand All @@ -83,7 +83,7 @@ export default class extends Component {
extraAction={{
color: 'subdued',
onClick: this.link2Clicked,
iconType: favorite2 === 'link2' ? 'pinFilled' : 'pin',
iconType: favorite2 === 'link2' ? 'starFilled' : 'starEmpty',
iconSize: 's',
'aria-label': 'Favorite link2',
alwaysShow: favorite2 === 'link2',
Expand All @@ -98,7 +98,7 @@ export default class extends Component {
extraAction={{
color: 'subdued',
onClick: this.link3Clicked,
iconType: favorite3 === 'link3' ? 'pinFilled' : 'pin',
iconType: favorite3 === 'link3' ? 'starFilled' : 'starEmpty',
iconSize: 's',
'aria-label': 'Favorite link3',
alwaysShow: favorite3 === 'link3',
Expand All @@ -114,7 +114,7 @@ export default class extends Component {
extraAction={{
color: 'subdued',
onClick: () => window.alert('Action clicked'),
iconType: 'pin',
iconType: 'starEmpty',
iconSize: 's',
'aria-label': 'Favorite link4',
}}
Expand Down
53 changes: 53 additions & 0 deletions src-docs/src/views/list_group/pinnable_list_group.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import React from 'react';

import {
EuiPinnableListGroup,
EuiPinnableListGroupItemProps,
} from '../../../../src/components/list_group';

const someListItems: EuiPinnableListGroupItemProps[] = [
{
label: 'Label with iconType',
iconType: 'stop',
},
{
label: 'Pinned button with onClick',
pinned: true,
onClick: e => {
console.log('Pinned button clicked', e);
},
},
{
label: 'Link with href and custom pin titles',
href: '/#',
},
{
label: 'Active link',
isActive: true,
href: '/#',
},
{
label: 'Custom extra actions will override pinning ability',
extraAction: {
iconType: 'bell',
alwaysShow: true,
'aria-label': 'bell',
},
},
];

export default () => (
<>
<EuiPinnableListGroup
listItems={someListItems}
onPinClick={item => {
console.warn('Clicked: ', item);
}}
maxWidth="none"
pinTitle={(item: EuiPinnableListGroupItemProps) => `Pin ${item.label}`}
unpinTitle={(item: EuiPinnableListGroupItemProps) =>
`Unpin ${item.label}`
}
/>
</>
);
7 changes: 7 additions & 0 deletions src-docs/src/views/list_group/props.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import React, { FunctionComponent } from 'react';

import { EuiPinnableListGroupItemProps } from '../../../../src/components/list_group';

export const EuiPinnableListGroupItem: FunctionComponent<
EuiPinnableListGroupItemProps
> = () => <div />;
2 changes: 1 addition & 1 deletion src/components/collapsible_nav/_index.scss
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
@import 'variables';

@import 'collapsible_nav_group/index';
@import 'collapsible_nav';
@import 'collapsible_nav_group/index';
6 changes: 5 additions & 1 deletion src/components/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,11 @@ export {

export { EuiLink } from './link';

export { EuiListGroup, EuiListGroupItem } from './list_group';
export {
EuiListGroup,
EuiListGroupItem,
EuiPinnableListGroup,
} from './list_group';

export { EuiMark } from './mark';

Expand Down
32 changes: 32 additions & 0 deletions src/components/list_group/__snapshots__/list_group.test.tsx.snap
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ exports[`EuiListGroup is rendered with listItems 1`] = `
</span>
</span>
<button
aria-label="bell"
class="euiButtonIcon euiButtonIcon--primary euiListGroupItem__extraAction euiListGroupItem__extraAction-alwaysShow"
type="button"
>
Expand All @@ -69,6 +70,21 @@ exports[`EuiListGroup is rendered with listItems 1`] = `
</span>
</button>
</li>
<li
class="euiListGroupItem euiListGroupItem--medium euiListGroupItem-isActive euiListGroupItem-isClickable"
>
<a
class="euiListGroupItem__button"
href="#"
>
<span
class="euiListGroupItem__label"
title="Active link"
>
Active link
</span>
</a>
</li>
<li
class="euiListGroupItem euiListGroupItem--medium euiListGroupItem-isClickable"
>
Expand Down Expand Up @@ -123,6 +139,7 @@ exports[`EuiListGroup is rendered with listItems and color 1`] = `
</span>
</span>
<button
aria-label="bell"
class="euiButtonIcon euiButtonIcon--primary euiListGroupItem__extraAction euiListGroupItem__extraAction-alwaysShow"
type="button"
>
Expand All @@ -148,6 +165,21 @@ exports[`EuiListGroup is rendered with listItems and color 1`] = `
</span>
</button>
</li>
<li
class="euiListGroupItem euiListGroupItem--medium euiListGroupItem--primary euiListGroupItem-isActive euiListGroupItem-isClickable"
>
<a
class="euiListGroupItem__button"
href="#"
>
<span
class="euiListGroupItem__label"
title="Active link"
>
Active link
</span>
</a>
</li>
<li
class="euiListGroupItem euiListGroupItem--medium euiListGroupItem--primary euiListGroupItem-isClickable"
>
Expand Down
1 change: 1 addition & 0 deletions src/components/list_group/_index.scss
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@

@import 'list_group';
@import 'list_group_item';
@import 'pinnable_list_group/index';
35 changes: 29 additions & 6 deletions src/components/list_group/_list_group_item.scss
Original file line number Diff line number Diff line change
Expand Up @@ -13,29 +13,52 @@
background-color: $euiListGroupItemHoverBackground;
}

&.euiListGroupItem-isClickable .euiListGroupItem__button:focus {
// Can't be grouped with above or else IE will ignore the whole group
&.euiListGroupItem-isClickable:focus-within {
background-color: $euiListGroupItemHoverBackground;
text-decoration: underline;
}

&.euiListGroupItem--ghost {
&.euiListGroupItem-isActive,
&.euiListGroupItem-isClickable:hover,
&.euiListGroupItem-isClickable .euiListGroupItem__button:focus {
&.euiListGroupItem-isClickable:hover {
background-color: $euiListGroupItemHoverBackgroundGhost;
}

// Can't be grouped with above or else IE will ignore the whole group
&.euiListGroupItem-isClickable:focus-within {
background-color: $euiListGroupItemHoverBackgroundGhost;
}
}

&.euiListGroupItem-isClickable:hover .euiListGroupItem__button,
.euiListGroupItem__button:hover,
.euiListGroupItem__button:focus {
text-decoration: underline;
}

// Style all disabled list items whether or not they are links or buttons
&.euiListGroupItem-isDisabled,
&.euiListGroupItem-isDisabled:hover,
&.euiListGroupItem-isDisabled:focus,
&.euiListGroupItem-isDisabled .euiListGroupItem__button:hover,
&.euiListGroupItem-isDisabled .euiListGroupItem__button:focus {
color: $euiButtonColorDisabled;
text-decoration: none;
cursor: not-allowed;
background-color: transparent;
text-decoration: none;
}
}

// IE doesn't support :focus-within
@include internetExplorerOnly {
.euiListGroupItem__button:hover,
.euiListGroupItem__button:focus {
background-color: $euiListGroupItemHoverBackground;
border-radius: $euiBorderRadius;

.euiListGroupItem--ghost .euiListGroupItem__button:hover,
.euiListGroupItem--ghost .euiListGroupItem__button:focus {
background-color: $euiListGroupItemHoverBackgroundGhost;
}
}
}

Expand Down
5 changes: 5 additions & 0 deletions src/components/list_group/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,7 @@
export { EuiListGroup, EuiListGroupProps } from './list_group';
export { EuiListGroupItem, EuiListGroupItemProps } from './list_group_item';
export {
EuiPinnableListGroup,
EuiPinnableListGroupProps,
EuiPinnableListGroupItemProps,
} from './pinnable_list_group';
6 changes: 6 additions & 0 deletions src/components/list_group/list_group.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ const someListItems: EuiListGroupItemProps[] = [
extraAction: {
iconType: 'bell',
alwaysShow: true,
'aria-label': 'bell',
},
},
{
Expand All @@ -23,6 +24,11 @@ const someListItems: EuiListGroupItemProps[] = [
console.log('Visualize clicked', e);
},
},
{
label: 'Active link',
isActive: true,
href: '#',
},
{
label: 'Link with href',
href: '#',
Expand Down
Loading

0 comments on commit 6d62843

Please sign in to comment.