Skip to content

Commit

Permalink
Add Scrollbox container component
Browse files Browse the repository at this point in the history
  • Loading branch information
lyzadanger committed Aug 11, 2021
1 parent 99f304c commit 83090c8
Show file tree
Hide file tree
Showing 9 changed files with 127 additions and 14 deletions.
17 changes: 17 additions & 0 deletions src/components/containers.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,20 @@ export function Actions({ children, direction = 'row', classes = '' }) {
const baseClass = `Hyp-Actions--${direction}`;
return <div className={classnames(baseClass, classes)}>{children}</div>;
}

/**
*
* @typedef ScrollboxBaseProps
* @prop {boolean} [withHeader=false] - Provide layout affordances for a sticky
* header in the scrollable content
*/

/**
* Render a scrollable container to contain content that might overflow.
*
* @param {ScrollboxBaseProps & ContainerProps} props
*/
export function Scrollbox({ children, classes = '', withHeader = false }) {
const baseClass = withHeader ? 'Hyp-Scrollbox--with-header' : 'Hyp-Scrollbox';
return <div className={classnames(baseClass, classes)}>{children}</div>;
}
29 changes: 28 additions & 1 deletion src/components/test/containers-test.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { mount } from 'enzyme';

import { Frame, Card, Actions } from '../containers';
import { Frame, Card, Actions, Scrollbox } from '../containers';

describe('Frame', () => {
const createComponent = (props = {}) =>
Expand Down Expand Up @@ -70,3 +70,30 @@ describe('Actions', () => {
assert.isTrue(wrapper.find('div.Hyp-Actions--column').exists());
});
});

describe('Scrollbox', () => {
const createComponent = (props = {}) =>
mount(
<Scrollbox {...props}>
<div>This is content inside of a Scrollbox</div>
</Scrollbox>
);

it('renders children inside of a div with appropriate classnames', () => {
const wrapper = createComponent();

assert.isTrue(wrapper.find('.Hyp-Scrollbox').exists());
});

it('applies extra classes', () => {
const wrapper = createComponent({ classes: 'foo bar' });

assert.isTrue(wrapper.find('div.Hyp-Scrollbox.foo.bar').exists());
});

it('applies header-affordance layout class if `withHeader`', () => {
const wrapper = createComponent({ withHeader: true });

assert.isTrue(wrapper.find('div.Hyp-Scrollbox--with-header').exists());
});
});
2 changes: 1 addition & 1 deletion src/index.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Components
export { IconButton, LabeledButton, LinkButton } from './components/buttons';
export { LabeledCheckbox, Checkbox } from './components/Checkbox';
export { Frame, Card, Actions } from './components/containers';
export { Frame, Card, Actions, Scrollbox } from './components/containers';
export { Dialog } from './components/Dialog';
export { Modal, ConfirmModal } from './components/Modal';
export { Panel } from './components/Panel';
Expand Down
42 changes: 41 additions & 1 deletion src/pattern-library/components/patterns/ContainerComponents.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import { Frame, Card, Actions } from '../../..';
import { Frame, Card, Actions, Scrollbox } from '../../..';
import { LabeledButton } from '../../..';

import Library from '../Library';

import { SampleListElements } from './samples';

export default function ContainerComponents() {
return (
<Library.Page title="Containers">
Expand Down Expand Up @@ -75,6 +77,44 @@ export default function ContainerComponents() {
</Library.Demo>
</Library.Example>
</Library.Pattern>

<Library.Pattern title="Scrollbox">
<p>
The <code>Scrollbox</code> component is a container for (potentially-)
overflowing content. It provides a scroll context and is styled with
the <code>scrollbox</code> pattern.
</p>
<Library.Example variant="wide">
<p>
A <code>Scrollbox</code> will fill its available space. Constraints
to that space need to be applied to a parent element. Here a parent
element is set to a width and height.
</p>
<Library.Demo title="Basic scrollbox" withSource>
<div style="height:250px;max-height:250px;width:200px">
<Scrollbox>
<ul className="hyp-u-padding hyp-u-vertical-spacing">
<SampleListElements />
</ul>
</Scrollbox>
</div>
</Library.Demo>
<Library.Demo title="Scrollbox with header" withSource>
<div style="height:250px;max-height:250px;width:200px">
<Scrollbox withHeader>
<div className="hyp-sticky-header">
<div className="hyp-sticky-header__heading">
NATO Alphabet
</div>
</div>
<ul className="hyp-u-padding hyp-u-vertical-spacing">
<SampleListElements />
</ul>
</Scrollbox>
</div>
</Library.Demo>
</Library.Example>
</Library.Pattern>
</Library.Page>
);
}
7 changes: 2 additions & 5 deletions src/pattern-library/components/patterns/ContainerPatterns.js
Original file line number Diff line number Diff line change
Expand Up @@ -253,11 +253,8 @@ export default function ContainerPatterns() {
<Library.Demo withSource>
<div style="height:250px;width:250px">
<div className="hyp-scrollbox--with-header">
<div
className="hyp-u-layout-row--center hyp-u-border--bottom hyp-u-bg-color--grey-1"
style="position:sticky;top:0;min-height:44px;"
>
<div>
<div className="hyp-sticky-header">
<div className="hyp-sticky-header__heading">
<strong>NATO Phonetic Alphabet</strong>
</div>
</div>
Expand Down
8 changes: 8 additions & 0 deletions styles/components/containers.scss
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,11 @@
.Hyp-Actions--column {
@include containers.actions($direction: column);
}

.Hyp-Scrollbox {
@include containers.scrollbox;
}

.Hyp-Scrollbox--with-header {
@include containers.scrollbox--with-header;
}
23 changes: 23 additions & 0 deletions styles/mixins/patterns/_containers.scss
Original file line number Diff line number Diff line change
Expand Up @@ -235,3 +235,26 @@ $-header-height: var.$touch-target-size;
@mixin scrollbox--with-header {
@include scrollbox($shadow-top-position: $-header-height);
}

/**
* A sticky container that is sized one-touch-unit high. This is currently
* expanded upon by table styling, but not used in other patterns (yet).
*/
@mixin sticky-header {
position: sticky;
top: 0;
height: $-header-height;

@include layout.padding;
@include atoms.border(bottom);

background-color: var.$color-grey-1;
font-weight: bold;

width: 100%;

&__heading {
@include layout.row($align: center, $justify: center);
height: 100%;
}
}
9 changes: 3 additions & 6 deletions styles/mixins/patterns/_tables.scss
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
@use '../focus';
@use '../layout';

@use './containers';

$-color-background--light: var.$color-white;
$-color-background--dark: var.$color-grey-7;
$-color-header-background: var.$color-grey-1;
Expand Down Expand Up @@ -39,16 +41,11 @@ $-min-row-height: var.$touch-target-size;
line-height: 1;

th {
@include atoms.border(bottom);
height: $-min-row-height;
position: sticky;
top: 0;

@include containers.sticky-header;
// Ensure the header is displayed above content in the table when it is
// scrolled, including any content which establishes a new stacking context.
z-index: 1;

background-color: $-color-header-background;
text-align: left;
}
}
Expand Down
4 changes: 4 additions & 0 deletions styles/patterns/_containers.scss
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,7 @@
.hyp-scrollbox--with-header {
@include containers.scrollbox--with-header;
}

.hyp-sticky-header {
@include containers.sticky-header;
}

0 comments on commit 83090c8

Please sign in to comment.