Skip to content

Commit

Permalink
feat(pie-monorepo): DSW-2056 resolve conflicts
Browse files Browse the repository at this point in the history
  • Loading branch information
kevinrodrigues committed Jul 11, 2024
2 parents b8924f5 + 8e4ab30 commit 0ebf772
Show file tree
Hide file tree
Showing 11 changed files with 654 additions and 285 deletions.
11 changes: 11 additions & 0 deletions .changeset/long-bottles-think.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
"@justeattakeaway/pie-textarea": minor
"pie-storybook": patch
---

[Added] - resize prop for textarea
[Added] - auto and manual sizing functionality
[Added] - styling for different sizes
[Added] - disabled and focus styles
[Added] - visual and component tests
[Changed] - update textarea storybook story
24 changes: 18 additions & 6 deletions apps/pie-storybook/stories/pie-textarea.stories.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ import { ifDefined } from 'lit/directives/if-defined.js';

/* eslint-disable import/no-duplicates */
import '@justeattakeaway/pie-textarea';
import { TextareaProps, defaultProps, sizes } from '@justeattakeaway/pie-textarea';
import {
TextareaProps, defaultProps, resizeModes, sizes,
} from '@justeattakeaway/pie-textarea';
/* eslint-enable import/no-duplicates */

import { type StoryMeta } from '../types';
Expand All @@ -21,7 +23,7 @@ const textareaStoryMeta: TextareaStoryMeta = {
description: 'If true, disables the textarea field.',
control: 'boolean',
defaultValue: {
summary: false,
summary: defaultProps.disabled,
},
},
size: {
Expand All @@ -32,6 +34,14 @@ const textareaStoryMeta: TextareaStoryMeta = {
summary: defaultProps.size,
},
},
resize: {
description: 'Controls the resizing behaviour of the textarea. Can be `auto` or `manual`. Defaults to `auto`.',
control: 'select',
options: resizeModes,
defaultValue: {
summary: defaultProps.resize,
},
},
},
args: defaultArgs,
parameters: {
Expand All @@ -44,12 +54,14 @@ const textareaStoryMeta: TextareaStoryMeta = {

const Template = ({
disabled,
resize,
size,
}: TextareaProps) => html`
<pie-textarea
?disabled="${disabled}"
size="${ifDefined(size)}">
</pie-textarea>
<pie-textarea
?disabled="${disabled}"
size="${ifDefined(size)}"
resize="${ifDefined(resize)}">
</pie-textarea>
`;

export const Default = createStory<TextareaProps>(Template, defaultArgs)();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -640,7 +640,7 @@ test.describe('Prop: `isFooterPinned`', () => {

test.describe('Prop: `hasStackedActions`', () => {
test.describe('when true', () => {
(['small', 'medium', 'large'] as Array<ModalProps['size']>)
sizes
.forEach((size) => {
test(`should display actions full width (at narrow viewports – with leading action on top) for a modal with size = ${size}`, async ({ page, mount }) => {
await mount(PieModal, {
Expand Down
9 changes: 5 additions & 4 deletions packages/components/pie-textarea/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,10 +72,11 @@ import { PieTextarea } from '@justeattakeaway/pie-textarea/dist/react';

## Props

| Property | Type | Default | Description |
|------------|----------------------------|----------|----------------------------------------------------|
| `disabled` | `boolean` | `false` | Indicates whether or not the textarea is disabled. |
| `size` | `small`, `medium`, `large` | `medium` | The size of the textarea field. |
| Property | Type | Default | Description |
| --- | --- | --- | --- |
| `disabled` | `boolean` | `false` | Indicates whether or not the textarea is disabled. |
| `size` | `"small"`, `"medium"`, `"large"` | `"medium"` | The size of the textarea field. |
| `resize` | `"auto"`, `"manual"` | `"auto"` | Controls the resizing behaviour of the textarea. |

In your markup or JSX, you can then use these to set the properties for the `pie-textarea` component:

Expand Down
4 changes: 3 additions & 1 deletion packages/components/pie-textarea/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,12 @@
"devDependencies": {
"@custom-elements-manifest/analyzer": "0.9.0",
"@justeattakeaway/pie-components-config": "0.16.0",
"@types/lodash.throttle": "4.1.9",
"cem-plugin-module-file-extensions": "0.0.5"
},
"dependencies": {
"@justeattakeaway/pie-webc-core": "0.24.0"
"@justeattakeaway/pie-webc-core": "0.24.0",
"lodash.throttle": "4.1.1"
},
"volta": {
"extends": "../../../package.json"
Expand Down
9 changes: 9 additions & 0 deletions packages/components/pie-textarea/src/defs.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { type ComponentDefaultProps } from '@justeattakeaway/pie-webc-core';

export const sizes = ['small', 'medium', 'large'] as const;
export const resizeModes = ['auto', 'manual'] as const;

export interface TextareaProps {
/**
Expand All @@ -12,6 +13,13 @@ export interface TextareaProps {
* The size of the textarea field. Can be `small`, `medium` or `large`. Defaults to `medium`.
*/
size?: typeof sizes[number];

/**
* The resize mode of the textarea. Can be `auto` or `manual`. Defaults to `auto`.
* When set to `auto`, the textarea will resize vertically as needed.
* When set to `manual`, the textarea will not resize automatically but can be resized by the user.
*/
resize?: typeof resizeModes[number];
}

/**
Expand All @@ -25,4 +33,5 @@ type DefaultProps = ComponentDefaultProps<TextareaProps>;
export const defaultProps: DefaultProps = {
disabled: false,
size: 'medium',
resize: 'auto',
};
49 changes: 40 additions & 9 deletions packages/components/pie-textarea/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
import { LitElement, html, unsafeCSS } from 'lit';
import { property } from 'lit/decorators.js';
import { ifDefined } from 'lit/directives/if-defined.js';
import {
LitElement, html, unsafeCSS, PropertyValues,
} from 'lit';
import { property, query } from 'lit/decorators.js';
import throttle from 'lodash.throttle';

import { validPropertyValues, RtlMixin, defineCustomElement } from '@justeattakeaway/pie-webc-core';

import styles from './textarea.scss?inline';
import { TextareaProps, defaultProps, sizes } from './defs';
import {
TextareaProps, defaultProps, sizes, resizeModes,
} from './defs';

// Valid values available to consumers
export * from './defs';
Expand All @@ -19,25 +23,52 @@ export class PieTextarea extends RtlMixin(LitElement) implements TextareaProps {
static shadowRootOptions = { ...LitElement.shadowRootOptions, delegatesFocus: true };

@property({ type: Boolean, reflect: true })
public disabled?: TextareaProps['disabled'];
public disabled = defaultProps.disabled;

@property({ type: String })
@validPropertyValues(componentSelector, sizes, defaultProps.size)
public size?: TextareaProps['size'] = defaultProps.size;
public size = defaultProps.size;

@property({ type: String })
@validPropertyValues(componentSelector, resizeModes, defaultProps.resize)
public resize = defaultProps.resize;

@query('textarea')
private _textarea!: HTMLTextAreaElement;

private _throttledResize = throttle(() => {
if (this.resize === 'auto') {
this._textarea.style.height = 'auto';
this._textarea.style.height = `${this._textarea.scrollHeight + 2}px`; // +2 for border thicknesses
}
}, 100);

private handleResize () {
this._throttledResize();
}

updated (changedProperties: PropertyValues<this>) {
if (this.resize === 'auto' && (changedProperties.has('resize') || changedProperties.has('size'))) {
this.handleResize();
}
}

render () {
const {
disabled,
resize,
size,
} = this;

return html`
<div
class="c-textarea"
data-test-id="pie-textarea-shell"
data-pie-size=${ifDefined(size)}>
class="c-textareaWrapper"
data-test-id="pie-textarea-wrapper"
data-pie-size="${size}"
data-pie-resize="${resize}">
<textarea
data-test-id="pie-textarea"
@input=${this.handleResize}
?disabled=${disabled}
></textarea>
</div>`;
Expand Down
85 changes: 76 additions & 9 deletions packages/components/pie-textarea/src/textarea.scss
Original file line number Diff line number Diff line change
@@ -1,22 +1,89 @@
@use '@justeattakeaway/pie-css/scss' as p;

.c-textarea {
--textarea-height: 72px;
// Heights are being defined based on the line height of the text and the padding.
// Changing the `size` property affects the padding and therefore the height of the textarea.
// Default height is two lines of text.
// Minimum height in manual resize mode is one line of text.
// Maximum height in auto resize mode is six lines of text.
.c-textareaWrapper {
--textarea-line-height: #{p.line-height(--dt-font-body-l-line-height)};
--textarea-border-thickness: 1px;
--textarea-resize: none;
--textarea-padding-inline: var(--dt-spacing-d);
--textarea-padding-block: var(--dt-spacing-c);
--textarea-background-color: var(--dt-color-container-default);
--textarea-border-color: var(--dt-color-interactive-form);
--textarea-content-color: var(--dt-color-content-default);

height: var(--textarea-height);
// Default height is two lines of text
--textarea-height: calc((var(--textarea-line-height) * 2) + (var(--textarea-padding-block) * 2) + (var(--textarea-border-thickness) * 2));

line-height: 0; // Remove once there is text outside the textarea

textarea {
@include p.font-size(--dt-font-body-l-size);
line-height: var(--textarea-line-height);
font-family: var(--dt-font-body-l-family);
resize: var(--textarea-resize);
border: var(--textarea-border-thickness) solid var(--textarea-border-color);
background-color: var(--textarea-background-color);
color: var(--textarea-content-color);

border-radius: var(--dt-radius-rounded-c);
block-size: var(--textarea-height);
max-block-size: var(--textarea-max-height);
min-block-size: var(--textarea-min-height);

padding-block-start: var(--textarea-padding-block);
padding-block-end: var(--textarea-padding-block);
padding-inline-start: var(--textarea-padding-inline);
padding-inline-end: var(--textarea-padding-inline);

&[disabled] {
--textarea-background-color: var(--dt-color-disabled-01);
--textarea-border-color: var(--dt-color-disabled-01);
--textarea-content-color: var(--dt-color-content-disabled);
}

@media (hover: hover) {
&:hover:not([disabled]) {
--textarea-background-color: hsl(var(--dt-color-container-default-h), var(--dt-color-container-default-s), calc(var(--dt-color-container-default-l) + calc(-1 * var(--dt-color-hover-01))));
}
}

&:focus-visible {
@include p.focus;
}
}

&[data-pie-size="large"] {
--textarea-height: 80px;
--textarea-padding-block: var(--dt-spacing-d);
}

&[data-pie-size="small"] {
--textarea-height: 64px;
--textarea-padding-block: var(--dt-spacing-b);
}

textarea {
width: 100%;
height: 100%;
&[data-pie-resize="manual"] {
--textarea-resize: vertical;

// Minimum is one line of text
--textarea-min-height: calc((var(--textarea-line-height) * 1) + (var(--textarea-padding-block) * 2) + (var(--textarea-border-thickness) * 2)); // One line of text

@media (pointer: coarse) {
// Fixed size for touch devices
--textarea-height: calc((var(--textarea-line-height) * 6) + (var(--textarea-padding-block) * 2) + (var(--textarea-border-thickness) * 2));
--textarea-min-height: calc((var(--textarea-line-height) * 6) + (var(--textarea-padding-block) * 2) + (var(--textarea-border-thickness) * 2));
--textarea-max-height: calc((var(--textarea-line-height) * 6) + (var(--textarea-padding-block) * 2) + (var(--textarea-border-thickness) * 2));
--textarea-resize: none;
}
}
}

&[data-pie-resize="auto"] {
// Maximum is six lines of text
--textarea-max-height: calc((var(--textarea-line-height) * 6) + (var(--textarea-padding-block) * 2) + (var(--textarea-border-thickness) * 2));

// Minimum is two lines of text
--textarea-min-height: var(--textarea-height);
}
}
Loading

0 comments on commit 0ebf772

Please sign in to comment.