Skip to content

Commit aa9d809

Browse files
authored
Draft permissions UI (#255)
* WIP sidebar tweaks * Prototype success animation * Improved animations and icon-display logic * Prep for loading state * Update index.ts * Create index.hbs * Move folders * Popover tweak, type fixes * Cleanup, style tweaks * WIP Tooltip states * Improve most UX bugs * Add isSelected check * Copy and design tweaks * WIP: Tooltip delay * Add delay to tooltip * Reduce default delay * Cleanup and documentation * Cleanup and documentation * Add open animation * WIP tile styles * Update thumbnail.hbs * Badge style tweaks * Add default animation * Update tooltip.ts * Update sidebar.scss * Update sidebar.hbs * Basic wiring up * Update copyable URL (draft) * Add documentation to CopyURL * Revert out-of-scope changes * Revert drastic design changes * Rename a prop * Improve UI reactivity * Remove unused property * Remove unused import * Rename didInsert * Documentation and dasherize test * Remove old code, unused color variables * CSS tweak * Add CopyURLButton tests * Additional tests and cleanup * Fix failing tests
1 parent 295e045 commit aa9d809

File tree

14 files changed

+822
-93
lines changed

14 files changed

+822
-93
lines changed
Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
1-
{{! @glint-nocheck: not typesafe yet }}
21
<Action
32
data-test-copy-url-button
3+
data-test-url={{@url}}
4+
data-test-icon={{this.icon}}
45
{{tooltip
5-
(if this.urlWasRecentlyCopied "Copied!" "Copy URL")
6-
placement=(or @tooltipPlacement "top")
6+
this.tooltipText
7+
placement=@tooltipPlacement
8+
isForcedOpen=this.tooltipIsForcedOpen
79
stayOpenOnClick=true
810
}}
911
{{did-insert this.didInsertButton}}
1012
{{on "click" (perform this.copyURL)}}
1113
...attributes
1214
>
13-
<FlightIcon @name={{if this.urlWasRecentlyCopied "check" "link"}} />
15+
<FlightIcon @name={{this.icon}} />
1416
</Action>

web/app/components/copy-u-r-l-button.ts

Lines changed: 47 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@ interface CopyURLButtonComponentSignature {
1313
Args: {
1414
url: string;
1515
tooltipPlacement?: Placement;
16+
tooltipIsForcedOpen?: boolean;
17+
tooltipText?: string;
18+
icon?: string;
1619
};
1720
}
1821

@@ -21,20 +24,55 @@ export default class CopyURLButtonComponent extends Component<CopyURLButtonCompo
2124

2225
/**
2326
* Whether the URL was recently copied to the clipboard.
24-
* Used to determine if the tooltip should say "Copy URL" or "Copied."
27+
* Used to determine if the tooltip should say "Copy link" or "Copied."
2528
* Temporarily set true when the URL is successfully copied.
2629
*/
2730
@tracked protected urlWasRecentlyCopied = false;
2831

2932
/**
30-
* The button element.
33+
* The button element, captured on render.
3134
* Used to get the tooltip's ID by way of the `aria-describedby` attribute.
3235
*/
3336
@tracked private button: HTMLElement | null = null;
3437

38+
/**
39+
* Whether the tooltip is forced open regardless of hover state.
40+
* True when the parent has provided text for the tooltip,
41+
* such as "Creating link..." and "Link created!"
42+
*/
43+
protected get tooltipIsForcedOpen() {
44+
return this.args.tooltipIsForcedOpen ?? false;
45+
}
46+
47+
/**
48+
* The icon to show in the button.
49+
* If the parent has provided an icon, e.g., "loading," use that.
50+
* Otherwise use use "link" or, if a URL was recently copied, "check."
51+
*/
52+
protected get icon() {
53+
if (this.args.icon) {
54+
return this.args.icon;
55+
} else {
56+
return this.urlWasRecentlyCopied ? "check" : "link";
57+
}
58+
}
59+
60+
/**
61+
* The text to show in the tooltip.
62+
* If the parent has provided text, e.g., "Loading," use that.
63+
* Otherwise use "Copy link" or, if a URL was recently copied, "Link copied!"
64+
*/
65+
get tooltipText(): string {
66+
if (this.args.tooltipText) {
67+
return this.args.tooltipText;
68+
} else {
69+
return this.urlWasRecentlyCopied ? "Link copied!" : "Copy link";
70+
}
71+
}
72+
3573
/**
3674
* The action called when the button is clicked.
37-
* Registers the button element locally.
75+
* Registers the button locally for its `aria-describedby` attribute.
3876
*/
3977
@action protected didInsertButton(e: HTMLElement) {
4078
this.button = e;
@@ -83,3 +121,9 @@ export default class CopyURLButtonComponent extends Component<CopyURLButtonCompo
83121
}
84122
});
85123
}
124+
125+
declare module "@glint/environment-ember-loose/registry" {
126+
export default interface Registry {
127+
CopyURLButton: typeof CopyURLButtonComponent;
128+
}
129+
}

web/app/components/document/sidebar.hbs

Lines changed: 111 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,16 @@
33
@isCollapsed={{@isCollapsed}}
44
@toggleCollapsed={{@toggleCollapsed}}
55
@userHasScrolled={{this.userHasScrolled}}
6+
@shareButtonIsShown={{this.shareButtonIsShown}}
7+
@shareButtonTooltipText={{this.temporaryShareButtonTooltipText}}
8+
@shareButtonIcon={{this.temporaryShareButtonIcon}}
69
/>
710

811
{{#unless @isCollapsed}}
912
<div
1013
class="sidebar-body"
1114
{{on "scroll" this.onScroll}}
12-
{{did-insert this.registerBody}}
15+
{{did-insert this.didInsertBody}}
1316
>
1417
{{#let (get-product-id this.product) as |productIcon|}}
1518
{{#if productIcon}}
@@ -24,62 +27,119 @@
2427
{{/let}}
2528

2629
<div class="sidebar-body-container">
27-
<div class="flex flex-col items-start space-y-2">
28-
{{#if (is-empty @document.docNumber)}}
29-
<small class="hds-typography-body-100 hds-foreground-faint">{{#unless
30-
(is-empty @document.docType)
31-
}}{{@document.docType}}{{/unless}}
32-
</small>
33-
{{else}}
34-
<small class="hds-typography-body-100 hds-foreground-faint">{{#unless
35-
(is-empty @document.docType)
36-
}}{{@document.docType}}{{/unless}}
37-
&bullet;
38-
<span data-test-sidebar-doc-number>
39-
{{@document.docNumber}}
40-
</span>
41-
</small>
42-
{{/if}}
30+
<div>
31+
{{! div to break the parent's space-y styles }}
32+
<div
33+
class="flex items-center space-x-1.5
34+
{{if this.isDraft 'mb-4 -mt-2' 'mb-2'}}"
35+
>
36+
<Hds::Badge
37+
data-test-sidebar-title-badge
38+
@text={{if this.isDraft "Draft" @document.docNumber}}
39+
class="uppercase !rounded-[3px]
40+
{{if
41+
@document.isDraft
42+
'!bg-color-palette-neutral-500 !text-white'
43+
'!bg-transparent pl-0 !text-color-foreground-faint'
44+
}}
45+
"
46+
/>
47+
{{#if this.isDraft}}
48+
<X::DropdownList
49+
data-test-draft-visibility-dropdown
50+
@items={{this.draftVisibilityOptions}}
51+
@selected={{this.draftVisibility}}
52+
@renderOut={{true}}
53+
@offset={{hash mainAxis=0 crossAxis=-7}}
54+
class="w-[350px]"
55+
>
56+
<:anchor as |dd|>
57+
<dd.ToggleAction
58+
data-test-draft-visibility-toggle
59+
data-test-icon={{this.draftVisibilityIcon}}
60+
data-test-chevron-direction={{if
61+
dd.contentIsShown
62+
"up"
63+
"down"
64+
}}
65+
class="flex items-center text-color-foreground-faint sidebar-header-button draft-visibility-button"
66+
{{tooltip
67+
this.toggleDraftVisibilityTooltipText
68+
placement="bottom"
69+
}}
70+
>
71+
<FlightIcon @name={{this.draftVisibilityIcon}} />
72+
<FlightIcon
73+
@name={{if dd.contentIsShown "chevron-up" "chevron-down"}}
74+
/>
75+
</dd.ToggleAction>
76+
</:anchor>
77+
<:item as |dd|>
78+
<dd.Action
79+
data-test-draft-visibility-option
80+
data-test-is-checked={{dd.isSelected}}
81+
data-test-value={{dd.value}}
82+
class="flex items-start gap-3 py-2.5 pl-4 pr-6"
83+
{{on "click" (perform this.setDraftVisibility dd.value)}}
84+
>
85+
<FlightIcon @name={{dd.attrs.icon}} class="shrink-0 mt-0.5" />
86+
<div class="w-full">
87+
<h4>{{dd.attrs.title}}</h4>
88+
<p>{{dd.attrs.description}}</p>
89+
</div>
90+
<FlightIcon
91+
@name="check"
92+
class="check shrink-0 mt-0.5
93+
{{if dd.isSelected 'visible' 'invisible'}}"
94+
/>
95+
</dd.Action>
96+
</:item>
97+
</X::DropdownList>
98+
{{/if}}
99+
</div>
43100
{{#if this.editingIsDisabled}}
44101
<h1
45102
class="hds-typography-display-300 hds-font-weight-semibold hds-foreground-strong"
46103
>{{this.title}}</h1>
47104
{{else}}
48-
<EditableField
49-
@value={{this.title}}
50-
@onChange={{perform this.save "title"}}
51-
@loading={{this.save.isRunning}}
52-
@disabled={{this.editingIsDisabled}}
53-
>
54-
<:default>
55-
{{#unless (is-empty this.title)}}
56-
<h1
57-
class="hds-typography-display-300 hds-font-weight-semibold hds-foreground-strong"
58-
>{{this.title}}</h1>
59-
{{else}}
60-
<h1
61-
class="hds-typography-display-300 hds-font-weight-semibold hds-foreground-faint"
62-
>Enter a title here.</h1>
63-
{{/unless}}
64-
</:default>
65-
<:editing as |F|>
66-
<Hds::Form::Textarea::Field
67-
{{auto-height-textarea}}
68-
@value={{F.value}}
69-
class="primary-textarea"
70-
name="title"
71-
{{on "blur" F.update}}
72-
as |F|
73-
/>
74-
</:editing>
75-
</EditableField>
105+
<div class="mb-8">
106+
<EditableField
107+
@value={{this.title}}
108+
@onChange={{perform this.save "title"}}
109+
@loading={{this.save.isRunning}}
110+
@disabled={{this.editingIsDisabled}}
111+
>
112+
<:default>
113+
{{#unless (is-empty this.title)}}
114+
<h1
115+
class="hds-typography-display-300 hds-font-weight-semibold hds-foreground-strong"
116+
>{{this.title}}</h1>
117+
{{else}}
118+
<h1
119+
class="hds-typography-display-300 hds-font-weight-semibold hds-foreground-faint"
120+
>Enter a title here.</h1>
121+
{{/unless}}
122+
</:default>
123+
<:editing as |F|>
124+
<Hds::Form::Textarea::Field
125+
{{auto-height-textarea}}
126+
@value={{F.value}}
127+
class="primary-textarea"
128+
name="title"
129+
{{on "blur" F.update}}
130+
as |F|
131+
/>
132+
</:editing>
133+
</EditableField>
134+
</div>
76135
{{/if}}
77136
</div>
78137

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

81-
<div class="flex flex-col items-start space-y-2">
82-
<Document::Sidebar::SectionHeader @title="Summary" />
140+
{{! Summary }}
141+
<div class="mb-5">
142+
<Document::Sidebar::SectionHeader @title="Summary" class="mb-2" />
83143
{{#if this.editingIsDisabled}}
84144
<p
85145
class="hds-typography-body-200 hds-font-weight-medium hds-foreground-primary"
@@ -120,7 +180,10 @@
120180

121181
<div class="flex flex-col items-start space-y-2">
122182
<Document::Sidebar::SectionHeader @title="Status" />
123-
<Doc::State @state={{@document.status}} @hideProgress={{true}} />
183+
<div class="flex space-x-1">
184+
<Doc::State @state={{@document.status}} @hideProgress={{true}} />
185+
<Hds::Badge @text={{@document.docType}} />
186+
</div>
124187
</div>
125188

126189
<div class="flex flex-col items-start space-y-2">

0 commit comments

Comments
 (0)