diff --git a/demo/js/components/ComponentExample/component-overrides.scss b/demo/js/components/ComponentExample/component-overrides.scss
index e64aace7ff20..6d7b3e8bc026 100644
--- a/demo/js/components/ComponentExample/component-overrides.scss
+++ b/demo/js/components/ComponentExample/component-overrides.scss
@@ -65,6 +65,7 @@
.button .bx--btn {
margin-bottom: 0.5rem;
+ vertical-align: top;
}
.data-table > div {
diff --git a/src/components/button/_button.scss b/src/components/button/_button.scss
index bba4473d9cd3..85652ce3a338 100644
--- a/src/components/button/_button.scss
+++ b/src/components/button/_button.scss
@@ -292,6 +292,19 @@
}
}
+ .#{$prefix}--btn--icon-only,
+ .#{$prefix}--btn--sm.#{$prefix}--btn--icon-only {
+ padding-right: rem(15px);
+
+ .#{$prefix}--btn__icon {
+ position: static;
+ }
+
+ &.#{$prefix}--btn--ghost .#{$prefix}--btn__icon {
+ margin: 0;
+ }
+ }
+
.#{$prefix}--btn--danger {
@include button-theme--x($support-01, $support-01, $text-04, $hover-danger, $icon-03, $active-danger);
diff --git a/src/components/button/button.hbs b/src/components/button/button.hbs
index 0977d8c583fa..6f205d96e4ed 100644
--- a/src/components/button/button.hbs
+++ b/src/components/button/button.hbs
@@ -36,4 +36,16 @@
A variety of content types can live here. Be sure to follow Carbon design guidelines for spacing and alignment.
- `, - section: true, - select: { - id: `${prefix}--checkbox-13`, - name: 'checkbox-13', - value: 'green', - label: 'Label name', - }, - name: 'Load Balancer 1', - protocol: 'HTTP', - port: '80', - rule: 'Round Robin', - attachedGroups: "Maureen's VM Groups", - status: 'Active', - }, - { - sectionContent: - /* eslint-disable max-len */ - `A variety of content types can live here. Be sure to follow Carbon design guidelines for spacing and alignment.
- `, - select: { - id: `${prefix}--checkbox-12`, - name: 'checkbox-12', - value: 'green', - label: 'Label name', - }, - section: true, - name: 'Load Balancer 1', - protocol: 'HTTP', - port: '80', - rule: 'Round Robin', - attachedGroups: "Maureen's VM Groups", - status: 'Active', - }, -]; - module.exports = { - label: 'Data Table V2', - context: { - prefix, - componentsX, - }, - variants: [ - { - name: 'default', - label: 'Data Table V2', - notes: ` - Data Tables are used to represent a collection of resources, displaying a - subset of their fields in columns, or headers. - `, - context: { - state: 'default', - title: 'Table title', - optionalHelper: 'Optional Helper Text', - batchActions, - toolbarActions, - toolbarActionsX, - columns, - rows, - selectedItemsCounterLabel: ` - 3 items selected - `, - searchInputId: 'search__input-2', - searchLabelId: 'search-input-label-1', - searchLabel: 'Search', - clearSearchLabel: 'Clear search input', - addNewLabel: 'Add new', - cancelLabel: 'Cancel', - sortLabel: 'Sort rows by this header in descending order', - hasToolbar: true, - sort: true, - }, - }, - { - name: 'zebra-select', - label: 'Zebra Select', - notes: ` - Data Tables are used to represent a collection of resources, displaying a - subset of their fields in columns, or headers. - `, - context: { - state: 'default', - title: 'Table title', - optionalHelper: 'Optional Helper Text', - batchActions, - toolbarActions, - toolbarActionsX, - columns, - rows, - selectedItemsCounterLabel: ` - 3 items selected - `, - searchInputId: 'search__input-2', - searchLabelId: 'search-input-label-1', - searchLabel: 'Search', - clearSearchLabel: 'Clear search input', - addNewLabel: 'Add new', - cancelLabel: 'Cancel', - sortLabel: 'Sort rows by this header in descending order', - hasToolbar: true, - sort: true, - zebra: true, - }, - }, - { - name: 'zebra', - label: 'Zebra', - context: { - small: true, - columns: columnsSmall, - rows, - zebra: true, - }, - }, - { - name: 'expandable', - label: 'Expandable', - context: { - state: 'persistent-search', - title: 'Table title', - columns: columnsExpandable, - rows: rowsExpandable, - searchInputId: 'search__input-2', - searchLabelId: 'search-input-label-1', - searchLabel: 'Search', - clearSearchLabel: 'Clear search input', - hasToolbar: true, - sort: true, - batchActions, - toolbarActions, - toolbarActionsX, - selectedItemsCounterLabel: ` - 3 items selected - `, - addNewLabel: 'Add new', - cancelLabel: 'Cancel', - sortLabel: 'Sort rows by this header in descending order', - }, - }, - { - name: 'small', - label: 'Small', - context: { - small: true, - columns: columnsSmall, - rows, - }, - }, - { - name: 'with-pager', - label: 'Pagination', - context: { - state: 'persistent-search', - hasPager: true, - title: 'Table title', - batchActions, - toolbarActions, - toolbarActionsX, - columns, - rows, - selectedItemsCounterLabel: ` - 3 items selected - `, - searchInputId: 'search__input-2', - searchLabelId: 'search-input-label-1', - searchLabel: 'Search', - clearSearchLabel: 'Clear search input', - addNewLabel: 'Add new', - cancelLabel: 'Cancel', - sortLabel: 'Sort rows by this header in descending order', - hasToolbar: true, - sort: true, - }, - }, - ], + hidden: true, }; diff --git a/src/components/data-table-v2/data-table-v2.js b/src/components/data-table-v2/data-table-v2.js index b5e1cf2599c7..1aa7776ec91c 100644 --- a/src/components/data-table-v2/data-table-v2.js +++ b/src/components/data-table-v2/data-table-v2.js @@ -5,373 +5,6 @@ * LICENSE file in the root directory of this source tree. */ -import { componentsX } from '../../globals/js/feature-flags'; -import settings from '../../globals/js/settings'; -import mixin from '../../globals/js/misc/mixin'; -import createComponent from '../../globals/js/mixins/create-component'; -import initComponentBySearch from '../../globals/js/mixins/init-component-by-search'; -import eventedState from '../../globals/js/mixins/evented-state'; -import eventMatches from '../../globals/js/misc/event-matches'; - -const toArray = arrayLike => Array.prototype.slice.call(arrayLike); -const suffix = componentsX ? '' : '-v2'; - -class DataTableV2 extends mixin(createComponent, initComponentBySearch, eventedState) { - /** - * Data Table - * @extends CreateComponent - * @extends InitComponentBySearch - * @extends EventedState - * @param {HTMLElement} element The root element of tables - * @param {Object} [options] the... options - * @param {string} [options.selectorInit] selector initialization - * @param {string} [options.selectorExpandCells] css selector for expand - * @param {string} [options.expandableRow] css selector for expand - * @param {string} [options.selectorParentRows] css selector for rows housing expansion - * @param {string} [options.selectorTableBody] root css for table body - * @param {string} [options.eventTrigger] selector for event bubble capture points - * @param {string} [options.eventParentContainer] used find the bubble container - */ - constructor(element, options) { - super(element, options); - - this.container = element.parentNode; - this.toolbarEl = this.element.querySelector(this.options.selectorToolbar); - this.batchActionEl = this.element.querySelector(this.options.selectorActions); - this.countEl = this.element.querySelector(this.options.selectorCount); - this.cancelEl = this.element.querySelector(this.options.selectorActionCancel); - this.tableHeaders = this.element.querySelectorAll('th'); - this.tableBody = this.element.querySelector(this.options.selectorTableBody); - this.expandCells = []; - this.expandableRows = []; - this.parentRows = []; - - this.refreshRows(); - - this.element.addEventListener('mouseover', evt => { - const eventElement = eventMatches(evt, this.options.selectorChildRow); - - if (eventElement) { - this._expandableHoverToggle(eventElement, true); - } - }); - - this.element.addEventListener('click', evt => { - const eventElement = eventMatches(evt, this.options.eventTrigger); - const searchContainer = this.element.querySelector(this.options.selectorToolbarSearchContainer); - - if (eventElement) { - this._toggleState(eventElement, evt); - } - - if (componentsX && searchContainer) { - this._handleDocumentClick(evt); - } - }); - - this.element.addEventListener('keydown', this._keydownHandler); - - this.state = { - checkboxCount: 0, - }; - } - - _handleDocumentClick(evt) { - const searchContainer = this.element.querySelector(this.options.selectorToolbarSearchContainer); - const searchEvent = eventMatches(evt, this.options.selectorSearchMagnifier); - const activeSearch = searchContainer.classList.contains(this.options.classToolbarSearchActive); - - if (searchContainer && searchEvent) { - this.activateSearch(searchContainer); - } - - if (activeSearch) { - this.deactivateSearch(searchContainer, evt); - } - } - - activateSearch(container) { - const input = container.querySelector(this.options.selectorSearchInput); - container.classList.add(this.options.classToolbarSearchActive); - input.focus(); - } - - deactivateSearch(container, evt) { - const trigger = container.querySelector(this.options.selectorSearchMagnifier); - const input = container.querySelector(this.options.selectorSearchInput); - const svg = trigger.querySelector('svg'); - if (input.value.length === 0 && evt.target !== input && evt.target !== trigger && evt.target !== svg) { - container.classList.remove(this.options.classToolbarSearchActive); - trigger.focus(); - } - - if (evt.which === 27 && evt.target === input) { - container.classList.remove(this.options.classToolbarSearchActive); - trigger.focus(); - } - } - - _sortToggle = detail => { - const { element, previousValue } = detail; - - toArray(this.tableHeaders).forEach(header => { - const sortEl = header.querySelector(this.options.selectorTableSort); - - if (sortEl !== null && sortEl !== element) { - sortEl.classList.remove(this.options.classTableSortActive); - sortEl.classList.remove(this.options.classTableSortAscending); - } - }); - - if (!previousValue) { - element.dataset.previousValue = 'ascending'; - element.classList.add(this.options.classTableSortActive); - element.classList.add(this.options.classTableSortAscending); - } else if (previousValue === 'ascending') { - element.dataset.previousValue = 'descending'; - element.classList.add(this.options.classTableSortActive); - element.classList.remove(this.options.classTableSortAscending); - } else if (previousValue === 'descending') { - element.removeAttribute('data-previous-value'); - element.classList.remove(this.options.classTableSortActive); - element.classList.remove(this.options.classTableSortAscending); - } - }; - - _selectToggle = detail => { - const { element } = detail; - const { checked } = element; - - // increment the count - this.state.checkboxCount += checked ? 1 : -1; - this.countEl.textContent = this.state.checkboxCount; - - const row = element.parentNode.parentNode; - - row.classList.toggle(this.options.classTableSelected); - - // toggle on/off batch action bar - this._actionBarToggle(this.state.checkboxCount > 0); - }; - - _selectAllToggle = ({ element }) => { - const { checked } = element; - - const inputs = toArray(this.element.querySelectorAll(this.options.selectorCheckbox)); - - this.state.checkboxCount = checked ? inputs.length - 1 : 0; - - inputs.forEach(item => { - item.checked = checked; - - const row = item.parentNode.parentNode; - if (checked && row) { - row.classList.add(this.options.classTableSelected); - } else { - row.classList.remove(this.options.classTableSelected); - } - }); - - this._actionBarToggle(this.state.checkboxCount > 0); - - if (this.batchActionEl) { - this.countEl.textContent = this.state.checkboxCount; - } - }; - - _actionBarCancel = () => { - const inputs = toArray(this.element.querySelectorAll(this.options.selectorCheckbox)); - const row = toArray(this.element.querySelectorAll(this.options.selectorTableSelected)); - - row.forEach(item => { - item.classList.remove(this.options.classTableSelected); - }); - - inputs.forEach(item => { - item.checked = false; - }); - - this.state.checkboxCount = 0; - this._actionBarToggle(false); - - if (this.batchActionEl) { - this.countEl.textContent = this.state.checkboxCount; - } - }; - - _actionBarToggle = toggleOn => { - const transition = evt => { - this.batchActionEl.removeEventListener('transitionend', transition); - - if (evt.target.matches(this.options.selectorActions)) { - if (this.batchActionEl.dataset.active === 'false') { - this.batchActionEl.setAttribute('tabIndex', -1); - } else { - this.batchActionEl.setAttribute('tabIndex', 0); - } - } - }; - - if (toggleOn) { - this.batchActionEl.dataset.active = true; - this.batchActionEl.classList.add(this.options.classActionBarActive); - } else if (this.batchActionEl) { - this.batchActionEl.dataset.active = false; - this.batchActionEl.classList.remove(this.options.classActionBarActive); - } - if (this.batchActionEl) { - this.batchActionEl.addEventListener('transitionend', transition); - } - }; - - _expandableRowsInit = expandableRows => { - expandableRows.forEach(item => { - if (!componentsX) { - item.classList.remove(this.options.classExpandableRowHidden); - this.tableBody.removeChild(item); - } - }); - }; - - _rowExpandToggle = ({ element, initialEvt }) => { - const parent = eventMatches(initialEvt, this.options.eventParentContainer); - - const index = this.expandCells.indexOf(element); - if (element.dataset.previousValue === undefined || element.dataset.previousValue === 'expanded') { - element.dataset.previousValue = 'collapsed'; - parent.classList.add(this.options.classExpandableRow); - if (!componentsX) { - this.tableBody.insertBefore(this.expandableRows[index], this.parentRows[index + 1]); - } - } else { - parent.classList.remove(this.options.classExpandableRow); - if (!componentsX) { - this.tableBody.removeChild(parent.nextElementSibling); - } - element.dataset.previousValue = 'expanded'; - } - }; - - _expandableHoverToggle = element => { - element.previousElementSibling.classList.add(this.options.classExpandableRowHover); - - const mouseout = () => { - element.previousElementSibling.classList.remove(this.options.classExpandableRowHover); - element.removeEventListener('mouseout', mouseout); - }; - - element.addEventListener('mouseout', mouseout); - }; - - _toggleState = (element, evt) => { - const data = element.dataset; - const label = data.label ? data.label : ''; - const previousValue = data.previousValue ? data.previousValue : ''; - const initialEvt = evt; - - this.changeState({ - group: data.event, - element, - label, - previousValue, - initialEvt, - }); - }; - - _keydownHandler = evt => { - const searchContainer = this.element.querySelector(this.options.selectorToolbarSearchContainer); - const searchEvent = eventMatches(evt, this.options.selectorSearchMagnifier); - const activeSearch = searchContainer.classList.contains(this.options.classToolbarSearchActive); - - if (evt.which === 27) { - this._actionBarCancel(); - } - - if (searchContainer && searchEvent && evt.which === 13) { - this.activateSearch(searchContainer); - } - - if (activeSearch && evt.which === 27) { - this.deactivateSearch(searchContainer, evt); - } - }; - - _changeState(detail, callback) { - this[this.constructor.eventHandlers[detail.group]](detail); - callback(); - } - - refreshRows = () => { - const newExpandCells = toArray(this.element.querySelectorAll(this.options.selectorExpandCells)); - const newExpandableRows = toArray(this.element.querySelectorAll(this.options.selectorExpandableRows)); - const newParentRows = toArray(this.element.querySelectorAll(this.options.selectorParentRows)); - - // check if this is a refresh or the first time - if (this.parentRows.length > 0) { - const diffParentRows = newParentRows.filter(newRow => !this.parentRows.some(oldRow => oldRow === newRow)); - - // check if there are expandable rows - if (newExpandableRows.length > 0) { - const diffExpandableRows = diffParentRows.map(newRow => newRow.nextElementSibling); - const mergedExpandableRows = [...toArray(this.expandableRows), ...toArray(diffExpandableRows)]; - this._expandableRowsInit(diffExpandableRows); - this.expandableRows = mergedExpandableRows; - } - } else if (newExpandableRows.length > 0) { - this._expandableRowsInit(newExpandableRows); - this.expandableRows = newExpandableRows; - } - - this.expandCells = newExpandCells; - this.parentRows = newParentRows; - }; - - static components /* #__PURE_CLASS_PROPERTY__ */ = new WeakMap(); - - // UI Events - static eventHandlers /* #__PURE_CLASS_PROPERTY__ */ = { - expand: '_rowExpandToggle', - sort: '_sortToggle', - select: '_selectToggle', - 'select-all': '_selectAllToggle', - 'action-bar-cancel': '_actionBarCancel', - }; - - static get options() { - const { prefix } = settings; - return { - selectorInit: `[data-table${suffix}]`, - selectorToolbar: `.${prefix}--table--toolbar`, - selectorActions: `.${prefix}--batch-actions`, - selectorCount: '[data-items-selected]', - selectorActionCancel: `.${prefix}--batch-summary__cancel`, - selectorCheckbox: `.${prefix}--checkbox`, - selectorExpandCells: `td.${prefix}--table-expand${suffix}`, - selectorExpandableRows: `.${prefix}--expandable-row${suffix}`, - selectorParentRows: `.${prefix}--parent-row${suffix}`, - selectorChildRow: '[data-child-row]', - selectorTableBody: 'tbody', - selectorTableSort: `.${prefix}--table-sort${suffix}`, - selectorTableSelected: `.${prefix}--data-table${suffix}--selected`, - selectorToolbarSearchContainer: `.${prefix}--toolbar-search-container-expandable`, - selectorSearchMagnifier: `.${prefix}--search-magnifier`, - selectorSearchInput: `.${prefix}--search-input`, - classExpandableRow: `${prefix}--expandable-row${suffix}`, - classExpandableRowHidden: `${prefix}--expandable-row--hidden${suffix}`, - classExpandableRowHover: `${prefix}--expandable-row--hover${suffix}`, - classTableSortAscending: `${prefix}--table-sort${suffix}--ascending`, - classTableSortActive: `${prefix}--table-sort${suffix}--active`, - classToolbarSearchActive: `${prefix}--toolbar-search-container-active`, - classActionBarActive: `${prefix}--batch-actions--active`, - classTableSelected: `${prefix}--data-table${suffix}--selected`, - eventBeforeExpand: `data-table${suffix}-beforetoggleexpand`, - eventAfterExpand: `data-table${suffix}-aftertoggleexpand`, - eventBeforeSort: `data-table${suffix}-beforetogglesort`, - eventAfterSort: `data-table${suffix}-aftertogglesort`, - eventTrigger: '[data-event]', - eventParentContainer: '[data-parent-row]', - }; - } -} +import DataTableV2 from '../data-table/data-table'; export default DataTableV2; diff --git a/src/components/data-table-v2/ARCHITECTURE.md b/src/components/data-table/ARCHITECTURE.md similarity index 100% rename from src/components/data-table-v2/ARCHITECTURE.md rename to src/components/data-table/ARCHITECTURE.md diff --git a/src/components/data-table-v2/README.md b/src/components/data-table/README.md similarity index 88% rename from src/components/data-table-v2/README.md rename to src/components/data-table/README.md index ac83b7937527..dac6ddb023d1 100644 --- a/src/components/data-table-v2/README.md +++ b/src/components/data-table/README.md @@ -4,13 +4,13 @@ The update to tables splits out the `scss` files into multiple partial files wit #### Files -| Name | Description | -| -------------------------- | ---------------------------------------- | -| `data-table` | index file, brings in all functionality | -| `data-table-v2-core` | Core styles and base modifiers, required | -| `data-table-v2-action` | Action bar styles | -| `data-table-v2-expandable` | Expandable row styles | -| `data-table-v2-sort` | Sortable header styles | +| Name | Description | +| ----------------------- | ---------------------------------------- | +| `data-table` | index file, brings in all functionality | +| `data-table-core` | Core styles and base modifiers, required | +| `data-table-action` | Action bar styles | +| `data-table-expandable` | Expandable row styles | +| `data-table-sort` | Sortable header styles | #### Modifiers @@ -30,20 +30,20 @@ The update to tables splits out the `scss` files into multiple partial files wit ##### ES2015 ```javascript -import { DataTableV2 } from 'carbon-components'; +import { DataTable } from 'carbon-components'; ``` ##### With pre-build bundle (`carbon-components.min.js`) ```javascript -var DataTableV2 = CarbonComponents.DataTableV2; +var DataTable = CarbonComponents.DataTable; ``` #### Instantiating ```javascript // `#my-data-table` is an element with `[data-data-table]` attribute -DataTableV2.create(document.getElementById('my-data-table')); +DataTable.create(document.getElementById('my-data-table')); ``` #### Public Methods @@ -57,8 +57,8 @@ DataTableV2.create(document.getElementById('my-data-table')); ```javascript // `#my-data-table` is an element with `[data-data-table]` attribute -var dataTableV2Instance = DataTableV2.create(document.getElementById('my-data-table')); -dataTableV2Instance.refreshRows(); +var dataTableInstance = DataTable.create(document.getElementById('my-data-table')); +dataTableInstance.refreshRows(); ``` #### Events diff --git a/src/components/data-table/_data-table-action.scss b/src/components/data-table/_data-table-action.scss new file mode 100644 index 000000000000..775a7a0647b3 --- /dev/null +++ b/src/components/data-table/_data-table-action.scss @@ -0,0 +1,540 @@ +// +// Copyright IBM Corp. 2016, 2018 +// +// This source code is licensed under the Apache-2.0 license found in the +// LICENSE file in the root directory of this source tree. +// + +@import '../../globals/scss/helper-mixins'; +@import '../../globals/scss/vendor/@carbon/elements/scss/import-once/import-once'; +@import '../../globals/scss/vars'; + +@mixin data-table-v2-action { + .#{$prefix}--table-toolbar { + display: flex; + padding-top: $spacing-xs; + padding-bottom: $spacing-xs; + width: 100%; + position: relative; + + .#{$prefix}--search-input { + position: relative; + + &:focus { + box-shadow: inset 0px 0px 0px 1px $brand-01; + outline: 0; + } + } + } + + .#{$prefix}--toolbar-content { + display: flex; + margin-left: auto; + } + + .#{$prefix}--toolbar-action { + @include button-reset; + cursor: pointer; + padding-left: $spacing-sm; + padding-right: $spacing-sm; + + &:hover { + > .#{$prefix}--toolbar-action__icon { + fill: $hover-secondary; + } + } + + &:focus { + @include focus-outline; + > .#{$prefix}--toolbar-action__icon { + fill: $hover-secondary; + } + } + + &:active { + > .#{$prefix}--toolbar-action__icon { + fill: $hover-secondary; + } + } + + &:last-of-type { + padding-right: 0; + } + + ~ .#{$prefix}--btn { + margin-left: $spacing-sm; + margin-right: $spacing-sm; + } + } + + .#{$prefix}--toolbar-action__icon { + height: rem(16px); + width: auto; + max-width: 16px; + fill: $ui-05; + transition: $transition--base; + } + + .#{$prefix}--batch-actions { + display: flex; + align-items: center; + position: absolute; + opacity: 0; + left: 0; + top: 0; + padding-left: $spacing-lg; + padding-right: $spacing-lg; + width: 100%; + height: 100%; + z-index: z('header'); + background-color: transparent; + transition: opacity 200ms $carbon--standard-easing, background-color 200ms $carbon--standard-easing; + pointer-events: none; + visibility: hidden; + + &:focus { + @include focus-outline; + } + + .#{$prefix}--btn { + color: $ui-01; + } + + .#{$prefix}--btn__icon { + fill: $ui-01; + } + + .#{$prefix}--btn--ghost { + &:hover, + &:focus { + background-color: $ui-01; + color: $brand-01; + + .#{$prefix}--btn__icon { + fill: $brand-01; + } + } + + &:focus { + border: 2px solid $brand-01; + outline: 2px solid $ui-02; + } + } + } + + .#{$prefix}--batch-actions--active { + visibility: visible; + background-color: $brand-01; + pointer-events: all; + transition: opacity 200ms cubic-bezier(0.5, 0, 0.1, 1), background-color 200ms cubic-bezier(0.5, 0, 0.1, 1); + opacity: 1; + } + + .#{$prefix}--action-list { + margin-left: -0.5rem; + } + + .#{$prefix}--action-icons { + margin-left: auto; + svg { + padding: 0 $spacing-sm; + fill: $ui-01; + height: rem(16px); + width: auto; + } + } + + .#{$prefix}--batch-summary { + margin-left: auto; + display: flex; + align-items: center; + color: $ui-01; + } + + .#{$prefix}--batch-summary__para { + @include typescale('zeta'); + margin-right: $spacing-lg; + } + + .#{$prefix}--batch-summary__cancel { + @include button-reset(auto); + @include typescale('zeta'); + color: $ui-01; + border-bottom: 1px solid transparent; + font-weight: 600; + cursor: pointer; + transition: border $transition--base $carbon--standard-easing; + + &:hover, + &:focus { + border-bottom: 1px solid $ui-01; + } + } + + .#{$prefix}--batch-actions ~ .#{$prefix}--toolbar-search-container, + .#{$prefix}--batch-actions ~ .#{$prefix}--toolbar-content { + opacity: 1; + transition: opacity $transition--base; + } + + .#{$prefix}--batch-actions--active ~ .#{$prefix}--toolbar-search-container, + .#{$prefix}--batch-actions--active ~ .#{$prefix}--toolbar-content { + opacity: 0; + } +} + +@mixin data-table-v2-action--x { + //------------------------------------------------- + //TOOLBAR + //------------------------------------------------- + .#{$prefix}--table-toolbar { + display: flex; + width: 100%; + background: $ui-01; + height: $layout-04; + position: relative; //need for batch actions + } + + .#{$prefix}--toolbar-content { + display: flex; + height: $layout-04; + width: 100%; + justify-content: flex-end; + } + + //------------------------------------------------- + //HIDDEN SEARCH - DEFAULT TOOLBAR + //------------------------------------------------- + .#{$prefix}--toolbar-search-container-expandable { + height: $layout-04; + width: $layout-04; + position: relative; + transition: flex $transition--expansion $carbon--standard-easing; + box-shadow: none; + } + + .#{$prefix}--toolbar-search-container-expandable .#{$prefix}--search { + width: $layout-04; + height: 100%; + } + + .#{$prefix}--toolbar-search-container-expandable .#{$prefix}--search .#{$prefix}--search-magnifier { + height: $layout-04; + width: $layout-04; + padding: $spacing-md; + left: 0; + } + + .#{$prefix}--toolbar-search-container-expandable .#{$prefix}--search .#{$prefix}--search-magnifier:focus { + @include focus-outline('outline'); + } + + .#{$prefix}--toolbar-search-container-expandable .#{$prefix}--search .#{$prefix}--search-magnifier:hover { + background: $hover-field; + } + + .#{$prefix}--toolbar-search-container-expandable .#{$prefix}--search .#{$prefix}--search-input { + border: none; + height: 100%; + visibility: hidden; + padding: 0; + background-color: transparent; + } + + .#{$prefix}--toolbar-search-container-expandable .#{$prefix}--search .#{$prefix}--search-close { + height: $layout-04; + width: $layout-04; + } + + //------------------------------------------------- + //ACTIVE SEARCH - DEFAULT TOOLBAR + //------------------------------------------------- + .#{$prefix}--toolbar-search-container-active { + flex: auto; + transition: flex $transition--expansion $carbon--standard-easing; + } + + .#{$prefix}--toolbar-search-container-active .#{$prefix}--search { + width: 100%; + } + + .#{$prefix}--toolbar-search-container-active .#{$prefix}--search .#{$prefix}--search-input { + padding-left: $spacing-3xl; + visibility: visible; + } + + .#{$prefix}--toolbar-search-container-active .#{$prefix}--search .#{$prefix}--search-input:focus { + @include focus-outline('outline'); + } + + .#{$prefix}--toolbar-search-container-active .#{$prefix}--search .#{$prefix}--search-input:focus + .#{$prefix}--search-close { + border: none; + box-shadow: none; + outline: none; + } + + .#{$prefix}--toolbar-search-container-active .#{$prefix}--search .#{$prefix}--search-input:not(:placeholder-shown) { + background: $hover-field; + border: none; + } + + .#{$prefix}--toolbar-search-container-active .#{$prefix}--search .#{$prefix}--search-magnifier:focus, + .#{$prefix}--toolbar-search-container-active .#{$prefix}--search .#{$prefix}--search-magnifier:active, + .#{$prefix}--toolbar-search-container-active .#{$prefix}--search .#{$prefix}--search-magnifier:hover { + outline: none; + border: none; + background: transparent; + } + + //------------------------------------------------- + //SEARCH CLOSE BUTTON + //------------------------------------------------- + .#{$prefix}--toolbar-search-container-persistent .#{$prefix}--search-close, + .#{$prefix}--toolbar-search-container-persistent .#{$prefix}--search-close:hover, + .#{$prefix}--toolbar-search-container-active .#{$prefix}--search .#{$prefix}--search-close, + .#{$prefix}--toolbar-search-container-active .#{$prefix}--search .#{$prefix}--search-close:hover { + border: none; //to-do: is there a spec for close button on hover? + background-color: transparent; + } + + //------------------------------------------------- + //TOOLBAR BUTTONS + //------------------------------------------------- + .#{$prefix}--overflow-menu.#{$prefix}--toolbar-action { + @include button-reset; + display: flex; + cursor: pointer; + height: $layout-04; + width: $layout-04; + padding: $spacing-md; + } + + .#{$prefix}--toolbar-action:hover:not([disabled]) { + background: $hover-field; + } + + .#{$prefix}--toolbar-action:hover[aria-expanded='true'] { + background: $ui-01; + } + + .#{$prefix}--toolbar-action[disabled] { + cursor: not-allowed; + } + + .#{$prefix}--toolbar-action[disabled] .#{$prefix}--toolbar-action__icon { + fill: $disabled; + cursor: not-allowed; + } + + .#{$prefix}--toolbar-action:focus:not([disabled]), + .#{$prefix}--toolbar-action:active:not([disabled]) { + @include focus-outline('outline'); + } + + .#{$prefix}--toolbar-action ~ .#{$prefix}--btn { + margin: 0; + height: $layout-04; + } + + .#{$prefix}--overflow-menu--data-table { + height: $layout-04; + } + + //------------------------------------------------- + //TOOLBAR BUTTON ICONS + //------------------------------------------------- + .#{$prefix}--toolbar-action__icon { + height: $layout-01; + width: auto; + max-width: $layout-01; + fill: $ui-05; + transition: $transition--base; + } + + //------------------------------------------------- + //PERSISTENT SEARCH - OPTIONAL TOOLBAR + //------------------------------------------------- + .#{$prefix}--toolbar-search-container-persistent { + width: 100%; + height: $layout-04; + opacity: 1; + position: relative; + transition: opacity $transition--base; + } + + .#{$prefix}--toolbar-search-container-persistent + .#{$prefix}--toolbar-content { + position: relative; + width: auto; + } + + .#{$prefix}--toolbar-search-container-persistent .#{$prefix}--search { + position: initial; + } + + .#{$prefix}--toolbar-search-container-persistent .#{$prefix}--search .#{$prefix}--search-magnifier { + left: $spacing-md; + } + + .#{$prefix}--toolbar-search-container-persistent .#{$prefix}--search .#{$prefix}--search-input { + height: $layout-04; + padding-left: $spacing-3xl; + border: none; + } + + .#{$prefix}--toolbar-search-container-persistent .#{$prefix}--search .#{$prefix}--search-input:focus:not([disabled]) { + @include focus-outline('outline'); + } + + .#{$prefix}--toolbar-search-container-persistent .#{$prefix}--search .#{$prefix}--search-input:hover:not([disabled]) { + background: $hover-field; + } + + .#{$prefix}--toolbar-search-container-persistent .#{$prefix}--search .#{$prefix}--search-input:active:not([disabled]), + .#{$prefix}--toolbar-search-container-persistent .#{$prefix}--search .#{$prefix}--search-input:not(:placeholder-shown) { + background: $hover-field; + } + + .#{$prefix}--toolbar-search-container-persistent .#{$prefix}--search .#{$prefix}--search-close { + height: $layout-04; + width: $layout-04; + } + + .#{$prefix}--batch-actions--active ~ .#{$prefix}--toolbar-search-container, + .#{$prefix}--batch-actions--active ~ .#{$prefix}--toolbar-content { + opacity: 0; + } + + //------------------------------------------------- + //BATCH ACTIONS + //------------------------------------------------- + .#{$prefix}--batch-actions { + display: flex; + position: absolute; + top: 0; + left: 0; + align-items: center; + opacity: 0; + padding-left: $spacing-lg; + padding-right: $spacing-lg; + width: 100%; + height: 100%; + z-index: z('header'); + background-color: transparent; + transition: opacity $transition--base $carbon--standard-easing, background-color $transition--base $carbon--standard-easing; + pointer-events: none; + visibility: hidden; + } + + .#{$prefix}--batch-actions:focus { + @include focus-outline; + } + + .#{$prefix}--batch-actions--active { + visibility: visible; + background-color: $brand-01; + pointer-events: all; + transition: opacity $transition--base $carbon--standard-easing, background-color $transition--base $carbon--standard-easing; + opacity: 1; + } + + //btns container + .#{$prefix}--action-list { + position: absolute; + right: 0; + display: flex; + } + + .#{$prefix}--action-list .#{$prefix}--btn { + color: $ui-01; + } + + .#{$prefix}--action-list .#{$prefix}--btn .#{$prefix}--btn__icon { + fill: $ui-01; + margin-left: $spacing-03; + } + + .#{$prefix}--action-list .#{$prefix}--btn .#{$prefix}--btn__icon .st0 { + fill: none; + } + + .#{$prefix}--batch-download { + padding: rem(1px); //makes it smaller to match other icons + } + + //override btn styles + .#{$prefix}--action-list .#{$prefix}--btn--primary:focus::before, + .#{$prefix}--action-list .#{$prefix}--btn--primary:focus::before, + .#{$prefix}--action-list .#{$prefix}--btn--primary::before, + .#{$prefix}--action-list .#{$prefix}--btn--primary::before, + .#{$prefix}--action-list .#{$prefix}--btn--primary:focus::after, + .#{$prefix}--action-list .#{$prefix}--btn--primary:focus::after, + .#{$prefix}--action-list .#{$prefix}--btn--primary::after, + .#{$prefix}--action-list .#{$prefix}--btn--primary::after { + display: none; + } + + .#{$prefix}--action-list .#{$prefix}--btn--primary:focus { + outline: 2px solid $ui-01; + outline-offset: rem(-2px); + } + + .#{$prefix}--action-list .#{$prefix}--btn { + min-width: 0; + } + + // cancel btn pseudo element + .#{$prefix}--action-list + .#{$prefix}--btn--primary:nth-child(3):hover + + .#{$prefix}--btn--primary.#{$prefix}--batch-summary__cancel::before, + .#{$prefix}--action-list + .#{$prefix}--btn--primary:nth-child(3):focus + + .#{$prefix}--btn--primary.#{$prefix}--batch-summary__cancel::before { + opacity: 0; + } + + .#{$prefix}--btn--primary.#{$prefix}--batch-summary__cancel::before { + display: block; + position: absolute; + opacity: 1; + top: rem(15px); //visually 16px spacing is 1px too low + left: 0; + height: $layout-01; + width: rem(1px); + content: ''; + background-color: $ui-01; + border: none; + } + + .#{$prefix}--btn--primary.#{$prefix}--batch-summary__cancel:hover::before { + opacity: 0; + transition: opacity $transition--base $carbon--standard-easing; + } + + // cancel btn + .#{$prefix}--batch-summary__cancel { + padding-right: $spacing-05; + position: relative; + } + + // items selected text + .#{$prefix}--batch-summary { + position: absolute; + left: 0; + margin-left: $spacing-05; + display: flex; + align-items: center; + color: $ui-01; + } + + .#{$prefix}--batch-summary__para { + @include type-style('body-short-01'); + } +} + +@include exports('data-table-v2-action') { + @if feature-flag-enabled('components-x') { + @include data-table-v2-action--x; + } @else { + @include data-table-v2-action; + } +} diff --git a/src/components/data-table/_data-table-core.scss b/src/components/data-table/_data-table-core.scss new file mode 100644 index 000000000000..84f0b68f54ba --- /dev/null +++ b/src/components/data-table/_data-table-core.scss @@ -0,0 +1,424 @@ +// +// Copyright IBM Corp. 2016, 2018 +// +// This source code is licensed under the Apache-2.0 license found in the +// LICENSE file in the root directory of this source tree. +// + +@import '../../globals/scss/css--typography'; +@import '../../globals/scss/functions'; +@import '../../globals/scss/vendor/@carbon/elements/scss/import-once/import-once'; +@import '../../globals/scss/vars'; +@import '../../globals/scss/helper-mixins'; + +@mixin data-table-v2-core { + .#{$prefix}--data-table-v2-container { + width: 100%; + min-width: rem(500px); + overflow-x: auto; + padding-top: $spacing-3xs; // allow space for focus styles + } + + .#{$prefix}--data-table-v2 { + border-collapse: collapse; + border-spacing: 0; + width: 100%; + border-bottom: 1px solid $ui-03; + + @if feature-flag-enabled('breaking-changes-x') { + min-width: rem(500px); + } + + thead { + @include typescale('zeta'); + background-color: $ui-02; + font-weight: 700; + border-right: 1px solid $ui-03; + } + + tbody { + @include typescale('zeta'); + background-color: $ui-01; + border-right: 1px solid $ui-03; + } + + tr { + height: rem(48px); + + &:hover { + td { + background-color: rgba($brand-02, 0.1); + border-top: 1px solid $brand-01; + border-bottom: 1px solid $brand-01; + + &:first-of-type { + border-left: 1px solid $brand-01; + } + + &:last-of-type { + border-right: 1px solid $brand-01; + } + } + + .#{$prefix}--overflow-menu { + opacity: 1; + } + } + } + + th { + border-top: 1px solid $ui-03; + } + + th, + td { + @include typescale('zeta'); + border-top: 1px solid $ui-03; + padding-left: $spacing-sm; + vertical-align: middle; + text-align: left; + color: $text-01; + + &:first-of-type { + padding-left: rem(24px); + border-left: 1px solid $ui-03; + } + + &:last-of-type { + padding-right: $spacing-lg; + } + } + + // Overrrides + .#{$prefix}--checkbox-label { + padding-left: rem(28px); + } + + .#{$prefix}--overflow-menu { + opacity: 0; + + &:focus { + outline: 0; + opacity: 1; + box-shadow: none; + + .#{$prefix}--overflow-menu__icon { + box-shadow: inset 0px 0px 0px 1px $brand-01; + } + } + } + + .#{$prefix}--overflow-menu__icon { + transform: rotate(90deg); + } + } + + // Options + + .#{$prefix}--data-table-v2-header { + margin-bottom: $spacing-xs; + color: $text-01; + } + + .#{$prefix}--data-table-v2--zebra { + tbody tr:nth-child(even) { + background-color: $ui-02; + } + } + + .#{$prefix}--data-table-v2--no-border { + & { + border-bottom-color: transparent; + } + + thead, + tbody { + border-right-color: transparent; + } + + th, + td { + &:first-of-type { + border-left-color: transparent; + } + } + } + + .#{$prefix}--data-table-v2--compact { + tbody tr { + height: rem(24px); + } + } + + .#{$prefix}--data-table-v2--short { + tbody tr { + height: rem(32px); + } + } + + .#{$prefix}--data-table-v2--tall { + tbody tr { + height: rem(64px); + } + } + + .#{$prefix}--data-table-v2--static { + width: auto; + } + + .#{$prefix}--data-table-v2--zebra tbody tr.#{$prefix}--data-table-v2--selected, + tbody tr.#{$prefix}--data-table-v2--selected { + background-color: rgba($brand-02, 0.1); + } +} + +@mixin data-table-core--x { + //---------------------------------------------------------------------------- + // Container + //---------------------------------------------------------------------------- + .#{$prefix}--data-table-container { + min-width: rem(500px); + overflow-x: auto; + padding-top: $spacing-01; // allow space for focus styles + } + + //---------------------------------------------------------------------------- + // Table title text + //---------------------------------------------------------------------------- + .#{$prefix}--data-table-header { + background: $ui-01; + padding: $spacing-05 0 $spacing-06 $spacing-05; + } + + .#{$prefix}--data-table-header__title { + @include type-style('productive-heading-03'); + color: $text-01; + } + + .#{$prefix}--data-table-header__description { + @include type-style('body-short-01'); + color: $text-02; + } + + //---------------------------------------------------------------------------- + // Data table + //---------------------------------------------------------------------------- + .#{$prefix}--data-table { + border-collapse: collapse; + border-spacing: 0; + width: 100%; + } + + .#{$prefix}--data-table thead { + @include type-style('heading-01'); + background-color: $ui-03; + } + + .#{$prefix}--data-table tbody { + @include type-style('body-short-01'); + background-color: $ui-01; + width: 100%; + } + + .#{$prefix}--data-table tr { + border: none; + height: $layout-04; + width: 100%; + } + + .#{$prefix}--data-table tbody tr:hover { + background: $hover-field; + } + + .#{$prefix}--data-table tbody tr:hover td { + color: $text-01; + background: $hover-field; + border-bottom: 1px solid $hover-field; + border-top: 1px solid $hover-field; + } + + .#{$prefix}--data-table th, + .#{$prefix}--data-table td { + padding-left: $spacing-04; + padding-right: $spacing-04; + vertical-align: top; + text-align: left; + } + + .#{$prefix}--data-table th { + color: $text-01; + background-color: $ui-03; + border-top: 1px solid $ui-03; + border-bottom: 1px solid $ui-03; + } + + .#{$prefix}--data-table th:first-of-type { + padding-left: $spacing-05; + } + + .#{$prefix}--data-table .#{$prefix}--table-header-label { + display: block; + padding: rem(14px) 0; + } + + .#{$prefix}--data-table td { + background: $ui-01; + color: $text-02; + border-top: 1px solid $ui-01; + border-bottom: 1px solid $ui-03; + padding: rem(14px) $spacing-04; + padding-bottom: rem(13px); + } + + @supports (-moz-appearance: none) { + .#{$prefix}--data-table td { + background-clip: padding-box; // fix to show borders in ff + } + } + + .#{$prefix}--data-table td:first-of-type { + padding-left: $spacing-05; + } + + .#{$prefix}--data-table td:last-of-type { + padding-right: $spacing-05; + } + + // specific padding for overflow menu columns + .#{$prefix}--data-table .#{$prefix}--table-column-menu, + .#{$prefix}--data-table .#{$prefix}--table-column-menu:last-of-type { + padding-top: $spacing-03; + padding-right: $spacing-03; + } + + .#{$prefix}--data-table td.#{$prefix}--table-column-menu { + padding-bottom: 0; + } + + .#{$prefix}--data-table td.#{$prefix}--table-column-menu .#{$prefix}--overflow-menu[aria-expanded='false']:hover { + background: $ui-03; + } + + // Overflow Menu Overrides + .#{$prefix}--data-table td.#{$prefix}--table-column-menu .#{$prefix}--overflow-menu[aria-expanded='false']:focus { + @include focus-outline('outline'); + } + + .#{$prefix}--data-table td.#{$prefix}--table-column-menu .#{$prefix}--overflow-menu[aria-expanded='true']:focus { + outline: none; + } + + .#{$prefix}--data-table td.#{$prefix}--table-column-menu .#{$prefix}--overflow-menu .#{$prefix}--overflow-menu__icon { + opacity: 0; + } + + .#{$prefix}--data-table td.#{$prefix}--table-column-menu .#{$prefix}--overflow-menu:hover .#{$prefix}--overflow-menu__icon, + .#{$prefix}--data-table td.#{$prefix}--table-column-menu .#{$prefix}--overflow-menu:focus .#{$prefix}--overflow-menu__icon, + .#{$prefix}--data-table tr:hover td.#{$prefix}--table-column-menu .#{$prefix}--overflow-menu .#{$prefix}--overflow-menu__icon { + opacity: 1; + } + + .#{$prefix}--table-row--menu-option + .#{$prefix}--overflow-menu-options__btn + .#{$prefix}--overflow-menu-options__option-content + svg { + margin-right: $spacing-03; + position: relative; + top: rem(3px); //used to center svg without setting display flex //display block needed for overflow text truncation + } + + //---------------------------------------------------------------------------- + //ZEBRA + //---------------------------------------------------------------------------- + + .#{$prefix}--data-table--zebra tbody tr:nth-child(even) td { + border-bottom: 1px solid $ui-01; + } + + .#{$prefix}--data-table--zebra tbody tr:nth-child(odd) td { + background-color: $data-table-zebra-color; + border-bottom: 1px solid $data-table-zebra-color; + border-top: 1px solid $data-table-zebra-color; + } + + .#{$prefix}--data-table--zebra tbody tr:hover td { + background-color: $hover-field; + border-bottom: 1px solid $hover-field; + border-top: 1px solid $hover-field; + } + + //---------------------------------------------------------------------------- + // Select + //---------------------------------------------------------------------------- + .#{$prefix}--table-column-checkbox .#{$prefix}--checkbox-label { + padding-left: $spacing-05; + } + + .#{$prefix}--data-table th.#{$prefix}--table-column-checkbox { + padding: rem(12px) $spacing-03 0 $spacing-05; + width: rem(44px); // 16px padding left + 8px padding right + 20px checkbox width + } + + .#{$prefix}--data-table td.#{$prefix}--table-column-checkbox { + padding-top: rem(11px); + padding-bottom: 0; + } + + th.#{$prefix}--table-column-checkbox:hover { + background: $data-table-column-hover; + } + + // default selected row + zebra select - even child + .#{$prefix}--data-table--zebra tbody tr:nth-child(odd).#{$prefix}--data-table--selected td, + tr.#{$prefix}--data-table--selected td { + color: $text-01; + background-color: $ui-03; + border-top: 1px solid $ui-03; + border-bottom: 1px solid $active-01; //bottom border acts as separator from other rows + } + + // first row + .#{$prefix}--data-table--zebra tbody tr:first-of-type:nth-child(odd).#{$prefix}--data-table--selected td, + tr.#{$prefix}--data-table--selected:first-of-type td { + border-top: 1px solid $active-01; //top border acts as separator from thead + } + + // last row + zebra select last + .#{$prefix}--data-table--zebra tbody tr:last-of-type:nth-child(odd).#{$prefix}--data-table--selected td, + .#{$prefix}--data-table--zebra tbody tr:last-of-type:nth-child(even).#{$prefix}--data-table--selected td, + tr.#{$prefix}--data-table--selected:last-of-type td { + border-top: 1px solid $ui-03; // doesn't need separators + border-bottom: 1px solid $ui-03; + } + + // zebra select - odd child + .#{$prefix}--data-table--zebra tbody tr:nth-child(even).#{$prefix}--data-table--selected td { + border-bottom: 1px solid $active-01; + } + + .#{$prefix}--data-table--zebra tbody tr:nth-child(even).#{$prefix}--data-table--selected:hover td { + border-bottom: 1px solid $data-table-column-hover; + } + + // hover + zebra select - even child + .#{$prefix}--data-table--zebra tbody tr:nth-child(odd).#{$prefix}--data-table--selected:hover td, + .#{$prefix}--data-table tbody .#{$prefix}--data-table--selected:hover td { + color: $text-01; + background: $data-table-column-hover; + border-top: 1px solid $data-table-column-hover; + border-bottom: 1px solid $data-table-column-hover; + } + + // selected overflow menu + .#{$prefix}--data-table--selected .#{$prefix}--overflow-menu .#{$prefix}--overflow-menu__icon { + opacity: 1; + } +} + +@include exports('data-table-v2-core') { + @if feature-flag-enabled('components-x') { + @include data-table-core--x; + } @else { + @include data-table-v2-core; + } +} diff --git a/src/components/data-table/_data-table-expandable.scss b/src/components/data-table/_data-table-expandable.scss new file mode 100644 index 000000000000..44118c4f1ec9 --- /dev/null +++ b/src/components/data-table/_data-table-expandable.scss @@ -0,0 +1,372 @@ +// +// Copyright IBM Corp. 2016, 2018 +// +// This source code is licensed under the Apache-2.0 license found in the +// LICENSE file in the root directory of this source tree. +// + +@import '../../globals/scss/helper-mixins'; +@import '../../globals/scss/vendor/@carbon/elements/scss/import-once/import-once'; +@import '../../globals/scss/vars'; + +@mixin data-table-v2-expandable { + tr.#{$prefix}--expandable-row-v2 { + // hide on init + &.#{$prefix}--expandable-row--hidden-v2 { + display: none; + } + + > td:first-of-type { + position: relative; + + &:before { + content: ''; + position: absolute; + top: 0; + left: 0; + height: 100%; + width: 2px; + background-color: $brand-01; + } + } + + + tr[data-child-row] { + td { + border-top: 0; + padding-bottom: $spacing-xs; + } + } + + &:hover { + > td { + background-color: $hover-row; + } + + > td:first-of-type { + border-left: 1px solid transparent; + } + + > td:last-of-type { + border-right: 1px solid $brand-01; + } + + &[data-parent-row] > td { + border-bottom: 0; + } + + + tr[data-child-row] { + > td { + background-color: $hover-row; + border-bottom: 1px solid $brand-01; + border-right: 1px solid $brand-01; + } + } + } + } + + tr.#{$prefix}--expandable-row--hover-v2 { + > td { + background-color: $hover-row; + border-top: 1px solid $brand-01; + } + + > td:last-of-type { + border-right: 1px solid $brand-01; + } + } + + .#{$prefix}--table-expand-v2 { + width: 2.5rem; + } + + .#{$prefix}--table-expand-v2[data-previous-value='collapsed'] .#{$prefix}--table-expand-v2__svg { + transform: rotate(90deg); + transition: transform 200ms $carbon--standard-easing; + } + + .#{$prefix}--table-expand-v2__button { + @include button-reset(false); + + &:focus { + outline: 1px solid transparent; + + svg { + box-shadow: inset 0px 0px 0px 1px $brand-01; + } + } + } + + .#{$prefix}--table-expand-v2__svg { + fill: $ui-05; + transform: rotate(0deg); + transition: transform 200ms $carbon--standard-easing; + height: 16px; + width: auto; + max-width: 16px; + padding: $spacing-3xs; + } +} + +@mixin data-table-expandable--x { + //---------------------------------------------------------------------------- + // Parent row + //---------------------------------------------------------------------------- + //first row top border + .#{$prefix}--data-table tr.#{$prefix}--parent-row:first-of-type td { + border-top: 1px solid $ui-03; + } + + //---------------------------------------------------------------------------- + // Child row + //---------------------------------------------------------------------------- + // default styles + .#{$prefix}--expandable-row--hidden td { + border-top: 0; + width: auto; + padding: $spacing-05; + } + + //child row hidden + tr.#{$prefix}--parent-row:not(.#{$prefix}--expandable-row) + tr[data-child-row] { + height: 0; + transition: height $transition--expansion $carbon--standard-easing; + } + + tr.#{$prefix}--parent-row:not(.#{$prefix}--expandable-row) + tr[data-child-row] td { + padding-top: 0; + padding-bottom: 0; + border: 0; + background-color: $hover-field; + transition: padding $transition--expansion $carbon--standard-easing, + background-color $transition--expansion $carbon--standard-easing; + } + + tr.#{$prefix}--parent-row:not(.#{$prefix}--expandable-row) + tr[data-child-row] td .#{$prefix}--child-row-inner-container { + overflow: hidden; + max-height: 0; + } + + //child row visible + tr.#{$prefix}--parent-row.#{$prefix}--expandable-row + tr[data-child-row] { + transition: height $transition--expansion $carbon--standard-easing; + } + + tr.#{$prefix}--parent-row.#{$prefix}--expandable-row + tr[data-child-row] td { + padding-bottom: rem(23px); + transition: padding $transition--expansion $carbon--standard-easing; + } + + tr.#{$prefix}--parent-row.#{$prefix}--expandable-row + tr[data-child-row] td .#{$prefix}--child-row-inner-container { + max-height: 100%; + } + + // bottom border overrides + .#{$prefix}--parent-row.#{$prefix}--expandable-row > td, + .#{$prefix}--parent-row.#{$prefix}--expandable-row + tr[data-child-row] > td { + border-bottom: 1px solid transparent; + box-shadow: 0 1px $ui-03; + } + + .#{$prefix}--parent-row:not(.#{$prefix}--expandable-row) + tr[data-child-row] > td { + box-shadow: none; + } + + .#{$prefix}--parent-row.#{$prefix}--expandable-row > td:first-of-type { + box-shadow: none; // first td doesn't have a visible border + } + + //---------------------------------------------------------------------------- + // Hover styles + //---------------------------------------------------------------------------- + //hovering on collapsed parent + tr.#{$prefix}--parent-row:not(.#{$prefix}--expandable-row):first-of-type:hover td { + border-top: 1px solid $hover-field; + border-bottom: 1px solid $hover-field; + } + + // hovering on expanded parent + tr.#{$prefix}--parent-row.#{$prefix}--expandable-row:hover td { + background-color: $hover-field; + border-top: 1px solid $hover-field; + border-bottom: 1px solid $ui-03; + color: $text-01; + } + + tr.#{$prefix}--parent-row.#{$prefix}--expandable-row:hover td:first-of-type { + border-bottom: 1px solid $hover-field; // first td doesn't have a visible border + } + + // child row when hovering on expanded parent + tr.#{$prefix}--parent-row.#{$prefix}--expandable-row:hover + tr[data-child-row] td { + background-color: $hover-field; + color: $text-01; + border-bottom: 1px solid $ui-03; + } + + //hovering on expanded child row + tr.#{$prefix}--expandable-row--hover + tr[data-child-row] td { + border-bottom: 1px solid $ui-03; + } + + //hovering on expanded child row (class added to parent) + tr.#{$prefix}--expandable-row--hover { + background-color: $hover-field; + } + + tr.#{$prefix}--expandable-row--hover td { + background-color: $hover-field; + border-bottom: 1px solid $ui-03; + border-top: 1px solid $hover-field; + color: $text-01; + } + + tr.#{$prefix}--parent-row.#{$prefix}--expandable-row.#{$prefix}--expandable-row--hover td:first-of-type { + border-bottom: 1px solid $hover-field; // first parent td doesnt have visible bottom border + } + + //---------------------------------------------------------------------------- + // Expand icon column + //---------------------------------------------------------------------------- + .#{$prefix}--data-table td.#{$prefix}--table-expand { + width: 2.5rem; + min-width: 2.5rem; + vertical-align: top; + padding-top: rem(7px); + padding-bottom: 0; + } + + @supports (-moz-appearance: none) { + .#{$prefix}--data-table td.#{$prefix}--table-expand { + padding-top: rem(14px); + } + } + + .#{$prefix}--table-expand[data-previous-value='collapsed'] .#{$prefix}--table-expand__svg { + transform: rotate(270deg); + transition: transform $transition--expansion $carbon--standard-easing; + } + + .#{$prefix}--table-expand__button { + @include button-reset('false'); + display: flex; + justify-content: space-around; + height: $layout-03; + width: $layout-01; + } + + .#{$prefix}--table-expand__button:focus { + outline: 1px solid transparent; + } + + .#{$prefix}--table-expand__button:focus .#{$prefix}--table-expand__svg { + box-shadow: inset 0px 0px 0px 1px $focus; + } + + .#{$prefix}--table-expand__svg { + fill: $ui-05; + transform: rotate(90deg); + transition: transform $transition--expansion $carbon--standard-easing; + } + + th.#{$prefix}--table-expand + th.#{$prefix}--table-column-checkbox { + padding-left: $spacing-03; + } + + // fix expanded parent separating border length + tr.#{$prefix}--parent-row.#{$prefix}--expandable-row td.#{$prefix}--table-expand + td::after { + position: absolute; + content: ''; + left: 0; + bottom: rem(-1px); + height: rem(1px); + width: rem(8px); + background: $ui-01; + } + + tr.#{$prefix}--parent-row.#{$prefix}--expandable-row:hover td.#{$prefix}--table-expand + td::after, + tr.#{$prefix}--parent-row.#{$prefix}--expandable-row.#{$prefix}--expandable-row--hover td.#{$prefix}--table-expand + td::after { + background: $hover-field; + } + + tr.#{$prefix}--parent-row.#{$prefix}--data-table--selected td.#{$prefix}--table-expand + td::after { + display: none; + } + + //---------------------------------------------------------------------------- + // Selected + //---------------------------------------------------------------------------- + // parent collapsed + tr.#{$prefix}--parent-row.#{$prefix}--data-table--selected:first-of-type td { + background: $ui-03; + border-top: 1px solid $active-01; + border-bottom: 1px solid transparent; + box-shadow: 0 1px $active-01; + } + + tr.#{$prefix}--parent-row.#{$prefix}--data-table--selected td { + background: $ui-03; + color: $text-01; + border-bottom: 1px solid transparent; + box-shadow: 0 1px $active-01; + } + + tr.#{$prefix}--parent-row.#{$prefix}--data-table--selected:last-of-type td { + background: $ui-03; + border-bottom: 1px solid transparent; + box-shadow: 0 1px $ui-03; + } + + // parent collapsed hover + tr.#{$prefix}--parent-row.#{$prefix}--data-table--selected:not(.#{$prefix}--expandable-row):hover td { + background: $hover-selected-ui; + border-top: 1px solid $hover-selected-ui; + border-bottom: 1px solid transparent; + box-shadow: 0 1px $hover-selected-ui; + } + + // parent expanded + tr.#{$prefix}--parent-row.#{$prefix}--data-table--selected.#{$prefix}--expandable-row td, + tr.#{$prefix}--parent-row.#{$prefix}--data-table--selected.#{$prefix}--expandable-row td:first-of-type { + border-bottom: 1px solid transparent; + box-shadow: 0 1px $ui-03; //no visible border when expanded + } + + // parent expanded hover + tr.#{$prefix}--parent-row.#{$prefix}--data-table--selected.#{$prefix}--expandable-row:hover td, + tr.#{$prefix}--parent-row.#{$prefix}--data-table--selected.#{$prefix}--expandable-row:hover td:first-of-type, + tr.#{$prefix}--parent-row.#{$prefix}--data-table--selected.#{$prefix}--expandable-row--hover td, + tr.#{$prefix}--parent-row.#{$prefix}--data-table--selected.#{$prefix}--expandable-row--hover td:first-of-type { + background: $hover-selected-ui; + border-top: 1px solid $hover-selected-ui; + border-bottom: 1px solid transparent; + box-shadow: 0 1px $hover-selected-ui; + } + + // child row expanded + tr.#{$prefix}--parent-row.#{$prefix}--data-table--selected.#{$prefix}--expandable-row + tr[data-child-row] td { + color: $text-01; + background-color: $hover-field; + border-bottom: 1px solid transparent; + box-shadow: 0 1px $active-01; + border-top: 1px solid $active-ui; + } + + tr.#{$prefix}--parent-row.#{$prefix}--data-table--selected.#{$prefix}--expandable-row + tr[data-child-row]:last-of-type td { + box-shadow: inset 0 -1px $active-01; + padding-bottom: rem(24px); + } + + // child row expanded hover + tr.#{$prefix}--parent-row.#{$prefix}--data-table--selected.#{$prefix}--expandable-row:hover + tr[data-child-row] td, + tr.#{$prefix}--parent-row.#{$prefix}--data-table--selected.#{$prefix}--expandable-row--hover + tr[data-child-row] td { + background: $ui-03; + } +} + +@include exports('data-table-v2-expandable') { + @if feature-flag-enabled('components-x') { + @include data-table-expandable--x; + } @else { + @include data-table-v2-expandable; + } +} diff --git a/src/components/data-table/_data-table-inline-edit-cell.scss b/src/components/data-table/_data-table-inline-edit-cell.scss new file mode 100644 index 000000000000..af357ba40042 --- /dev/null +++ b/src/components/data-table/_data-table-inline-edit-cell.scss @@ -0,0 +1,363 @@ +// +// Copyright IBM Corp. 2016, 2018 +// +// This source code is licensed under the Apache-2.0 license found in the +// LICENSE file in the root directory of this source tree. +// + +@import '../../globals/scss/helper-mixins'; +@import '../../globals/scss/vendor/@carbon/elements/scss/import-once/import-once'; +@import '../../globals/scss/layer'; +@import '../../globals/scss/layout'; +@import '../../globals/scss/vars'; + +@mixin assistive-text { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; + visibility: visible; + white-space: nowrap; +} + +@include exports('data-table-v2-inline-edit-cell') { + // Spacing for cells that are the first in their row + $spacing--columns--first: 1.5rem; + // Spacing before columns in cell + $spacing--columns--before: 0.75rem; + // Spacing for activity areas in a cell, namely status and actions + $spacing--cell--activity: 3.5rem; + // Offset used on input nodes to offer space to activity indicators such that + // the input doesn't overlap with the status + $spacing--cell--status: 2rem; + + //---------------------------------------------------------------------------- + // Table + //---------------------------------------------------------------------------- + + // Reset hover styles while editing + .#{$prefix}--data-table--editing tr:hover td { + background-color: inherit; + border-top: 1px solid $ui-04; + border-bottom: 1px solid $ui-04; + } + + .#{$prefix}--data-table--editing tr:hover td:first-of-type { + border-left: 1px solid $ui-04; + } + + .#{$prefix}--data-table--editing tr:hover td:last-of-type { + border-right: 1px solid $ui-04; + } + + //---------------------------------------------------------------------------- + // Cell Edit + //---------------------------------------------------------------------------- + + // Buffer is created on the right-hand side so that status indicators have the + // appropriate space to display. + .#{$prefix}--data-table-cell--editable { + position: relative; + padding-right: $spacing--cell--activity; + } + + td.#{$prefix}--data-table-cell--editable:last-of-type { + // Reset the styles inherited from data-table-v2 for padding-right styles + // but adding our manual offset plus the spacing used before columns to get + // a similar look for when an editable cell is in the middle of a table. + padding-right: #{$spacing--cell--activity + $spacing--columns--before}; + } + + // Minor offset for the last cell in a row so that the action bar does not + // touch the edge of the cell + td.#{$prefix}--data-table-cell--editable:last-of-type > .#{$prefix}--data-table-cell__activity { + margin-right: $spacing--columns--before; + } + + //---------------------------------------------------------------------------- + // Cell Edit - Content + //---------------------------------------------------------------------------- + .#{$prefix}--data-table-cell__content { + position: relative; + z-index: 1000; + // Set line-height to match that within inputs + line-height: normal; + } + + //---------------------------------------------------------------------------- + // Cell Edit - Activity + //---------------------------------------------------------------------------- + + // Styles used for getting 100% width and height on an descendant of a table + // cell. Display is used for alignment of most items to the end of the cell + .#{$prefix}--data-table-cell__activity { + display: flex; + justify-content: flex-end; + align-items: center; + position: absolute; + top: 0; + right: 1rem; + bottom: 0; + left: 0; + } + + //---------------------------------------------------------------------------- + // Cell Edit - Trigger + //---------------------------------------------------------------------------- + + .#{$prefix}--data-table-cell__edit { + @include button-reset(false); + opacity: 0; + } + + .#{$prefix}--data-table-cell__edit:focus, + .#{$prefix}--data-table-cell--editable:hover .#{$prefix}--data-table-cell__edit { + opacity: 1; + } + + .#{$prefix}--data-table-cell__icon--edit { + fill: $ui-05; + } + + .#{$prefix}--data-table-cell__edit:active > .#{$prefix}--data-table-cell__icon--edit { + fill: $brand-01; + } + + .#{$prefix}--data-table-cell__edit:focus { + outline: 1px solid $brand-01; + outline-offset: 2px; + } + + //---------------------------------------------------------------------------- + // Cell Edit - Fields // Inputs + //---------------------------------------------------------------------------- + + .#{$prefix}--data-table__edit-field { + display: flex; + justify-content: flex-end; + align-items: center; + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 100; + } + + .#{$prefix}--data-table__edit-field > label.#{$prefix}--label { + @include assistive-text(); + } + + // Spacing resets on inputs + + // All inputs should span as much height and width as possible, but should + // still buffer the right hand side with some padding to allow space for + // status indicators to render without clipping the input content + .#{$prefix}--data-table__edit-field > input { + min-height: 100%; + min-width: 100%; + padding: 0 $spacing--cell--status 0 0; + } + + // Set the default padding on the left-hand side of the input to match what is + // given by the default table class. Visually this makes it look like the + // content is aligned with the other cells in the table. + td.#{$prefix}--data-table-cell--editable input { + padding-left: $spacing--columns--before; + } + + // Substitute the left-hand padding for the padding specified on the first td + // of each row + td.#{$prefix}--data-table-cell--editable:first-of-type input { + padding-left: $spacing--columns--first; + } + + //---------------------------------------------------------------------------- + // Cell Edit - Actions + //---------------------------------------------------------------------------- + + // Spacing that should exist around, and in-between, elements in the action + // bar + $spacing--cell-actions: 0.5rem; + $size--edit-actions--height: 3rem; + + .#{$prefix}--data-table__edit-actions { + @include layer('overlay'); + + display: flex; + justify-content: flex-end; + align-items: center; + position: absolute; + top: $size--edit-actions--height; + right: 0; + bottom: 0; + height: $size--edit-actions--height; + background-color: $inverse-01; + padding: $spacing--cell-actions; + z-index: z('overlay'); + } + + // Undo default margin-left from btn classes + .#{$prefix}--data-table__edit-actions .#{$prefix}--btn--secondary + .#{$prefix}--btn--primary { + margin-left: $spacing--cell-actions; + } + + //---------------------------------------------------------------------------- + // Cell Edit - Status + //---------------------------------------------------------------------------- + + // Containing node + .#{$prefix}--data-table__edit-status { + display: flex; + justify-content: flex-end; + align-items: center; + position: absolute; + top: 0; + // Value should be 0.5rem, but doing so will cause the loading box to clip + // the bounding box of the last cells in a row. This will cause the + // overflow-x scrollbar to behave erratically as it constantly shifts to + // adjust to the new width of the table + right: 1rem; + bottom: 0; + left: 0; + } + + // Status - Saving ----------------------------------------------------------- + + .#{$prefix}--data-table-cell--saving { + cursor: not-allowed; + } + + // Cell should go to 25% opacity when saving + .#{$prefix}--data-table-cell--saving input { + background-color: inherit; + opacity: 0.25; + } + + // Manually center the loading indicator given the offset of its bounding box + .#{$prefix}--data-table-cell--saving .#{$prefix}--loading { + position: relative; + left: rem(7px); + } + + // Status - Success ---------------------------------------------------------- + .#{$prefix}--data-table__icon--success { + fill: $support-02; + } + + // Status - Error ------------------------------------------------------------ + + .#{$prefix}--data-table__status--error { + display: flex; + justify-content: flex-end; + align-items: center; + fill: $support-01; + width: 100%; + height: 100%; + } + + .#{$prefix}--data-table__edit-field--error { + border-bottom: 2px solid $support-01; + } + + .#{$prefix}--data-table__status--error { + position: relative; + } + + .#{$prefix}--data-table__error-text { + @include layer('overlay'); + + position: absolute; + top: rem(-1px); + right: -1rem; + color: $support-01; + // TODO: sync with caption sizes + font-size: rem(12px); + background-color: $inverse-01; + padding: 1rem; + transform: translateY(-100%); + border: 1px solid $ui-03; + z-index: 1000; + box-shadow: 0 -4px 8px rgba(0, 0, 0, 0.1); + opacity: 0; + } + + .#{$prefix}--data-table__error-text::after { + content: ''; + position: absolute; + // Manually offset and center triangle + right: 1rem; + // TODO: shift down half of height + bottom: -7px; + width: rem(10px); + height: rem(10px); + background-color: $inverse-01; + border: 1px solid $ui-03; + border-top: 1px solid transparent; + border-left: 1px solid transparent; + transform: rotate(45deg); + z-index: 10; + opacity: 0; + } + + .#{$prefix}--data-table__icon--error { + z-index: 1000; + } + + .#{$prefix}--data-table__status--error { + // Specify outline on child SVG node instead + outline: none; + } + + .#{$prefix}--data-table__status--error:focus .#{$prefix}--data-table__error-text { + box-shadow: 0 0 0 1px $brand-01; + } + + .#{$prefix}--data-table__status--error:focus .#{$prefix}--data-table__error-text::after { + border-right-color: $brand-01; + border-bottom-color: $brand-01; + } + + // Visually show the error message + + // Display the text area itself on hover + .#{$prefix}--data-table__icon--error:hover + ~ .#{$prefix}--data-table__error-text, + + /* Display text area triangle on hover*/ + .#{$prefix}--data-table__icon--error:hover + ~ .#{$prefix}--data-table__error-text::after, + + /* Display text area on focus*/ + .#{$prefix}--data-table__status--error:focus + > .#{$prefix}--data-table__error-text, + + /* Display text area triangle on focus*/ + .#{$prefix}--data-table__status--error:focus + > .#{$prefix}--data-table__error-text::after, + + /* Display when user is typing in edit field*/ + .#{$prefix}--data-table__edit-field--editing.#{$prefix}--data-table__edit-field--error + + .#{$prefix}--data-table__edit-status .#{$prefix}--data-table__error-text, + + .#{$prefix}--data-table__edit-field--editing.#{$prefix}--data-table__edit-field--error + + .#{$prefix}--data-table__edit-status + .#{$prefix}--data-table__error-text::after { + opacity: 1; + } + + //---------------------------------------------------------------------------- + // Browser Quirks + //---------------------------------------------------------------------------- + + // IE11 - cells are not going full height. Set min-height to compensate + .#{$prefix}--data-table__edit-field, + .#{$prefix}--data-table-cell__activity, + .#{$prefix}--data-table__edit-status { + min-height: 3rem; + } +} diff --git a/src/components/data-table/_data-table-inline-edit.scss b/src/components/data-table/_data-table-inline-edit.scss new file mode 100644 index 000000000000..9037a4ec8c3e --- /dev/null +++ b/src/components/data-table/_data-table-inline-edit.scss @@ -0,0 +1,81 @@ +// +// Copyright IBM Corp. 2016, 2018 +// +// This source code is licensed under the Apache-2.0 license found in the +// LICENSE file in the root directory of this source tree. +// + +@import '../../globals/scss/helper-mixins'; +@import '../../globals/scss/vendor/@carbon/elements/scss/import-once/import-once'; +@import '../../globals/scss/vars'; + +@include exports('data-table-v2-inline-edit') { + /// @access private + $data-table-suffix: if(feature-flag-enabled('components-x'), '-v2', ''); + + .#{$prefix}--inline-edit-label { + display: flex; + justify-content: space-between; + align-items: center; + + &:hover { + .#{$prefix}--inline-edit-label__icon { + opacity: 1; + } + } + } + + .#{$prefix}--inline-edit-label--inactive { + display: none; + } + + .#{$prefix}--inline-edit-label__action { + @include button-reset(false); + + &:hover { + cursor: pointer; + } + + &:focus { + @include focus-outline; + padding: $spacing-3xs; + + .#{$prefix}--inline-edit-label__icon { + width: auto; + opacity: 1; + } + } + } + + .#{$prefix}--inline-edit-label__icon { + fill: $ui-05; + opacity: 0; + } + + .#{$prefix}--inline-edit-input { + display: none; + } + + .#{$prefix}--inline-edit-input--active { + display: block; + margin-left: rem(-12px); + + input { + padding-left: $spacing-sm; + } + } + + .#{$prefix}--data-table#{$data-table-suffix}--short { + input { + height: rem(32px); + } + + select { + padding: 0.45rem 2.75rem 0.45rem $spacing-md; + } + + .#{$prefix}--select__arrow { + top: 0.875rem; + } + } +} diff --git a/src/components/data-table/_data-table-skeleton.scss b/src/components/data-table/_data-table-skeleton.scss new file mode 100644 index 000000000000..34130259e9e9 --- /dev/null +++ b/src/components/data-table/_data-table-skeleton.scss @@ -0,0 +1,57 @@ +// +// Copyright IBM Corp. 2016, 2018 +// +// This source code is licensed under the Apache-2.0 license found in the +// LICENSE file in the root directory of this source tree. +// + +@import '../../globals/scss/helper-mixins'; +@import '../../globals/scss/vendor/@carbon/elements/scss/import-once/import-once'; +@import '../../globals/scss/vars'; + +@include exports('data-table-v2-skeleton') { + /// @access private + $data-table-suffix: if(feature-flag-enabled('components-x'), '-v2', ''); + + .#{$prefix}--data-table#{$data-table-suffix}.#{$prefix}--skeleton { + th { + border-bottom: 1px solid $brand-01; + + &:nth-child(3n + 1) { + width: 10%; + } + + &:nth-child(3n + 2) { + width: 30%; + } + + &:nth-child(3n + 3) { + width: 15%; + } + } + + th span, + td span { + @include skeleton; + width: 75%; + height: 1rem; + display: block; + } + + tr:hover { + td { + border-color: $ui-03; + background: transparent; + + &:first-of-type, + &:last-of-type { + border-color: $ui-03; + } + } + } + } + + .#{$prefix}--data-table-v2.#{$prefix}--skeleton .#{$prefix}--table-sort-v2 { + pointer-events: none; + } +} diff --git a/src/components/data-table/_data-table-sort.scss b/src/components/data-table/_data-table-sort.scss new file mode 100644 index 000000000000..26776d951533 --- /dev/null +++ b/src/components/data-table/_data-table-sort.scss @@ -0,0 +1,178 @@ +// +// Copyright IBM Corp. 2016, 2018 +// +// This source code is licensed under the Apache-2.0 license found in the +// LICENSE file in the root directory of this source tree. +// + +@import '../../globals/scss/helper-mixins'; +@import '../../globals/scss/vendor/@carbon/elements/scss/import-once/import-once'; +@import '../../globals/scss/vars'; + +@mixin data-table-v2-sort { + .#{$prefix}--table-sort-v2--ascending { + .#{$prefix}--table-sort-v2__icon { + transform: rotate(180deg); + transition: transform 200ms $carbon--standard-easing; + } + } + + .#{$prefix}--table-sort-v2--active { + .#{$prefix}--table-sort-v2__icon { + opacity: 1; + } + } + + .#{$prefix}--data-table-v2 th { + &:hover { + .#{$prefix}--table-sort-v2__icon { + opacity: 1; + } + } + } + + .#{$prefix}--table-sort-v2 { + @include button-reset(false); + position: relative; + font: inherit; + cursor: pointer; + display: flex; + align-items: center; + width: 100%; + color: $text-01; + + &:focus { + outline: 0; + + svg { + opacity: 1; + outline: 1px solid $brand-01; + fill: $brand-01; + outline-offset: -0.5px; // safari fix + } + } + } + + .#{$prefix}--table-sort-v2__icon { + position: relative; + left: 2px; + transition: transform 200ms $carbon--standard-easing; + transform: rotate(0); + opacity: 0; + fill: $ui-05; + height: rem(9px); + padding: $spacing-3xs; + width: auto; + min-width: 14px; + } +} + +@mixin data-table-sort--x { + // ------------------------------------- + // Sortable table + // ------------------------------------- + .#{$prefix}--data-table--sort th, + .#{$prefix}--data-table--sort th:first-of-type:not(.#{$prefix}--table-column-checkbox) { + padding: 0; + height: $layout-04; + border-top: none; + border-bottom: none; + } + + .#{$prefix}--data-table--sort td { + padding-left: $spacing-03; + padding-right: $spacing-03; + } + + .#{$prefix}--data-table--sort th:first-of-type .#{$prefix}--table-sort { + padding-left: $spacing-04; + } + + // ------------------------------------- + // Th > Button + // ------------------------------------- + .#{$prefix}--table-sort { + @include button-reset(false); + position: relative; + font: inherit; + display: flex; + align-items: center; + justify-content: space-between; + width: 100%; + color: $text-01; + padding: 0 $spacing-03; + height: 100%; + } + + .#{$prefix}--table-sort:focus { + @include focus-outline('outline'); + } + + .#{$prefix}--table-sort:hover { + background: $data-table-column-hover; + } + + // changes opacity when th is inactive (see line 161) + .#{$prefix}--table-sort:focus svg, + .#{$prefix}--table-sort:hover svg { + opacity: 1; + } + + // ------------------------------------- + //Th > Button > Svg (Sort Icons) + // ------------------------------------- + // inactive icons + .#{$prefix}--table-sort .#{$prefix}--table-sort__icon-inactive { + display: block; + } + + .#{$prefix}--table-sort .#{$prefix}--table-sort__icon { + display: none; + } + + .#{$prefix}--table-sort__icon-unsorted { + position: relative; + left: rem(2px); + margin-left: $spacing-03; + margin-right: 0; + opacity: 0; + fill: $ui-05; + width: auto; + min-width: $layout-01; + } + + // active icons + .#{$prefix}--table-sort.#{$prefix}--table-sort--active .#{$prefix}--table-sort__icon-unsorted { + display: none; + } + + .#{$prefix}--table-sort.#{$prefix}--table-sort--active .#{$prefix}--table-sort__icon { + display: block; + opacity: 1; //changes opacity when th is active (see line 125) + } + + .#{$prefix}--table-sort--ascending .#{$prefix}--table-sort__icon { + transform: rotate(180deg); + } + + .#{$prefix}--table-sort__icon { + position: relative; + left: rem(2px); + margin-left: $spacing-03; + margin-right: 0; + transition: transform $transition--base $carbon--standard-easing; + transform: rotate(0); + opacity: 0; + fill: $ui-05; + width: auto; + min-width: $layout-01; + } +} + +@include exports('data-table-sort') { + @if feature-flag-enabled('components-x') { + @include data-table-sort--x; + } @else { + @include data-table-v2-sort; + } +} diff --git a/src/components/data-table/_data-table.scss b/src/components/data-table/_data-table.scss new file mode 100644 index 000000000000..ccace4de3ab4 --- /dev/null +++ b/src/components/data-table/_data-table.scss @@ -0,0 +1,13 @@ +// +// Copyright IBM Corp. 2016, 2018 +// +// This source code is licensed under the Apache-2.0 license found in the +// LICENSE file in the root directory of this source tree. +// + +@import 'data-table-action'; +@import 'data-table-core'; +@import 'data-table-expandable'; +@import 'data-table-sort'; +@import 'data-table-inline-edit'; +@import 'data-table-skeleton'; diff --git a/src/components/data-table/data-table.config.js b/src/components/data-table/data-table.config.js new file mode 100644 index 000000000000..a9cce513a416 --- /dev/null +++ b/src/components/data-table/data-table.config.js @@ -0,0 +1,492 @@ +/** + * Copyright IBM Corp. 2016, 2018 + * + * This source code is licensed under the Apache-2.0 license found in the + * LICENSE file in the root directory of this source tree. + */ + +'use strict'; + +const { prefix } = require('../../globals/js/settings'); +const { componentsX } = require('../../globals/js/feature-flags'); + +const iconAddSolid = ` + +`; + +const iconDownload = ` + +`; + +/* eslint-disable max-len */ +const iconEdit = ` + +`; + +const iconSettings = ` + +`; +/* eslint-enable max-len */ + +const menuItems = [ + { + label: 'Stop app', + primaryFocus: true, + }, + { + label: 'Restart app', + }, + { + label: 'Rename app', + }, + { + label: 'Edit routes and access, use title when', + }, + { + label: 'Delete app', + danger: true, + }, +]; + +const batchActions = [ + { + label: 'Ghost', + icon: iconAddSolid, + }, + { + label: 'Ghost', + icon: iconAddSolid, + }, + { + label: 'Ghost', + icon: iconAddSolid, + }, +]; + +const toolbarActions = [ + { + icon: iconDownload, + }, + { + icon: iconEdit, + }, + { + icon: iconSettings, + }, +]; + +const toolbarActionsX = [ + { + overflowItems: [ + { + label: 'Option 1', + primaryFocus: true, + }, + { + label: 'Option 2', + }, + { + label: 'Option 3', + }, + ], + }, +]; + +const columns = [ + { + name: 'select', + title: 'Label name', + checkbox: true, + checkboxId: `${prefix}--checkbox-20`, + checkboxName: 'checkbox-20', + checkboxValue: 'green', + }, + { + name: 'name', + title: 'Name', + sortable: true, + }, + { + name: 'protocol', + title: 'Protocol', + sortable: true, + }, + { + name: 'port', + title: 'Port', + sortable: true, + }, + { + name: 'rule', + title: 'Rule', + sortable: true, + }, + { + name: 'attachedGroups', + title: 'Attached Groups', + sortable: true, + }, + { + name: 'status', + title: 'Status', + sortable: true, + }, + { + name: 'menu', + menu: true, + }, +]; + +const columnsExpandable = [ + { + name: 'section', + section: true, + }, + { + name: 'select', + title: 'Label name', + checkbox: true, + checkboxId: `${prefix}--checkbox-20`, + checkboxName: 'checkbox-20', + checkboxValue: 'green', + }, + { + name: 'name', + title: 'Name', + sortable: true, + }, + { + name: 'protocol', + title: 'Protocol', + sortable: true, + }, + { + name: 'port', + title: 'Ports', + sortable: true, + }, + { + name: 'rule', + title: 'Rule', + sortable: true, + }, + { + name: 'attachedGroups', + title: 'Attached Groups', + sortable: true, + }, + { + name: 'status', + title: 'Status', + sortable: true, + }, +]; + +const columnsSmall = columns.slice(1, -1).map(column => ({ + ...column, + sortable: false, +})); + +const rows = [ + { + id: 'row-id-13', + select: { + id: `${prefix}--checkbox-13`, + name: 'checkbox-13', + value: 'green', + label: 'Label name', + }, + name: 'Load Balancer 1', + protocol: 'HTTP', + port: '80', + rule: 'Round Robin', + attachedGroups: "Maureen's VM Groups Testing a really long text here", + status: 'Active', + menu: { + label: 'Overflow menu description', + items: menuItems, + flip: true, + }, + }, + { + id: 'row-id-14', + select: { + id: `${prefix}--checkbox-14`, + name: 'checkbox-14', + value: 'green', + label: 'Label name', + }, + name: 'Load Balancer 5', + protocol: 'HTTP', + port: '80', + rule: 'Round Robin', + attachedGroups: "Maureen's VM Groups", + status: 'Active', + menu: { + label: 'Overflow menu description', + items: menuItems, + flip: true, + }, + }, + { + id: 'row-id-15', + select: { + id: `${prefix}--checkbox-15`, + name: 'checkbox-15', + value: 'green', + label: 'Label name', + }, + name: 'Load Balancer 5', + protocol: 'HTTP', + port: '80', + rule: 'Round Robin', + attachedGroups: "Maureen's VM Groups", + status: 'Active', + menu: { + label: 'Overflow menu description', + items: menuItems, + flip: true, + }, + }, + { + id: 'row-id-11', + select: { + id: `${prefix}--checkbox-11`, + name: 'checkbox-11', + value: 'green', + label: 'Label name', + }, + name: 'Load Balancer 5', + protocol: 'HTTP', + port: '80', + rule: 'Round Robin', + attachedGroups: "Maureen's VM Groups", + status: 'Active', + menu: { + label: 'Overflow menu description', + items: menuItems, + flip: true, + }, + }, + { + id: 'row-id-12', + select: { + id: `${prefix}--checkbox-12`, + name: 'checkbox-12', + value: 'green', + label: 'Label name', + }, + name: 'Load Balancer 5', + protocol: 'HTTP', + port: '80', + rule: 'Round Robin', + attachedGroups: "Maureen's VM Groups", + status: 'Active', + menu: { + label: 'Overflow menu description', + items: menuItems, + flip: true, + }, + }, +]; + +const rowsExpandable = [ + { + sectionContent: + /* eslint-disable max-len */ + `A variety of content types can live here. Be sure to follow Carbon design guidelines for spacing and alignment.
+ `, + section: true, + select: { + id: `${prefix}--checkbox-13`, + name: 'checkbox-13', + value: 'green', + label: 'Label name', + }, + name: 'Load Balancer 1', + protocol: 'HTTP', + port: '80', + rule: 'Round Robin', + attachedGroups: "Maureen's VM Groups", + status: 'Active', + }, + { + sectionContent: + /* eslint-disable max-len */ + `A variety of content types can live here. Be sure to follow Carbon design guidelines for spacing and alignment.
+ `, + select: { + id: `${prefix}--checkbox-12`, + name: 'checkbox-12', + value: 'green', + label: 'Label name', + }, + section: true, + name: 'Load Balancer 1', + protocol: 'HTTP', + port: '80', + rule: 'Round Robin', + attachedGroups: "Maureen's VM Groups", + status: 'Active', + }, +]; + +module.exports = { + label: 'Data Table', + context: { + prefix, + componentsX, + }, + variants: [ + { + name: 'default', + label: 'Data Table', + notes: ` + Data Tables are used to represent a collection of resources, displaying a + subset of their fields in columns, or headers. + `, + context: { + state: 'default', + title: 'Table title', + optionalHelper: 'Optional Helper Text', + batchActions, + toolbarActions, + toolbarActionsX, + columns, + rows, + selectedItemsCounterLabel: ` + 3 items selected + `, + searchInputId: 'search__input-2', + searchLabelId: 'search-input-label-1', + searchLabel: 'Search', + clearSearchLabel: 'Clear search input', + addNewLabel: 'Add new', + cancelLabel: 'Cancel', + sortLabel: 'Sort rows by this header in descending order', + hasToolbar: true, + sort: true, + }, + }, + { + name: 'zebra-select', + label: 'Zebra Select', + notes: ` + Data Tables are used to represent a collection of resources, displaying a + subset of their fields in columns, or headers. + `, + context: { + state: 'default', + title: 'Table title', + optionalHelper: 'Optional Helper Text', + batchActions, + toolbarActions, + toolbarActionsX, + columns, + rows, + selectedItemsCounterLabel: ` + 3 items selected + `, + searchInputId: 'search__input-2', + searchLabelId: 'search-input-label-1', + searchLabel: 'Search', + clearSearchLabel: 'Clear search input', + addNewLabel: 'Add new', + cancelLabel: 'Cancel', + sortLabel: 'Sort rows by this header in descending order', + hasToolbar: true, + sort: true, + zebra: true, + }, + }, + { + name: 'zebra', + label: 'Zebra', + context: { + small: true, + columns: columnsSmall, + rows, + zebra: true, + }, + }, + { + name: 'expandable', + label: 'Expandable', + context: { + state: 'persistent-search', + title: 'Table title', + columns: columnsExpandable, + rows: rowsExpandable, + searchInputId: 'search__input-2', + searchLabelId: 'search-input-label-1', + searchLabel: 'Search', + clearSearchLabel: 'Clear search input', + hasToolbar: true, + sort: true, + batchActions, + toolbarActions, + toolbarActionsX, + selectedItemsCounterLabel: ` + 3 items selected + `, + addNewLabel: 'Add new', + cancelLabel: 'Cancel', + sortLabel: 'Sort rows by this header in descending order', + }, + }, + { + name: 'small', + label: 'Small', + context: { + small: true, + columns: columnsSmall, + rows, + }, + }, + { + name: 'with-pager', + label: 'Pagination', + context: { + state: 'persistent-search', + hasPager: true, + title: 'Table title', + batchActions, + toolbarActions, + toolbarActionsX, + columns, + rows, + selectedItemsCounterLabel: ` + 3 items selected + `, + searchInputId: 'search__input-2', + searchLabelId: 'search-input-label-1', + searchLabel: 'Search', + clearSearchLabel: 'Clear search input', + addNewLabel: 'Add new', + cancelLabel: 'Cancel', + sortLabel: 'Sort rows by this header in descending order', + hasToolbar: true, + sort: true, + }, + }, + ], +}; diff --git a/src/components/data-table-v2/data-table-v2.hbs b/src/components/data-table/data-table.hbs similarity index 100% rename from src/components/data-table-v2/data-table-v2.hbs rename to src/components/data-table/data-table.hbs diff --git a/src/components/data-table/data-table.js b/src/components/data-table/data-table.js new file mode 100644 index 000000000000..91b295417d06 --- /dev/null +++ b/src/components/data-table/data-table.js @@ -0,0 +1,377 @@ +/** + * Copyright IBM Corp. 2016, 2018 + * + * This source code is licensed under the Apache-2.0 license found in the + * LICENSE file in the root directory of this source tree. + */ + +import { componentsX } from '../../globals/js/feature-flags'; +import settings from '../../globals/js/settings'; +import mixin from '../../globals/js/misc/mixin'; +import createComponent from '../../globals/js/mixins/create-component'; +import initComponentBySearch from '../../globals/js/mixins/init-component-by-search'; +import eventedState from '../../globals/js/mixins/evented-state'; +import eventMatches from '../../globals/js/misc/event-matches'; + +const toArray = arrayLike => Array.prototype.slice.call(arrayLike); +const suffix = componentsX ? '' : '-v2'; + +class DataTable extends mixin(createComponent, initComponentBySearch, eventedState) { + /** + * Data Table + * @extends CreateComponent + * @extends InitComponentBySearch + * @extends EventedState + * @param {HTMLElement} element The root element of tables + * @param {Object} [options] the... options + * @param {string} [options.selectorInit] selector initialization + * @param {string} [options.selectorExpandCells] css selector for expand + * @param {string} [options.expandableRow] css selector for expand + * @param {string} [options.selectorParentRows] css selector for rows housing expansion + * @param {string} [options.selectorTableBody] root css for table body + * @param {string} [options.eventTrigger] selector for event bubble capture points + * @param {string} [options.eventParentContainer] used find the bubble container + */ + constructor(element, options) { + super(element, options); + + this.container = element.parentNode; + this.toolbarEl = this.element.querySelector(this.options.selectorToolbar); + this.batchActionEl = this.element.querySelector(this.options.selectorActions); + this.countEl = this.element.querySelector(this.options.selectorCount); + this.cancelEl = this.element.querySelector(this.options.selectorActionCancel); + this.tableHeaders = this.element.querySelectorAll('th'); + this.tableBody = this.element.querySelector(this.options.selectorTableBody); + this.expandCells = []; + this.expandableRows = []; + this.parentRows = []; + + this.refreshRows(); + + this.element.addEventListener('mouseover', evt => { + const eventElement = eventMatches(evt, this.options.selectorChildRow); + + if (eventElement) { + this._expandableHoverToggle(eventElement, true); + } + }); + + this.element.addEventListener('click', evt => { + const eventElement = eventMatches(evt, this.options.eventTrigger); + const searchContainer = this.element.querySelector(this.options.selectorToolbarSearchContainer); + + if (eventElement) { + this._toggleState(eventElement, evt); + } + + if (componentsX && searchContainer) { + this._handleDocumentClick(evt); + } + }); + + this.element.addEventListener('keydown', this._keydownHandler); + + this.state = { + checkboxCount: 0, + }; + } + + _handleDocumentClick(evt) { + const searchContainer = this.element.querySelector(this.options.selectorToolbarSearchContainer); + const searchEvent = eventMatches(evt, this.options.selectorSearchMagnifier); + const activeSearch = searchContainer.classList.contains(this.options.classToolbarSearchActive); + + if (searchContainer && searchEvent) { + this.activateSearch(searchContainer); + } + + if (activeSearch) { + this.deactivateSearch(searchContainer, evt); + } + } + + activateSearch(container) { + const input = container.querySelector(this.options.selectorSearchInput); + container.classList.add(this.options.classToolbarSearchActive); + input.focus(); + } + + deactivateSearch(container, evt) { + const trigger = container.querySelector(this.options.selectorSearchMagnifier); + const input = container.querySelector(this.options.selectorSearchInput); + const svg = trigger.querySelector('svg'); + if (input.value.length === 0 && evt.target !== input && evt.target !== trigger && evt.target !== svg) { + container.classList.remove(this.options.classToolbarSearchActive); + trigger.focus(); + } + + if (evt.which === 27 && evt.target === input) { + container.classList.remove(this.options.classToolbarSearchActive); + trigger.focus(); + } + } + + _sortToggle = detail => { + const { element, previousValue } = detail; + + toArray(this.tableHeaders).forEach(header => { + const sortEl = header.querySelector(this.options.selectorTableSort); + + if (sortEl !== null && sortEl !== element) { + sortEl.classList.remove(this.options.classTableSortActive); + sortEl.classList.remove(this.options.classTableSortAscending); + } + }); + + if (!previousValue) { + element.dataset.previousValue = 'ascending'; + element.classList.add(this.options.classTableSortActive); + element.classList.add(this.options.classTableSortAscending); + } else if (previousValue === 'ascending') { + element.dataset.previousValue = 'descending'; + element.classList.add(this.options.classTableSortActive); + element.classList.remove(this.options.classTableSortAscending); + } else if (previousValue === 'descending') { + element.removeAttribute('data-previous-value'); + element.classList.remove(this.options.classTableSortActive); + element.classList.remove(this.options.classTableSortAscending); + } + }; + + _selectToggle = detail => { + const { element } = detail; + const { checked } = element; + + // increment the count + this.state.checkboxCount += checked ? 1 : -1; + this.countEl.textContent = this.state.checkboxCount; + + const row = element.parentNode.parentNode; + + row.classList.toggle(this.options.classTableSelected); + + // toggle on/off batch action bar + this._actionBarToggle(this.state.checkboxCount > 0); + }; + + _selectAllToggle = ({ element }) => { + const { checked } = element; + + const inputs = toArray(this.element.querySelectorAll(this.options.selectorCheckbox)); + + this.state.checkboxCount = checked ? inputs.length - 1 : 0; + + inputs.forEach(item => { + item.checked = checked; + + const row = item.parentNode.parentNode; + if (checked && row) { + row.classList.add(this.options.classTableSelected); + } else { + row.classList.remove(this.options.classTableSelected); + } + }); + + this._actionBarToggle(this.state.checkboxCount > 0); + + if (this.batchActionEl) { + this.countEl.textContent = this.state.checkboxCount; + } + }; + + _actionBarCancel = () => { + const inputs = toArray(this.element.querySelectorAll(this.options.selectorCheckbox)); + const row = toArray(this.element.querySelectorAll(this.options.selectorTableSelected)); + + row.forEach(item => { + item.classList.remove(this.options.classTableSelected); + }); + + inputs.forEach(item => { + item.checked = false; + }); + + this.state.checkboxCount = 0; + this._actionBarToggle(false); + + if (this.batchActionEl) { + this.countEl.textContent = this.state.checkboxCount; + } + }; + + _actionBarToggle = toggleOn => { + const transition = evt => { + this.batchActionEl.removeEventListener('transitionend', transition); + + if (evt.target.matches(this.options.selectorActions)) { + if (this.batchActionEl.dataset.active === 'false') { + this.batchActionEl.setAttribute('tabIndex', -1); + } else { + this.batchActionEl.setAttribute('tabIndex', 0); + } + } + }; + + if (toggleOn) { + this.batchActionEl.dataset.active = true; + this.batchActionEl.classList.add(this.options.classActionBarActive); + } else if (this.batchActionEl) { + this.batchActionEl.dataset.active = false; + this.batchActionEl.classList.remove(this.options.classActionBarActive); + } + if (this.batchActionEl) { + this.batchActionEl.addEventListener('transitionend', transition); + } + }; + + _expandableRowsInit = expandableRows => { + expandableRows.forEach(item => { + if (!componentsX) { + item.classList.remove(this.options.classExpandableRowHidden); + this.tableBody.removeChild(item); + } + }); + }; + + _rowExpandToggle = ({ element, initialEvt }) => { + const parent = eventMatches(initialEvt, this.options.eventParentContainer); + + const index = this.expandCells.indexOf(element); + if (element.dataset.previousValue === undefined || element.dataset.previousValue === 'expanded') { + element.dataset.previousValue = 'collapsed'; + parent.classList.add(this.options.classExpandableRow); + if (!componentsX) { + this.tableBody.insertBefore(this.expandableRows[index], this.parentRows[index + 1]); + } + } else { + parent.classList.remove(this.options.classExpandableRow); + if (!componentsX) { + this.tableBody.removeChild(parent.nextElementSibling); + } + element.dataset.previousValue = 'expanded'; + } + }; + + _expandableHoverToggle = element => { + element.previousElementSibling.classList.add(this.options.classExpandableRowHover); + + const mouseout = () => { + element.previousElementSibling.classList.remove(this.options.classExpandableRowHover); + element.removeEventListener('mouseout', mouseout); + }; + + element.addEventListener('mouseout', mouseout); + }; + + _toggleState = (element, evt) => { + const data = element.dataset; + const label = data.label ? data.label : ''; + const previousValue = data.previousValue ? data.previousValue : ''; + const initialEvt = evt; + + this.changeState({ + group: data.event, + element, + label, + previousValue, + initialEvt, + }); + }; + + _keydownHandler = evt => { + const searchContainer = this.element.querySelector(this.options.selectorToolbarSearchContainer); + const searchEvent = eventMatches(evt, this.options.selectorSearchMagnifier); + const activeSearch = searchContainer.classList.contains(this.options.classToolbarSearchActive); + + if (evt.which === 27) { + this._actionBarCancel(); + } + + if (searchContainer && searchEvent && evt.which === 13) { + this.activateSearch(searchContainer); + } + + if (activeSearch && evt.which === 27) { + this.deactivateSearch(searchContainer, evt); + } + }; + + _changeState(detail, callback) { + this[this.constructor.eventHandlers[detail.group]](detail); + callback(); + } + + refreshRows = () => { + const newExpandCells = toArray(this.element.querySelectorAll(this.options.selectorExpandCells)); + const newExpandableRows = toArray(this.element.querySelectorAll(this.options.selectorExpandableRows)); + const newParentRows = toArray(this.element.querySelectorAll(this.options.selectorParentRows)); + + // check if this is a refresh or the first time + if (this.parentRows.length > 0) { + const diffParentRows = newParentRows.filter(newRow => !this.parentRows.some(oldRow => oldRow === newRow)); + + // check if there are expandable rows + if (newExpandableRows.length > 0) { + const diffExpandableRows = diffParentRows.map(newRow => newRow.nextElementSibling); + const mergedExpandableRows = [...toArray(this.expandableRows), ...toArray(diffExpandableRows)]; + this._expandableRowsInit(diffExpandableRows); + this.expandableRows = mergedExpandableRows; + } + } else if (newExpandableRows.length > 0) { + this._expandableRowsInit(newExpandableRows); + this.expandableRows = newExpandableRows; + } + + this.expandCells = newExpandCells; + this.parentRows = newParentRows; + }; + + static components /* #__PURE_CLASS_PROPERTY__ */ = new WeakMap(); + + // UI Events + static eventHandlers /* #__PURE_CLASS_PROPERTY__ */ = { + expand: '_rowExpandToggle', + sort: '_sortToggle', + select: '_selectToggle', + 'select-all': '_selectAllToggle', + 'action-bar-cancel': '_actionBarCancel', + }; + + static get options() { + const { prefix } = settings; + return { + selectorInit: `[data-table${suffix}]`, + selectorToolbar: `.${prefix}--table--toolbar`, + selectorActions: `.${prefix}--batch-actions`, + selectorCount: '[data-items-selected]', + selectorActionCancel: `.${prefix}--batch-summary__cancel`, + selectorCheckbox: `.${prefix}--checkbox`, + selectorExpandCells: `td.${prefix}--table-expand${suffix}`, + selectorExpandableRows: `.${prefix}--expandable-row${suffix}`, + selectorParentRows: `.${prefix}--parent-row${suffix}`, + selectorChildRow: '[data-child-row]', + selectorTableBody: 'tbody', + selectorTableSort: `.${prefix}--table-sort${suffix}`, + selectorTableSelected: `.${prefix}--data-table${suffix}--selected`, + selectorToolbarSearchContainer: `.${prefix}--toolbar-search-container-expandable`, + selectorSearchMagnifier: `.${prefix}--search-magnifier`, + selectorSearchInput: `.${prefix}--search-input`, + classExpandableRow: `${prefix}--expandable-row${suffix}`, + classExpandableRowHidden: `${prefix}--expandable-row--hidden${suffix}`, + classExpandableRowHover: `${prefix}--expandable-row--hover${suffix}`, + classTableSortAscending: `${prefix}--table-sort${suffix}--ascending`, + classTableSortActive: `${prefix}--table-sort${suffix}--active`, + classToolbarSearchActive: `${prefix}--toolbar-search-container-active`, + classActionBarActive: `${prefix}--batch-actions--active`, + classTableSelected: `${prefix}--data-table${suffix}--selected`, + eventBeforeExpand: `data-table${suffix}-beforetoggleexpand`, + eventAfterExpand: `data-table${suffix}-aftertoggleexpand`, + eventBeforeSort: `data-table${suffix}-beforetogglesort`, + eventAfterSort: `data-table${suffix}-aftertogglesort`, + eventTrigger: '[data-event]', + eventParentContainer: '[data-parent-row]', + }; + } +} + +export default DataTable; diff --git a/src/components/data-table-v2/migrate-to-10.x.md b/src/components/data-table/migrate-to-10.x.md similarity index 100% rename from src/components/data-table-v2/migrate-to-10.x.md rename to src/components/data-table/migrate-to-10.x.md diff --git a/src/components/tile/tile--grid.hbs b/src/components/tile/tile--grid.hbs index f7b355d6886a..d55650a927b8 100644 --- a/src/components/tile/tile--grid.hbs +++ b/src/components/tile/tile--grid.hbs @@ -30,7 +30,7 @@