UNPKG

@navinc/base-react-components

Version:
227 lines (218 loc) 8.84 kB
var _a, _b; import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime"; import { useState } from 'react'; import { styled, keyframes, css } from 'styled-components'; import Cookies from 'js-cookie'; import { global } from '@navinc/utils'; import { Button } from './button.js'; import { Copy } from './copy.js'; import { IconButton } from './icon-button.js'; // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- not sure if it is safe to remove the optional chaining const { CLIENT_COOKIE_DOMAIN } = (_b = (_a = global === null || global === void 0 ? void 0 : global.process) === null || _a === void 0 ? void 0 : _a.env) !== null && _b !== void 0 ? _b : ''; const slideInFromSide = keyframes ` 0% { transform: translateX(50%); opacity: 0; } 100% { transform: translateX(0); opacity: 1; } `; const slideInFromBottom = keyframes ` 0% { transform: translateY(50%); opacity: 0; } 100% { transform: translateX(0); opacity: 1; } `; const slideOutAnimation = (theme) => keyframes ` 0% { opacity: 1; transform: translateY(0); } 10% { transform: translateY(calc(100% - 4px)); opacity: 1; border-top: 4px solid ${theme.navNeutral300}; } 50% { opacity: 1; border-top: 4px solid ${theme.navStatusPositive}; } 60% { opacity: 1; border-top: 4px solid ${theme.navStatusPositive}; } 80% { transform: translateY(calc(100% - 4px)) translateX(0); opacity: 1; } 100% { transform: translateY(calc(100% - 4px)) translateX(100%); opacity: 0; } `; const slideOut = css ` opacity: 0; transform: translateY(100%); animation: ${({ theme }) => slideOutAnimation(theme)} 2s ease-in-out; `; const UserFeedbackPrompt = styled.div.withConfig({ displayName: "brc-sc-UserFeedbackPrompt", componentId: "brc-sc-1j3r51s" }) ` display: flex; width: 100%; align-items: center; justify-content: flex-end; margin-top: 16px; opacity: 1; transition: opacity 0.2s linear; `; export const UserFeedbackContainer = styled.div.withConfig({ displayName: "brc-sc-UserFeedbackContainer", componentId: "brc-sc-8mc7xx" }) ` position: relative; display: flex; height: 52px; max-height: 52px; min-width: 240px; margin-left: auto; opacity: 1; overflow: hidden; transition: opacity 0.2s linear 15s, height 0.2s linear 15s, max-height 0.2s linear; ${({ isTouched }) => isTouched && ` height: 0; opacity: 0; & > ${UserFeedbackPrompt} { opacity: 0; } `} ${({ shouldHideImmediately }) => shouldHideImmediately && ` max-height: 0; `} `; export const ThankYouMessage = styled.div.withConfig({ displayName: "brc-sc-ThankYouMessage", componentId: "brc-sc-8lsusu" }) ` position: absolute; top: 16px; right: 0; padding-left: 8px; overflow: hidden; animation: ${slideInFromSide} 0.4s ease-in-out; &::after { position: absolute; content: ''; top: 0; left: 0; width: 2px; height: 100%; border-radius: 2px; background: ${({ theme }) => theme.navPrimary400}; z-index: 5; } `; const StyledIconButton = styled(IconButton).withConfig({ displayName: "brc-sc-StyledIconButton", componentId: "brc-sc-d87met" }) ` height: 16px; color: ${({ theme }) => theme.navNeutral400}; transition: color 0.2s linear; cursor: pointer; &:hover, &:focus, &:active, &:hover:active, &:focus:active, &:hover:not([disabled]) { color: ${({ theme }) => theme.navStatusPositive500}; box-shadow: none; } `; const MoreFeedbackLink = styled(Copy).attrs(() => ({ size: 'xs', as: 'a', })).withConfig({ displayName: "brc-sc-MoreFeedbackLink", componentId: "brc-sc-1ub5gzc" }) ` color: ${({ theme }) => theme.navPrimary}; align-content: center; cursor: pointer; `; export const AdditionalFeedbackContainer = styled.div.withConfig({ displayName: "brc-sc-AdditionalFeedbackContainer", componentId: "brc-sc-1hr53qy" }) ` position: fixed; bottom: 0; left: 0; width: 100%; border-top: 4px solid ${({ theme }) => theme.navNeutral300}; background-color: ${({ theme }) => theme.navNeutralLight}; opacity: 1; transform: translateY(0); z-index: 60; animation: ${slideInFromBottom} 0.4s ease-in-out; ${({ shouldHide }) => shouldHide && slideOut} `; const Form = styled.div.withConfig({ displayName: "brc-sc-Form", componentId: "brc-sc-1sx5p7m" }) ` display: flex; flex-wrap: wrap; justify-content: flex-end; max-width: ${({ theme }) => theme.contentWidth}px; margin: 0 auto; padding: 16px; ${Copy} { width: 100%; max-width: 100%; text-align: center; } ${Button} { margin-left: 16px; } `; const Textarea = styled.textarea.withConfig({ displayName: "brc-sc-Textarea", componentId: "brc-sc-1df98j2" }) ` width: 100%; margin: 8px 0 16px; border: 1px solid ${({ theme }) => theme.navNeutral300}; border-radius: 4px; `; const InternalUserFeedback = ({ trackingLabel = '', className, initialPrompt = 'Was this useful?', thumbsUpThankYouText = `We're glad this helps.`, thumbsDownThankYouText = `We're sorry this isn't helpful.`, thumbsUpAdditionalFeedbackPrompt = 'Tell us more', thumbsDownAdditionalFeedbackPrompt = 'Tell us how we can improve', additionalFeedbackQuestion = 'What can we do to improve your experience?', }) => { const [isTouched, setIsTouched] = useState(false); const [showAdditionalDialogue, setShowAdditionalDialogue] = useState(false); const [userReaction, setUserReaction] = useState(''); const [userFeedback, setUserFeedback] = useState(''); const trackClick = (newUserReaction) => () => { setIsTouched(true); setUserReaction(newUserReaction); Cookies.set(trackingLabel, 'true', { domain: CLIENT_COOKIE_DOMAIN, path: '/', expires: 30, }); }; const handleShowMoreFeedback = () => { setShowAdditionalDialogue(true); }; const handleHideMoreFeedback = () => setShowAdditionalDialogue(false); const handleSubmitMoreFeedback = (event) => { event.preventDefault(); setShowAdditionalDialogue(false); }; const handleTextChange = ({ target }) => setUserFeedback(target.value); if (!isTouched && !showAdditionalDialogue && Cookies.get(trackingLabel)) return null; return (_jsxs(_Fragment, { children: [_jsxs(UserFeedbackContainer, { isTouched: isTouched, shouldHideImmediately: !!userFeedback, className: className, "data-id": `user-feedback-${trackingLabel}`, children: [_jsxs(UserFeedbackPrompt, { children: [_jsx(Copy, { size: "sm", light: true, children: initialPrompt }), _jsx(StyledIconButton, { onClick: trackClick('Thumbs Up'), name: "feedback/thumbs-up", "data-testid": "user-feedback:button-positive", size: "16" }), _jsx(StyledIconButton, { onClick: trackClick('Thumbs Down'), name: "feedback/thumbs-down", "data-testid": "user-feedback:button-negative", size: "16" })] }), isTouched && (_jsxs(ThankYouMessage, { children: [_jsx(Copy, { size: "xs", children: userReaction === 'Thumbs Up' ? thumbsUpThankYouText : thumbsDownThankYouText }), _jsx(MoreFeedbackLink, { onClick: handleShowMoreFeedback, "data-testid": "user-feedback:tell-us-more-link", children: userReaction === 'Thumbs Up' ? thumbsUpAdditionalFeedbackPrompt : thumbsDownAdditionalFeedbackPrompt })] }))] }), (showAdditionalDialogue || userFeedback) && (_jsx(AdditionalFeedbackContainer, { shouldHide: !showAdditionalDialogue, children: _jsxs(Form, { children: [_jsx(Copy, { bold: true, children: additionalFeedbackQuestion }), _jsx(Textarea, { onChange: handleTextChange, "data-testid": "user-feedback:text-area" }), _jsx(Button, { onClick: handleHideMoreFeedback, variation: "outline", "data-testid": "user-feedback:cancel", children: "Cancel" }), _jsx(Button, { onClick: handleSubmitMoreFeedback, disabled: !userFeedback, "data-testid": "user-feedback:submit", children: "Submit" })] }) }))] })); }; /** Include this in a feature to collect user feedback. Once one has been interacted with it will hide for 30 days. There can be as many per page as you would like as long as they all use different `trackingLabel` values. `trackingLabel` should follow the [FE Tracking Standards](https://docs.google.com/document/d/1lo82s9spvkpuQwhT3W30hpIh-QKSnmk9oWuicqCktLE/edit) Props: - trackingLabel (Required) - initialPrompt (Optional) - thumbsUpThankYouText (Optional) - thumbsDownThankYouText (Optional) - thumbsUpAdditionalFeedbackPrompt (Optional) - thumbsDownAdditionalFeedbackPrompt (Optional) - additionalFeedbackQuestion (Optional) Note: If you are not seeing the demo above then clear your cookies. */ export const UserFeedback = styled(InternalUserFeedback).withConfig({ displayName: "brc-sc-UserFeedback", componentId: "brc-sc-1ey2tky" }) ``; //# sourceMappingURL=user-feedback.js.map