Skip to content

Commit ae4e49f

Browse files
committed
wip
1 parent e87a9e7 commit ae4e49f

File tree

7 files changed

+98
-87
lines changed

7 files changed

+98
-87
lines changed

packages/feedback2/src/core/components/Actor.ts

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -16,16 +16,6 @@ export interface ActorComponent {
1616
* The style element for this component
1717
*/
1818
style: HTMLStyleElement;
19-
20-
/**
21-
* Show the actor element
22-
*/
23-
show: () => void;
24-
25-
/**
26-
* Hide the actor element
27-
*/
28-
hide: () => void;
2919
}
3020

3121
/**
@@ -54,13 +44,5 @@ export function Actor({ buttonLabel }: ActorProps): ActorComponent {
5444
get style() {
5545
return style;
5646
},
57-
show: (): void => {
58-
el.classList.remove('widget__actor--hidden');
59-
el.setAttribute('aria-hidden', 'false');
60-
},
61-
hide: (): void => {
62-
el.classList.add('widget__actor--hidden');
63-
el.setAttribute('aria-hidden', 'true');
64-
},
6547
};
6648
}

packages/feedback2/src/core/integration.ts

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import {
1717
SUBMIT_BUTTON_LABEL,
1818
SUCCESS_MESSAGE_TEXT,
1919
} from '../constants';
20-
import type { DialogComponent } from '../modal/Dialog';
20+
import type { DialogComponent } from '../modal/components/Dialog';
2121
import type { DialogLifecycleCallbacks, feedback2ModalIntegration } from '../modal/integration';
2222
import type { feedback2ScreenshotIntegration } from '../screenshot/integration';
2323
import type {
@@ -182,26 +182,31 @@ export class Feedback2 implements Integration {
182182

183183
const shadow = this._getShadow(options);
184184
const actor = Actor({ buttonLabel: options.buttonLabel });
185-
shadow.appendChild(actor.style);
186-
shadow.appendChild(actor.el);
185+
const insertActor = (): void => {
186+
shadow.appendChild(actor.style);
187+
shadow.appendChild(actor.el);
188+
};
187189
this.attachTo(actor.el, {
188190
onFormOpen() {
189-
actor.hide();
191+
shadow.removeChild(actor.el);
192+
shadow.removeChild(actor.style);
190193
options.onFormOpen && options.onFormOpen();
191194
},
192195
onFormClose() {
193-
actor.show();
196+
insertActor();
194197
options.onFormClose && options.onFormClose();
195198
},
196199
onSubmitSuccess(data: FeedbackFormData) {
197-
actor.show();
200+
insertActor();
198201
options.onSubmitSuccess && options.onSubmitSuccess(data);
199202
},
200203
onSubmitError() {
201-
actor.show();
204+
insertActor();
202205
options.onSubmitError && options.onSubmitError();
203206
},
204207
});
208+
209+
insertActor();
205210
}
206211

207212
/**

packages/feedback2/src/modal/Dialog.ts

Lines changed: 0 additions & 45 deletions
This file was deleted.
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
// biome-ignore lint/nursery/noUnusedImports: reason
2+
import { Fragment, h, render } from 'preact'; // eslint-disable-line @typescript-eslint/no-unused-vars
3+
import type { VNode } from 'preact';
4+
import { useCallback, useMemo, useState } from 'preact/hooks';
5+
import { DOCUMENT } from '../../constants';
6+
import type { FeedbackFormData } from '../../types';
7+
import { createDialogStyles } from './Dialog.css';
8+
import { DialogContent } from './DialogContent';
9+
import type { Props as DialogContentProps } from './DialogContent';
10+
import { SuccessIcon } from './SuccessIcon';
11+
12+
export interface Props extends DialogContentProps {
13+
successMessageText: string;
14+
onDone: () => void;
15+
}
16+
17+
export interface DialogComponent {
18+
/**
19+
* The dialog element itself
20+
*/
21+
el: HTMLElement;
22+
23+
/**
24+
* The style element for this component
25+
*/
26+
style: HTMLStyleElement;
27+
}
28+
29+
/**
30+
*
31+
*/
32+
export function Dialog(props: Props): DialogComponent {
33+
const el = DOCUMENT.createElement('div');
34+
render(<DialogContainer {...props} />, el);
35+
36+
const style = createDialogStyles();
37+
38+
return {
39+
get el() {
40+
return el;
41+
},
42+
get style() {
43+
return style;
44+
},
45+
};
46+
}
47+
48+
function DialogContainer({ onDone, ...props }: Props): VNode {
49+
const successIconHtml = useMemo(() => {
50+
const logo = SuccessIcon();
51+
return { __html: logo.outerHTML };
52+
}, []);
53+
54+
const [timeoutId, setTimeoutId] = useState<NodeJS.Timeout | null>(null);
55+
56+
const onSubmitSuccess = useCallback(
57+
(data: FeedbackFormData) => {
58+
props.onSubmitSuccess(data);
59+
setTimeoutId(() => setTimeout(onDone, 5000));
60+
},
61+
[onDone],
62+
);
63+
64+
return (
65+
<Fragment>
66+
{didSubmit ? (
67+
<div class="success-message" onClick={onDone}>
68+
{props.successMessageText}
69+
<span dangerouslySetInnerHTML={successIconHtml} />
70+
</div>
71+
) : (
72+
<dialog class="dialog" onClick={props.onFormClose} open>
73+
<DialogContent {...props} onSubmitSuccess={onSubmitSuccess} />
74+
</dialog>
75+
)}
76+
</Fragment>
77+
);
78+
}

packages/feedback2/src/modal/components/DialogContent.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
import { h } from 'preact'; // eslint-disable-line @typescript-eslint/no-unused-vars
33
import type { ComponentChildren, VNode } from 'preact';
44
import { useMemo } from 'preact/hooks';
5-
65
import { Form } from './Form';
76
import type { Props as FormProps } from './Form';
87
import type { Props as LogoProps } from './Logo';

packages/feedback2/src/modal/components/renderDialogContent.tsx

Lines changed: 0 additions & 11 deletions
This file was deleted.

packages/feedback2/src/modal/integration.ts

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ import type { Integration, IntegrationFn } from '@sentry/types';
33
import { isBrowser } from '@sentry/utils';
44
import type { FeedbackFormData, FeedbackInternalOptions } from '../types';
55
import type { SendFeedbackOptions, SendFeedbackParams } from '../types';
6-
import { makeDialog } from './Dialog';
7-
import type { DialogComponent } from './Dialog';
6+
import { Dialog } from './components/Dialog';
7+
import type { DialogComponent } from './components/Dialog';
88

99
export interface DialogLifecycleCallbacks {
1010
/**
@@ -22,7 +22,7 @@ export interface DialogLifecycleCallbacks {
2222
/**
2323
* When the dialog is either closed, or was submitted successfully, and nothing is rendered anymore.
2424
*
25-
* This is called after onClose OR onSuccess
25+
* This is called after onFormClose OR onSubmitSuccess
2626
*/
2727
onDone: (dialog: DialogComponent) => void;
2828
}
@@ -79,7 +79,7 @@ export class Feedback2Modal implements Integration {
7979
const user = scope && scope.getUser();
8080

8181
// TODO: options may have changed?
82-
const dialog = makeDialog({
82+
const dialog = Dialog({
8383
colorScheme: options.colorScheme,
8484
showBranding: options.showBranding,
8585
showName: options.showName || options.isNameRequired,
@@ -97,18 +97,21 @@ export class Feedback2Modal implements Integration {
9797
namePlaceholder: options.namePlaceholder,
9898
defaultName: (userKey && user && user[userKey.name]) || '',
9999
defaultEmail: (userKey && user && user[userKey.email]) || '',
100+
successMessageText: options.successMessageText,
100101
onFormClose: () => {
101102
callbacks.onDone(dialog);
102103
options.onFormClose && options.onFormClose();
103104
},
104105
onSubmit: callbacks.onSubmit,
105106
onSubmitSuccess: (data: FeedbackFormData) => {
106-
callbacks.onDone(dialog);
107107
options.onSubmitSuccess && options.onSubmitSuccess(data);
108108
},
109109
onSubmitError: () => {
110110
options.onSubmitError && options.onSubmitError();
111111
},
112+
onDone: () => {
113+
callbacks.onDone(dialog);
114+
},
112115
});
113116
this._dialog = dialog;
114117
}

0 commit comments

Comments
 (0)