diff --git a/packages/ui/CHANGELOG.md b/packages/ui/CHANGELOG.md index 91370e60ceebe5..64f06b6b9f8e74 100644 --- a/packages/ui/CHANGELOG.md +++ b/packages/ui/CHANGELOG.md @@ -5,6 +5,7 @@ ### New Features - Add `Tabs` primitive ([#74652](https://github.com/WordPress/gutenberg/pull/74652)). +- Add `Textarea` primitive ([#74707](https://github.com/WordPress/gutenberg/pull/74707)). ### Enhancements diff --git a/packages/ui/src/form/primitives/index.ts b/packages/ui/src/form/primitives/index.ts index c5531ce572579b..4e6973efd0b084 100644 --- a/packages/ui/src/form/primitives/index.ts +++ b/packages/ui/src/form/primitives/index.ts @@ -3,3 +3,4 @@ export * as Fieldset from './fieldset'; export { Input } from './input'; export { InputLayout } from './input-layout'; export * as Select from './select'; +export { Textarea } from './textarea'; diff --git a/packages/ui/src/form/primitives/textarea/index.ts b/packages/ui/src/form/primitives/textarea/index.ts new file mode 100644 index 00000000000000..0c82925ff6c0fe --- /dev/null +++ b/packages/ui/src/form/primitives/textarea/index.ts @@ -0,0 +1 @@ +export { Textarea } from './textarea'; diff --git a/packages/ui/src/form/primitives/textarea/stories/index.story.tsx b/packages/ui/src/form/primitives/textarea/stories/index.story.tsx new file mode 100644 index 00000000000000..24479466b4e83c --- /dev/null +++ b/packages/ui/src/form/primitives/textarea/stories/index.story.tsx @@ -0,0 +1,40 @@ +import type { Meta, StoryObj } from '@storybook/react-vite'; +import { Textarea } from '../index'; + +const meta: Meta< typeof Textarea > = { + title: 'Design System/Components/Form/Primitives/Textarea', + component: Textarea, +}; +export default meta; + +type Story = StoryObj< typeof Textarea >; + +export const Default: Story = { + args: { + placeholder: 'Placeholder', + }, +}; + +export const Disabled: Story = { + args: { + ...Default.args, + disabled: true, + }, +}; + +export const WithOverflow: Story = { + args: { + ...Default.args, + defaultValue: `Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.`, + }, +}; + +/** + * When `rows` is set to `1`, the textarea will have the same footprint as a default `Input`. + */ +export const WithOneRow: Story = { + args: { + ...Default.args, + rows: 1, + }, +}; diff --git a/packages/ui/src/form/primitives/textarea/style.module.css b/packages/ui/src/form/primitives/textarea/style.module.css new file mode 100644 index 00000000000000..7447d1f290b32d --- /dev/null +++ b/packages/ui/src/form/primitives/textarea/style.module.css @@ -0,0 +1,22 @@ +@layer wp-ui-utilities, wp-ui-components, wp-ui-compositions, wp-ui-overrides; + +@layer wp-ui-components { + .wrapper { + --wp-ui-textarea-min-height: 40px; + } + + .textarea { + /* Prevents users from resizing the textarea below this height. */ + min-height: calc(var(--wp-ui-textarea-min-height) - 2px); + resize: block; + } +} + +@layer wp-ui-compositions { + .wrapper { + --wp-ui-input-padding-block: 9.9px; + + height: auto; + line-height: 1.4; /* TODO: Use variable */ + } +} diff --git a/packages/ui/src/form/primitives/textarea/test/index.test.tsx b/packages/ui/src/form/primitives/textarea/test/index.test.tsx new file mode 100644 index 00000000000000..04e194f31436f3 --- /dev/null +++ b/packages/ui/src/form/primitives/textarea/test/index.test.tsx @@ -0,0 +1,143 @@ +import { render, screen } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import { createRef, useState } from '@wordpress/element'; +import { Textarea } from '../index'; + +describe( 'Textarea', () => { + it( 'forwards ref', () => { + const ref = createRef< HTMLTextAreaElement >(); + + render(