diff --git a/.changeset/clever-trees-sort.md b/.changeset/clever-trees-sort.md new file mode 100644 index 0000000000..f90d1b40aa --- /dev/null +++ b/.changeset/clever-trees-sort.md @@ -0,0 +1,5 @@ +--- +"@justeattakeaway/pie-button": minor +--- + +[Changed] - Styling allowing for text-overflow in buttons diff --git a/.changeset/rotten-chefs-divide.md b/.changeset/rotten-chefs-divide.md new file mode 100644 index 0000000000..039643e25f --- /dev/null +++ b/.changeset/rotten-chefs-divide.md @@ -0,0 +1,5 @@ +--- +"@justeattakeaway/pie-button": minor +--- + +[Changed] - enabled text wrapping onto multiple lines for all button types diff --git a/packages/components/pie-button/src/button.scss b/packages/components/pie-button/src/button.scss index 7acd5bf464..9c52ec046b 100644 --- a/packages/components/pie-button/src/button.scss +++ b/packages/components/pie-button/src/button.scss @@ -25,59 +25,83 @@ // currently this sets the primary button styles --btn-bg-color: var(--dt-color-interactive-brand); --btn-text-color: var(--dt-color-content-interactive-primary); - - // Heights for the different button sizes - --btn-height--xsmall: 32px; - --btn-height--small: 40px; - --btn-height--medium: 48px; - --btn-height--large: 56px; --icon-display-override: block; + // Vertical and horizontal padding values for the button + --btn-padding-vertical-xsmall: 6px; + --btn-padding-vertical-small: 8px; + --btn-padding-vertical-medium: 10px; + --btn-padding-vertical-large: 14px; + --btn-padding-horizontal-small: var(--dt-spacing-b); + --btn-padding-horizontal-medium: var(--dt-spacing-d); + --btn-padding-horizontal-large: var(--dt-spacing-e); + /** * Mixin for updating the button styles based on the size passed in. * Takes in the name of the size to be used. */ @mixin button-size($size) { @if $size == 'xsmall' { - --btn-height: var(--btn-height--xsmall); - --btn-padding: 6px var(--dt-spacing-b); --btn-font-size: #{p.font-size(--dt-font-size-14)}; --btn-line-height: calc(var(--dt-font-size-14-line-height) * 1px); --icon-size-override: 16px; } @else if $size == 'small-expressive' { - --btn-height: var(--btn-height--small); - --btn-padding: 6px var(--dt-spacing-d); --btn-font-size: #{p.font-size(--dt-font-size-20)}; --btn-line-height: calc(var(--dt-font-size-20-line-height) * 1px); --icon-size-override: 20px; } @else if $size == 'small-productive' { - --btn-height: var(--btn-height--small); - --btn-padding: 8px var(--dt-spacing-d); --btn-font-size: #{p.font-size(--dt-font-size-16)}; --btn-line-height: calc(var(--dt-font-size-16-line-height) * 1px); --icon-size-override: 20px; } @else if $size == 'medium' { - --btn-height: var(--btn-height--medium); - --btn-padding: 10px var(--dt-spacing-e); --btn-font-size: #{p.font-size(--dt-font-size-20)}; --btn-line-height: calc(var(--dt-font-size-20-line-height) * 1px); --icon-size-override: 24px; } @else if $size == 'large' { - --btn-height: var(--btn-height--large); - --btn-padding: 14px var(--dt-spacing-e); --btn-font-size: #{p.font-size(--dt-font-size-20)}; --btn-line-height: calc(var(--dt-font-size-20-line-height) * 1px); --icon-size-override: 24px; } } + /** + * Mixin for applying the button padding based on the size passed in. + * $size: The name of the size to be used. + * $offsetPaddingForBorder: A boolean to specify whether the padding should be offset for a border + */ + @mixin button-padding($size, $offsetPaddingForBorder: false) { + $verticalPadding: ''; + $horizontalPadding: ''; + + @if $size == 'xsmall' { + $verticalPadding: '--btn-padding-vertical-xsmall'; + $horizontalPadding: '--btn-padding-horizontal-small'; + } @else if $size == 'small-expressive' { + $verticalPadding: '--btn-padding-vertical-xsmall'; + $horizontalPadding: '--btn-padding-horizontal-medium'; + } @else if $size == 'small-productive' { + $verticalPadding: '--btn-padding-vertical-small'; + $horizontalPadding: '--btn-padding-horizontal-medium'; + } @else if $size == 'medium' { + $verticalPadding: '--btn-padding-vertical-medium'; + $horizontalPadding: '--btn-padding-horizontal-large'; + } @else if $size == 'large' { + $verticalPadding: '--btn-padding-vertical-large'; + $horizontalPadding: '--btn-padding-horizontal-large'; + } + + @if $offsetPaddingForBorder { + padding: calc(var(#{$verticalPadding}) - 1px) var(#{$horizontalPadding}); + } @else { + padding: var(#{$verticalPadding}) var(#{$horizontalPadding}); + } + } + position: relative; display: inline-flex; gap: var(--dt-spacing-b); align-items: center; justify-content: center; - height: var(--btn-height); - padding: var(--btn-padding); border: none; border-radius: var(--btn-border-radius); outline: none; @@ -167,7 +191,7 @@ @include p.button-interactive-states('--dt-color-container-default', 'transparent'); } - &.o-btn--outline-inverse:not([disabled]) { + &.o-btn--outline-inverse { border: 1px solid var(--dt-color-border-strong); } @@ -191,43 +215,98 @@ // ********************* &.o-btn--xsmall { @include button-size(xsmall); + @include button-padding(xsmall); @include responsive-wide { // productive is the default size when responsive is enabled @include button-size(small-productive); + @include button-padding(small-productive); &.o-btn--expressive { @include button-size(small-expressive); + @include button-padding(small-expressive); + } + } + + &.o-btn--outline, + &.o-btn--outline-inverse { + @include button-padding(xsmall, true); + + @include responsive-wide { + @include button-padding(small-productive, true); + + &.o-btn--expressive { + @include button-padding(small-expressive, true); + } } } } &.o-btn--small-expressive { @include button-size(small-expressive); + @include button-padding(small-expressive); @include responsive-wide { @include button-size(medium); + @include button-padding(medium); + } + + &.o-btn--outline, + &.o-btn--outline-inverse { + @include button-padding(small-expressive, true); + + @include responsive-wide { + @include button-padding(medium, true); + } } } &.o-btn--small-productive { @include button-size(small-productive); + @include button-padding(small-productive); @include responsive-wide { @include button-size(medium); + @include button-padding(medium); + } + + &.o-btn--outline, + &.o-btn--outline-inverse { + @include button-padding(small-productive, true); + + @include responsive-wide { + @include button-padding(medium, true); + } } } &.o-btn--medium { @include button-size(medium); + @include button-padding(medium); @include responsive-wide { @include button-size(large); + @include button-padding(large); + } + + &.o-btn--outline, + &.o-btn--outline-inverse { + @include button-padding(medium, true); + + @include responsive-wide { + @include button-padding(large, true); + } } } &.o-btn--large { @include button-size(large); + @include button-padding(large); + + &.o-btn--outline, + &.o-btn--outline-inverse { + @include button-padding(large, true); + } } // ****************************** @@ -251,7 +330,8 @@ } // For outline variants, set the border to the disabled color - &.o-btn--outline { + &.o-btn--outline, + &.o-btn--outline-inverse { border-color: var(--dt-color-disabled-01) !important; } } @@ -277,6 +357,14 @@ } } +// The inner span for the button text is needed to handle the text-overflow +// Without this, single word overflow wouldn't be possible in combination +// with display: flex. +.o-btn-text { + text-overflow: ellipsis; + overflow: hidden; +} + // Used to size an SVG if one is passed in (when not using the component icons) ::slotted(svg) { height: var(--icon-size-override); diff --git a/packages/components/pie-button/src/index.ts b/packages/components/pie-button/src/index.ts index 9db2589e3e..7c7dbe7876 100644 --- a/packages/components/pie-button/src/index.ts +++ b/packages/components/pie-button/src/index.ts @@ -265,7 +265,7 @@ export class PieButton extends FormControlMixin(LitElement) implements ButtonPro ?disabled=${disabled}> ${isLoading ? this.renderSpinner() : nothing} ${iconPlacement === 'leading' ? html`` : nothing} - + ${iconPlacement === 'trailing' ? html`` : nothing} `; } diff --git a/packages/components/pie-button/test/visual/pie-button-size.spec.ts b/packages/components/pie-button/test/visual/pie-button-size.spec.ts index 5f97dfb25a..a0c2076a01 100644 --- a/packages/components/pie-button/test/visual/pie-button-size.spec.ts +++ b/packages/components/pie-button/test/visual/pie-button-size.spec.ts @@ -25,6 +25,7 @@ const props: PropObject = { // Renders a HTML string with the given prop values const renderTestPieButton = (propVals: WebComponentPropValues) => `Hello world`; +const renderTestPieButtonLargeText = (propVals: WebComponentPropValues) => `This is a really long button string to test the overflow`; const componentPropsMatrix = getAllPropCombinations(props); @@ -55,3 +56,25 @@ test('should render all size variations', async ({ page, mount }) => { await percySnapshot(page, 'PIE Button - sizes/isResponsive/responsiveSize', percyWidths); }); + +test('should render all size variations, with larger button text string', async ({ page, mount }) => { + for (const combo of componentPropsMatrix) { + const testComponent = createTestWebComponent(combo, renderTestPieButtonLargeText); + const propKeyValues = `size: ${testComponent.propValues.size}, isResponsive: ${testComponent.propValues.isResponsive}, responsiveSize: ${testComponent.propValues.responsiveSize}`; + + await mount( + WebComponentTestWrapper, + { + props: { propKeyValues }, + slots: { + component: testComponent.renderedString.trim(), + }, + }, + ); + } + + // Follow up to remove in Jan + await page.waitForTimeout(2500); + + await percySnapshot(page, 'PIE Button - sizes/isResponsive/responsiveSize - double line text', percyWidths); +});