Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions packages/storybook/src/stories/text-area.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { ScoutTextArea } from "@scouterna/ui-react";
import preview from "#.storybook/preview";

const meta = preview.meta({
title: "Uncategorized/Text-Area",
component: ScoutTextArea,
parameters: {
layout: "centered",
},
});

export default meta;

export const BasicExample = meta.story({
args: {
label: "",
},
render: (args) => <ScoutTextArea {...args} />,
});
12 changes: 12 additions & 0 deletions packages/ui-react/lib/components/stencil-generated/components.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { ScoutInput as ScoutInputElement, defineCustomElement as defineScoutInpu
import { ScoutListViewItem as ScoutListViewItemElement, defineCustomElement as defineScoutListViewItem } from "@scouterna/ui-webc/dist/components/scout-list-view-item.js";
import { ScoutListView as ScoutListViewElement, defineCustomElement as defineScoutListView } from "@scouterna/ui-webc/dist/components/scout-list-view.js";
import { ScoutSwitch as ScoutSwitchElement, defineCustomElement as defineScoutSwitch } from "@scouterna/ui-webc/dist/components/scout-switch.js";
import { ScoutTextArea as ScoutTextAreaElement, defineCustomElement as defineScoutTextArea } from "@scouterna/ui-webc/dist/components/scout-text-area.js";
import type { EventName, StencilReactComponent } from '@stencil/react-output-target/runtime';
import { createComponent } from '@stencil/react-output-target/runtime';
import React from 'react';
Expand Down Expand Up @@ -172,3 +173,14 @@ export const ScoutSwitch: StencilReactComponent<ScoutSwitchElement, ScoutSwitchE
} as ScoutSwitchEvents,
defineCustomElement: defineScoutSwitch
});

export type ScoutTextAreaEvents = NonNullable<unknown>;

export const ScoutTextArea: StencilReactComponent<ScoutTextAreaElement, ScoutTextAreaEvents> = /*@__PURE__*/ createComponent<ScoutTextAreaElement, ScoutTextAreaEvents>({
tagName: 'scout-text-area',
elementClass: ScoutTextAreaElement,
// @ts-ignore - ignore potential React type mismatches between the Stencil Output Target and your project.
react: React,
events: {} as ScoutTextAreaEvents,
defineCustomElement: defineScoutTextArea
});
37 changes: 37 additions & 0 deletions packages/ui-webc/src/components.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,20 @@ export namespace Components {
*/
"toggled": boolean;
}
interface ScoutTextArea {
/**
* @default false
*/
"autofocus": boolean;
"disabled"?: boolean;
"form": string;
"label"?: string;
"maxLength"?: number;
"placeholder"?: string;
"readOnly"?: boolean;
"required"?: boolean;
"value"?: string;
}
}
export interface ScoutBottomBarItemCustomEvent<T> extends CustomEvent<T> {
detail: T;
Expand Down Expand Up @@ -346,6 +360,12 @@ declare global {
prototype: HTMLScoutSwitchElement;
new (): HTMLScoutSwitchElement;
};
interface HTMLScoutTextAreaElement extends Components.ScoutTextArea, HTMLStencilElement {
}
var HTMLScoutTextAreaElement: {
prototype: HTMLScoutTextAreaElement;
new (): HTMLScoutTextAreaElement;
};
interface HTMLElementTagNameMap {
"scout-bottom-bar": HTMLScoutBottomBarElement;
"scout-bottom-bar-item": HTMLScoutBottomBarItemElement;
Expand All @@ -358,6 +378,7 @@ declare global {
"scout-list-view": HTMLScoutListViewElement;
"scout-list-view-item": HTMLScoutListViewItemElement;
"scout-switch": HTMLScoutSwitchElement;
"scout-text-area": HTMLScoutTextAreaElement;
}
}
declare namespace LocalJSX {
Expand Down Expand Up @@ -536,6 +557,20 @@ declare namespace LocalJSX {
*/
"toggled"?: boolean;
}
interface ScoutTextArea {
/**
* @default false
*/
"autofocus"?: boolean;
"disabled"?: boolean;
"form"?: string;
"label"?: string;
"maxLength"?: number;
"placeholder"?: string;
"readOnly"?: boolean;
"required"?: boolean;
"value"?: string;
}
interface IntrinsicElements {
"scout-bottom-bar": ScoutBottomBar;
"scout-bottom-bar-item": ScoutBottomBarItem;
Expand All @@ -548,6 +583,7 @@ declare namespace LocalJSX {
"scout-list-view": ScoutListView;
"scout-list-view-item": ScoutListViewItem;
"scout-switch": ScoutSwitch;
"scout-text-area": ScoutTextArea;
}
}
export { LocalJSX as JSX };
Expand Down Expand Up @@ -579,6 +615,7 @@ declare module "@stencil/core" {
"scout-list-view": LocalJSX.ScoutListView & JSXBase.HTMLAttributes<HTMLScoutListViewElement>;
"scout-list-view-item": LocalJSX.ScoutListViewItem & JSXBase.HTMLAttributes<HTMLScoutListViewItemElement>;
"scout-switch": LocalJSX.ScoutSwitch & JSXBase.HTMLAttributes<HTMLScoutSwitchElement>;
"scout-text-area": LocalJSX.ScoutTextArea & JSXBase.HTMLAttributes<HTMLScoutTextAreaElement>;
}
}
}
23 changes: 23 additions & 0 deletions packages/ui-webc/src/components/text-area/readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# scout-text-area

<!-- Auto Generated Below -->


## Properties

| Property | Attribute | Description | Type | Default |
| ------------- | ------------- | ----------- | --------- | ----------- |
| `autofocus` | `autofocus` | | `boolean` | `false` |
| `disabled` | `disabled` | | `boolean` | `undefined` |
| `form` | `form` | | `string` | `undefined` |
| `label` | `label` | | `string` | `undefined` |
| `maxLength` | `max-length` | | `number` | `undefined` |
| `placeholder` | `placeholder` | | `string` | `undefined` |
| `readOnly` | `read-only` | | `boolean` | `undefined` |
| `required` | `required` | | `boolean` | `undefined` |
| `value` | `value` | | `string` | `undefined` |


----------------------------------------------

*Built with [StencilJS](https://stenciljs.com/)*
21 changes: 21 additions & 0 deletions packages/ui-webc/src/components/text-area/text-area.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
:host {
display: inline-flex;
}

.flexbox{
display: inline-flex;
flex-direction: column;
padding: 0.5rem;
}

.textarea{
resize: none;
height: var(--spacing-24);
width: var(--spacing-50);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should keep the width and height unset so that the consumer can choose how to size the component. What we could do instead is expose the rows attribute as a prop and maybe set it to a higher default, say 3?

padding: var(--spacing-2);
font: var(--type-body-base);
border: 1px solid var(--color-gray-300);
border-radius: var(--spacing-2);
background-color: var(--color-white);
color: var(--color-text-base);
}
50 changes: 50 additions & 0 deletions packages/ui-webc/src/components/text-area/text-area.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { Component, h, Prop } from "@stencil/core";

@Component({
tag: "scout-text-area",
styleUrl: "text-area.css",
shadow: {
delegatesFocus: true,
},
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Related to other comment about adding support for the Field component, you'll have to disable the shadow DOM and use scoped styles for it to work:

Suggested change
shadow: {
delegatesFocus: true,
},
scoped: true,

})

export class ScoutTextArea {
@Prop() autofocus: boolean = false;

@Prop() disabled?: boolean;

@Prop() form: string;

@Prop() maxLength?: number;

@Prop() placeholder?: string;

@Prop() readOnly?: boolean;

@Prop() required?: boolean;

@Prop() value?: string;

@Prop() label?: string;

render() {
return (
<div class="flexbox">
<label>
{this.label}
</label>
<textarea
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we also add the name prop? Just realized we're missing that on all inputs. I'll add it to the others in a separate PR 😊

class="textarea"
autofocus={this.autofocus}
disabled={this.disabled}
form={this.form}
maxLength={this.maxLength}
placeholder={this.placeholder}
readOnly={this.readOnly}
required={this.required}
value={this.value}
/>
</div>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice that you've added a label as well! We've set up a generic Field component that wraps all input type components. I forgot to tell you about that, sorry 😣 I think we should add support for that here as well and remove the label from this component. In other words:

  1. Remove the div and label so that only the textarea is left.
  2. Implement the following from the Input component (reference code):
    1. Add the scoutInputChange event that tells the form field about changes that should cause re-validation.
    2. Add the scoutBlur event that tells the form field that the field is ready to be validated.
    3. Add the internal _fieldId event that's used by the form field to connect it to the text area.
    4. Add the internal ariaId state that keeps track of the internal ID used for connecting to form field.
    5. Assign the ariaId state in the componentWillLoad hook.
    6. Handle the onInput event and potential validation.
  3. See other comment about shadow DOM.
  4. Finally you might want to add another story in field.stories.tsx to test it out together, like we did for the input.

);
}
}
Loading