Skip to content
This repository has been archived by the owner on Aug 21, 2023. It is now read-only.

Commit

Permalink
Add MessageCard Emoji Survey variant (#1077)
Browse files Browse the repository at this point in the history
  • Loading branch information
Charca committed Aug 9, 2022
1 parent 358c8e8 commit 3c9df31
Show file tree
Hide file tree
Showing 5 changed files with 217 additions and 10 deletions.
3 changes: 2 additions & 1 deletion src/components/MessageCard/MessageCard.Survey.variants.js
@@ -1,5 +1,6 @@
import { MessageCardSurveyEmoji as EmojiSurvey } from './components/survey/MessageCard.Survey.Emoji'
import { MessageCardSurveyFaces as FacesSurvey } from './components/survey/MessageCard.Survey.Faces'
import { MessageCardSurveyThumbs as ThumbsSurvey } from './components/survey/MessageCard.Survey.Thumbs'
import { MessageCardSurveyMultipleChoice as MultipleChoiceSurvey } from './components/survey/MessageCard.Survey.MultipleChoice'

export { FacesSurvey, ThumbsSurvey, MultipleChoiceSurvey }
export { EmojiSurvey, FacesSurvey, ThumbsSurvey, MultipleChoiceSurvey }
46 changes: 46 additions & 0 deletions src/components/MessageCard/MessageCard.stories.mdx
Expand Up @@ -3,6 +3,7 @@ import { boolean, select, text } from '@storybook/addon-knobs'
import MessageCard from './'
import { MessageCardStoryWrapperUI } from './MessageCard.storiesHelper'
import {
EmojiSurvey,
FacesSurvey,
MultipleChoiceSurvey,
ThumbsSurvey,
Expand Down Expand Up @@ -239,6 +240,51 @@ This component renders a Message Card Notification with (optional) Title, Subtit
</Story>
</Canvas>

# With Emoji survey

<Canvas>
<Story name="With Emoji survey">
<MessageCardStoryWrapperUI>
<MessageCard
title="How did you feel about your checkout experience?"
body="Your feedback is valuable to us. Let us know how we did so we can continue to improve our services."
action={() => (
<ThemeProvider theme={{ brandColor: makeBrandColors('#5c8c3c') }}>
<MessageCard.Survey
withFeedbackForm
feedbackFormText="Tell us more..."
submitButtonText="Send with some long button text"
onSubmit={data => console.log(data)}
withShowFeedbackFormDelay
>
<EmojiSurvey
emojis={[
{
id: '+1',
name: 'Thumbs Up',
unicode: '1f44d',
},
{
id: '100',
name: 'Hundred Points',
unicode: '1f4af',
},
{
id: 'sunglasses',
name: 'Sunglasses',
unicode: '1f60e',
native: '😎',
},
]}
/>
</MessageCard.Survey>
</ThemeProvider>
)}
/>
</MessageCardStoryWrapperUI>
</Story>
</Canvas>

# With Multiple Choice survey

<Canvas>
Expand Down
@@ -0,0 +1,58 @@
import PropTypes from 'prop-types'

import {
EmojiButtonUI,
ImageEmojiUI,
SurveyOptionsUI,
} from './MessageCard.Survey.css'

import { useButtonResizeOnSelection } from '../../utils/MessageCard.hooks'
import { useSurveyContext } from '../../utils/MessageCard.Survey.context'

const EMOJI_CDN_BASE_PATH =
'https://beacon-v2.helpscout.net/static/img-apple-64'

export const MessageCardSurveyEmoji = ({ emojis = [] }) => {
const { onSelection, selected, withFeedbackForm } = useSurveyContext()
const { buttonSize, handleOnClick } = useButtonResizeOnSelection({
disableTransition: !withFeedbackForm,
onSelection,
})

const className = `is-${buttonSize}`

return (
<SurveyOptionsUI>
{emojis.map(({ id, name, unicode, native }) => (
<EmojiButtonUI
key={id}
onClick={() => handleOnClick(id)}
className={`${className} ${selected === id ? 'is-selected' : ''}`}
>
{native ? (
<span aria-label={name} role="img">
{native}
</span>
) : (
<ImageEmojiUI
alt={name}
src={`${EMOJI_CDN_BASE_PATH}/${unicode}.png`}
className={className}
/>
)}
</EmojiButtonUI>
))}
</SurveyOptionsUI>
)
}

MessageCardSurveyEmoji.propTypes = {
emojis: PropTypes.arrayOf(
PropTypes.shape({
id: PropTypes.string.isRequired,
name: PropTypes.string.isRequired,
unicode: PropTypes.string.isRequired,
native: PropTypes.string,
})
).isRequired,
}
@@ -0,0 +1,76 @@
import { render, screen } from '@testing-library/react'
import userEvent from '@testing-library/user-event'

import { SurveyContext } from '../../utils/MessageCard.Survey.context'
import { MessageCardSurveyEmoji } from './MessageCard.Survey.Emoji'

describe('MessageCard.Survey.Emoji', () => {
test('should only render the emojis passed in the emojis prop', () => {
render(
<MessageCardSurveyEmoji
emojis={[
{ id: 'happy', name: 'Happy', unicode: '1f600' },
{ id: 'sad', name: 'Sad', unicode: '1f622' },
]}
/>
)

expect(screen.getAllByRole('button')).toHaveLength(2)

expect(queryButtonByName('Happy')).toBeInTheDocument()
expect(queryButtonByName('Sad')).toBeInTheDocument()
})

test('should render a native emoji instead of an image if the native prop is provided', () => {
render(
<MessageCardSurveyEmoji
emojis={[
{ id: 'happy', name: 'Happy', unicode: '1f600' },
{ id: 'sad', name: 'Sad', unicode: '1f622' },
{
id: 'grimacing',
name: 'Grimacing',
unicode: '1f62c',
native: '😬',
},
]}
/>
)

expect(screen.getAllByRole('button')).toHaveLength(3)

expect(queryButtonByName('Happy')).toBeInTheDocument()
expect(queryButtonByName('Sad')).toBeInTheDocument()
expect(queryButtonByName('Grimacing')).toBeInTheDocument()
expect(queryButtonByName('Grimacing')).toHaveTextContent('😬')
})

test('should call the onSelection callback from the SurveyContext when an emoji is selected', () => {
const onSelection = jest.fn()
const contextValue = {
onSelection,
selected: null,
}

render(
<SurveyContext.Provider value={contextValue}>
<MessageCardSurveyEmoji
emojis={[
{ id: '+1::skin-tone-3', name: 'Thumbs Up', unicode: '1f602' },
{ id: 'sad', name: 'Sad', unicode: '1f622' },
]}
/>
</SurveyContext.Provider>
)

expect(onSelection).not.toHaveBeenCalled()

userEvent.click(queryButtonByName('Thumbs Up'))

expect(onSelection).toHaveBeenCalledWith('+1::skin-tone-3')
})

function queryButtonByName(name) {
return screen.queryByRole('button', { name })
}
})
Expand Up @@ -27,6 +27,9 @@ export const SurveyOptionsUI = styled('div')`
`

export const EmojiButtonUI = styled('button')`
display: flex;
align-items: center;
justify-content: center;
position: relative;
background: white;
border: none;
Expand Down Expand Up @@ -90,24 +93,47 @@ export const EmojiButtonUI = styled('button')`
height: 28px;
width: 28px;
}
& > span {
height: auto;
top: 1px;
}
}
& > span {
display: flex;
justify-content: center;
align-items: center;
display: block;
height: 26px;
position: relative;
}
// Native emojis show up off-centered on non-retina screens...
// Which is why we need to adjust the margin a little bit here.
@media not screen and (min-device-pixel-ratio: 2),
not screen and (min-resolution: 192dpi) {
& {
margin-right: 2px;
// Native emojis show up off-centered on non-retina screens...
// Which is why we need to adjust the margin a little bit here.
@media not screen and (min-device-pixel-ratio: 2),
not screen and (min-resolution: 192dpi) {
& > span {
top: -1px;
}
&.is-md {
font-size: 11px;
& > span {
top: 0;
}
}
}
`

export const ImageEmojiUI = styled('img')`
display: inline-block;
height: 22px;
position: relative;
width: auto;
${defaultTransition};
&.is-md {
height: 12px;
}
`

export const RateActionUI = styled(RateAction)`
margin-left: 5px !important;
margin-right: 5px !important;
Expand Down

0 comments on commit 3c9df31

Please sign in to comment.