Skip to content

Commit 7053828

Browse files
committed
ref: move theme/text labels to constants, fix dark mode for svgs
1 parent 46ce2e5 commit 7053828

File tree

10 files changed

+194
-124
lines changed

10 files changed

+194
-124
lines changed

packages/feedback/src/constants.ts

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
export const DEFAULT_THEME = {
2+
light: {
3+
fontFamily: "'Helvetica Neue', Arial, sans-serif",
4+
fontSize: '14px',
5+
background: '#ffffff',
6+
backgroundHover: '#f6f6f7',
7+
foreground: '#2B2233',
8+
success: '#268d75',
9+
error: '#df3338',
10+
border: '1.5px solid rgba(41, 35, 47, 0.13)',
11+
boxShadow: '0px 4px 24px 0px rgba(43, 34, 51, 0.12)',
12+
},
13+
dark: {
14+
fontFamily: "'Helvetica Neue', Arial, sans-serif",
15+
fontSize: '14px',
16+
background: '#29232f',
17+
backgroundHover: '#352f3b',
18+
foreground: '#EBE6EF',
19+
success: '#2da98c',
20+
error: '#f55459',
21+
border: '1.5px solid rgba(235, 230, 239, 0.15)',
22+
boxShadow: '0px 4px 24px 0px rgba(43, 34, 51, 0.12)',
23+
},
24+
};
25+
26+
27+
export const ACTOR_LABEL = 'Report a Bug';
28+
export const CANCEL_BUTTON_LABEL = 'Cancel';
29+
export const SUBMIT_BUTTON_LABEL = 'Send Bug Report';
30+
export const FORM_TITLE = 'Report a Bug';
31+
export const EMAIL_PLACEHOLDER = '[email protected]';
32+
export const EMAIL_LABEL = 'Email';
33+
export const MESSAGE_PLACEHOLDER = "What's the bug? What did you expect?";
34+
export const MESSAGE_LABEL = 'Description';
35+
export const NAME_PLACEHOLDER = 'Your Name';
36+
export const NAME_LABEL= 'Name';
37+
export const SUCCESS_MESSAGE_TEXT = 'Thank you for your report!';

packages/feedback/src/integration.ts

Lines changed: 31 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
import { getCurrentHub } from '@sentry/core';
22
import type { Integration } from '@sentry/types';
33
import { isNodeEnv, logger } from '@sentry/utils';
4+
import { ACTOR_LABEL, CANCEL_BUTTON_LABEL, DEFAULT_THEME, EMAIL_LABEL, EMAIL_PLACEHOLDER, FORM_TITLE, MESSAGE_LABEL, MESSAGE_PLACEHOLDER, NAME_LABEL, NAME_PLACEHOLDER, SUBMIT_BUTTON_LABEL, SUCCESS_MESSAGE_TEXT } from './constants';
45

5-
import type { FeedbackConfigurationWithDefaults, FeedbackFormData } from './types';
6+
import type { FeedbackConfigurationWithDefaults, FeedbackFormData, FeedbackTheme } from './types';
67
import { handleFeedbackSubmit } from './util/handleFeedbackSubmit';
78
import { Actor } from './widget/Actor';
89
import { createActorStyles } from './widget/Actor.css';
@@ -25,20 +26,12 @@ function isBrowser(): boolean {
2526
return typeof window !== 'undefined' && (!isNodeEnv() || isElectronNodeRenderer());
2627
}
2728

28-
const THEME = {
29-
light: {
30-
background: '#ffffff',
31-
foreground: '#2B2233',
32-
success: '#268d75',
33-
error: '#df3338',
34-
},
35-
dark: {
36-
background: '#29232f',
37-
foreground: '#EBE6EF',
38-
success: '#2da98c',
39-
error: '#f55459',
40-
},
41-
};
29+
interface FeedbackConfiguration extends Partial<Omit<FeedbackConfigurationWithDefaults, 'theme'>> {
30+
theme?: {
31+
dark?: Partial<FeedbackTheme>;
32+
light?: Partial<FeedbackTheme>;
33+
}
34+
}
4235

4336
/**
4437
* Feedback integration. When added as an integration to the SDK, it will
@@ -100,20 +93,23 @@ export class Feedback implements Integration {
10093
isEmailRequired = false,
10194
isNameRequired = false,
10295

103-
buttonLabel = 'Report a Bug',
104-
cancelButtonLabel = 'Cancel',
105-
submitButtonLabel = 'Send Bug Report',
106-
formTitle = 'Report a Bug',
107-
emailPlaceholder = '[email protected]',
108-
emailLabel = 'Email',
109-
messagePlaceholder = "What's the bug? What did you expect?",
110-
messageLabel = 'Description',
111-
namePlaceholder = 'Your Name',
112-
nameLabel = 'Name',
113-
successMessageText = 'Thank you for your report!',
96+
theme,
97+
colorScheme = 'system',
98+
99+
buttonLabel = ACTOR_LABEL,
100+
cancelButtonLabel = CANCEL_BUTTON_LABEL,
101+
submitButtonLabel = SUBMIT_BUTTON_LABEL,
102+
formTitle = FORM_TITLE,
103+
emailPlaceholder = EMAIL_PLACEHOLDER,
104+
emailLabel = EMAIL_LABEL,
105+
messagePlaceholder = MESSAGE_PLACEHOLDER,
106+
messageLabel = MESSAGE_LABEL,
107+
namePlaceholder = NAME_PLACEHOLDER,
108+
nameLabel = NAME_LABEL,
109+
successMessageText = SUCCESS_MESSAGE_TEXT,
114110

115111
onOpenDialog,
116-
}: Partial<FeedbackConfigurationWithDefaults> = {}) {
112+
}: FeedbackConfiguration = {}) {
117113
// Initializations
118114
this.name = Feedback.id;
119115
this._actor = null;
@@ -133,6 +129,12 @@ export class Feedback implements Integration {
133129
showName,
134130
useSentryUser,
135131

132+
colorScheme,
133+
theme: {
134+
dark: Object.assign({}, DEFAULT_THEME.dark, theme && theme.dark),
135+
light: Object.assign({}, DEFAULT_THEME.light, theme && theme.light),
136+
},
137+
136138
buttonLabel,
137139
cancelButtonLabel,
138140
submitButtonLabel,
@@ -229,7 +231,6 @@ export class Feedback implements Integration {
229231
if (this._dialog) {
230232
this._dialog.open();
231233
this._isDialogOpen = true;
232-
console.log('dialog already open');
233234
return;
234235
}
235236

@@ -326,7 +327,7 @@ export class Feedback implements Integration {
326327
// Create the shadow root
327328
const shadow = this._host.attachShadow({ mode: 'open' });
328329

329-
shadow.appendChild(createMainStyles(document, THEME));
330+
shadow.appendChild(createMainStyles(document, this.options.colorScheme, this.options.theme));
330331

331332
return shadow;
332333
}
@@ -344,7 +345,7 @@ export class Feedback implements Integration {
344345
this._shadow.appendChild(createActorStyles(document));
345346

346347
// Create Actor component
347-
this._actor = Actor({ options: this.options, theme: THEME, onClick: this._handleActorClick });
348+
this._actor = Actor({ options: this.options, onClick: this._handleActorClick });
348349

349350
this._shadow.appendChild(this._actor.$el);
350351
} catch (err) {
@@ -370,7 +371,6 @@ export class Feedback implements Integration {
370371
}
371372
this.showActor();
372373
},
373-
theme: THEME,
374374
});
375375

376376
this._shadow.appendChild(success.$el);

packages/feedback/src/types/index.ts

Lines changed: 40 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,21 @@ export interface FeedbackConfigurationWithDefaults {
8080
name: string;
8181
};
8282

83+
// * Color theme customization * //
84+
/**
85+
* The colorscheme to use. "system" will choose the scheme based on the user's system settings
86+
*/
87+
colorScheme: 'system' | 'light' | 'dark';
88+
89+
/**
90+
* Theme customization, will be merged with default theme values.
91+
*/
92+
theme: {
93+
dark: FeedbackTheme;
94+
light: FeedbackTheme;
95+
};
96+
// * End of Color theme customization * //
97+
8398
// * Text customization * //
8499
/**
85100
* The label for the Feedback widget button that opens the dialog
@@ -132,11 +147,31 @@ export interface FeedbackConfigurationWithDefaults {
132147
// * End of Callbacks * //
133148
}
134149

135-
interface BaseTheme {
150+
export interface FeedbackTheme {
151+
/**
152+
* Font family for widget
153+
*/
154+
fontFamily: string;
136155
/**
137-
* Background color
156+
* Font size for widget
157+
*/
158+
fontSize: string;
159+
/**
160+
* Background color for actor and dialog
138161
*/
139162
background: string;
163+
/**
164+
* Background color on hover
165+
*/
166+
backgroundHover: string;
167+
/**
168+
* Border styling for actor and dialog
169+
*/
170+
border: string;
171+
/**
172+
* Box shadow for actor and dialog
173+
*/
174+
boxShadow: string;
140175
/**
141176
* Foreground color (i.e. text color)
142177
*/
@@ -151,9 +186,9 @@ interface BaseTheme {
151186
error: string;
152187
}
153188

154-
export interface FeedbackTheme {
155-
light: BaseTheme;
156-
dark: BaseTheme;
189+
export interface FeedbackThemes {
190+
dark: FeedbackTheme;
191+
light: FeedbackTheme;
157192
}
158193

159194
export interface FeedbackComponent<T extends HTMLElement> {

packages/feedback/src/widget/Actor.css.ts

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -45,21 +45,8 @@ export function createActorStyles(d: Document): HTMLStyleElement {
4545
.widget__actor__text {
4646
}
4747
48-
.success-message {
49-
background-color: var(--bg-color);
50-
border: var(--border);
51-
border-radius: 12px;
52-
box-shadow: var(--box-shadow);
53-
font-weight: 600;
54-
color: var(--success-color);
55-
padding: 12px 24px;
56-
line-height: 25px;
57-
display: grid;
58-
align-items: center;
59-
grid-auto-flow: column;
60-
gap: 6px;
61-
cursor: default;
62-
48+
.feedback-icon path {
49+
fill: var(--fg-color);
6350
}
6451
`;
6552

packages/feedback/src/widget/Actor.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import { createElement as h } from './util/createElement';
44

55
interface Props {
66
options: FeedbackConfigurationWithDefaults;
7-
theme: FeedbackTheme;
87
onClick?: (e: MouseEvent) => void;
98
}
109

@@ -22,7 +21,7 @@ interface ActorComponent extends FeedbackComponent<HTMLButtonElement> {
2221
/**
2322
*
2423
*/
25-
export function Actor({ options, theme, onClick }: Props): ActorComponent {
24+
export function Actor({ options, onClick }: Props): ActorComponent {
2625
function _handleClick(e: MouseEvent) {
2726
onClick && onClick(e);
2827
}
@@ -34,7 +33,7 @@ export function Actor({ options, theme, onClick }: Props): ActorComponent {
3433
className: 'widget__actor',
3534
ariaLabel: options.buttonLabel,
3635
},
37-
Icon({ color: theme.light.foreground }).$el,
36+
Icon().$el,
3837
h(
3938
'span',
4039
{

packages/feedback/src/widget/Dialog.css.ts

Lines changed: 36 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@ export function createDialogStyles(d: Document): HTMLStyleElement {
2626
pointer-events: none;
2727
visibility: hidden;
2828
}
29+
.dialog:not([open]) .dialog__content {
30+
transform: translate(0, -16px) scale(0.98);
31+
}
2932
3033
.dialog__content {
3134
position: fixed;
@@ -48,9 +51,6 @@ export function createDialogStyles(d: Document): HTMLStyleElement {
4851
0 4px 16px rgba(0, 0, 0, 0.2);
4952
transition: transform 0.2s ease-in-out;
5053
transform: translate(0, 0) scale(1);
51-
dialog:not([open]) & {
52-
transform: translate(0, -16px) scale(0.98);
53-
}
5454
}
5555
5656
.dialog__header {
@@ -98,9 +98,9 @@ export function createDialogStyles(d: Document): HTMLStyleElement {
9898
font-size: 14px;
9999
font-weight: 500;
100100
padding: 6px 12px;
101-
&:focus {
102-
border-color: rgba(108, 95, 199, 1);
103-
}
101+
}
102+
.form__input:focus {
103+
border-color: rgba(108, 95, 199, 1);
104104
}
105105
106106
.form__input--textarea {
@@ -122,29 +122,48 @@ export function createDialogStyles(d: Document): HTMLStyleElement {
122122
font-size: 14px;
123123
font-weight: 600;
124124
padding: 6px 16px;
125-
126-
&[disabled] {
127-
opacity: 0.6;
128-
pointer-events: none;
129-
}
125+
}
126+
.btn[disabled] {
127+
opacity: 0.6;
128+
pointer-events: none;
130129
}
131130
132131
.btn--primary {
133132
background-color: rgba(108, 95, 199, 1);
134133
border-color: rgba(108, 95, 199, 1);
135134
color: #fff;
136-
&:hover {
137-
background-color: rgba(88, 74, 192, 1);
138-
}
135+
}
136+
.btn--primary:hover {
137+
background-color: rgba(88, 74, 192, 1);
139138
}
140139
141140
.btn--default {
142141
background-color: transparent;
143142
color: var(--fg-color);
144143
font-weight: 500;
145-
&:hover {
146-
background-color: var(--bg-accent-color);
147-
}
144+
}
145+
.btn--default:hover {
146+
background-color: var(--bg-accent-color);
147+
}
148+
149+
.success-message {
150+
background-color: var(--bg-color);
151+
border: var(--border);
152+
border-radius: 12px;
153+
box-shadow: var(--box-shadow);
154+
font-weight: 600;
155+
color: var(--success-color);
156+
padding: 12px 24px;
157+
line-height: 25px;
158+
display: grid;
159+
align-items: center;
160+
grid-auto-flow: column;
161+
gap: 6px;
162+
cursor: default;
163+
}
164+
165+
.success-icon path {
166+
fill: var(--success-color);
148167
}
149168
`;
150169

0 commit comments

Comments
 (0)