Skip to content

Commit

Permalink
Improve UX for string-based EditableFields (#301)
Browse files Browse the repository at this point in the history
* Fixes to EditableTextField

* Add tests

* Tests, documentation and cleanup
  • Loading branch information
jeffdaley authored Aug 23, 2023
1 parent b6fa8c9 commit b82acac
Show file tree
Hide file tree
Showing 10 changed files with 696 additions and 263 deletions.
26 changes: 10 additions & 16 deletions web/app/components/custom-editable-field.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -6,27 +6,21 @@
@loading={{@loading}}
@disabled={{@disabled}}
>
<:default>
{{#let (get @document @field) as |documentField|}}
<p
class="hds-typography-body-200 hds-foreground-primary truncate
{{unless documentField 'italic'}}"
title="{{or documentField 'None'}}"
>
{{#if documentField}}
{{documentField}}
{{else}}
<CustomEditableFields::EmptyState />
{{/if}}
<:default as |F|>
{{#if F.value}}
<p class="truncate text-body-200" title={{F.value}}>
{{F.value}}
</p>
{{/let}}
{{else}}
<CustomEditableFields::EmptyState />
{{/if}}
</:default>
<:editing as |F|>
<Hds::Form::Textarea::Field
{{F.input}}
{{auto-height-textarea}}
@value={{F.value}}
name={{@field}}
{{auto-height-textarea}}
{{on "blur" F.update}}
data-test-custom-string-field-input
/>
</:editing>
Expand All @@ -48,7 +42,7 @@
{{#if person.imgURL}}
<img
src="{{person.imgURL}}"
class="align-middle h-4 w-4 rounded-full"
class="h-4 w-4 rounded-full align-middle"
/>
{{/if}}
{{person.email}}
Expand Down
18 changes: 18 additions & 0 deletions web/app/components/custom-editable-fields/empty-state.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import Component from '@glimmer/component';

interface CustomEditableFieldsEmptyStateComponentSignature {
Element: null;
Args: {
};
Blocks: {
};
}

export default class CustomEditableFieldsEmptyStateComponent extends Component<CustomEditableFieldsEmptyStateComponentSignature> {
}

declare module '@glint/environment-ember-loose/registry' {
export default interface Registry {
'CustomEditableFields::EmptyState': typeof CustomEditableFieldsEmptyStateComponent;
}
}
252 changes: 99 additions & 153 deletions web/app/components/document/sidebar.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -98,94 +98,75 @@
</X::DropdownList>
{{/if}}
</div>
{{#if this.isOwner}}
<div class="mb-8">
<EditableField
data-test-document-title-editable
@value={{this.title}}
@onChange={{perform this.save "title"}}
@loading={{this.save.isRunning}}
@disabled={{this.editingIsDisabled}}
>
<:default>
{{#unless (is-empty this.title)}}
<h1
class="hds-typography-display-300 hds-font-weight-semibold hds-foreground-strong"
>{{this.title}}</h1>
{{else}}
<h1
data-test-document-title-read-only
class="hds-typography-display-300 hds-font-weight-semibold hds-foreground-faint"
>
Enter a title here.
</h1>
{{/unless}}
</:default>
<:editing as |F|>
<Hds::Form::Textarea::Field
{{auto-height-textarea}}
@value={{F.value}}
class="primary-textarea"
name="title"
{{on "blur" F.update}}
as |F|
/>
</:editing>
</EditableField>
</div>
{{else}}
<h1
data-test-document-title-read-only
class="hds-typography-display-300 hds-font-weight-semibold hds-foreground-strong"
>{{this.title}}</h1>
{{/if}}
</div>

<hr class="hds-border-faint border-0 border-b" />

{{! Summary }}
<div class="mb-5">
<Document::Sidebar::SectionHeader @title="Summary" class="mb-2" />
{{#if this.isOwner}}
<div class="mb-8">
<EditableField
data-test-document-summary-editable
@value={{this.summary}}
@onChange={{perform this.save "summary"}}
data-test-document-title
data-test-editable={{this.isOwner}}
@value={{this.title}}
@onChange={{this.updateTitle}}
@loading={{this.save.isRunning}}
@disabled={{this.editingIsDisabled}}
@disabled={{not this.isOwner}}
@isRequired={{true}}
>
<:default>
{{#unless (is-empty this.summary)}}
<p
class="hds-typography-body-200 hds-font-weight-medium hds-foreground-primary"
>
{{this.summary}}</p>
{{else}}
<p
class="hds-typography-body-200 hds-font-weight-medium hds-foreground-faint"
>
Enter a summary here.</p>
{{/unless}}
<:default as |F|>
<h1
class="hds-typography-display-300 hds-font-weight-semibold hds-foreground-strong"
>
{{F.value}}
</h1>
</:default>
<:editing as |F|>
<Hds::Form::Textarea::Field
data-test-document-title-editable-field
{{F.input}}
{{auto-height-textarea}}
@value={{F.value}}
class="primary-textarea"
name="summary"
{{on "blur" F.update}}
as |F|
/>
name="title"
as |FF|
>
{{#if F.emptyValueErrorIsShown}}
<FF.Error>
Title is required.
</FF.Error>
{{/if}}
</Hds::Form::Textarea::Field>
</:editing>
</EditableField>
{{else}}
<p
data-test-document-summary-read-only
class="hds-typography-body-200 hds-font-weight-medium hds-foreground-primary"
>
{{this.summary}}
</p>
{{/if}}
</div>
</div>

<hr class="hds-border-faint border-0 border-b" />

{{! Summary }}
<div class="mb-5">
<Document::Sidebar::SectionHeader @title="Summary" class="mb-2" />
<EditableField
data-test-document-summary
data-test-editable={{this.isOwner}}
@value={{this.summary}}
@onChange={{perform this.updateSummary}}
@loading={{this.save.isRunning}}
@disabled={{not this.isOwner}}
>
<:default as |F|>
<p
class="hds-typography-body-200 hds-font-weight-medium hds-foreground-primary"
>
{{or F.value "Enter a summary"}}
</p>
</:default>
<:editing as |F|>
<Hds::Form::Textarea::Field
data-test-document-summary-editable-field
{{F.input}}
{{auto-height-textarea}}
@value={{F.value}}
class="primary-textarea"
name="summary"
/>
</:editing>
</EditableField>
</div>

<div class="flex flex-col items-start space-y-2">
Expand Down Expand Up @@ -227,41 +208,15 @@

<div class="flex flex-col items-start space-y-2">
<Document::Sidebar::SectionHeader @title="Contributors" />
{{#if this.isOwner}}
<EditableField
data-test-document-contributors-editable
@value={{this.contributors}}
@onChange={{perform this.save "contributors"}}
@loading={{this.save.isRunning}}
@disabled={{this.editingIsDisabled}}
>
<:default>
{{#if this.contributors.length}}
<ol class="person-list">
{{#each this.contributors as |contributor|}}
<li>
<Person
@imgURL={{contributor.imgURL}}
@email={{contributor.email}}
/>
</li>
{{/each}}
</ol>
{{else}}
<em>No contributors</em>
{{/if}}
</:default>
<:editing as |F|>
<Inputs::PeopleSelect
class="multiselect--narrow"
@selected={{this.contributors}}
@onChange={{this.updateContributors}}
{{click-outside (fn F.update this.contributors)}}
/>
</:editing>
</EditableField>
{{else}}
<div data-test-document-contributors-read-only>
<EditableField
data-test-document-contributors
data-test-editable={{this.isOwner}}
@value={{this.contributors}}
@onChange={{perform this.save "contributors"}}
@loading={{this.save.isRunning}}
@disabled={{not this.isOwner}}
>
<:default>
{{#if this.contributors.length}}
<ol class="person-list">
{{#each this.contributors as |contributor|}}
Expand All @@ -276,48 +231,30 @@
{{else}}
<em>No contributors</em>
{{/if}}
</div>
{{/if}}
</:default>
<:editing as |F|>
<Inputs::PeopleSelect
data-test-document-contributors-editable
class="multiselect--narrow"
@selected={{this.contributors}}
@onChange={{this.updateContributors}}
{{click-outside (fn F.update this.contributors)}}
/>
</:editing>
</EditableField>
</div>

<div class="flex flex-col items-start space-y-2">
<Document::Sidebar::SectionHeader @title="Approvers" />
{{#if this.isOwner}}
<EditableField
data-test-document-approvers-editable
@value={{this.approvers}}
@onChange={{perform this.save "approvers"}}
@loading={{this.save.isRunning}}
@disabled={{this.editingIsDisabled}}
>
<:default>
{{#if this.approvers.length}}
<ol class="person-list">
{{#each this.approvers as |approver|}}
<li>
<Person::Approver
@document={{@document}}
@imgURL={{approver.imgURL}}
@email={{approver.email}}
/>
</li>
{{/each}}
</ol>
{{else}}
<em>No approvers</em>
{{/if}}
</:default>
<:editing as |F|>
<Inputs::PeopleSelect
class="multiselect--narrow"
@selected={{this.approvers}}
@onChange={{this.updateApprovers}}
{{click-outside (fn F.update this.approvers)}}
/>
</:editing>
</EditableField>
{{else}}
<div data-test-document-approvers-read-only>
<EditableField
data-test-document-approvers
data-test-editable={{this.isOwner}}
@value={{this.approvers}}
@onChange={{perform this.save "approvers"}}
@loading={{this.save.isRunning}}
@disabled={{this.editingIsDisabled}}
>
<:default>
{{#if this.approvers.length}}
<ol class="person-list">
{{#each this.approvers as |approver|}}
Expand All @@ -333,8 +270,17 @@
{{else}}
<em>No approvers</em>
{{/if}}
</div>
{{/if}}
</:default>
<:editing as |F|>
<Inputs::PeopleSelect
data-test-document-approvers-editable
class="multiselect--narrow"
@selected={{this.approvers}}
@onChange={{this.updateApprovers}}
{{click-outside (fn F.update this.approvers)}}
/>
</:editing>
</EditableField>
</div>

<div class="flex flex-col items-start space-y-2">
Expand Down Expand Up @@ -374,7 +320,7 @@
@attributes={{attributes}}
@onChange={{perform this.save field}}
@loading={{this.save.isRunning}}
@disabled={{this.editingIsDisabled}}
@disabled={{not this.isOwner}}
/>
</div>
{{/if}}
Expand Down
Loading

0 comments on commit b82acac

Please sign in to comment.