@beydesign/storybook 0.7.1 → 0.7.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/stories/Feedback/FeedbackCard.d.ts +3 -0
- package/dist/stories/Feedback/FeedbackCard.js +139 -0
- package/dist/stories/Feedback/FeedbackCard.stories.d.ts +10 -0
- package/dist/stories/Feedback/FeedbackCard.stories.js +133 -0
- package/dist/stories/Feedback/FeedbackRatingIcon.d.ts +3 -0
- package/dist/stories/Feedback/FeedbackRatingIcon.js +59 -0
- package/dist/stories/Feedback/FeedbackRatingIcon.stories.d.ts +11 -0
- package/dist/stories/Feedback/FeedbackRatingIcon.stories.js +61 -0
- package/dist/stories/Feedback/index.d.ts +3 -0
- package/dist/stories/Feedback/index.js +3 -0
- package/dist/stories/Feedback/types.d.ts +89 -0
- package/dist/stories/Feedback/types.js +11 -0
- package/dist/stories/Navigation/CallHeader.d.ts +3 -0
- package/dist/stories/Navigation/CallHeader.js +13 -0
- package/dist/stories/Navigation/CallHeader.stories.d.ts +8 -0
- package/dist/stories/Navigation/CallHeader.stories.js +91 -0
- package/dist/stories/Navigation/index.d.ts +1 -0
- package/dist/stories/Navigation/index.js +1 -0
- package/dist/stories/Navigation/types.d.ts +23 -0
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ export * from './stories/UI';
|
|
|
2
2
|
export * from './stories/Agent';
|
|
3
3
|
export * from './stories/EntityCard';
|
|
4
4
|
export * from './stories/PlanCard';
|
|
5
|
+
export * from './stories/Feedback';
|
|
5
6
|
export * from './stories/Form';
|
|
6
7
|
export * from './stories/Buttons';
|
|
7
8
|
export * from './stories/Typography';
|
package/dist/index.js
CHANGED
|
@@ -2,6 +2,7 @@ export * from './stories/UI';
|
|
|
2
2
|
export * from './stories/Agent';
|
|
3
3
|
export * from './stories/EntityCard';
|
|
4
4
|
export * from './stories/PlanCard';
|
|
5
|
+
export * from './stories/Feedback';
|
|
5
6
|
export * from './stories/Form';
|
|
6
7
|
export * from './stories/Buttons';
|
|
7
8
|
export * from './stories/Typography';
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { Box, Checkbox, Chip, TextField } from '@mui/material';
|
|
4
|
+
import { FeedbackRating } from './types';
|
|
5
|
+
import { FeedbackRatingIcon } from './FeedbackRatingIcon';
|
|
6
|
+
import { ButtonHierarchy, ButtonSize, MainButton } from '../Buttons';
|
|
7
|
+
import { Typography, TypographySize, TypographyWeight } from '../Typography';
|
|
8
|
+
const RATING_SCALE = [
|
|
9
|
+
FeedbackRating.VeryUnsatisfied,
|
|
10
|
+
FeedbackRating.Unsatisfied,
|
|
11
|
+
FeedbackRating.Neutral,
|
|
12
|
+
FeedbackRating.Satisfied,
|
|
13
|
+
FeedbackRating.VerySatisfied,
|
|
14
|
+
];
|
|
15
|
+
const DEFAULT_RATING_LABELS = {
|
|
16
|
+
[FeedbackRating.VeryUnsatisfied]: 'Very unsatisfied',
|
|
17
|
+
[FeedbackRating.Unsatisfied]: 'Unsatisfied',
|
|
18
|
+
[FeedbackRating.Neutral]: 'Neutral',
|
|
19
|
+
[FeedbackRating.Satisfied]: 'Satisfied',
|
|
20
|
+
[FeedbackRating.VerySatisfied]: 'Very satisfied',
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* The card sits on the dark call backdrop, so the defaults are the dark-surface
|
|
24
|
+
* washes rather than theme-aware semantics. `surfaceColor` is the brand-tinted
|
|
25
|
+
* one: a consumer under custom branding passes a wash of the brand color.
|
|
26
|
+
*/
|
|
27
|
+
const DEFAULT_SURFACE = 'var(--primitives-white-primary-transparent-violet-20)';
|
|
28
|
+
const DEFAULT_ITEM = 'var(--primitives-white-primary-black-40)';
|
|
29
|
+
const MAX_WIDTH = 696;
|
|
30
|
+
/** The face bleeds 10% of its box on every side so the heart is not clipped. */
|
|
31
|
+
const FACE_BOX = { xs: 50, sm: 60 };
|
|
32
|
+
const FACE_BLEED = { xs: '-5px', sm: '-6px' };
|
|
33
|
+
export const FeedbackCard = ({ title = 'How was your call experience with this agent?', rating, onRatingChange, ratingLabels = DEFAULT_RATING_LABELS, ratingInkColor, expanded = false, detailsTitle = 'Please help us improve! What can be done better?', topics = [], selectedTopic = null, onTopicChange, comment = '', onCommentChange, commentPlaceholder = 'Your comment', contactConsent = false, onContactConsentChange, contactConsentLabel = 'You can contact me about this feedback', submitText = 'Submit Feedback', onSubmit, submitDisabled = false, submitLoading = false, submitId, errorText, surfaceColor = DEFAULT_SURFACE, itemColor = DEFAULT_ITEM, className, sx, }) => {
|
|
34
|
+
const handleRatingClick = (option) => {
|
|
35
|
+
onRatingChange(option === rating ? null : option);
|
|
36
|
+
};
|
|
37
|
+
const handleTopicClick = (topic) => {
|
|
38
|
+
onTopicChange?.(topic === selectedTopic ? null : topic);
|
|
39
|
+
};
|
|
40
|
+
const handleCommentChange = (event) => {
|
|
41
|
+
onCommentChange?.(event.target.value);
|
|
42
|
+
};
|
|
43
|
+
const handleContactConsentChange = (event) => {
|
|
44
|
+
onContactConsentChange?.(event.target.checked);
|
|
45
|
+
};
|
|
46
|
+
return (_jsxs(Box, { className: className, display: 'flex', flexDirection: 'column', width: '100%', maxWidth: MAX_WIDTH, boxSizing: 'border-box', minHeight: 0, overflow: 'auto', borderRadius: 'var(--spacing-tokens-size-in-px-radius-radius-lg)', border: '1px solid var(--color-border-border-divider)', sx: [
|
|
47
|
+
{
|
|
48
|
+
gap: {
|
|
49
|
+
xs: 'var(--spacing-tokens-size-in-px-spacing-spacing-xl)',
|
|
50
|
+
sm: 'var(--spacing-tokens-size-in-px-spacing-spacing-3xl)',
|
|
51
|
+
},
|
|
52
|
+
paddingX: {
|
|
53
|
+
xs: 'var(--spacing-tokens-size-in-px-spacing-spacing-lg)',
|
|
54
|
+
sm: 'var(--spacing-tokens-size-in-px-spacing-spacing-3xl)',
|
|
55
|
+
},
|
|
56
|
+
paddingY: {
|
|
57
|
+
xs: 'var(--spacing-tokens-size-in-px-spacing-spacing-xl)',
|
|
58
|
+
sm: 'var(--spacing-tokens-size-in-px-spacing-spacing-4xl)',
|
|
59
|
+
},
|
|
60
|
+
backgroundColor: surfaceColor,
|
|
61
|
+
},
|
|
62
|
+
...(Array.isArray(sx) ? sx : [sx]),
|
|
63
|
+
], children: [_jsx(Box, { textAlign: 'center', children: _jsx(Typography, { size: TypographySize.HeadingS, weight: TypographyWeight.SemiBold, color: 'var(--color-text-text-white)', children: title }) }), errorText && (_jsx(Box, { textAlign: 'center', children: _jsx(Typography, { size: TypographySize.TextS, weight: TypographyWeight.Regular, color: 'var(--color-text-text-error)', children: errorText }) })), _jsx(Box, { display: 'grid', sx: {
|
|
64
|
+
gridTemplateColumns: { xs: 'repeat(3, 1fr)', sm: 'repeat(5, 1fr)' },
|
|
65
|
+
gap: {
|
|
66
|
+
xs: 'var(--spacing-tokens-size-in-px-spacing-spacing-md)',
|
|
67
|
+
sm: 'var(--spacing-tokens-size-in-px-spacing-spacing-lg)',
|
|
68
|
+
},
|
|
69
|
+
}, children: RATING_SCALE.map((option) => (_jsx(FeedbackOption, { rating: option, label: ratingLabels[option], selected: rating === option, inkColor: ratingInkColor, itemColor: itemColor, onClick: handleRatingClick }, option))) }), expanded && (_jsxs(React.Fragment, { children: [_jsxs(Box, { display: 'flex', flexDirection: 'column', gap: 'var(--spacing-tokens-size-in-px-spacing-spacing-md)', children: [_jsx(Typography, { size: TypographySize.TextS, weight: TypographyWeight.SemiBold, color: 'var(--color-text-text-white)', children: detailsTitle }), topics.length > 0 && (_jsx(Box, { display: 'flex', flexWrap: 'wrap', gap: '8px', children: topics.map((topic) => (_jsx(FeedbackTopicChip, { topic: topic, selected: selectedTopic === topic, itemColor: itemColor, onClick: handleTopicClick }, topic))) })), _jsx(TextField, { multiline: true, rows: 3, fullWidth: true, variant: 'outlined', placeholder: commentPlaceholder, value: comment, onChange: handleCommentChange, sx: {
|
|
70
|
+
'& .MuiOutlinedInput-root': {
|
|
71
|
+
color: 'var(--color-text-text-title)',
|
|
72
|
+
backgroundColor: 'var(--color-background-bg-component)',
|
|
73
|
+
fontSize: '0.875rem',
|
|
74
|
+
'& fieldset': {
|
|
75
|
+
borderColor: 'var(--color-border-border-component)',
|
|
76
|
+
},
|
|
77
|
+
'&:hover fieldset': {
|
|
78
|
+
borderColor: 'var(--color-border-border-component-active)',
|
|
79
|
+
},
|
|
80
|
+
'&.Mui-focused fieldset': {
|
|
81
|
+
borderColor: 'var(--color-border-border-brand)',
|
|
82
|
+
},
|
|
83
|
+
},
|
|
84
|
+
} })] }), _jsxs(Box, { display: 'flex', alignItems: 'center', children: [_jsx(Checkbox, { checked: contactConsent, onChange: handleContactConsentChange, sx: {
|
|
85
|
+
color: 'var(--color-foreground-fg-secondary)',
|
|
86
|
+
'&.Mui-checked': {
|
|
87
|
+
color: 'var(--color-foreground-fg-brand-primary)',
|
|
88
|
+
},
|
|
89
|
+
} }), _jsx(Typography, { size: TypographySize.TextS, weight: TypographyWeight.Regular, color: 'var(--color-text-text-white)', children: contactConsentLabel })] })] })), _jsx(Box, { display: 'flex', justifyContent: 'center', children: _jsx(MainButton, { text: submitText, disabled: submitDisabled, loading: submitLoading, onClick: onSubmit, hierarchy: ButtonHierarchy.Primary, size: ButtonSize.sm, id: submitId }) })] }));
|
|
90
|
+
};
|
|
91
|
+
const FeedbackOption = ({ rating, label, selected, inkColor, itemColor, onClick, }) => {
|
|
92
|
+
const handleClick = () => {
|
|
93
|
+
onClick(rating);
|
|
94
|
+
};
|
|
95
|
+
return (_jsxs(Box, { component: 'button', type: 'button', onClick: handleClick, "aria-pressed": selected, display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 'var(--spacing-tokens-size-in-px-spacing-spacing-md)', borderRadius: 'var(--spacing-tokens-size-in-px-radius-radius-lg)', sx: {
|
|
96
|
+
paddingX: 'var(--spacing-tokens-size-in-px-spacing-spacing-md)',
|
|
97
|
+
paddingY: {
|
|
98
|
+
xs: 'var(--spacing-tokens-size-in-px-spacing-spacing-lg)',
|
|
99
|
+
sm: 'var(--spacing-tokens-size-in-px-spacing-spacing-xl)',
|
|
100
|
+
},
|
|
101
|
+
border: selected
|
|
102
|
+
? '1px solid var(--color-border-border-brand)'
|
|
103
|
+
: '1px solid transparent',
|
|
104
|
+
backgroundColor: itemColor,
|
|
105
|
+
cursor: 'pointer',
|
|
106
|
+
transition: 'border-color 0.2s ease',
|
|
107
|
+
'&:hover': { borderColor: 'var(--color-border-border-brand)' },
|
|
108
|
+
}, children: [_jsx(Box, { sx: {
|
|
109
|
+
width: FACE_BOX,
|
|
110
|
+
height: FACE_BOX,
|
|
111
|
+
margin: FACE_BLEED,
|
|
112
|
+
'& svg': { width: '100%', height: '100%' },
|
|
113
|
+
}, children: _jsx(FeedbackRatingIcon, { rating: rating, inkColor: inkColor }) }), _jsx(Box, { width: '100%', textAlign: 'center', sx: {
|
|
114
|
+
fontFamily: 'var(--global-text-s-semi-bold-font-family), sans-serif',
|
|
115
|
+
fontWeight: 'var(--global-text-s-semi-bold-font-weight)',
|
|
116
|
+
fontSize: { xs: '12px', sm: '14px' },
|
|
117
|
+
lineHeight: { xs: '16px', sm: '20px' },
|
|
118
|
+
color: 'var(--color-text-text-white)',
|
|
119
|
+
}, children: label })] }));
|
|
120
|
+
};
|
|
121
|
+
const FeedbackTopicChip = ({ topic, selected, itemColor, onClick, }) => {
|
|
122
|
+
const handleClick = () => {
|
|
123
|
+
onClick(topic);
|
|
124
|
+
};
|
|
125
|
+
return (_jsx(Chip, { label: topic, onClick: handleClick, sx: {
|
|
126
|
+
backgroundColor: selected
|
|
127
|
+
? 'var(--color-background-bg-secondary-action)'
|
|
128
|
+
: itemColor,
|
|
129
|
+
color: selected
|
|
130
|
+
? 'var(--color-text-text-clicable)'
|
|
131
|
+
: 'var(--color-text-text-white)',
|
|
132
|
+
border: selected
|
|
133
|
+
? '1px solid var(--color-border-border-secondary-action)'
|
|
134
|
+
: '1px solid transparent',
|
|
135
|
+
'&:hover': {
|
|
136
|
+
backgroundColor: 'var(--color-background-bg-secondary-action)',
|
|
137
|
+
},
|
|
138
|
+
} }));
|
|
139
|
+
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react';
|
|
2
|
+
import { FeedbackCard } from './FeedbackCard';
|
|
3
|
+
declare const meta: Meta<typeof FeedbackCard>;
|
|
4
|
+
export default meta;
|
|
5
|
+
type Story = StoryObj<typeof FeedbackCard>;
|
|
6
|
+
export declare const Collapsed: Story;
|
|
7
|
+
export declare const Expanded: Story;
|
|
8
|
+
export declare const WithError: Story;
|
|
9
|
+
export declare const Submitting: Story;
|
|
10
|
+
export declare const CustomBranding: Story;
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useState } from 'react';
|
|
3
|
+
import { FeedbackCard } from './FeedbackCard';
|
|
4
|
+
import { FeedbackRating } from './types';
|
|
5
|
+
const TOPICS = [
|
|
6
|
+
'Audio quality',
|
|
7
|
+
'Avatar quality',
|
|
8
|
+
'Responses',
|
|
9
|
+
'Interface',
|
|
10
|
+
'Chat',
|
|
11
|
+
];
|
|
12
|
+
/**
|
|
13
|
+
* The card is fully controlled, so the stories hold the state a consumer would
|
|
14
|
+
* own and let the controls drive everything else.
|
|
15
|
+
*/
|
|
16
|
+
const ControlledFeedbackCard = (props) => {
|
|
17
|
+
const [rating, setRating] = useState(props.rating ?? null);
|
|
18
|
+
const [topic, setTopic] = useState(props.selectedTopic ?? null);
|
|
19
|
+
const [comment, setComment] = useState(props.comment ?? '');
|
|
20
|
+
const [contactConsent, setContactConsent] = useState(props.contactConsent ?? false);
|
|
21
|
+
return (_jsx(FeedbackCard, { ...props, rating: rating, onRatingChange: setRating, selectedTopic: topic, onTopicChange: setTopic, comment: comment, onCommentChange: setComment, contactConsent: contactConsent, onContactConsentChange: setContactConsent, submitDisabled: props.submitDisabled ?? !rating }));
|
|
22
|
+
};
|
|
23
|
+
const meta = {
|
|
24
|
+
title: 'Design System/Components/Feedback/FeedbackCard',
|
|
25
|
+
component: FeedbackCard,
|
|
26
|
+
parameters: {
|
|
27
|
+
layout: 'centered',
|
|
28
|
+
},
|
|
29
|
+
tags: ['autodocs'],
|
|
30
|
+
decorators: [
|
|
31
|
+
(Story) => (_jsx("div", { style: {
|
|
32
|
+
padding: '32px',
|
|
33
|
+
background: 'var(--color-background-bg-page)',
|
|
34
|
+
display: 'flex',
|
|
35
|
+
justifyContent: 'center',
|
|
36
|
+
}, children: _jsx(Story, {}) })),
|
|
37
|
+
],
|
|
38
|
+
render: (args) => _jsx(ControlledFeedbackCard, { ...args }),
|
|
39
|
+
argTypes: {
|
|
40
|
+
title: {
|
|
41
|
+
control: 'text',
|
|
42
|
+
description: 'Question shown above the rating scale',
|
|
43
|
+
table: { type: { summary: 'string' } },
|
|
44
|
+
},
|
|
45
|
+
expanded: {
|
|
46
|
+
control: 'boolean',
|
|
47
|
+
description: 'Whether the follow-up fields are shown',
|
|
48
|
+
table: {
|
|
49
|
+
type: { summary: 'boolean' },
|
|
50
|
+
defaultValue: { summary: 'false' },
|
|
51
|
+
},
|
|
52
|
+
},
|
|
53
|
+
topics: {
|
|
54
|
+
control: 'object',
|
|
55
|
+
description: 'Selectable topics offered with the follow-up fields',
|
|
56
|
+
table: { type: { summary: 'string[]' } },
|
|
57
|
+
},
|
|
58
|
+
submitText: {
|
|
59
|
+
control: 'text',
|
|
60
|
+
description: 'Label of the submit button',
|
|
61
|
+
table: {
|
|
62
|
+
type: { summary: 'string' },
|
|
63
|
+
defaultValue: { summary: 'Submit Feedback' },
|
|
64
|
+
},
|
|
65
|
+
},
|
|
66
|
+
submitLoading: {
|
|
67
|
+
control: 'boolean',
|
|
68
|
+
description: 'Whether the submit button shows its loading spinner',
|
|
69
|
+
table: {
|
|
70
|
+
type: { summary: 'boolean' },
|
|
71
|
+
defaultValue: { summary: 'false' },
|
|
72
|
+
},
|
|
73
|
+
},
|
|
74
|
+
errorText: {
|
|
75
|
+
control: 'text',
|
|
76
|
+
description: 'Error message shown under the question',
|
|
77
|
+
table: { type: { summary: 'string | null' } },
|
|
78
|
+
},
|
|
79
|
+
surfaceColor: {
|
|
80
|
+
control: 'color',
|
|
81
|
+
description: 'Background of the card; override to follow a custom brand color',
|
|
82
|
+
table: { type: { summary: 'string' } },
|
|
83
|
+
},
|
|
84
|
+
itemColor: {
|
|
85
|
+
control: 'color',
|
|
86
|
+
description: 'Background of each rating tile and topic chip',
|
|
87
|
+
table: { type: { summary: 'string' } },
|
|
88
|
+
},
|
|
89
|
+
ratingInkColor: {
|
|
90
|
+
control: 'color',
|
|
91
|
+
description: 'Brand-colored part of the faces',
|
|
92
|
+
table: { type: { summary: 'string' } },
|
|
93
|
+
},
|
|
94
|
+
},
|
|
95
|
+
};
|
|
96
|
+
export default meta;
|
|
97
|
+
export const Collapsed = {
|
|
98
|
+
args: {
|
|
99
|
+
rating: null,
|
|
100
|
+
expanded: false,
|
|
101
|
+
submitId: 'call-postscreen-submit-feedback',
|
|
102
|
+
onSubmit: () => { },
|
|
103
|
+
onRatingChange: () => { },
|
|
104
|
+
},
|
|
105
|
+
};
|
|
106
|
+
export const Expanded = {
|
|
107
|
+
args: {
|
|
108
|
+
...Collapsed.args,
|
|
109
|
+
rating: FeedbackRating.Satisfied,
|
|
110
|
+
expanded: true,
|
|
111
|
+
topics: TOPICS,
|
|
112
|
+
},
|
|
113
|
+
};
|
|
114
|
+
export const WithError = {
|
|
115
|
+
args: {
|
|
116
|
+
...Collapsed.args,
|
|
117
|
+
errorText: 'Please rate the product',
|
|
118
|
+
},
|
|
119
|
+
};
|
|
120
|
+
export const Submitting = {
|
|
121
|
+
args: {
|
|
122
|
+
...Expanded.args,
|
|
123
|
+
submitLoading: true,
|
|
124
|
+
submitDisabled: true,
|
|
125
|
+
},
|
|
126
|
+
};
|
|
127
|
+
export const CustomBranding = {
|
|
128
|
+
args: {
|
|
129
|
+
...Expanded.args,
|
|
130
|
+
surfaceColor: 'rgba(180, 35, 24, 0.2)',
|
|
131
|
+
ratingInkColor: '#B42318',
|
|
132
|
+
},
|
|
133
|
+
};
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { FeedbackRating } from './types';
|
|
3
|
+
/**
|
|
4
|
+
* Illustration colors lifted straight from the Figma feedback frames. They have
|
|
5
|
+
* no token equivalents — the faces are drawn the same way in both themes, so
|
|
6
|
+
* pinning the primitives here keeps them matching the design.
|
|
7
|
+
*
|
|
8
|
+
* `DEFAULT_INK` is only a default: it is the one brand-colored part of the face, so a
|
|
9
|
+
* consumer under custom branding passes `inkColor` instead. It cannot default to
|
|
10
|
+
* `--color-background-bg-brand-primary`, which resolves to lemon in dark theme.
|
|
11
|
+
*/
|
|
12
|
+
const DEFAULT_INK = '#6301FE';
|
|
13
|
+
const FACE_MUTED = '#C8CCED';
|
|
14
|
+
const FACE_LAVENDER = '#D8A3FE';
|
|
15
|
+
const FACE_LEMON = '#C5EB28';
|
|
16
|
+
/**
|
|
17
|
+
* The glyph is drawn on a 48-unit grid. The viewBox is bled 6 units on every
|
|
18
|
+
* side so the heart on the `VerySatisfied` face, which sits outside the grid,
|
|
19
|
+
* is not clipped.
|
|
20
|
+
*/
|
|
21
|
+
const VIEW_BOX = '-6 -6 60 60';
|
|
22
|
+
const SMILEY_SAD = 'M24.0012 4.23438C29.1709 4.24083 34.1269 6.29763 37.7825 9.95312C41.438 13.6087 43.4948 18.5646 43.5012 23.7344C43.5012 27.5911 42.3578 31.3616 40.2151 34.5684C38.0725 37.7749 35.027 40.2741 31.4641 41.75C27.901 43.2259 23.98 43.6117 20.1975 42.8594C16.415 42.107 12.9402 40.2504 10.2131 37.5234C7.4861 34.7964 5.62867 31.3215 4.8762 27.5391C4.12382 23.7566 4.50981 19.8355 5.98558 16.2725C7.46149 12.7093 9.96144 9.6632 13.1682 7.52051C16.3748 5.37802 20.1447 4.23442 24.0012 4.23438ZM33.2209 32.8506C30.2584 29.5818 26.5808 28.606 23.3127 28.957C20.127 29.2993 17.2271 30.9167 15.7405 32.9814C15.2567 33.6537 15.4101 34.5912 16.0823 35.0752C16.7545 35.5588 17.6921 35.4065 18.176 34.7344C19.0845 33.4727 21.1482 32.2074 23.633 31.9404C26.0356 31.6824 28.7365 32.3707 30.9973 34.8652C31.5536 35.479 32.5026 35.525 33.1164 34.9688C33.7299 34.4125 33.7768 33.4643 33.2209 32.8506ZM31.6125 17.9053C31.2015 17.735 30.7491 17.6906 30.3127 17.7773C29.8763 17.8642 29.4751 18.0789 29.1604 18.3936C28.8458 18.7082 28.631 19.1095 28.5442 19.5459C28.4575 19.9822 28.5029 20.4347 28.6731 20.8457C28.8434 21.2567 29.1313 21.6083 29.5012 21.8555C29.8712 22.1027 30.3063 22.2343 30.7512 22.2344C31.3479 22.2344 31.9201 21.9971 32.342 21.5752C32.764 21.1532 33.0012 20.5811 33.0012 19.9844C33.0012 19.5394 32.8695 19.1044 32.6223 18.7344C32.3751 18.3644 32.0237 18.0756 31.6125 17.9053ZM17.2512 17.7344C16.6545 17.7344 16.0823 17.9716 15.6604 18.3936C15.2385 18.8155 15.0012 19.3877 15.0012 19.9844C15.0012 20.4293 15.133 20.8644 15.3801 21.2344C15.6273 21.6044 15.9797 21.8932 16.3909 22.0635C16.8018 22.2336 17.2544 22.2782 17.6907 22.1914C18.127 22.1046 18.5274 21.8898 18.842 21.5752C19.1567 21.2605 19.3714 20.8593 19.4582 20.4229C19.5449 19.9865 19.5005 19.534 19.3303 19.123C19.16 18.712 18.8712 18.3605 18.5012 18.1133C18.1313 17.8662 17.6961 17.7344 17.2512 17.7344Z';
|
|
23
|
+
const SMILEY_FROWN = 'M24.0012 4.23438C29.1709 4.24083 34.1269 6.29763 37.7825 9.95312C41.438 13.6087 43.4948 18.5646 43.5012 23.7344C43.5012 27.5911 42.3578 31.3616 40.2151 34.5684C38.0725 37.7749 35.027 40.2741 31.4641 41.75C27.901 43.2259 23.98 43.6117 20.1975 42.8594C16.415 42.107 12.9402 40.2504 10.2131 37.5234C7.4861 34.7964 5.62867 31.3215 4.8762 27.5391C4.12382 23.7566 4.50981 19.8355 5.98558 16.2725C7.46149 12.7093 9.96144 9.6632 13.1682 7.52051C16.3748 5.37802 20.1447 4.23442 24.0012 4.23438ZM33.3762 28.0049C33.1512 27.2079 32.3227 26.744 31.5256 26.9688L17.6633 30.8789C16.866 31.1038 16.4013 31.9332 16.6262 32.7305C16.8512 33.5277 17.6805 33.9915 18.4778 33.7666L32.3401 29.8564C33.1373 29.6315 33.6011 28.8022 33.3762 28.0049ZM31.6125 17.9053C31.2015 17.735 30.7491 17.6906 30.3127 17.7773C29.8763 17.8642 29.4751 18.0789 29.1604 18.3936C28.8458 18.7082 28.631 19.1095 28.5442 19.5459C28.4575 19.9822 28.5029 20.4347 28.6731 20.8457C28.8434 21.2567 29.1313 21.6083 29.5012 21.8555C29.8712 22.1027 30.3063 22.2343 30.7512 22.2344C31.3479 22.2344 31.9201 21.9971 32.342 21.5752C32.764 21.1532 33.0012 20.5811 33.0012 19.9844C33.0012 19.5394 32.8695 19.1044 32.6223 18.7344C32.3751 18.3644 32.0237 18.0756 31.6125 17.9053ZM17.2512 17.7344C16.6545 17.7344 16.0823 17.9716 15.6604 18.3936C15.2385 18.8155 15.0012 19.3877 15.0012 19.9844C15.0012 20.4293 15.133 20.8644 15.3801 21.2344C15.6273 21.6044 15.9797 21.8932 16.3909 22.0635C16.8018 22.2336 17.2544 22.2782 17.6907 22.1914C18.127 22.1046 18.5274 21.8898 18.842 21.5752C19.1567 21.2605 19.3714 20.8593 19.4582 20.4229C19.5449 19.9865 19.5005 19.534 19.3303 19.123C19.16 18.712 18.8712 18.3605 18.5012 18.1133C18.1313 17.8662 17.6961 17.7344 17.2512 17.7344Z';
|
|
24
|
+
const SMILEY_MEH = 'M23.6607 4.23438C19.8039 4.23438 16.0338 5.37803 12.827 7.52072C9.62028 9.66341 7.12091 12.7089 5.645 16.272C4.16909 19.8352 3.78293 23.756 4.53534 27.5386C5.28775 31.3213 7.14495 34.7958 9.87207 37.523C12.5992 40.2501 16.0738 42.1073 19.8564 42.8597C23.639 43.6121 27.5598 43.2259 31.123 41.75C34.6861 40.2741 37.7316 37.7748 39.8743 34.568C42.017 31.3612 43.1607 27.5911 43.1607 23.7344C43.1542 18.5646 41.0977 13.6085 37.4421 9.95292C33.7866 6.29735 28.8304 4.24083 23.6607 4.23438ZM16.9107 17.7344C17.3557 17.7344 17.7907 17.8663 18.1607 18.1136C18.5307 18.3608 18.8191 18.7122 18.9894 19.1233C19.1597 19.5345 19.2042 19.9869 19.1174 20.4233C19.0306 20.8598 18.8163 21.2607 18.5016 21.5754C18.187 21.89 17.7861 22.1043 17.3496 22.1911C16.9132 22.278 16.4608 22.2334 16.0496 22.0631C15.6385 21.8928 15.2871 21.6044 15.0398 21.2344C14.7926 20.8644 14.6607 20.4294 14.6607 19.9844C14.6607 19.3876 14.8977 18.8153 15.3197 18.3934C15.7416 17.9714 16.3139 17.7344 16.9107 17.7344ZM31.1607 31.2344H16.1607C15.7628 31.2344 15.3813 31.0763 15.1 30.795C14.8187 30.5137 14.6607 30.1322 14.6607 29.7344C14.6607 29.3366 14.8187 28.955 15.1 28.6737C15.3813 28.3924 15.7628 28.2344 16.1607 28.2344H31.1607C31.5585 28.2344 31.94 28.3924 32.2213 28.6737C32.5026 28.955 32.6607 29.3366 32.6607 29.7344C32.6607 30.1322 32.5026 30.5137 32.2213 30.795C31.94 31.0763 31.5585 31.2344 31.1607 31.2344ZM30.4107 22.2344C29.9656 22.2344 29.5306 22.1024 29.1606 21.8552C28.7906 21.608 28.5022 21.2565 28.3319 20.8454C28.1616 20.4343 28.1171 19.9819 28.2039 19.5454C28.2907 19.109 28.505 18.7081 28.8197 18.3934C29.1343 18.0787 29.5352 17.8644 29.9717 17.7776C30.4082 17.6908 30.8606 17.7353 31.2717 17.9056C31.6828 18.0759 32.0342 18.3643 32.2815 18.7343C32.5287 19.1044 32.6607 19.5394 32.6607 19.9844C32.6607 20.5811 32.4236 21.1534 32.0016 21.5754C31.5797 21.9973 31.0074 22.2344 30.4107 22.2344Z';
|
|
25
|
+
const SMILEY_HAPPY = 'M23.5 4.68945C19.6433 4.68945 15.8731 5.83311 12.6664 7.9758C9.45963 10.1185 6.96027 13.164 5.48436 16.7271C4.00845 20.2903 3.62228 24.2111 4.3747 27.9937C5.12711 31.7763 6.9843 35.2509 9.71143 37.978C12.4386 40.7052 15.9131 42.5624 19.6957 43.3148C23.4784 44.0672 27.3992 43.681 30.9623 42.2051C34.5255 40.7292 37.571 38.2298 39.7137 35.0231C41.8564 31.8163 43 28.0462 43 24.1895C42.9946 19.0194 40.9383 14.0627 37.2826 10.4069C33.6268 6.75112 28.6701 4.69491 23.5 4.68945ZM16.75 18.1895C17.195 18.1895 17.63 18.3214 18 18.5686C18.3701 18.8159 18.6584 19.1673 18.8287 19.5784C18.999 19.9896 19.0436 20.442 18.9568 20.8784C18.87 21.3149 18.6557 21.7158 18.341 22.0304C18.0263 22.3451 17.6254 22.5594 17.189 22.6462C16.7525 22.733 16.3001 22.6885 15.889 22.5182C15.4778 22.3479 15.1264 22.0595 14.8792 21.6895C14.632 21.3195 14.5 20.8845 14.5 20.4395C14.5 19.8427 14.7371 19.2704 15.159 18.8485C15.581 18.4265 16.1533 18.1895 16.75 18.1895ZM32.2975 29.4395C30.3681 32.7751 27.1619 34.6895 23.5 34.6895C19.8381 34.6895 16.6319 32.777 14.7025 29.4395C14.594 29.2687 14.5211 29.0778 14.4883 28.8782C14.4554 28.6786 14.4633 28.4744 14.5115 28.2779C14.5596 28.0814 14.647 27.8967 14.7683 27.7348C14.8897 27.573 15.0426 27.4373 15.2177 27.3361C15.3929 27.2348 15.5867 27.1701 15.7875 27.1457C15.9883 27.1213 16.192 27.1378 16.3863 27.1941C16.5806 27.2505 16.7615 27.3456 16.9181 27.4737C17.0747 27.6018 17.2037 27.7602 17.2975 27.9395C18.6981 30.3601 20.8994 31.6895 23.5 31.6895C26.1006 31.6895 28.3019 30.3582 29.7025 27.9395C29.7963 27.7602 29.9253 27.6018 30.0819 27.4737C30.2385 27.3456 30.4194 27.2505 30.6137 27.1941C30.808 27.1378 31.0117 27.1213 31.2125 27.1457C31.4133 27.1701 31.6072 27.2348 31.7823 27.3361C31.9575 27.4373 32.1103 27.573 32.2317 27.7348C32.3531 27.8967 32.4404 28.0814 32.4886 28.2779C32.5367 28.4744 32.5446 28.6786 32.5117 28.8782C32.4789 29.0778 32.406 29.2687 32.2975 29.4395ZM30.25 22.6895C29.805 22.6895 29.37 22.5575 29 22.3103C28.63 22.063 28.3416 21.7116 28.1713 21.3005C28.001 20.8894 27.9564 20.437 28.0432 20.0005C28.1301 19.564 28.3444 19.1631 28.659 18.8485C28.9737 18.5338 29.3746 18.3195 29.8111 18.2327C30.2475 18.1459 30.6999 18.1904 31.111 18.3607C31.5222 18.531 31.8736 18.8194 32.1208 19.1894C32.368 19.5594 32.5 19.9944 32.5 20.4395C32.5 21.0362 32.263 21.6085 31.841 22.0304C31.419 22.4524 30.8467 22.6895 30.25 22.6895Z';
|
|
26
|
+
const SMILEY_HAPPY_SHIFTED = 'M24.5 4.68945C20.6433 4.68945 16.8731 5.83311 13.6664 7.9758C10.4596 10.1185 7.96027 13.164 6.48436 16.7271C5.00845 20.2903 4.62228 24.2111 5.3747 27.9937C6.12711 31.7763 7.9843 35.2509 10.7114 37.978C13.4386 40.7052 16.9131 42.5624 20.6957 43.3148C24.4784 44.0672 28.3992 43.681 31.9623 42.2051C35.5255 40.7292 38.571 38.2298 40.7137 35.0231C42.8564 31.8163 44 28.0462 44 24.1895C43.9946 19.0194 41.9383 14.0627 38.2826 10.4069C34.6268 6.75112 29.6701 4.69491 24.5 4.68945ZM17.75 18.1895C18.195 18.1895 18.63 18.3214 19 18.5686C19.3701 18.8159 19.6584 19.1673 19.8287 19.5784C19.999 19.9896 20.0436 20.442 19.9568 20.8784C19.87 21.3149 19.6557 21.7158 19.341 22.0304C19.0263 22.3451 18.6254 22.5594 18.189 22.6462C17.7525 22.733 17.3001 22.6885 16.889 22.5182C16.4778 22.3479 16.1264 22.0595 15.8792 21.6895C15.632 21.3195 15.5 20.8845 15.5 20.4395C15.5 19.8427 15.7371 19.2704 16.159 18.8485C16.581 18.4265 17.1533 18.1895 17.75 18.1895ZM33.2975 29.4395C31.3681 32.7751 28.1619 34.6895 24.5 34.6895C20.8381 34.6895 17.6319 32.777 15.7025 29.4395C15.594 29.2687 15.5211 29.0778 15.4883 28.8782C15.4554 28.6786 15.4633 28.4744 15.5115 28.2779C15.5596 28.0814 15.647 27.8967 15.7683 27.7348C15.8897 27.573 16.0426 27.4373 16.2177 27.3361C16.3929 27.2348 16.5867 27.1701 16.7875 27.1457C16.9883 27.1213 17.192 27.1378 17.3863 27.1941C17.5806 27.2505 17.7615 27.3456 17.9181 27.4737C18.0747 27.6018 18.2037 27.7602 18.2975 27.9395C19.6981 30.3601 21.8994 31.6895 24.5 31.6895C27.1006 31.6895 29.3019 30.3582 30.7025 27.9395C30.7963 27.7602 30.9253 27.6018 31.0819 27.4737C31.2385 27.3456 31.4194 27.2505 31.6137 27.1941C31.808 27.1378 32.0117 27.1213 32.2125 27.1457C32.4133 27.1701 32.6072 27.2348 32.7823 27.3361C32.9575 27.4373 33.1103 27.573 33.2317 27.7348C33.3531 27.8967 33.4404 28.0814 33.4886 28.2779C33.5367 28.4744 33.5446 28.6786 33.5117 28.8782C33.4789 29.0778 33.406 29.2687 33.2975 29.4395ZM31.25 22.6895C30.805 22.6895 30.37 22.5575 30 22.3103C29.63 22.063 29.3416 21.7116 29.1713 21.3005C29.001 20.8894 28.9564 20.437 29.0432 20.0005C29.1301 19.564 29.3444 19.1631 29.659 18.8485C29.9737 18.5338 30.3746 18.3195 30.8111 18.2327C31.2475 18.1459 31.6999 18.1904 32.111 18.3607C32.5222 18.531 32.8736 18.8194 33.1208 19.1894C33.368 19.5594 33.5 19.9944 33.5 20.4395C33.5 21.0362 33.263 21.6085 32.841 22.0304C32.419 22.4524 31.8467 22.6895 31.25 22.6895Z';
|
|
27
|
+
const HEART = 'M24.7945 18.7681C23.1038 17.0773 20.3812 17.0773 18.6905 18.7681L18.0313 19.4279L17.3722 18.7688C15.6814 17.078 12.9589 17.078 11.2681 18.7688C9.5773 20.4595 9.5773 23.1821 11.2681 24.8728L18.0312 31.636L24.7944 24.8728C26.4852 23.1814 26.4852 20.4425 24.7944 18.7682L24.7945 18.7681Z';
|
|
28
|
+
const FACES = {
|
|
29
|
+
[FeedbackRating.VeryUnsatisfied]: {
|
|
30
|
+
disc: { cx: 24.0014, cy: 23.7346 },
|
|
31
|
+
color: FACE_MUTED,
|
|
32
|
+
path: SMILEY_SAD,
|
|
33
|
+
},
|
|
34
|
+
[FeedbackRating.Unsatisfied]: {
|
|
35
|
+
disc: { cx: 24.0014, cy: 23.7346 },
|
|
36
|
+
color: FACE_MUTED,
|
|
37
|
+
path: SMILEY_FROWN,
|
|
38
|
+
},
|
|
39
|
+
[FeedbackRating.Neutral]: {
|
|
40
|
+
disc: { cx: 23.6607, cy: 23.7346 },
|
|
41
|
+
color: FACE_LAVENDER,
|
|
42
|
+
path: SMILEY_MEH,
|
|
43
|
+
},
|
|
44
|
+
[FeedbackRating.Satisfied]: {
|
|
45
|
+
disc: { cx: 21.5568, cy: 24.1896 },
|
|
46
|
+
color: FACE_LEMON,
|
|
47
|
+
path: SMILEY_HAPPY,
|
|
48
|
+
},
|
|
49
|
+
[FeedbackRating.VerySatisfied]: {
|
|
50
|
+
disc: { cx: 22.5568, cy: 24.1896 },
|
|
51
|
+
color: FACE_LEMON,
|
|
52
|
+
path: SMILEY_HAPPY_SHIFTED,
|
|
53
|
+
},
|
|
54
|
+
};
|
|
55
|
+
const DISC_RADIUS = 17.5568;
|
|
56
|
+
export const FeedbackRatingIcon = ({ rating, size = 60, inkColor = DEFAULT_INK, className, }) => {
|
|
57
|
+
const face = FACES[rating];
|
|
58
|
+
return (_jsxs("svg", { className: className, width: size, height: size, viewBox: VIEW_BOX, fill: 'none', xmlns: 'http://www.w3.org/2000/svg', style: { display: 'block', overflow: 'visible' }, role: 'presentation', children: [_jsx("circle", { cx: face.disc.cx, cy: face.disc.cy, r: DISC_RADIUS, fill: inkColor }), _jsx("path", { d: face.path, fill: face.color }), rating === FeedbackRating.VerySatisfied && (_jsx("g", { transform: 'translate(26 -21)', children: _jsx("path", { d: HEART, fill: inkColor }) }))] }));
|
|
59
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react';
|
|
2
|
+
import { FeedbackRatingIcon } from './FeedbackRatingIcon';
|
|
3
|
+
declare const meta: Meta<typeof FeedbackRatingIcon>;
|
|
4
|
+
export default meta;
|
|
5
|
+
type Story = StoryObj<typeof FeedbackRatingIcon>;
|
|
6
|
+
export declare const VeryUnsatisfied: Story;
|
|
7
|
+
export declare const Unsatisfied: Story;
|
|
8
|
+
export declare const Neutral: Story;
|
|
9
|
+
export declare const Satisfied: Story;
|
|
10
|
+
export declare const VerySatisfied: Story;
|
|
11
|
+
export declare const CustomBrandInk: Story;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { FeedbackRatingIcon } from './FeedbackRatingIcon';
|
|
2
|
+
import { FeedbackRating } from './types';
|
|
3
|
+
const meta = {
|
|
4
|
+
title: 'Design System/Components/Feedback/FeedbackRatingIcon',
|
|
5
|
+
component: FeedbackRatingIcon,
|
|
6
|
+
parameters: {
|
|
7
|
+
layout: 'centered',
|
|
8
|
+
},
|
|
9
|
+
tags: ['autodocs'],
|
|
10
|
+
argTypes: {
|
|
11
|
+
rating: {
|
|
12
|
+
control: 'select',
|
|
13
|
+
options: [
|
|
14
|
+
FeedbackRating.VeryUnsatisfied,
|
|
15
|
+
FeedbackRating.Unsatisfied,
|
|
16
|
+
FeedbackRating.Neutral,
|
|
17
|
+
FeedbackRating.Satisfied,
|
|
18
|
+
FeedbackRating.VerySatisfied,
|
|
19
|
+
],
|
|
20
|
+
description: 'Which face of the rating scale to draw',
|
|
21
|
+
table: {
|
|
22
|
+
type: { summary: 'FeedbackRating' },
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
size: {
|
|
26
|
+
control: 'number',
|
|
27
|
+
description: 'Rendered width and height in px',
|
|
28
|
+
table: {
|
|
29
|
+
type: { summary: 'number' },
|
|
30
|
+
defaultValue: { summary: '60' },
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
inkColor: {
|
|
34
|
+
control: 'color',
|
|
35
|
+
description: 'Color of the disc behind the face; pass the active brand color under custom branding',
|
|
36
|
+
table: {
|
|
37
|
+
type: { summary: 'string' },
|
|
38
|
+
defaultValue: { summary: '#6301FE' },
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
};
|
|
43
|
+
export default meta;
|
|
44
|
+
export const VeryUnsatisfied = {
|
|
45
|
+
args: { rating: FeedbackRating.VeryUnsatisfied },
|
|
46
|
+
};
|
|
47
|
+
export const Unsatisfied = {
|
|
48
|
+
args: { rating: FeedbackRating.Unsatisfied },
|
|
49
|
+
};
|
|
50
|
+
export const Neutral = {
|
|
51
|
+
args: { rating: FeedbackRating.Neutral },
|
|
52
|
+
};
|
|
53
|
+
export const Satisfied = {
|
|
54
|
+
args: { rating: FeedbackRating.Satisfied },
|
|
55
|
+
};
|
|
56
|
+
export const VerySatisfied = {
|
|
57
|
+
args: { rating: FeedbackRating.VerySatisfied },
|
|
58
|
+
};
|
|
59
|
+
export const CustomBrandInk = {
|
|
60
|
+
args: { rating: FeedbackRating.VerySatisfied, inkColor: '#B42318' },
|
|
61
|
+
};
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { SxProps, Theme } from '@mui/material';
|
|
2
|
+
/**
|
|
3
|
+
* The five points of the call-experience rating scale
|
|
4
|
+
*/
|
|
5
|
+
export declare enum FeedbackRating {
|
|
6
|
+
VeryUnsatisfied = 1,
|
|
7
|
+
Unsatisfied = 2,
|
|
8
|
+
Neutral = 3,
|
|
9
|
+
Satisfied = 4,
|
|
10
|
+
VerySatisfied = 5
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* FeedbackRatingIcon component props
|
|
14
|
+
*/
|
|
15
|
+
export type FeedbackRatingIconProps = {
|
|
16
|
+
/** Which face of the rating scale to draw */
|
|
17
|
+
rating: FeedbackRating;
|
|
18
|
+
/** Rendered width and height in px */
|
|
19
|
+
size?: number;
|
|
20
|
+
/**
|
|
21
|
+
* Color of the disc behind the face, and of the heart on `VerySatisfied`.
|
|
22
|
+
* This is the brand-colored part of the illustration — pass the active brand
|
|
23
|
+
* color to make the faces follow custom branding.
|
|
24
|
+
*/
|
|
25
|
+
inkColor?: string;
|
|
26
|
+
/** CSS class name for additional styling */
|
|
27
|
+
className?: string;
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* FeedbackCard component props
|
|
31
|
+
*
|
|
32
|
+
* The card is fully controlled: it renders the rating scale, and — once
|
|
33
|
+
* `expanded` is set — the follow-up topic, comment and consent fields. State
|
|
34
|
+
* and submission belong to the consumer.
|
|
35
|
+
*/
|
|
36
|
+
export type FeedbackCardProps = {
|
|
37
|
+
/** Question shown above the rating scale */
|
|
38
|
+
title?: string;
|
|
39
|
+
/** Currently selected rating, or `null` while the scale is untouched */
|
|
40
|
+
rating: FeedbackRating | null;
|
|
41
|
+
/** Callback function to handle a rating change; `null` when it is cleared */
|
|
42
|
+
onRatingChange: (rating: FeedbackRating | null) => void;
|
|
43
|
+
/** Labels under each face, keyed by rating */
|
|
44
|
+
ratingLabels?: Record<FeedbackRating, string>;
|
|
45
|
+
/** Brand-colored part of the faces; see `FeedbackRatingIconProps.inkColor` */
|
|
46
|
+
ratingInkColor?: string;
|
|
47
|
+
/** Whether the follow-up fields are shown */
|
|
48
|
+
expanded?: boolean;
|
|
49
|
+
/** Heading of the follow-up fields */
|
|
50
|
+
detailsTitle?: string;
|
|
51
|
+
/** Selectable topics offered with the follow-up fields */
|
|
52
|
+
topics?: string[];
|
|
53
|
+
/** Currently selected topic, or `null` when none is picked */
|
|
54
|
+
selectedTopic?: string | null;
|
|
55
|
+
/** Callback function to handle a topic change; `null` when it is cleared */
|
|
56
|
+
onTopicChange?: (topic: string | null) => void;
|
|
57
|
+
/** Free-text comment */
|
|
58
|
+
comment?: string;
|
|
59
|
+
/** Callback function to handle a comment change */
|
|
60
|
+
onCommentChange?: (comment: string) => void;
|
|
61
|
+
/** Placeholder of the comment field */
|
|
62
|
+
commentPlaceholder?: string;
|
|
63
|
+
/** Whether the contact-consent checkbox is ticked */
|
|
64
|
+
contactConsent?: boolean;
|
|
65
|
+
/** Callback function to handle a contact-consent change */
|
|
66
|
+
onContactConsentChange?: (contactConsent: boolean) => void;
|
|
67
|
+
/** Label of the contact-consent checkbox */
|
|
68
|
+
contactConsentLabel?: string;
|
|
69
|
+
/** Label of the submit button */
|
|
70
|
+
submitText?: string;
|
|
71
|
+
/** Callback function to handle submit button click */
|
|
72
|
+
onSubmit: () => void;
|
|
73
|
+
/** Whether the submit button is disabled */
|
|
74
|
+
submitDisabled?: boolean;
|
|
75
|
+
/** Whether the submit button shows its loading spinner */
|
|
76
|
+
submitLoading?: boolean;
|
|
77
|
+
/** DOM id forwarded to the submit button, for analytics hooks */
|
|
78
|
+
submitId?: string;
|
|
79
|
+
/** Error message shown under the question */
|
|
80
|
+
errorText?: string | null;
|
|
81
|
+
/** Background of the card; override to follow a custom brand color */
|
|
82
|
+
surfaceColor?: string;
|
|
83
|
+
/** Background of each rating tile and topic chip */
|
|
84
|
+
itemColor?: string;
|
|
85
|
+
/** CSS class name for additional styling */
|
|
86
|
+
className?: string;
|
|
87
|
+
/** Style object to apply to the component */
|
|
88
|
+
sx?: SxProps<Theme>;
|
|
89
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The five points of the call-experience rating scale
|
|
3
|
+
*/
|
|
4
|
+
export var FeedbackRating;
|
|
5
|
+
(function (FeedbackRating) {
|
|
6
|
+
FeedbackRating[FeedbackRating["VeryUnsatisfied"] = 1] = "VeryUnsatisfied";
|
|
7
|
+
FeedbackRating[FeedbackRating["Unsatisfied"] = 2] = "Unsatisfied";
|
|
8
|
+
FeedbackRating[FeedbackRating["Neutral"] = 3] = "Neutral";
|
|
9
|
+
FeedbackRating[FeedbackRating["Satisfied"] = 4] = "Satisfied";
|
|
10
|
+
FeedbackRating[FeedbackRating["VerySatisfied"] = 5] = "VerySatisfied";
|
|
11
|
+
})(FeedbackRating || (FeedbackRating = {}));
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Box } from '@mui/material';
|
|
3
|
+
import { ButtonHierarchy, ButtonSize, MainButton } from '../Buttons';
|
|
4
|
+
import { Logo, LogoVariant } from '../UI';
|
|
5
|
+
export const CallHeader = ({ logoUrl, logoColor, onLogoClick, actionText = 'Create Your Own Agent', onActionClick, showAction = true, actionId, className, sx, }) => {
|
|
6
|
+
return (_jsxs(Box, { component: 'header', className: className, display: 'flex', flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between', gap: 'var(--spacing-tokens-size-in-px-spacing-spacing-lg)', flexShrink: 0, width: '100%', boxSizing: 'border-box', borderBottom: '1px solid var(--color-border-border-divider)', bgcolor: 'var(--color-background-bg-page)', paddingX: 'var(--spacing-tokens-size-in-px-spacing-spacing-4xl)', paddingY: 'var(--spacing-tokens-size-in-px-spacing-spacing-xl)', sx: sx, children: [_jsx(Box, { display: 'flex', alignItems: 'center', onClick: onLogoClick, sx: {
|
|
7
|
+
cursor: onLogoClick ? 'pointer' : 'default',
|
|
8
|
+
'& svg, & img': {
|
|
9
|
+
maxWidth: { xs: 140, sm: 'none' },
|
|
10
|
+
height: 'auto',
|
|
11
|
+
},
|
|
12
|
+
}, children: _jsx(Logo, { svgUrl: logoUrl ?? undefined, variant: LogoVariant.Horizontal, color: logoColor }) }), showAction && (_jsx(MainButton, { hierarchy: ButtonHierarchy.SecondaryColor, size: ButtonSize.sm, text: actionText, onClick: onActionClick, id: actionId }))] }));
|
|
13
|
+
};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react';
|
|
2
|
+
import { CallHeader } from './CallHeader';
|
|
3
|
+
declare const meta: Meta<typeof CallHeader>;
|
|
4
|
+
export default meta;
|
|
5
|
+
type Story = StoryObj<typeof CallHeader>;
|
|
6
|
+
export declare const Default: Story;
|
|
7
|
+
export declare const WithoutAction: Story;
|
|
8
|
+
export declare const CustomBranding: Story;
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { CallHeader } from './CallHeader';
|
|
2
|
+
const meta = {
|
|
3
|
+
title: 'Design System/Components/Navigation/CallHeader',
|
|
4
|
+
component: CallHeader,
|
|
5
|
+
parameters: {
|
|
6
|
+
layout: 'fullscreen',
|
|
7
|
+
},
|
|
8
|
+
tags: ['autodocs'],
|
|
9
|
+
argTypes: {
|
|
10
|
+
logoUrl: {
|
|
11
|
+
control: 'text',
|
|
12
|
+
description: 'Custom-branding logo URL; the Beyond Presence mark is drawn when omitted',
|
|
13
|
+
table: {
|
|
14
|
+
type: { summary: 'string | null' },
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
logoColor: {
|
|
18
|
+
control: 'text',
|
|
19
|
+
description: 'Color of the built-in logo mark; ignored once `logoUrl` is set',
|
|
20
|
+
table: {
|
|
21
|
+
type: { summary: 'string' },
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
onLogoClick: {
|
|
25
|
+
description: 'Callback function to handle logo click',
|
|
26
|
+
table: {
|
|
27
|
+
type: { summary: 'function' },
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
|
+
actionText: {
|
|
31
|
+
control: 'text',
|
|
32
|
+
description: 'Label of the trailing call-to-action button',
|
|
33
|
+
table: {
|
|
34
|
+
type: { summary: 'string' },
|
|
35
|
+
defaultValue: { summary: 'Create Your Own Agent' },
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
onActionClick: {
|
|
39
|
+
description: 'Callback function to handle call-to-action button click',
|
|
40
|
+
table: {
|
|
41
|
+
type: { summary: 'function' },
|
|
42
|
+
},
|
|
43
|
+
},
|
|
44
|
+
showAction: {
|
|
45
|
+
control: 'boolean',
|
|
46
|
+
description: 'Whether the trailing call-to-action button is rendered',
|
|
47
|
+
table: {
|
|
48
|
+
type: { summary: 'boolean' },
|
|
49
|
+
defaultValue: { summary: 'true' },
|
|
50
|
+
},
|
|
51
|
+
},
|
|
52
|
+
actionId: {
|
|
53
|
+
control: 'text',
|
|
54
|
+
description: 'DOM id forwarded to the call-to-action button, for analytics hooks',
|
|
55
|
+
table: {
|
|
56
|
+
type: { summary: 'string' },
|
|
57
|
+
},
|
|
58
|
+
},
|
|
59
|
+
className: {
|
|
60
|
+
control: 'text',
|
|
61
|
+
description: 'CSS class name for additional styling',
|
|
62
|
+
table: {
|
|
63
|
+
type: { summary: 'string' },
|
|
64
|
+
},
|
|
65
|
+
},
|
|
66
|
+
},
|
|
67
|
+
};
|
|
68
|
+
export default meta;
|
|
69
|
+
export const Default = {
|
|
70
|
+
args: {
|
|
71
|
+
logoColor: 'var(--color-foreground-fg-brand-logo)',
|
|
72
|
+
actionText: 'Create Your Own Agent',
|
|
73
|
+
showAction: true,
|
|
74
|
+
actionId: 'call-header-create-agent',
|
|
75
|
+
onLogoClick: () => { },
|
|
76
|
+
onActionClick: () => { },
|
|
77
|
+
},
|
|
78
|
+
};
|
|
79
|
+
export const WithoutAction = {
|
|
80
|
+
args: {
|
|
81
|
+
...Default.args,
|
|
82
|
+
showAction: false,
|
|
83
|
+
},
|
|
84
|
+
};
|
|
85
|
+
export const CustomBranding = {
|
|
86
|
+
args: {
|
|
87
|
+
...Default.args,
|
|
88
|
+
logoUrl: 'https://placehold.co/160x28/6301fe/ffffff.png?text=ACME',
|
|
89
|
+
showAction: false,
|
|
90
|
+
},
|
|
91
|
+
};
|
|
@@ -215,3 +215,26 @@ export interface MobileNavBarProps {
|
|
|
215
215
|
/** The class name to apply to the component */
|
|
216
216
|
className?: string;
|
|
217
217
|
}
|
|
218
|
+
/**
|
|
219
|
+
* CallHeader component props
|
|
220
|
+
*/
|
|
221
|
+
export type CallHeaderProps = {
|
|
222
|
+
/** Custom-branding logo URL; the Beyond Presence mark is drawn when omitted */
|
|
223
|
+
logoUrl?: string | null;
|
|
224
|
+
/** Color of the built-in logo mark; ignored once `logoUrl` is set */
|
|
225
|
+
logoColor?: string;
|
|
226
|
+
/** Callback function to handle logo click */
|
|
227
|
+
onLogoClick?: () => void;
|
|
228
|
+
/** Label of the trailing call-to-action button */
|
|
229
|
+
actionText?: string;
|
|
230
|
+
/** Callback function to handle call-to-action button click */
|
|
231
|
+
onActionClick?: () => void;
|
|
232
|
+
/** Whether the trailing call-to-action button is rendered */
|
|
233
|
+
showAction?: boolean;
|
|
234
|
+
/** DOM id forwarded to the call-to-action button, for analytics hooks */
|
|
235
|
+
actionId?: string;
|
|
236
|
+
/** CSS class name for additional styling */
|
|
237
|
+
className?: string;
|
|
238
|
+
/** Style object to apply to the component */
|
|
239
|
+
sx?: SxProps<Theme>;
|
|
240
|
+
};
|