Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions packages/components/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,15 @@
"./components/hds/dropdown/toggle/button.js": "./dist/_app_/components/hds/dropdown/toggle/button.js",
"./components/hds/dropdown/toggle/chevron.js": "./dist/_app_/components/hds/dropdown/toggle/chevron.js",
"./components/hds/dropdown/toggle/icon.js": "./dist/_app_/components/hds/dropdown/toggle/icon.js",
"./components/hds/filter-bar/checkbox.js": "./dist/_app_/components/hds/filter-bar/checkbox.js",
"./components/hds/filter-bar/filter-group.js": "./dist/_app_/components/hds/filter-bar/filter-group.js",
"./components/hds/filter-bar/filters-dropdown.js": "./dist/_app_/components/hds/filter-bar/filters-dropdown.js",
"./components/hds/filter-bar.js": "./dist/_app_/components/hds/filter-bar.js",
"./components/hds/filter-bar/radio.js": "./dist/_app_/components/hds/filter-bar/radio.js",
"./components/hds/filter-bar/range.js": "./dist/_app_/components/hds/filter-bar/range.js",
"./components/hds/filter-bar/tabs.js": "./dist/_app_/components/hds/filter-bar/tabs.js",
"./components/hds/filter-bar/tabs/panel.js": "./dist/_app_/components/hds/filter-bar/tabs/panel.js",
"./components/hds/filter-bar/tabs/tab.js": "./dist/_app_/components/hds/filter-bar/tabs/tab.js",
"./components/hds/flyout/body.js": "./dist/_app_/components/hds/flyout/body.js",
"./components/hds/flyout/description.js": "./dist/_app_/components/hds/flyout/description.js",
"./components/hds/flyout/footer.js": "./dist/_app_/components/hds/flyout/footer.js",
Expand Down
12 changes: 12 additions & 0 deletions packages/components/src/components.ts
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,18 @@ export * from './components/hds/dropdown/list-item/types.ts';
export * from './components/hds/dropdown/toggle/types.ts';
export * from './components/hds/dropdown/types.ts';

// FilterBar
export { default as HdsFilterBar } from './components/hds/filter-bar/index.ts';
export { default as HdsFilterBarCheckbox } from './components/hds/filter-bar/checkbox.ts';
export { default as HdsFilterBarFiltersDropdown } from './components/hds/filter-bar/filters-dropdown.ts';
export { default as HdsFilterBarFilterGroup } from './components/hds/filter-bar/filter-group.ts';
export { default as HdsFilterBarRadio } from './components/hds/filter-bar/radio.ts';
export { default as HdsFilterBarRange } from './components/hds/filter-bar/range.ts';
export { default as HdsFilterBarTabs } from './components/hds/filter-bar/tabs/index.ts';
export { default as HdsFilterBarTabsPanel } from './components/hds/filter-bar/tabs/panel.ts';
export { default as HdsFilterBarTabsTab } from './components/hds/filter-bar/tabs/tab.ts';
export * from './components/hds/filter-bar/types.ts';

// Flyout
export { default as HdsFlyout } from './components/hds/flyout/index.ts';
export * from './components/hds/flyout/types.ts';
Expand Down
154 changes: 93 additions & 61 deletions packages/components/src/components/hds/advanced-table/index.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@
SPDX-License-Identifier: MPL-2.0
}}

{{#if (has-block "actions")}}
<div class="hds-advanced-table__actions">
{{yield (hash FilterBar=(component "hds/filter-bar")) to="actions"}}
</div>
{{/if}}
<div
class="hds-advanced-table__container
{{(if this.isStickyHeaderPinned 'hds-advanced-table__container--header-is-pinned')}}"
Expand Down Expand Up @@ -107,79 +112,81 @@
</div>

{{! Body }}
<div class="hds-advanced-table__tbody" role="rowgroup">
{{! ----------------------------------------------------------------------------------------
{{#unless this.isEmpty}}
<div class="hds-advanced-table__tbody" role="rowgroup">
{{! ----------------------------------------------------------------------------------------
IMPORTANT: we loop on the `model` array and for each record
we yield the Tr/Td/Th elements _and_ the record itself as `data`
this means the consumer will *have to* use the `data` key to access it in their template
-------------------------------------------------------------------------------------------- }}
{{#each this._tableModel.sortedRows key=this.identityKey as |record index|}}
{{#if this._tableModel.hasRowsWithChildren}}
<Hds::AdvancedTable::ExpandableTrGroup
@record={{record}}
@rowIndex={{index}}
@onClickToggle={{record.onClickToggle}}
as |T|
>
{{#each this._tableModel.sortedRows key=this.identityKey as |record index|}}
{{#if this._tableModel.hasRowsWithChildren}}
<Hds::AdvancedTable::ExpandableTrGroup
@record={{record}}
@rowIndex={{index}}
@onClickToggle={{record.onClickToggle}}
as |T|
>
{{yield
(hash
Tr=(component
"hds/advanced-table/tr"
isLastRow=(eq this._tableModel.lastVisibleRow.id T.data.id)
isParentRow=T.isExpandable
depth=T.depth
displayRow=T.shouldDisplayChildRows
data=T.data
)
Th=(component
"hds/advanced-table/th"
depth=T.depth
isExpandable=T.isExpandable
isExpanded=T.isExpanded
newLabel=T.id
parentId=T.parentId
scope="row"
onClickToggle=T.onClickToggle
)
Td=(component "hds/advanced-table/td" align=@align)
data=T.data
isOpen=T.isExpanded
rowIndex=T.rowIndex
)
to="body"
}}
</Hds::AdvancedTable::ExpandableTrGroup>
{{else}}
{{yield
(hash
Tr=(component
"hds/advanced-table/tr"
isLastRow=(eq this._tableModel.lastVisibleRow.id T.data.id)
isParentRow=T.isExpandable
depth=T.depth
displayRow=T.shouldDisplayChildRows
data=T.data
selectionScope="row"
isLastRow=(eq this._tableModel.lastVisibleRow.id record.id)
isSelectable=this.isSelectable
onSelectionChange=this.onSelectionRowChange
didInsert=this.didInsertRowCheckbox
willDestroy=this.willDestroyRowCheckbox
selectionAriaLabelSuffix=@selectionAriaLabelSuffix
hasStickyColumn=this.hasStickyFirstColumn
isStickyColumnPinned=this.isStickyColumnPinned
data=record
)
Th=(component
"hds/advanced-table/th"
depth=T.depth
isExpandable=T.isExpandable
isExpanded=T.isExpanded
newLabel=T.id
parentId=T.parentId
scope="row"
onClickToggle=T.onClickToggle
isStickyColumn=this.hasStickyFirstColumn
isStickyColumnPinned=this.isStickyColumnPinned
)
Td=(component "hds/advanced-table/td" align=@align)
data=T.data
isOpen=T.isExpanded
rowIndex=T.rowIndex
data=record
rowIndex=index
)
to="body"
}}
</Hds::AdvancedTable::ExpandableTrGroup>
{{else}}
{{yield
(hash
Tr=(component
"hds/advanced-table/tr"
selectionScope="row"
isLastRow=(eq this._tableModel.lastVisibleRow.id record.id)
isSelectable=this.isSelectable
onSelectionChange=this.onSelectionRowChange
didInsert=this.didInsertRowCheckbox
willDestroy=this.willDestroyRowCheckbox
selectionAriaLabelSuffix=@selectionAriaLabelSuffix
hasStickyColumn=this.hasStickyFirstColumn
isStickyColumnPinned=this.isStickyColumnPinned
data=record
)
Th=(component
"hds/advanced-table/th"
scope="row"
isStickyColumn=this.hasStickyFirstColumn
isStickyColumnPinned=this.isStickyColumnPinned
)
Td=(component "hds/advanced-table/td" align=@align)
data=record
rowIndex=index
)
to="body"
}}
{{/if}}
{{/each}}
</div>
{{/if}}
{{/each}}
</div>
{{/unless}}
</div>

{{#if this.showScrollIndicatorLeft}}
Expand All @@ -196,10 +203,35 @@
/>
{{/if}}

{{#if this.showScrollIndicatorBottom}}
<div
class="hds-advanced-table__scroll-indicator hds-advanced-table__scroll-indicator-bottom"
{{style bottom=this.scrollIndicatorDimensions.bottom width=this.scrollIndicatorDimensions.width}}
/>
{{#unless this.isEmpty}}
{{#if this.showScrollIndicatorBottom}}
<div
class="hds-advanced-table__scroll-indicator hds-advanced-table__scroll-indicator-bottom"
{{style bottom=this.scrollIndicatorDimensions.bottom width=this.scrollIndicatorDimensions.width}}
/>
{{/if}}
{{/unless}}

{{#if this.isEmpty}}
<div class="hds-advanced-table__empty-state">
<div class="hds-advanced-table__empty-state__content">
{{#if (has-block "emptyState")}}
{{yield to="emptyState"}}
{{else}}
<Hds::Layout::Flex @direction="column" @gap="8">
<Hds::Text::Display @tag="h3" @size="300">{{hds-t
"hds.components.advanced-table.empty-state.title"
default="No data available"
}}</Hds::Text::Display>
<Hds::Text::Body>
{{hds-t
"hds.components.advanced-table.empty-state.description"
default="There is currently no data to display in the table."
}}
</Hds::Text::Body>
</Hds::Layout::Flex>
{{/if}}
</div>
</div>
{{/if}}
</div>
17 changes: 17 additions & 0 deletions packages/components/src/components/hds/advanced-table/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import HdsAdvancedTableTableModel from './models/table.ts';

import type Owner from '@ember/owner';
import type { WithBoundArgs } from '@glint/template';
import type { ComponentLike } from '@glint/template';
import {
HdsAdvancedTableDensityValues,
HdsAdvancedTableVerticalAlignmentValues,
Expand All @@ -30,6 +31,7 @@ import type {
HdsAdvancedTableExpandState,
HdsAdvancedTableColumnReorderCallback,
} from './types.ts';
import type { HdsFilterBarSignature } from '../filter-bar/index.ts';
import type HdsAdvancedTableColumnType from './models/column.ts';
import type { HdsFormCheckboxBaseSignature } from '../form/checkbox/base.ts';
import type HdsAdvancedTableTd from './td.ts';
Expand Down Expand Up @@ -149,6 +151,7 @@ export interface HdsAdvancedTableSignature {
hasStickyFirstColumn?: boolean;
childrenKey?: string;
maxHeight?: string;
isEmpty?: boolean;
onColumnReorder?: HdsAdvancedTableColumnReorderCallback;
onColumnResize?: (columnKey: string, newWidth?: string) => void;
onSelectionChange?: (
Expand All @@ -157,6 +160,11 @@ export interface HdsAdvancedTableSignature {
onSort?: (sortBy: string, sortOrder: HdsAdvancedTableThSortOrder) => void;
};
Blocks: {
actions?: [
{
FilterBar?: ComponentLike<HdsFilterBarSignature>;
},
];
body?: [
{
Td?: WithBoundArgs<typeof HdsAdvancedTableTd, 'align'>;
Expand Down Expand Up @@ -192,6 +200,7 @@ export interface HdsAdvancedTableSignature {
isOpen?: HdsAdvancedTableExpandState;
},
];
emptyState?: [];
};
Element: HTMLDivElement;
}
Expand Down Expand Up @@ -259,6 +268,14 @@ export default class HdsAdvancedTable extends Component<HdsAdvancedTableSignatur
}
}

get isEmpty(): boolean {
const { isEmpty } = this.args;
if (isEmpty !== undefined) {
return isEmpty;
}
return false;
}

get identityKey(): string | undefined {
// we have to provide a way for the consumer to pass undefined because Ember tries to interpret undefined as missing an arg and therefore falls back to the default
if (this.args.identityKey === 'none') {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{{!
Copyright (c) HashiCorp, Inc.
SPDX-License-Identifier: MPL-2.0
}}
<li class="hds-filter-bar__filters-dropdown__filter-option">
<Hds::Form::Checkbox::Field checked={{this.isChecked}} @value={{@value}} {{on "change" this.onChange}} as |F|>
<F.Label>{{yield}}</F.Label>
</Hds::Form::Checkbox::Field>
</li>
39 changes: 39 additions & 0 deletions packages/components/src/components/hds/filter-bar/checkbox.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/**
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: MPL-2.0
*/

import Component from '@glimmer/component';
import { action } from '@ember/object';

import type { HdsFilterBarData } from './types.ts';

export interface HdsFilterBarCheckboxSignature {
Args: {
value?: string;
keyFilter: HdsFilterBarData | undefined;
onChange?: (event: Event) => void;
};
Blocks: {
default: [];
};
Element: HTMLDivElement;
}

export default class HdsFilterBarCheckbox extends Component<HdsFilterBarCheckboxSignature> {
@action
onChange(event: Event): void {
const { onChange } = this.args;
if (onChange && typeof onChange === 'function') {
onChange(event);
}
}

get isChecked(): boolean {
const { keyFilter, value } = this.args;
if (Array.isArray(keyFilter)) {
return keyFilter.some((filter) => filter.value === value);
}
return false;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
{{!
Copyright (c) HashiCorp, Inc.
SPDX-License-Identifier: MPL-2.0
}}
{{#let @tab as |Tab|}}
<Tab>
{{@text}}
{{#unless (eq this.numFilters 0)}}
<Hds::BadgeCount
@text={{this.numFilters}}
@type="outlined"
@size="small"
class="hds-filter-bar__filters-dropdown__filter-group__filters-count"
/>
{{/unless}}
</Tab>
{{/let}}
{{#let @panel as |Panel|}}
<Panel {{this._setUpFilterPanel}}>
{{#if @searchEnabled}}
<div class="hds-filter-bar__filters-dropdown__filter-group__search">
<Hds::Form::TextInput::Base
@type="search"
placeholder={{hds-t "components.filter-bar.filter-group.search-input-placeholder" default="Search"}}
{{on "input" this.onSearch}}
/>
</div>
{{/if}}
{{#if (eq @type "range")}}
<Hds::FilterBar::Range @keyFilter={{this.keyFilter}} @onChange={{this.onRangeChange}} />
{{else}}
<ul class="hds-filter-bar__filters-dropdown__filter-group__list">
{{yield
(hash
Checkbox=(component "hds/filter-bar/checkbox" keyFilter=this.keyFilter onChange=this.onSelectionChange)
Radio=(component "hds/filter-bar/radio" keyFilter=this.keyFilter onChange=this.onSelectionChange)
)
}}
</ul>
{{/if}}
</Panel>
{{/let}}
Loading
Loading