diff --git a/web-components/packages/carbon-web-components/src/components/button/button.scss b/web-components/packages/carbon-web-components/src/components/button/button.scss index ac1ec129519f..2ae289f0f625 100644 --- a/web-components/packages/carbon-web-components/src/components/button/button.scss +++ b/web-components/packages/carbon-web-components/src/components/button/button.scss @@ -12,6 +12,7 @@ $css--plex: true !default; @use '@carbon/styles/scss/components/button'; @use '@carbon/styles/scss/components/popover/index'; @use '@carbon/styles/scss/components/tooltip'; +@use '@carbon/styles/scss/theme' as *; :host(#{$prefix}-button), :host(#{$prefix}-modal-footer-button) { @@ -21,6 +22,30 @@ $css--plex: true !default; width: rem(20px); height: rem(20px); } + + &[pagination] { + .#{$prefix}--btn { + border: none; + border-left: 1px solid $border-subtle; + transition: none; + + &:focus { + outline: 2px solid $focus; + outline-offset: -2px; + box-shadow: none; + border-left: 1px solid transparent; + } + } + + &:not([disabled]) { + .#{$prefix}--btn { + color: $icon-primary; + &:active { + background-color: $layer-hover; + } + } + } + } } :host(#{$prefix}-button[kind='ghost']:hover) .#{$prefix}--btn--ghost, diff --git a/web-components/packages/carbon-web-components/src/components/button/button.ts b/web-components/packages/carbon-web-components/src/components/button/button.ts index 606cca86b88c..590f60bcda2e 100644 --- a/web-components/packages/carbon-web-components/src/components/button/button.ts +++ b/web-components/packages/carbon-web-components/src/components/button/button.ts @@ -76,7 +76,7 @@ class CDSButton extends HostListenerMixin(FocusMixin(LitElement)) { @HostListener('mouseover') // @ts-ignore: The decorator refers to this method but TS thinks this method is not referred to private _handleOver = () => { - this.openTooltip = !this.openTooltip; + this.openTooltip = true; }; /** @@ -85,7 +85,7 @@ class CDSButton extends HostListenerMixin(FocusMixin(LitElement)) { @HostListener('mouseout') // @ts-ignore: The decorator refers to this method but TS thinks this method is not referred to private _handleHoverOut = async () => { - this.openTooltip = !this.openTooltip; + this.openTooltip = false; }; /** @@ -95,7 +95,7 @@ class CDSButton extends HostListenerMixin(FocusMixin(LitElement)) { @HostListener('focus') // @ts-ignore: The decorator refers to this method but TS thinks this method is not referred to private _handleFocus = async (event) => { - this._handleOver(); + this.openTooltip = true; }; /** @@ -105,7 +105,7 @@ class CDSButton extends HostListenerMixin(FocusMixin(LitElement)) { @HostListener('focusout') // @ts-ignore: The decorator refers to this method but TS thinks this method is not referred to private _handleFocusout = async (event) => { - this._handleOver(); + this.openTooltip = false; }; /** @@ -114,6 +114,12 @@ class CDSButton extends HostListenerMixin(FocusMixin(LitElement)) { @property({ type: Boolean, reflect: true }) autofocus = false; + /** + * Specify an optional className to be added to your Button + */ + @property({ reflect: true, attribute: 'class-name' }) + className; + /** * Specify the message read by screen readers for the danger button variant */ @@ -229,6 +235,7 @@ class CDSButton extends HostListenerMixin(FocusMixin(LitElement)) { render() { const { autofocus, + className, dangerDescriptor, disabled, download, @@ -251,7 +258,8 @@ class CDSButton extends HostListenerMixin(FocusMixin(LitElement)) { _hasMainContent: hasMainContent, _handleSlotChange: handleSlotChange, } = this; - const classes = classMap({ + + let defaultClasses = { [`${prefix}--btn`]: true, [`${prefix}--btn--${kind}`]: kind, [`${prefix}--btn--disabled`]: disabled, @@ -260,7 +268,16 @@ class CDSButton extends HostListenerMixin(FocusMixin(LitElement)) { [`${prefix}-ce--btn--has-icon`]: hasIcon, [`${prefix}--btn--expressive`]: isExpressive, [`${prefix}--btn--selected`]: isSelected && kind === 'ghost', - }); + }; + + if (className) { + const outputObject = {}; + className?.split(' ').forEach((element) => { + outputObject[element] = true; + }); + defaultClasses = outputObject; + } + const classes = classMap(defaultClasses); const isDanger = kind.includes('danger'); @@ -308,7 +325,7 @@ class CDSButton extends HostListenerMixin(FocusMixin(LitElement)) { [`${prefix}--popover--${tooltipPosition}${alignmentClass}`]: tooltipText, }); - return tooltipText + return tooltipText && !disabled ? html` - + ${CaretRight16({ slot: 'icon' })} + `; @@ -269,14 +430,14 @@ class BXPagination extends FocusMixin(HostListenerMixin(LitElement)) { * A selector that will return the select box for the current page. */ static get selectorPagesSelect() { - return `${prefix}-pages-select`; + return `${prefix}-select#pages-select`; } /** * A selector that will return the select box for page sizes. */ static get selectorPageSizesSelect() { - return `${prefix}-page-sizes-select`; + return `${prefix}-select`; } /** @@ -286,18 +447,11 @@ class BXPagination extends FocusMixin(HostListenerMixin(LitElement)) { return `${prefix}-pagination-changed-current`; } - /** - * The name of the custom event fired after the current page is changed from ``. - */ - static get eventChangePage() { - return `${prefix}-pages-select-changed`; - } - /** * The name of the custom event fired after the number of rows per page is changed from ``. */ - static get eventChangePageSize() { - return `${prefix}-page-sizes-select-changed`; + static get eventChangeSelect() { + return `${prefix}-select-selected`; } static shadowRootOptions = { @@ -307,4 +461,4 @@ class BXPagination extends FocusMixin(HostListenerMixin(LitElement)) { static styles = styles; // `styles` here is a `CSSResult` generated by custom WebPack loader } -export default BXPagination; +export default CDSPagination; diff --git a/web-components/packages/carbon-web-components/src/components/select/select.scss b/web-components/packages/carbon-web-components/src/components/select/select.scss index 3678eeb88140..a8850b3088e2 100644 --- a/web-components/packages/carbon-web-components/src/components/select/select.scss +++ b/web-components/packages/carbon-web-components/src/components/select/select.scss @@ -8,7 +8,9 @@ $css--plex: true !default; @use '@carbon/styles/scss/config' as *; +@use '@carbon/styles/scss/spacing' as *; @use '@carbon/styles/scss/components/select'; +@use '@carbon/styles/scss/theme' as *; :host(#{$prefix}-select) { @extend .#{$prefix}--select; @@ -39,7 +41,32 @@ $css--plex: true !default; } .#{$prefix}--select__invalid-icon--warning { - right: 2rem; + right: $spacing-07; + } + } + + &[pagination] { + .#{$prefix}--label { + margin: 0; + } + + .#{$prefix}--select-input { + padding: 0 2.25rem 0 $spacing-05; + + &:focus { + background-color: transparent; + } + } + + .#{$prefix}--select__arrow { + top: 50%; + transform: translate(-#{$spacing-03}, -50%); + } + + &[left-select] { + .#{$prefix}--select-input { + border-right: 1px solid $border-subtle; + } } } } diff --git a/web-components/packages/carbon-web-components/src/components/select/select.ts b/web-components/packages/carbon-web-components/src/components/select/select.ts index cc63df0ab5be..a76fb9430d01 100644 --- a/web-components/packages/carbon-web-components/src/components/select/select.ts +++ b/web-components/packages/carbon-web-components/src/components/select/select.ts @@ -287,7 +287,7 @@ class CDSSelect extends FormMixin(LitElement) { /** * The value of the text area. */ - @property() + @property({ reflect: true }) value = ''; connectedCallback() { diff --git a/web-components/packages/carbon-web-components/src/index.ts b/web-components/packages/carbon-web-components/src/index.ts index 3846fd4377de..cc78125426fb 100644 --- a/web-components/packages/carbon-web-components/src/index.ts +++ b/web-components/packages/carbon-web-components/src/index.ts @@ -76,8 +76,6 @@ export { default as CDSOverflowMenu } from './components/overflow-menu/overflow- export { default as CDSOverflowMenuBody } from './components/overflow-menu/overflow-menu-body'; export { default as CDSOverflowMenuItem } from './components/overflow-menu/overflow-menu-item'; export { default as CDSPagination } from './components/pagination/pagination'; -export { default as CDSPageSizesSelect } from './components/pagination/page-sizes-select'; -export { default as CDSPagesSelect } from './components/pagination/pages-select'; export { default as CDSProgressBar } from './components/progress-bar/progress-bar'; export { default as CDSProgressIndicator } from './components/progress-indicator/progress-indicator'; export { default as CDSProgressIndicatorSkeleton } from './components/progress-indicator/progress-indicator-skeleton'; diff --git a/web-components/packages/carbon-web-components/tests/spec/pagination_spec.ts b/web-components/packages/carbon-web-components/tests/spec/pagination_spec.ts index f9e3323ec7df..80c7516ddc4f 100644 --- a/web-components/packages/carbon-web-components/tests/spec/pagination_spec.ts +++ b/web-components/packages/carbon-web-components/tests/spec/pagination_spec.ts @@ -9,13 +9,12 @@ import { render } from 'lit'; import EventManager from '../utils/event-manager'; -import BXPagination from '../../src/components/pagination/pagination'; -import BXPageSizesSelect from '../../src/components/pagination/page-sizes-select'; -import BXPagesSelect from '../../src/components/pagination/pages-select'; -import { Default } from '../../src/components/pagination/pagination-story'; +import CDSPagination from '../../src/components/pagination/pagination'; +import { Playground } from '../../src/components/pagination/pagination-story'; +import CDSSelect from '../../src/components/select/select'; const template = (props?) => - Default({ + Playground({ 'cds-pagination': props, }); @@ -38,7 +37,7 @@ describe('cds-pagination', function () { template({ pageSize: 20, start: 10, - total: 200, + totalItems: 200, }), document.body ); @@ -60,7 +59,7 @@ describe('cds-pagination', function () { }); it('should render with minimum attributes', async function () { - render(template({ total: 100 }), document.body); + render(template({ totalItems: 100 }), document.body); await Promise.resolve(); // Update cycle for `` await Promise.resolve(); // Update cycle for `` expect( @@ -77,7 +76,7 @@ describe('cds-pagination', function () { template({ pageSize: 1, start: 0, - total: 1, + totalItems: 1, }), document.body ); @@ -93,7 +92,7 @@ describe('cds-pagination', function () { template({ pageSize: 20, start: 10, - total: null, + totalItems: null, }), document.body ); @@ -110,7 +109,7 @@ describe('cds-pagination', function () { atLastPage: true, pageSize: 20, start: 30, - total: null, + totalItems: null, }), document.body ); @@ -123,48 +122,45 @@ describe('cds-pagination', function () { }); describe('Propagating changes', function () { - it('should propagate `pageSize` property to ``', async function () { + it('should propagate `pageSize` property to ``', async function () { render(template(), document.body); await Promise.resolve(); const paginationNode = document.body.querySelector( 'cds-pagination' - ) as BXPagination; + ) as CDSPagination; paginationNode.pageSize = 20; await Promise.resolve(); - const pageSizesSelectNode = document.body.querySelector( - 'cds-page-sizes-select' - ) as BXPageSizesSelect; - expect(pageSizesSelectNode.value).toBe(20); + const pageSizesSelectNode = paginationNode.shadowRoot?.querySelector( + 'cds-select' + ) as CDSSelect; + expect(pageSizesSelectNode.value).toBe('20'); }); - it('should propagate the current page to ``', async function () { - render(template({ total: 100 }), document.body); + it('should propagate the current page to ``', async function () { + render(template({ totalItems: 100 }), document.body); await Promise.resolve(); const paginationNode = document.body.querySelector( 'cds-pagination' - ) as BXPagination; + ) as CDSPagination; paginationNode.pageSize = 5; paginationNode.start = 21; await Promise.resolve(); - const pagesSelectNode = document.body.querySelector( - 'cds-pages-select' - ) as BXPagesSelect; - expect(pagesSelectNode.value).toBe(4); + const pagesSelectNode = paginationNode.shadowRoot?.querySelector( + '#pages-select' + ) as CDSSelect; + expect(pagesSelectNode.value).toBe('4'); }); it('should propagate the total pages to ``', async function () { - render(template({ total: 100 }), document.body); + render(template({ totalItems: 100 }), document.body); await Promise.resolve(); const paginationNode = document.body.querySelector( 'cds-pagination' - ) as BXPagination; + ) as CDSPagination; paginationNode.pageSize = 5; - paginationNode.total = 21; + paginationNode.totalItems = 21; await Promise.resolve(); - const pagesSelectNode = document.body.querySelector( - 'cds-pages-select' - ) as BXPagesSelect; - expect(pagesSelectNode.total).toBe(5); + expect(paginationNode.totalItems).toBe(5); }); it('should handle change in page size at non-first page', async function () { @@ -174,20 +170,20 @@ describe('cds-pagination', function () { template({ pageSize: 10, start: 190, - total: 200, + totalItems: 200, }), document.body ); await Promise.resolve(); const paginationNode = document.body.querySelector( 'cds-pagination' - ) as BXPagination; + ) as CDSPagination; paginationNode.pageSize = 5; await Promise.resolve(); // Update in `` await Promise.resolve(); // Update in `` - const pagesSelectNode = document.body.querySelector( - 'cds-pages-select' - ) as BXPagesSelect; + const pagesSelectNode = paginationNode.shadowRoot?.querySelector( + '#pages-select' + ) as CDSSelect; expect(pagesSelectNode.shadowRoot!.querySelector('select')!.value).toBe( '38' ); @@ -207,7 +203,7 @@ describe('cds-pagination', function () { await Promise.resolve(); const paginationNode = document.body.querySelector( 'cds-pagination' - ) as BXPagination; + ) as CDSPagination; events.on( paginationNode, 'cds-pagination-changed-current', @@ -232,7 +228,7 @@ describe('cds-pagination', function () { await Promise.resolve(); const paginationNode = document.body.querySelector( 'cds-pagination' - ) as BXPagination; + ) as CDSPagination; events.on( paginationNode, 'cds-pagination-changed-current', @@ -256,7 +252,7 @@ describe('cds-pagination', function () { await Promise.resolve(); const paginationNode = document.body.querySelector( 'cds-pagination' - ) as BXPagination; + ) as CDSPagination; const spyChanged = jasmine.createSpy('changed'); events.on(paginationNode, 'cds-pagination-changed-current', spyChanged); // Prev button should be disabled when `start` indicates that we are at the first page, @@ -279,7 +275,7 @@ describe('cds-pagination', function () { await Promise.resolve(); const paginationNode = document.body.querySelector( 'cds-pagination' - ) as BXPagination; + ) as CDSPagination; events.on( paginationNode, 'cds-pagination-changed-current', @@ -297,14 +293,14 @@ describe('cds-pagination', function () { template({ pageSize: 10, start: 20, - total: 30, + totalItems: 30, }), document.body ); await Promise.resolve(); const paginationNode = document.body.querySelector( 'cds-pagination' - ) as BXPagination; + ) as CDSPagination; const spyChanged = jasmine.createSpy('changed'); events.on(paginationNode, 'cds-pagination-changed-current', spyChanged); // Next button should be disabled when `start` indicates that we are at the last page, @@ -320,14 +316,14 @@ describe('cds-pagination', function () { template({ pageSize: 10, start: 25, - total: 30, + totalItems: 30, }), document.body ); await Promise.resolve(); const paginationNode = document.body.querySelector( 'cds-pagination' - ) as BXPagination; + ) as CDSPagination; const spyChanged = jasmine.createSpy('changed'); events.on(paginationNode, 'cds-pagination-changed-current', spyChanged); // Next button should be disabled when `start` indicates that we are at the last page, @@ -344,14 +340,14 @@ describe('cds-pagination', function () { template({ pageSize: 10, start: 25, - total: null, + totalItems: null, }), document.body ); await Promise.resolve(); const paginationNode = document.body.querySelector( 'cds-pagination' - ) as BXPagination; + ) as CDSPagination; events.on( paginationNode, 'cds-pagination-changed-current', @@ -365,30 +361,30 @@ describe('cds-pagination', function () { }); it('should support user-initiated change in page size', async function () { - render(template({ total: 100 }), document.body); + render(template({ totalItems: 100 }), document.body); await Promise.resolve(); - const pagesSelectNode = document.body.querySelector( - 'cds-pages-select' - ) as BXPagesSelect; + const paginationNode = document.body.querySelector( + 'cds-pagination' + ) as CDSPagination; + const pagesSelectNode = paginationNode.shadowRoot?.querySelector( + '#pages-select' + ) as CDSSelect; pagesSelectNode.dispatchEvent( - new CustomEvent('cds-page-sizes-select-changed', { + new CustomEvent('cds-select-selected', { bubbles: true, detail: { value: 5 }, }) ); - const paginationNode = document.body.querySelector( - 'cds-pagination' - ) as BXPagination; expect(paginationNode.pageSize).toBe(5); }); it('should support user-initiated change in current page', async function () { let newStart; - render(template({ pageSize: 10, total: 100 }), document.body); + render(template({ pageSize: 10, totalItems: 100 }), document.body); await Promise.resolve(); const paginationNode = document.body.querySelector( 'cds-pagination' - ) as BXPagination; + ) as CDSPagination; events.on( paginationNode, 'cds-pagination-changed-current', @@ -396,11 +392,11 @@ describe('cds-pagination', function () { newStart = event.detail.start; } ); - const pagesSelectNode = document.body.querySelector( - 'cds-pages-select' - ) as BXPagesSelect; + const pagesSelectNode = paginationNode.shadowRoot?.querySelector( + '#pages-select' + ) as CDSSelect; pagesSelectNode.dispatchEvent( - new CustomEvent('cds-pages-select-changed', { + new CustomEvent('cds-select-selected', { bubbles: true, detail: { value: 3 }, })