Skip to content

Commit

Permalink
Add max prop.
Browse files Browse the repository at this point in the history
  • Loading branch information
cjcenizal committed May 10, 2018
1 parent cf2ed01 commit 356cb4e
Show file tree
Hide file tree
Showing 7 changed files with 297 additions and 5 deletions.
22 changes: 21 additions & 1 deletion src-docs/src/views/breadcrumbs/breadcrumbs_example.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ import Truncate from './truncate';
const truncateSource = require('!!raw-loader!./truncate');
const truncateHtml = renderToHtml(Truncate);

import Max from './max';
const maxSource = require('!!raw-loader!./max');
const maxHtml = renderToHtml(Max);

export const BreadcrumbsExample = {
title: 'Breadcrumbs',
sections: [{
Expand Down Expand Up @@ -59,7 +63,7 @@ export const BreadcrumbsExample = {
props: { EuiBreadcrumbs },
demo: <Responsive />,
}, {
title: 'Truncate',
title: 'Truncate each breadcrumb',
source: [{
type: GuideSectionTypes.JS,
code: truncateSource,
Expand All @@ -74,5 +78,21 @@ export const BreadcrumbsExample = {
),
props: { EuiBreadcrumbs },
demo: <Truncate />,
}, {
title: 'Limit the number of breadcrumbs',
source: [{
type: GuideSectionTypes.JS,
code: maxSource,
}, {
type: GuideSectionTypes.HTML,
code: maxHtml,
}],
text: (
<p>
Use the <EuiCode>max</EuiCode> prop to cull breadcrumbs beyond a certain number.
</p>
),
props: { EuiBreadcrumbs },
demo: <Max />,
}],
};
34 changes: 34 additions & 0 deletions src-docs/src/views/breadcrumbs/max.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import React from 'react';

import {
EuiBreadcrumbs,
} from '../../../../src/components';

export default () => {
const breadcrumbs = [{
text: 'Animals',
href: '#',
}, {
text: 'Metazoans',
href: '#',
}, {
text: 'Chordates',
href: '#',
}, {
text: 'Vertebrates',
href: '#',
}, {
text: 'Tetrapods',
href: '#',
}, {
text: 'Reptiles',
href: '#',
}, {
text: 'Boa constrictor',
href: '#',
}, {
text: 'Nebulosa subspecies',
}];

return <EuiBreadcrumbs breadcrumbs={breadcrumbs} max={5} />;
};
162 changes: 162 additions & 0 deletions src/components/breadcrumbs/__snapshots__/breadcrumbs.test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,132 @@ exports[`EuiBreadcrumbs is rendered 1`] = `
</div>
`;

exports[`EuiBreadcrumbs props max doesn't break when max exceeds the number of breadcrumbs 1`] = `
<div
class="euiBreadcrumbs"
>
<button
class="euiLink euiLink--subdued euiBreadcrumb"
type="button"
>
Animals
</button>
<div
class="euiBreadcrumbSeparator"
/>
<button
class="euiLink euiLink--subdued euiBreadcrumb"
type="button"
>
Reptiles
</button>
<div
class="euiBreadcrumbSeparator"
/>
<button
class="euiLink euiLink--subdued euiBreadcrumb"
type="button"
>
Boa constrictor
</button>
<div
class="euiBreadcrumbSeparator"
/>
<span
class="euiBreadcrumb euiBreadcrumb--last"
>
Edit
</span>
</div>
`;

exports[`EuiBreadcrumbs props max renders 1 item 1`] = `
<div
class="euiBreadcrumbs"
>
<div
class="euiBreadcrumb euiBreadcrumb--collapsed"
>
</div>
<div
class="euiBreadcrumbSeparator"
/>
<span
class="euiBreadcrumb euiBreadcrumb--last"
>
Edit
</span>
</div>
`;

exports[`EuiBreadcrumbs props max renders 2 items 1`] = `
<div
class="euiBreadcrumbs"
>
<button
class="euiLink euiLink--subdued euiBreadcrumb"
type="button"
>
Animals
</button>
<div
class="euiBreadcrumbSeparator"
/>
<div
class="euiBreadcrumb euiBreadcrumb--collapsed"
>
</div>
<div
class="euiBreadcrumbSeparator"
/>
<span
class="euiBreadcrumb euiBreadcrumb--last"
>
Edit
</span>
</div>
`;

exports[`EuiBreadcrumbs props max renders 3 items 1`] = `
<div
class="euiBreadcrumbs"
>
<button
class="euiLink euiLink--subdued euiBreadcrumb"
type="button"
>
Animals
</button>
<div
class="euiBreadcrumbSeparator"
/>
<div
class="euiBreadcrumb euiBreadcrumb--collapsed"
>
</div>
<div
class="euiBreadcrumbSeparator"
/>
<button
class="euiLink euiLink--subdued euiBreadcrumb"
type="button"
>
Boa constrictor
</button>
<div
class="euiBreadcrumbSeparator"
/>
<span
class="euiBreadcrumb euiBreadcrumb--last"
>
Edit
</span>
</div>
`;

exports[`EuiBreadcrumbs props responsive is rendered 1`] = `
<div
class="euiBreadcrumbs euiBreadcrumbs--responsive"
Expand All @@ -55,6 +181,24 @@ exports[`EuiBreadcrumbs props responsive is rendered 1`] = `
<div
class="euiBreadcrumbSeparator"
/>
<button
class="euiLink euiLink--subdued euiBreadcrumb"
type="button"
>
Reptiles
</button>
<div
class="euiBreadcrumbSeparator"
/>
<button
class="euiLink euiLink--subdued euiBreadcrumb"
type="button"
>
Boa constrictor
</button>
<div
class="euiBreadcrumbSeparator"
/>
<span
class="euiBreadcrumb euiBreadcrumb--last"
>
Expand All @@ -76,6 +220,24 @@ exports[`EuiBreadcrumbs props truncate is rendered 1`] = `
<div
class="euiBreadcrumbSeparator"
/>
<button
class="euiLink euiLink--subdued euiBreadcrumb"
type="button"
>
Reptiles
</button>
<div
class="euiBreadcrumbSeparator"
/>
<button
class="euiLink euiLink--subdued euiBreadcrumb"
type="button"
>
Boa constrictor
</button>
<div
class="euiBreadcrumbSeparator"
/>
<span
class="euiBreadcrumb euiBreadcrumb--last"
>
Expand Down
7 changes: 5 additions & 2 deletions src/components/breadcrumbs/_breadcrumbs.scss
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

.euiBreadcrumb {
display: inline-block;
position: relative;

&:not(.euiBreadcrumb--last) {
margin-right: $euiBreadcrumbSpacing;
Expand All @@ -15,13 +14,17 @@
font-weight: 500;
}

.euiBreadcrumb--collapsed {
color: $euiColorLightShade;
}

.euiBreadcrumbSeparator {
pointer-events: none;
display: inline-block;
margin-right: $euiBreadcrumbSpacing;
width: 1px;
height: $euiSize;
transform: rotate(15deg) translateY(0.2em);
transform: translateY(0.2em) rotate(15deg);
background: $euiColorLightShade;
}

Expand Down
51 changes: 49 additions & 2 deletions src/components/breadcrumbs/breadcrumbs.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,55 @@ import classNames from 'classnames';

import { EuiLink } from '../link';

const limitBreadcrumbs = (breadcrumbs, max) => {
const breadcrumbsAtStart = [];
const breadcrumbsAtEnd = [];
const limit = Math.min(max, breadcrumbs.length);

for (let i = 0; i < limit; i++) {
// We'll alternate with displaying breadcrumbs at the end and at the start, but be biased
// towards breadcrumbs the end so that if max is an odd number, we'll have one more
// breadcrumb visible at the end than at the beginning.
const isEven = i % 2 === 0;

// We're picking breadcrumbs from the front AND the back, so we treat each iteration as a
// half-iteration.
const normalizedIndex = Math.floor(i * 0.5);
const indexOfBreadcrumb = isEven ? breadcrumbs.length - 1 - normalizedIndex : normalizedIndex;
const breadcrumb = breadcrumbs[indexOfBreadcrumb];

if (isEven) {
breadcrumbsAtEnd.unshift(breadcrumb);
} else {
breadcrumbsAtStart.push(breadcrumb);
}
}

if (max < breadcrumbs.length) {
breadcrumbsAtStart.push(<EuiBreadcrumbCollapsed key='collapsed' />);
}

return [
...breadcrumbsAtStart,
...breadcrumbsAtEnd,
];
}

const EuiBreadcrumbCollapsed = () => (
<Fragment>
<div className="euiBreadcrumb euiBreadcrumb--collapsed">&#8230;</div>
<EuiBreadcrumbSeparator />
</Fragment>
);

const EuiBreadcrumbSeparator = () => <div className='euiBreadcrumbSeparator' />;

export const EuiBreadcrumbs = ({
breadcrumbs,
className,
responsive,
truncate,
max,
...rest,
}) => {
const breadcrumbElements = breadcrumbs.map((breadcrumb, index) => {
Expand Down Expand Up @@ -51,7 +95,7 @@ export const EuiBreadcrumbs = ({
let separator;

if (!isLastBreadcrumb) {
separator = <div className='euiBreadcrumbSeparator' />;
separator = <EuiBreadcrumbSeparator />;
}

return (
Expand All @@ -62,14 +106,16 @@ export const EuiBreadcrumbs = ({
);
})

const limitedBreadcrumbs = max ? limitBreadcrumbs(breadcrumbElements, max) : breadcrumbElements;

const classes = classNames('euiBreadcrumbs', className, {
'euiBreadcrumbs--truncate': truncate,
'euiBreadcrumbs--responsive': responsive,
});

return (
<div className={classes} {...rest}>
{breadcrumbElements}
{limitedBreadcrumbs}
</div>
);
};
Expand All @@ -78,6 +124,7 @@ EuiBreadcrumbs.propTypes = {
className: PropTypes.string,
responsive: PropTypes.bool,
truncate: PropTypes.bool,
max: PropTypes.number,
breadcrumbs: PropTypes.arrayOf(PropTypes.shape({
text: PropTypes.node.isRequired,
href: PropTypes.string,
Expand Down
Loading

0 comments on commit 356cb4e

Please sign in to comment.