-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: CrowdStrike/30-create-input-field
Adds Form::InputField component (in tests it's InputField) Adds tests for Form::InputField Adds docs
- Loading branch information
Showing
13 changed files
with
576 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
```hbs template | ||
<Form::InputField | ||
@label="Label" | ||
@hint="extra information about the field" | ||
type="text" | ||
@value="hello i am an input field" | ||
@onChange={{this.handleChange}} | ||
/> | ||
``` | ||
|
||
```js component | ||
import Component from '@glimmer/component'; | ||
import { action } from '@ember/object'; | ||
|
||
export default class extends Component { | ||
|
||
@action | ||
handleChange(value, event) { | ||
console.log({ value, event }); | ||
} | ||
} | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
# Input field | ||
|
||
Provides an underlying `<input>` element building on top of the Field component. | ||
|
||
## Label | ||
|
||
Provide a string to `@label` to render the text into the `<label>` of the Field. | ||
|
||
## Hint | ||
|
||
Provide a string to `@hint` to render the text into the Hint section of the Field. This is optional. | ||
|
||
## Error | ||
|
||
Provide a string to `@error` to render the text into the Error section of the Field. This is optional. | ||
|
||
## Value and onChange | ||
|
||
To tie into the input event, provide `@onChange`. `@onChange` will return two arguments, the first being the value, while the second being the raw event object. It's most common to use this in combination with `@value` which will set the value for the input based on the input received from the change event. | ||
|
||
```hbs | ||
<Form::InputField | ||
@label='Label' | ||
@value={{this.value}} | ||
@onChange={{this.handleChange}} | ||
/> | ||
``` | ||
|
||
```js | ||
import Component from '@glimmer/component'; | ||
import { action } from '@ember/object'; | ||
import { tracked } from '@glimmer/tracking'; | ||
export default class extends Component { | ||
@tracked value; | ||
@action | ||
handleChange(value, e) { | ||
console.log({ e, value }); | ||
this.value = value; | ||
} | ||
} | ||
``` | ||
|
||
## Disabled State | ||
|
||
Set the `@isDisabled` argument to disable the `<input>`. | ||
|
||
## Attributes and Modifiers | ||
|
||
Consumers have direct access to the underlying [input element](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input), so all attributes are supported. Modifiers can also be added directly to the input as shown in the demo. | ||
|
||
## Test Selectors | ||
|
||
### Root Element | ||
|
||
Provide a custom selector via `@rootTestSelector`. This test selector will be used as the value for the `data-root-field` attribute. The Field can be targeted via: | ||
|
||
```hbs | ||
<Form::InputField @label='Label' @rootTestSelector='example' /> | ||
``` | ||
|
||
```js | ||
assert.dom('[data-root-field="example"]'); | ||
// targeting this field's specific label | ||
assert.dom('[data-root-field="example"] > [data-label]'); | ||
``` | ||
|
||
### Label | ||
|
||
Target the label element via `data-label`. | ||
|
||
### Hint | ||
|
||
Target the hint block via `data-hint`. | ||
|
||
### Error | ||
|
||
Target the error block via `data-error`. | ||
|
||
## UI States | ||
|
||
### InputField with Label | ||
<div class="mb-4 w-64"> | ||
<Form::InputField | ||
@label="Label" | ||
type="text" | ||
/> | ||
</div> | ||
|
||
### InputField with Label and hint | ||
<div class="mb-4 w-64"> | ||
<Form::InputField | ||
@label="Label" | ||
@hint="With hint text" | ||
type="text" | ||
/> | ||
</div> | ||
|
||
### InputField with Label and error | ||
|
||
<div class="mb-4 w-64"> | ||
<Form::InputField | ||
@label="Label" | ||
type="text" | ||
@error="With error text" | ||
/> | ||
</div> | ||
|
||
### InputField with Label and isDisabled | ||
|
||
<div class="mb-4 w-64"> | ||
<Form::InputField | ||
@label="Label" | ||
type="text" | ||
@isDisabled={{true}} | ||
value="I am a disabled input field" | ||
/> | ||
</div> | ||
|
||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
```hbs template | ||
<Form::Controls::Input /> | ||
``` | ||
|
||
```js component | ||
import Component from '@glimmer/component'; | ||
|
||
export default class InputDemo extends Component {} | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
# Input | ||
|
||
Provides a Toucan-styled [input element](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input). If you are building forms, you may be interested in the InputField component instead. | ||
|
||
## Value | ||
|
||
To set the `value` attribute of the `<input>`, provide `@value`. | ||
|
||
```hbs | ||
<Form::Controls::Input @value='value' /> | ||
``` | ||
|
||
## onChange | ||
|
||
To tie into the input event, provide `@onChange`. `@onChange` will return two arguments, the first being the value, while the second being the raw event. | ||
|
||
```hbs | ||
<Form::Controls::Input | ||
@value={{this.value}} | ||
@onChange={{this.handleChange}} | ||
/> | ||
``` | ||
|
||
```js | ||
import Component from '@glimmer/component'; | ||
import { action } from '@ember/object'; | ||
import { tracked } from '@glimmer/tracking'; | ||
export default class extends Component { | ||
@tracked value; | ||
@action | ||
handleChange(value, e) { | ||
console.log({ e, value }); | ||
this.value = value; | ||
} | ||
} | ||
``` | ||
|
||
## Disabled State | ||
|
||
Set the `@isDisabled` argument to disable the `<input>`. | ||
|
||
## Error State | ||
Set the `@hasError` argument to apply an error box shadow to the `<input>`. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
<input | ||
class="bg-overlay-1 focus:outline-none focus:shadow-focus-outline block rounded-sm p-1 | ||
{{if @isDisabled 'text-disabled' 'text-titles-and-attributes'}} | ||
{{if @hasError 'shadow-error-outline' 'shadow-focusable-outline'}}" | ||
disabled={{@isDisabled}} | ||
value={{@value}} | ||
...attributes | ||
{{on "input" this.handleInput}} | ||
/> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
import Component from '@glimmer/component'; | ||
import { assert } from '@ember/debug'; | ||
import { action } from '@ember/object'; | ||
|
||
import type { OnChangeCallback } from '../../../-private/types'; | ||
|
||
interface ToucanFormControlsInputComponentSignature { | ||
Element: HTMLInputElement; | ||
Args: { | ||
hasError?: boolean; | ||
isDisabled?: boolean; | ||
onChange?: OnChangeCallback<string>; | ||
value?: string; | ||
}; | ||
} | ||
|
||
export default class ToucanFormControlsInputComponent extends Component<ToucanFormControlsInputComponentSignature> { | ||
@action | ||
handleInput(e: Event | InputEvent): void { | ||
assert('Expected HTMLInputElement', e.target instanceof HTMLInputElement); | ||
|
||
this.args.onChange?.(e.target.value, e); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
<div | ||
class="flex flex-col {{if @isDisabled 'text-disabled'}}" | ||
data-root-field={{if @rootTestSelector @rootTestSelector null}} | ||
> | ||
<Form::Field as |field|> | ||
<field.Label for={{field.id}} data-label>{{@label}}</field.Label> | ||
|
||
{{#if @hint}} | ||
<field.Hint id={{field.hintId}} data-hint>{{@hint}}</field.Hint> | ||
{{/if}} | ||
|
||
<field.Control class="flex"> | ||
<Form::Controls::Input | ||
id={{field.id}} | ||
aria-describedby="{{if @hint field.hintId}} {{if @error field.errorId}}" | ||
aria-invalid={{if @error "true"}} | ||
@isDisabled={{@isDisabled}} | ||
@value={{@value}} | ||
@onChange={{@onChange}} | ||
...attributes | ||
/> | ||
</field.Control> | ||
{{#if @error}} | ||
<field.Error id={{field.errorId}} data-error>{{@error}}</field.Error> | ||
{{/if}} | ||
</Form::Field> | ||
</div> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
import Component from '@glimmer/component'; | ||
import { assert } from '@ember/debug'; | ||
|
||
import type { OnChangeCallback } from '../../-private/types'; | ||
|
||
interface ToucanFormInputFieldComponentSignature { | ||
Element: HTMLInputElement; | ||
Args: { | ||
error?: string; | ||
label: string; | ||
hint?: string; | ||
isDisabled?: boolean; | ||
onChange?: OnChangeCallback<string>; | ||
rootTestSelector?: string; | ||
value?: string; | ||
}; | ||
Blocks: { | ||
default: []; | ||
}; | ||
} | ||
|
||
export default class ToucanFormInputFieldComponent extends Component<ToucanFormInputFieldComponentSignature> { | ||
constructor( | ||
owner: unknown, | ||
args: ToucanFormInputFieldComponentSignature['Args'] | ||
) { | ||
assert('input field requires a label', args.label !== undefined); | ||
super(owner, args); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,17 +1,21 @@ | ||
import type ButtonComponent from './components/button'; | ||
import type CheckboxFieldComponent from './components/form/checkbox-field'; | ||
import type CheckboxConrolComponent from './components/form/controls/checkbox'; | ||
import type CheckboxControlComponent from './components/form/controls/checkbox'; | ||
import type InputControlComponent from './components/form/controls/input'; | ||
import type TextareaControlComponent from './components/form/controls/textarea'; | ||
import type FieldComponent from './components/form/field'; | ||
import type FieldsetComponent from './components/form/fieldset'; | ||
import type InputFieldComponent from './components/form/input-field'; | ||
import type TextareaFieldComponent from './components/form/textarea-field'; | ||
|
||
export default interface Registry { | ||
Button: typeof ButtonComponent; | ||
'Form::Field': typeof FieldComponent; | ||
'Form::Fieldset': typeof FieldsetComponent; | ||
'Form::CheckboxField': typeof CheckboxFieldComponent; | ||
'Form::TextareaField': typeof TextareaFieldComponent; | ||
'Form::Controls::Checkbox': typeof CheckboxConrolComponent; | ||
'Form::InputField': typeof InputFieldComponent; | ||
'Form::Controls::Checkbox': typeof CheckboxControlComponent; | ||
'Form::Controls::Input': typeof InputControlComponent; | ||
'Form::Controls::Textarea': typeof TextareaControlComponent; | ||
'Form::TextareaField': typeof TextareaFieldComponent; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,36 @@ | ||
<h2 id="title">Welcome to Ember</h2> | ||
|
||
{{outlet}} | ||
{{! template-lint-disable require-input-label }} | ||
<Input /> | ||
{{! template-lint-disable require-input-label }} | ||
<Input hasError={{true}} /> | ||
<Input isDisabled={{true}} /> | ||
|
||
<Form::InputField @label="Label" @hint="hint text" type="text" /> | ||
|
||
<Form::InputField @label="Label" type="text" @error="There is an error" /> | ||
<Form::InputField @label="Label" type="text" @isDisabled={{true}} /> | ||
|
||
<Textarea /> | ||
<Textarea hasError={{true}} /> | ||
<Textarea isDisabled={{true}} /> | ||
|
||
<Form::TextareaField @label="Label" @hint="Hint text" /> | ||
<Form::TextareaField @label="Label" @hint="Hint text" @error="Error text" /> | ||
<Form::TextareaField | ||
@label="Label" | ||
@hint="Hint text" | ||
@error="Error text" | ||
isDisabled={{true}} | ||
/> | ||
|
||
<Form::Field as |field|> | ||
<field.Label>label</field.Label> | ||
<field.Hint>hint</field.Hint> | ||
{{! we'll handle the wiring of the label }} | ||
{{! template-lint-disable require-input-label }} | ||
<field.Control> | ||
<input type="text" /> | ||
</field.Control> | ||
<field.Error>error</field.Error> | ||
</Form::Field> |
Oops, something went wrong.