Skip to content

Commit

Permalink
Merge pull request #142 from US-CBP/feature/cbp-structured-list
Browse files Browse the repository at this point in the history
Feature/cbp structured list
  • Loading branch information
dgibson666 authored May 13, 2024
2 parents bfa62dc + 3e2d62c commit 30087ae
Show file tree
Hide file tree
Showing 11 changed files with 477 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ export const CbpPanel = /*@__PURE__*/createReactComponent<JSX.CbpPanel, HTMLCbpP
export const CbpSection = /*@__PURE__*/createReactComponent<JSX.CbpSection, HTMLCbpSectionElement>('cbp-section');
export const CbpSegmentedButtonGroup = /*@__PURE__*/createReactComponent<JSX.CbpSegmentedButtonGroup, HTMLCbpSegmentedButtonGroupElement>('cbp-segmented-button-group');
export const CbpSkipNav = /*@__PURE__*/createReactComponent<JSX.CbpSkipNav, HTMLCbpSkipNavElement>('cbp-skip-nav');
export const CbpStructuredList = /*@__PURE__*/createReactComponent<JSX.CbpStructuredList, HTMLCbpStructuredListElement>('cbp-structured-list');
export const CbpStructuredListItem = /*@__PURE__*/createReactComponent<JSX.CbpStructuredListItem, HTMLCbpStructuredListItemElement>('cbp-structured-list-item');
export const CbpTab = /*@__PURE__*/createReactComponent<JSX.CbpTab, HTMLCbpTabElement>('cbp-tab');
export const CbpTabPanel = /*@__PURE__*/createReactComponent<JSX.CbpTabPanel, HTMLCbpTabPanelElement>('cbp-tab-panel');
export const CbpTabs = /*@__PURE__*/createReactComponent<JSX.CbpTabs, HTMLCbpTabsElement>('cbp-tabs');
Expand Down
2 changes: 2 additions & 0 deletions packages/web-components/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ The React components are wrappers generated from this package and will share the
## [unreleased] TBD

* First cut of `cbp-expand`.
* First cut of `cbp-structured-list` and `cbp-structured-list-item`.
* Updates to `cbp-icon` and `cbp-button` in support of Expand and Accordion components.
* Renamed `data-container-theme` to `data-cbp-container-context` to convey that a specific container/DOM node is being displayed light or dark.

## [0.0.1-develop.8] 04-29-2024
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@
--cbp-expand-control-gap: var(--cbp-space-1x);
--cbp-expand-control-padding: var(--cbp-space-3x);
--cbp-expand-content-padding: var(--cbp-space-3x);
--cbp-expand-margin-bottom: var(--cbp-space-2x);
}

cbp-expand {
display: block;
margin-bottom: var(--cbp-expand-margin-bottom);

&:not([open]) {
--cbp-expand-rotate-icon: rotate(-90deg);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ The Link component renders (or wraps) an anchor for navigation styled in accorda
### Additional Notes and Considerations

* An anchor may be supplied as slotted content rather than rendered by the web component. This requirement supports frameworks that use component-based routers, such as React or Vue.
* TODO: need clarification on "definition" variant and expected functionality.
* TODO: investigate side effects and edge cases pertaining to "disabled" links.
* Are any interactive styles still inherited?
* Does a mouse click still emit a click event?
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ The Section component represents a generic block that may be used for semantic m
## Functional Requirements

* The Section component may render either a `section` tag, a `div` tag, or no tag inside of the host element.
* The Section component may be used apply a background color or horizontal line similar to the Typography component, but for a larger blocks of content.
* The Section component may be used to apply a background color or horizontal line similar to the Typography component, but for a larger blocks of content.

## Technical Specifications

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
cbp-structured-list-item {
display: block;

&[color=danger]:not([selected]) {
background-color: var(--cbp-color-danger-lighter) !important;
}

&[selected] {
background-color: var(--cbp-color-interactive-selected-light) !important;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { Component, Prop, Element, Host, h } from '@stencil/core';
import { setCSSProps } from '../../utils/utils';

@Component({
tag: 'cbp-structured-list-item',
styleUrl: 'cbp-structured-list-item.scss',
})

export class CbpStructuredListItem {

@Element() host: HTMLElement;

/** Optionally specifies a color variant based on design tokens. */
@Prop({ reflect: true }) color: 'danger';

/** Specifies whether the item is selected. */
@Prop({ reflect: true }) selected: boolean;

/** Supports adding inline styles as an object */
@Prop() sx: any = {};

componentWillLoad() {
if (typeof this.sx == 'string') {
this.sx = JSON.parse(this.sx) || {};
}
setCSSProps(this.host, {
...this.sx,
});
}

render() {
return (
<Host role="listitem">
<slot />
</Host>
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
:root {
--cbp-structured-list-item-padding: var(--cbp-space-4x);
}
cbp-structured-list {
display: block;
background-color: var(--cbp-color-white);

[slot] {
display: flex;
align-items: center;
padding: var(--cbp-space-3x);
min-height: var(--cbp-space-13x);
font-weight: var(--cbp-font-weight-bold);

// Nesting 2 flex contexts will not take up 100% of the width
*:only-child {
flex-basis: 100%;
}
}

[slot=cbp-structured-list-header] {
color: var(--cbp-color-text-darkest);
background-color: var(--cbp-color-gray-cool-30);
font-style: italic;
}

[slot=cbp-structured-list-footer] {
color: var(--cbp-color-text-lightest);
background-color: var(--cbp-color-gray-cool-70);
}

&[striped] [role=list] > *:nth-child(even) {
background-color: var(--cbp-color-gray-cool-4);
}

// Style all list items regardless of the element used to wrap/define them (don't leave this to cbp-structured-list-item)
div[role=list] > * {
display: block;
padding: var(--cbp-structured-list-item-padding);
border-bottom-style: solid;
border-bottom-width: var(--cbp-border-size-md);
border-bottom-color: var(--cbp-color-gray-cool-30);

&:hover {
background-color: var(--cbp-color-gray-cool-10) !important;
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { Meta } from '@storybook/addon-docs';

<Meta title="Components/Structured List/Specifications" />

# cbp-structured-list and cbp-structured-list-item

## Purpose

Structured lists are a way of displaying long lists of data where the user is not directly comparing raw data one row at a time.

## Functional Requirements

* The parent Structured List component renders a `div` with `role="list"`, with optional slots for header and footer information before and after it respectively.
* The Structured List may contain plain `li` elements slotted within the default slot.
* Optionally, the Structured List Item component (`cbp-structured-list-item`) may be slotted within the default slot if additional functionality will be used, such as:
* Selecting of items
* Shading of rows in a `danger` color.

## Technical Specifications

### User Interactions

* The Structured List supports styling for selected list items.
* The actual user interactions and implementation of checkboxes and buttons via slotted content is provided by the application code.

### Responsiveness

* The Structured List is semantically an unordered list. However, its contents may be complex and arranged in a grid with faux columns.
* Because each list item is separate, an overarching grid context that takes queues from content length cannot be established to lay out the list.
* Creating equal width columns can only be achieved using CSS Grid or the `cbp-grid` component within each list item.
* These grid columns should be explicitly defined and not determined by content length, since each row/item is independent and columns may not line up across rows/items.
* A responsive grid that wraps, containing equal sized (but flexible) columns may be achieved using some variant of `grid-template-columns` with `autofit`,
e.g., `grid-template-columns="repeat(auto-fit, minmax(5rem, 1fr))"`.
* For grids that require more granular definition of each column, the `cbp-grid` component's `breakpoint` property may be used to linearize the grid at a specified viewport size.

### Accessibility

* The Structured List should be recognizable as a semantic list, regardless of how it is marked up.
* The parent `cbp-structured-list` component renders a `div` with `role="list"`.
* The immediate children slotted within the default slot of the parent should be one of the following:
* `li` elements
* `cbp-structured-list-item` components
* any other container with a `role="listitem"`.
* The `cbp-structured-list-item` component applies a `role="listitem"` to its host tag, acting as a proper list item.
* The Structured List component should have a value specified for its `accessibilityText` property, which describes the list and is applied via `aria-label`.
* If the Structured List has a header (content in the `cbp-structured-list-header` named slot), this element should be given an `id`, which is also specified as the `headerId` property
and used to link the header to the list via the `aria-describedby` attribute, providing additional context for the list to screen readers.
* The Structured List is not a table and has no column headings. If you feel the need for column headings, you should use a table instead.

### Additional Notes and Considerations

* The named slot `cbp-structured-list-footer` is intended for an action bar when items are selected and should not be used otherwise.
* TODO: integrating the `cbp-structured-list-item` `selected` property with user interaction with a checkbox may take additional work and testing.
Loading

0 comments on commit 30087ae

Please sign in to comment.