Skip to content
This repository was archived by the owner on Feb 6, 2024. It is now read-only.

Commit 1e0a8dd

Browse files
Merge pull request #703 from deckgo/studio-list-color
feat: list ordered and unordered toggle with new standard UX
2 parents 9a2ac51 + 5d49b08 commit 1e0a8dd

File tree

7 files changed

+173
-39
lines changed

7 files changed

+173
-39
lines changed

studio/src/app/components/editor/actions/element/app-actions-element/app-actions-element.tsx

Lines changed: 37 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import {Component, Element, Event, EventEmitter, h, Listen, Method, State, Prop} from '@stencil/core';
1+
import {Component, Element, Event, EventEmitter, h, Listen, Method, Prop, State} from '@stencil/core';
22
import {modalController, OverlayEventDetail, popoverController} from '@ionic/core';
33

44
import {Subject, Subscription} from 'rxjs';
@@ -14,6 +14,7 @@ import {RevealSlotUtils} from '../../../../../utils/editor/reveal-slot.utils';
1414
import {SlotType} from '../../../../../utils/editor/slot-type';
1515
import {SlotUtils} from '../../../../../utils/editor/slot.utils';
1616
import {AlignUtils, TextAlign} from '../../../../../utils/editor/align.utils';
17+
import {ListUtils} from '../../../../../utils/editor/list.utils';
1718

1819
import {EditAction} from '../../../../../utils/editor/edit-action';
1920
import {MoreAction} from '../../../../../utils/editor/more-action';
@@ -55,7 +56,7 @@ export class AppActionsElement {
5556
private align: TextAlign | undefined;
5657

5758
@State()
58-
private list: SlotType;
59+
private list: SlotType.OL | SlotType.UL | undefined;
5960

6061
@Event() private blockSlide: EventEmitter<boolean>;
6162

@@ -243,18 +244,6 @@ export class AppActionsElement {
243244
return element && element.nodeName && element.nodeName.toLowerCase() === SlotType.DRAG_RESIZE_ROTATE;
244245
}
245246

246-
private isElementList(element: HTMLElement): SlotType {
247-
if (!SlotUtils.isNodeList(element)) {
248-
return undefined;
249-
}
250-
251-
if (SlotUtils.isNodeRevealList(element)) {
252-
return element && element.getAttribute('list-tag') === SlotType.UL ? SlotType.UL : SlotType.OL;
253-
} else {
254-
return element && element.nodeName && element.nodeName.toLowerCase() === SlotType.OL ? SlotType.OL : SlotType.UL;
255-
}
256-
}
257-
258247
private isElementImage(element: HTMLElement): boolean {
259248
return element && element.nodeName && element.nodeName.toLowerCase() === SlotType.IMG;
260249
}
@@ -570,7 +559,7 @@ export class AppActionsElement {
570559
await modal.present();
571560
}
572561

573-
private async openSingleAction($event: UIEvent, component: 'app-reveal' | 'app-align') {
562+
private async openSingleAction($event: UIEvent, component: 'app-reveal' | 'app-align' | 'app-list') {
574563
if (this.slide) {
575564
return;
576565
}
@@ -590,6 +579,8 @@ export class AppActionsElement {
590579
await this.toggleReveal(detail.data.reveal);
591580
} else if (detail.data && component === 'app-align') {
592581
await this.updateAlignAttribute(detail.data.align);
582+
} else if (detail.data && component === 'app-list') {
583+
await this.toggleList(detail.data.list);
593584
}
594585
});
595586

@@ -749,7 +740,7 @@ export class AppActionsElement {
749740

750741
this.align = await AlignUtils.getAlignment(element);
751742

752-
this.list = this.isElementList(element);
743+
this.list = await ListUtils.isElementList(element);
753744

754745
if (element) {
755746
element.addEventListener('paste', this.cleanOnPaste, false);
@@ -879,23 +870,19 @@ export class AppActionsElement {
879870
});
880871
}
881872

882-
private toggleList(): Promise<void> {
873+
private toggleList(destinationListType: SlotType.OL | SlotType.UL): Promise<void> {
883874
return new Promise<void>(async (resolve) => {
884875
if (!this.selectedElement || !this.list) {
885876
resolve();
886877
return;
887878
}
888879

889-
const destinationListType: SlotType = this.list === SlotType.UL ? SlotType.OL : SlotType.UL;
890-
891880
if (SlotUtils.isNodeRevealList(this.selectedElement)) {
892881
await this.updateRevealListAttribute(destinationListType);
893882
} else {
894883
await this.toggleSlotType(destinationListType);
895884
}
896885

897-
this.list = destinationListType;
898-
899886
resolve();
900887
});
901888
}
@@ -971,6 +958,8 @@ export class AppActionsElement {
971958
componentProps: {
972959
notes: this.slide,
973960
copy: this.slide || this.shape,
961+
reveal: !this.hideReveal(),
962+
list: this.list !== undefined,
974963
},
975964
event: $event,
976965
mode: 'ios',
@@ -984,22 +973,30 @@ export class AppActionsElement {
984973
await this.clone();
985974
} else if (detail.data.action === MoreAction.DELETE) {
986975
await this.confirmDeleteElement($event);
976+
} else if (detail.data.action === MoreAction.REVEAL) {
977+
await this.openSingleAction($event, 'app-reveal');
978+
} else if (detail.data.action === MoreAction.LIST) {
979+
await this.openSingleAction($event, 'app-list');
987980
}
988981
}
989982
});
990983

991984
await popover.present();
992985
}
993986

987+
private hideReveal(): boolean {
988+
return this.slide || this.code || this.shape || this.slideNodeName === 'deckgo-slide-youtube';
989+
}
990+
994991
render() {
995992
return (
996993
<ion-toolbar>
997994
<ion-buttons slot="start">
998995
{this.renderEdit()}
999996
{this.renderShapes()}
997+
{this.renderColor()}
1000998
{this.renderReveal()}
1001999
{this.renderAlign()}
1002-
{this.renderColor()}
10031000
{this.renderList()}
10041001
{this.renderImages()}
10051002
{this.renderCodeOptions()}
@@ -1122,7 +1119,7 @@ export class AppActionsElement {
11221119
}
11231120

11241121
private renderReveal() {
1125-
const classReveal: string | undefined = this.slide || this.code || this.shape || this.slideNodeName === 'deckgo-slide-youtube' ? 'hidden' : undefined;
1122+
const classReveal: string | undefined = this.hideReveal() ? 'hidden wider-devices' : 'wider-devices';
11261123

11271124
return (
11281125
<ion-tab-button
@@ -1147,26 +1144,30 @@ export class AppActionsElement {
11471144
color="primary"
11481145
mode="md"
11491146
class={classAlign}>
1150-
<ion-icon src={`/assets/icons/align-${this.align}.svg`}></ion-icon>
1147+
{this.align !== undefined ? (
1148+
<ion-icon src={`/assets/icons/align-${this.align}.svg`}></ion-icon>
1149+
) : (
1150+
<ion-icon src={`/assets/icons/align-left.svg`}></ion-icon>
1151+
)}
11511152
<ion-label>Alignment</ion-label>
11521153
</ion-tab-button>
11531154
);
11541155
}
11551156

11561157
private renderList() {
1157-
const classListOL: string | undefined = this.list === SlotType.OL ? undefined : 'hidden';
1158-
const classListUL: string | undefined = this.list === SlotType.UL ? undefined : 'hidden';
1158+
const classList: string | undefined = this.list === undefined ? 'hidden wider-devices' : 'wider-devices';
11591159

1160-
return [
1161-
<ion-tab-button onClick={() => this.toggleList()} aria-label="Toggle to an unordered list" color="primary" mode="md" class={classListUL}>
1162-
<ion-icon src="/assets/icons/ionicons/list.svg"></ion-icon>
1163-
<ion-label>Unordered list</ion-label>
1164-
</ion-tab-button>,
1165-
<ion-tab-button onClick={() => this.toggleList()} aria-label="Toggle to an ordered list" color="primary" mode="md" class={classListOL}>
1166-
<ion-icon src="/assets/icons/list-ol.svg"></ion-icon>
1167-
<ion-label>Ordered list</ion-label>
1168-
</ion-tab-button>,
1169-
];
1160+
return (
1161+
<ion-tab-button
1162+
onClick={($event: UIEvent) => this.openSingleAction($event, 'app-list')}
1163+
aria-label="Edit ordered or unordered list"
1164+
color="primary"
1165+
mode="md"
1166+
class={classList}>
1167+
<ion-icon src={this.list === SlotType.OL ? '/assets/icons/list-ol.svg' : '/assets/icons/ionicons/list.svg'}></ion-icon>
1168+
<ion-label>List</ion-label>
1169+
</ion-tab-button>
1170+
);
11701171
}
11711172

11721173
private renderMore() {

studio/src/app/popovers/editor/actions/app-more-element-actions/app-more-element-actions.tsx

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import {MoreAction} from '../../../../utils/editor/more-action';
33

44
@Component({
55
tag: 'app-more-element-actions',
6-
styleUrl: 'app-more-element-actions.scss'
6+
styleUrl: 'app-more-element-actions.scss',
77
})
88
export class AppMoreElementActions {
99
@Element() el: HTMLElement;
@@ -14,9 +14,15 @@ export class AppMoreElementActions {
1414
@Prop()
1515
copy: boolean = false;
1616

17+
@Prop()
18+
reveal: boolean = false;
19+
20+
@Prop()
21+
list: boolean = false;
22+
1723
private async closePopover(action: MoreAction) {
1824
await (this.el.closest('ion-popover') as HTMLIonPopoverElement).dismiss({
19-
action: action
25+
action: action,
2026
});
2127
}
2228

@@ -25,6 +31,8 @@ export class AppMoreElementActions {
2531
<div class="ion-padding">
2632
{this.renderNotes()}
2733
{this.renderCopy()}
34+
{this.renderReveal()}
35+
{this.renderList()}
2836
{this.renderDelete()}
2937
</div>
3038
);
@@ -54,6 +62,30 @@ export class AppMoreElementActions {
5462
);
5563
}
5664

65+
private renderList() {
66+
if (!this.list) {
67+
return undefined;
68+
}
69+
70+
return (
71+
<a onClick={() => this.closePopover(MoreAction.LIST)} aria-label="List">
72+
<p>List</p>
73+
</a>
74+
);
75+
}
76+
77+
private renderReveal() {
78+
if (!this.reveal) {
79+
return undefined;
80+
}
81+
82+
return (
83+
<a onClick={() => this.closePopover(MoreAction.REVEAL)} aria-label="Animation">
84+
<p>Animation</p>
85+
</a>
86+
);
87+
}
88+
5789
private renderDelete() {
5890
return (
5991
<a onClick={() => this.closePopover(MoreAction.DELETE)} aria-label="Delete">
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
app-list {
2+
@import "../../../../global/theme/editor/editor-popover";
3+
4+
ion-item {
5+
--background-activated: transparent;
6+
--background-focused: transparent;
7+
--background-hover: transparent;
8+
9+
cursor: pointer;
10+
11+
&:hover,
12+
&.active {
13+
--color: var(--ion-color-primary);
14+
}
15+
}
16+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import {Component, Element, h, Prop, State} from '@stencil/core';
2+
3+
import {SlotType} from '../../../utils/editor/slot-type';
4+
import {ListUtils} from '../../../utils/editor/list.utils';
5+
6+
@Component({
7+
tag: 'app-list',
8+
styleUrl: 'app-list.scss',
9+
})
10+
export class AppList {
11+
@Element() el: HTMLElement;
12+
13+
@Prop()
14+
selectedElement: HTMLElement;
15+
16+
@State()
17+
private currentList: SlotType.OL | SlotType.UL | undefined;
18+
19+
async componentWillLoad() {
20+
this.currentList = await ListUtils.isElementList(this.selectedElement);
21+
}
22+
23+
private async closePopover(list: SlotType.OL | SlotType.UL) {
24+
await (this.el.closest('ion-popover') as HTMLIonPopoverElement).dismiss({
25+
list: list,
26+
});
27+
}
28+
29+
private async selectList(list: SlotType.OL | SlotType.UL) {
30+
await this.closePopover(list);
31+
}
32+
33+
render() {
34+
return (
35+
<ion-list>
36+
<ion-item onClick={() => this.selectList(SlotType.UL)} class={this.currentList == SlotType.UL ? 'active' : undefined}>
37+
<ion-icon slot="start" src="/assets/icons/ionicons/list.svg"></ion-icon>
38+
<ion-label>Unordered list</ion-label>
39+
</ion-item>
40+
41+
<ion-item onClick={() => this.selectList(SlotType.OL)} class={this.currentList == SlotType.OL ? 'active' : undefined}>
42+
<ion-icon slot="start" src="/assets/icons/list-ol.svg"></ion-icon>
43+
<ion-label>Ordered list</ion-label>
44+
</ion-item>
45+
</ion-list>
46+
);
47+
}
48+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import {SlotType} from './slot-type';
2+
import {SlotUtils} from './slot.utils';
3+
4+
export class ListUtils {
5+
static async isElementList(element: HTMLElement): Promise<SlotType.OL | SlotType.UL | undefined> {
6+
if (!SlotUtils.isNodeList(element)) {
7+
return undefined;
8+
}
9+
10+
if (SlotUtils.isNodeRevealList(element)) {
11+
return element && element.getAttribute('list-tag') === SlotType.UL ? SlotType.UL : SlotType.OL;
12+
} else {
13+
return element && element.nodeName && element.nodeName.toLowerCase() === SlotType.OL ? SlotType.OL : SlotType.UL;
14+
}
15+
}
16+
}

studio/src/app/utils/editor/more-action.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,7 @@ export enum MoreAction {
99
NOTES,
1010
DELETE,
1111
HELP,
12-
OFFLINE
12+
OFFLINE,
13+
LIST,
14+
REVEAL,
1315
}

0 commit comments

Comments
 (0)