Skip to content

Commit

Permalink
[DevOverlay] Add error overlay footer and feedback
Browse files Browse the repository at this point in the history
  • Loading branch information
devjiwonchoi committed Jan 3, 2025
1 parent 1323336 commit b2a9169
Show file tree
Hide file tree
Showing 11 changed files with 268 additions and 1 deletion.
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
export type DialogFooterProps = {
children?: React.ReactNode
className?: string
}

export function DialogFooter({ children, className }: DialogFooterProps) {
return (
<div data-nextjs-dialog-footer className={className}>
{children}
</div>
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@ export { Dialog } from './Dialog'
export { DialogBody } from './DialogBody'
export { DialogContent } from './DialogContent'
export { DialogHeader } from './DialogHeader'
export { DialogFooter } from './dialog-footer'
export { styles } from './styles'
Original file line number Diff line number Diff line change
@@ -1,12 +1,19 @@
import type { ReadyRuntimeError } from '../../../helpers/get-error-by-type'
import type { DebugInfo } from '../../../../../types'
import type { VersionInfo } from '../../../../../../../../server/dev/parse-version-info'
import { Dialog, DialogHeader, DialogBody, DialogContent } from '../../Dialog'
import {
Dialog,
DialogHeader,
DialogBody,
DialogContent,
DialogFooter,
} from '../../Dialog'
import { Overlay } from '../../Overlay'
import { ErrorPagination } from '../ErrorPagination/ErrorPagination'
import { ToolButtonsGroup } from '../../ToolButtonsGroup/ToolButtonsGroup'
import { VersionStalenessInfo } from '../../VersionStalenessInfo'
import { ErrorOverlayBottomStacks } from '../error-overlay-bottom-stacks/error-overlay-bottom-stacks'
import { ErrorOverlayFooter } from '../error-overlay-footer/error-overlay-footer'

type ErrorOverlayLayoutProps = {
errorMessage: string | React.ReactNode
Expand Down Expand Up @@ -88,6 +95,11 @@ export function ErrorOverlayLayout({
<DialogBody className="nextjs-container-errors-body">
{children}
</DialogBody>
<DialogFooter>
{/* TODO: Replace message from BuildError.tsx */}
{/* TODO: errorCode should not be undefined whatsoever */}
<ErrorOverlayFooter message={''} errorCode={errorCode!} />
</DialogFooter>
</DialogContent>
</Dialog>
<ErrorOverlayBottomStacks
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import type { Meta, StoryObj } from '@storybook/react'
import { ErrorFeedbackToast } from './error-feedback-toast'
import { withShadowPortal } from '../../../../storybook/with-shadow-portal'

const meta: Meta<typeof ErrorFeedbackToast> = {
title: 'ErrorFeedbackToast',
component: ErrorFeedbackToast,
parameters: {
layout: 'centered',
},
decorators: [withShadowPortal],
}

export default meta
type Story = StoryObj<typeof ErrorFeedbackToast>

export const Default: Story = {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { Toast } from '../../../Toast'
import { CloseIcon } from '../../../../icons/CloseIcon'

export function ErrorFeedbackToast({
isVisible,
setIsVisible,
}: {
isVisible: boolean
setIsVisible: (isVisible: boolean) => void
}) {
if (!isVisible) {
return null
}

return (
<Toast role="status" className="error-feedback-toast">
<div className="error-feedback-toast-text">
Thanks for your feedback!
<button
onClick={() => setIsVisible(false)}
className="error-feedback-toast-hide-button"
aria-label="Hide error feedback toast"
>
<CloseIcon />
</button>
</div>
</Toast>
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { useState } from 'react'

import { ThumbsUp } from '../../../../icons/thumbs/thumbs-up'
import { ThumbsDown } from '../../../../icons/thumbs/thumbs-down'
import { ErrorFeedbackToast } from './error-feedback-toast'

// eslint-disable-next-line @typescript-eslint/no-unused-vars
export function ErrorFeedback({ errorCode }: { errorCode: string }) {
const [voted, setVoted] = useState<'good' | 'bad' | null>(null)
const [isToastVisible, setIsToastVisible] = useState(false)
const hasVoted = voted !== null

// TODO: make API call to /__nextjs_error_feedback
const handleFeedback = (value: 'good' | 'bad') => {
setVoted(value)
setIsToastVisible(true)
}

return (
<>
<div className="error-feedback">
<p>Was this helpful?</p>
<button
onClick={() => handleFeedback('good')}
disabled={hasVoted}
className={`feedback-button ${voted === 'good' ? 'voted' : ''}`}
>
<ThumbsUp />
</button>
<button
onClick={() => handleFeedback('bad')}
disabled={hasVoted}
className={`feedback-button ${voted === 'bad' ? 'voted' : ''}`}
>
<ThumbsDown />
</button>
</div>
<ErrorFeedbackToast
isVisible={isToastVisible}
setIsVisible={setIsToastVisible}
/>
</>
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { ErrorFeedback } from './error-feedback/error-feedback'

export type ErrorOverlayFooterProps = {
errorCode: string
message: string
}

export function ErrorOverlayFooter({
errorCode,
message,
}: ErrorOverlayFooterProps) {
return (
<footer className="error-overlay-footer">
<p>{message}</p>
<ErrorFeedback errorCode={errorCode} />
</footer>
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
import { noop as css } from '../../../helpers/noop-template'

const styles = css`
.error-overlay-footer {
display: flex;
align-items: center;
justify-content: space-between;
}
.error-overlay-footer p {
color: var(--color-gray-900);
margin: 0;
}
.error-feedback {
display: flex;
align-items: center;
gap: var(--size-gap);
}
.feedback-button {
background: none;
border: none;
border-radius: var(--rounded-md);
padding: var(--size-gap-half);
width: 1.5rem; /* 24px */
height: 1.5rem; /* 24px */
display: flex;
align-items: center;
cursor: pointer;
&:focus {
outline: none;
}
&:hover {
background: var(--color-gray-alpha-100);
}
&:active {
background: var(--color-gray-alpha-200);
}
}
.feedback-button:disabled {
opacity: 0.7;
cursor: not-allowed;
}
.feedback-button.voted {
background: var(--color-gray-alpha-200);
}
.thumbs-up-icon,
.thumbs-down-icon {
color: var(--color-gray-900);
}
.error-feedback-toast {
width: 420px;
height: auto;
overflow: hidden;
border: 0;
padding: var(--size-gap-double);
border-radius: var(--rounded-xl);
background: var(--color-blue-700);
bottom: var(--size-gap);
right: var(--size-gap);
left: auto;
}
.error-feedback-toast-text {
display: flex;
align-items: center;
justify-content: space-between;
color: var(--color-font);
}
.error-feedback-toast-hide-button {
width: var(--size-gap-quad);
height: var(--size-gap-quad);
border: none;
background: none;
&:focus {
outline: none;
}
color: var(--color-font);
}
`

export { styles }
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
export function ThumbsDown() {
return (
<svg
width="16"
height="16"
viewBox="0 0 16 16"
fill="none"
xmlns="http://www.w3.org/2000/svg"
className="thumbs-down-icon"
>
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M5.89531 12.7603C5.72984 12.8785 5.5 12.7602 5.5 12.5569V9.75C5.5 8.7835 4.7165 8 3.75 8H1.5V1.5H11.1884C11.762 1.5 12.262 1.89037 12.4011 2.44683L13.4011 6.44683C13.5984 7.23576 13.0017 8 12.1884 8H8.25H7.5V8.75V11.4854C7.5 11.5662 7.46101 11.6419 7.39531 11.6889L5.89531 12.7603ZM4 12.5569C4 13.9803 5.6089 14.8082 6.76717 13.9809L8.26717 12.9095C8.72706 12.581 9 12.0506 9 11.4854V9.5H12.1884C13.9775 9.5 15.2903 7.81868 14.8563 6.08303L13.8563 2.08303C13.5503 0.858816 12.4503 0 11.1884 0H0.75H0V0.75V8.75V9.5H0.75H3.75C3.88807 9.5 4 9.61193 4 9.75V12.5569Z"
fill="currentColor"
/>
</svg>
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
export function ThumbsUp() {
return (
<svg
width="16"
height="16"
viewBox="0 0 16 16"
fill="none"
xmlns="http://www.w3.org/2000/svg"
className="thumbs-up-icon"
>
<g id="thumb-up-16">
<path
id="Union"
fill-rule="evenodd"
clip-rule="evenodd"
d="M6.89531 2.23959C6.72984 2.1214 6.5 2.23968 6.5 2.44303V5.24989C6.5 6.21639 5.7165 6.99989 4.75 6.99989H2.5V13.4999H12.1884C12.762 13.4999 13.262 13.1095 13.4011 12.5531L14.4011 8.55306C14.5984 7.76412 14.0017 6.99989 13.1884 6.99989H9.25H8.5V6.24989V3.51446C8.5 3.43372 8.46101 3.35795 8.39531 3.31102L6.89531 2.23959ZM5 2.44303C5 1.01963 6.6089 0.191656 7.76717 1.01899L9.26717 2.09042C9.72706 2.41892 10 2.94929 10 3.51446V5.49989H13.1884C14.9775 5.49989 16.2903 7.18121 15.8563 8.91686L14.8563 12.9169C14.5503 14.1411 13.4503 14.9999 12.1884 14.9999H1.75H1V14.2499V6.24989V5.49989H1.75H4.75C4.88807 5.49989 5 5.38796 5 5.24989V2.44303Z"
fill="currentColor"
/>
</g>
</svg>
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { styles as dialog } from '../components/Dialog'
import { styles as bottomStacks } from '../components/Errors/error-overlay-bottom-stacks/error-overlay-bottom-stacks'
import { styles as pagination } from '../components/Errors/ErrorPagination/styles'
import { styles as overlay } from '../components/Overlay/styles'
import { styles as footer } from '../components/Errors/error-overlay-footer/styles'
import { styles as terminal } from '../components/Terminal/styles'
import { styles as toast } from '../components/Toast'
import { styles as versionStaleness } from '../components/VersionStalenessInfo'
Expand All @@ -18,6 +19,7 @@ export function ComponentStyles() {
${overlay}
${toast}
${dialog}
${footer}
${bottomStacks}
${pagination}
${codeFrame}
Expand Down

0 comments on commit b2a9169

Please sign in to comment.