diff --git a/web/src/components/CityContentToolbar.tsx b/web/src/components/CityContentToolbar.tsx
index 7c9c4dc59e..1c34472296 100644
--- a/web/src/components/CityContentToolbar.tsx
+++ b/web/src/components/CityContentToolbar.tsx
@@ -73,9 +73,7 @@ const CityContentToolbar = (props: CityContentToolbarProps) => {
id='copy-icon'
/>
- {hasFeedbackOption && (
-
- )}
+ {hasFeedbackOption && }
)
}
diff --git a/web/src/components/Feedback.tsx b/web/src/components/Feedback.tsx
index 201dd5b670..78b1abc9f2 100644
--- a/web/src/components/Feedback.tsx
+++ b/web/src/components/Feedback.tsx
@@ -46,7 +46,7 @@ type FeedbackProps = {
contactMail: string
onCommentChanged: (comment: string) => void
onContactMailChanged: (contactMail: string) => void
- onFeedbackChanged: (isPositiveFeedback: boolean | null) => void
+ onFeedbackChanged?: (isPositiveFeedback: boolean | null) => void
onSubmit: () => void
sendingStatus: SendingStatusType
noResults: boolean | undefined
@@ -94,7 +94,7 @@ const Feedback = ({
>
) : (
-
+ onFeedbackChanged &&
)}
void
+ isPositiveRating: boolean | null
+ setIsPositiveRating?: (isPositiveFeedback: boolean | null) => void
}
export type SendingStatusType = 'idle' | 'sending' | 'failed' | 'successful'
@@ -28,8 +30,9 @@ export const FeedbackContainer = ({
slug,
onClose,
onSubmit,
+ isPositiveRating,
+ setIsPositiveRating,
}: FeedbackContainerProps): ReactElement => {
- const [isPositiveRating, setIsPositiveRating] = useState(null)
const [comment, setComment] = useState('')
const [contactMail, setContactMail] = useState('')
const [sendingStatus, setSendingStatus] = useState('idle')
diff --git a/web/src/components/FeedbackToolbarItem.tsx b/web/src/components/FeedbackToolbarItem.tsx
index 7c962a6372..0bf40d9bf6 100644
--- a/web/src/components/FeedbackToolbarItem.tsx
+++ b/web/src/components/FeedbackToolbarItem.tsx
@@ -3,7 +3,7 @@ import { useTranslation } from 'react-i18next'
import { FeedbackRouteType } from 'shared/api'
-import { FeedbackIcon } from '../assets'
+import { HappySmileyIcon, SadSmileyIcon } from '../assets'
import useCityContentParams from '../hooks/useCityContentParams'
import { RouteType } from '../routes'
import FeedbackContainer from './FeedbackContainer'
@@ -13,20 +13,20 @@ import ToolbarItem from './ToolbarItem'
type FeedbackToolbarItemProps = {
route: RouteType
slug?: string
- isInBottomActionSheet: boolean
}
-const FeedbackToolbarItem = ({ route, slug, isInBottomActionSheet }: FeedbackToolbarItemProps): ReactElement => {
+const FeedbackToolbarItem = ({ route, slug }: FeedbackToolbarItemProps): ReactElement => {
const { cityCode, languageCode } = useCityContentParams()
const [isFeedbackOpen, setIsFeedbackOpen] = useState(false)
const [isSubmitted, setIsSubmitted] = useState(false)
+ const [isPositiveRating, setIsPositiveRating] = useState(null)
const { t } = useTranslation('feedback')
const title = isSubmitted ? t('thanksHeadline') : t('headline')
return (
<>
{isFeedbackOpen && (
- setIsFeedbackOpen(false)} wrapInPortal={isInBottomActionSheet}>
+ setIsFeedbackOpen(false)} wrapInPortal>
setIsFeedbackOpen(false)}
onSubmit={() => setIsSubmitted(true)}
@@ -34,10 +34,27 @@ const FeedbackToolbarItem = ({ route, slug, isInBottomActionSheet }: FeedbackToo
cityCode={cityCode}
language={languageCode}
slug={slug}
+ isPositiveRating={isPositiveRating}
+ setIsPositiveRating={setIsPositiveRating}
/>
)}
- setIsFeedbackOpen(true)} />
+ {
+ setIsFeedbackOpen(true)
+ setIsPositiveRating(true)
+ }}
+ />
+ {
+ setIsFeedbackOpen(true)
+ setIsPositiveRating(false)
+ }}
+ />
>
)
}
diff --git a/web/src/components/Layout.tsx b/web/src/components/Layout.tsx
index 37af04ecff..988a4fe823 100644
--- a/web/src/components/Layout.tsx
+++ b/web/src/components/Layout.tsx
@@ -1,11 +1,11 @@
-import React, { ReactNode, useLayoutEffect, useState } from 'react'
+import React, { ReactNode } from 'react'
import styled, { css } from 'styled-components'
import dimensions from '../constants/dimensions'
import useWindowDimensions from '../hooks/useWindowDimensions'
+import '../styles/Aside.css'
import { MobileBanner } from './MobileBanner'
-
-const additionalToolbarTopSpacing = 32
+import Portal from './Portal'
export const RichLayout = styled.div`
position: relative;
@@ -49,6 +49,7 @@ const Body = styled.div<{ $fullWidth: boolean; $disableScrollingSafari: boolean
background-color: ${props => props.theme.colors.backgroundColor};
word-wrap: break-word;
min-height: 100%;
+ display: flex;
/* Fix jumping iOS Safari Toolbar by prevent scrolling on body */
@@ -93,25 +94,6 @@ const Main = styled.main<{ $fullWidth: boolean }>`
}
`
-const Aside = styled.aside<{ $languageSelectorHeight: number }>`
- top: ${props => props.$languageSelectorHeight + dimensions.headerHeightLarge + additionalToolbarTopSpacing}px;
- margin-top: ${props => props.$languageSelectorHeight - dimensions.navigationMenuHeight}px;
- display: inline-block;
- position: sticky;
- width: ${dimensions.toolbarWidth}px;
- vertical-align: top;
- z-index: 10;
-
- &:empty {
- display: none;
- }
-
- &:empty + * {
- display: block;
- max-width: 100%;
- }
-`
-
export const LAYOUT_ELEMENT_ID = 'layout'
type LayoutProps = {
@@ -133,20 +115,18 @@ const Layout = ({
fullWidth = false,
disableScrollingSafari = false,
}: LayoutProps): JSX.Element => {
- const { width, viewportSmall } = useWindowDimensions()
- const [languageSelectorHeight, setLanguageSelectorHeight] = useState(0)
-
- useLayoutEffect(() => {
- const panelHeight = document.getElementById('languageSelector')?.clientHeight
- setLanguageSelectorHeight(panelHeight ?? 0)
- }, [width])
+ const { viewportSmall } = useWindowDimensions()
return (
{header}
- {!viewportSmall && }
+ {!viewportSmall && (
+
+ {toolbar}
+
+ )}
{children}
{viewportSmall && toolbar}
diff --git a/web/src/components/SearchFeedback.tsx b/web/src/components/SearchFeedback.tsx
index 8ddd9f9651..30cfb58d32 100644
--- a/web/src/components/SearchFeedback.tsx
+++ b/web/src/components/SearchFeedback.tsx
@@ -35,6 +35,7 @@ const SearchFeedback = ({ cityCode, languageCode, query, noResults }: SearchFeed
routeType={SEARCH_ROUTE}
query={query}
noResults={noResults}
+ isPositiveRating={null}
/>
)
diff --git a/web/src/components/__tests__/FeedbackContainer.spec.tsx b/web/src/components/__tests__/FeedbackContainer.spec.tsx
index fa69973f29..c09da48195 100644
--- a/web/src/components/__tests__/FeedbackContainer.spec.tsx
+++ b/web/src/components/__tests__/FeedbackContainer.spec.tsx
@@ -34,14 +34,13 @@ describe('FeedbackContainer', () => {
language,
onClose: closeModal,
query,
+ isPositiveRating: null,
})
it('should display thanks message for modal', async () => {
- const { getByRole, findByText } = renderWithTheme()
- const buttonRating = getByRole('button', {
- name: 'feedback:useful',
- })
- fireEvent.click(buttonRating)
+ const { getByRole, findByText } = renderWithTheme(
+ ,
+ )
const button = getByRole('button', {
name: 'feedback:send',
})
diff --git a/web/src/components/__tests__/FeedbackToolbarItem.spec.tsx b/web/src/components/__tests__/FeedbackToolbarItem.spec.tsx
index 68db4cfee5..7806782a44 100644
--- a/web/src/components/__tests__/FeedbackToolbarItem.spec.tsx
+++ b/web/src/components/__tests__/FeedbackToolbarItem.spec.tsx
@@ -18,18 +18,17 @@ jest.mock('focus-trap-react', () => ({ children }: { children: ReactElement }) =
describe('FeedbackToolbarItem', () => {
it('should open and update title on submit feedback', async () => {
const { queryByText, findByText, getByText } = renderWithRouterAndTheme(
- ,
+ ,
)
expect(queryByText('feedback:headline')).toBeFalsy()
expect(queryByText('feedback:thanksHeadline')).toBeFalsy()
- fireEvent.click(getByText('feedback:feedback'))
+ fireEvent.click(getByText('feedback:useful'))
expect(getByText('feedback:headline')).toBeTruthy()
expect(queryByText('feedback:thanksHeadline')).toBeFalsy()
- fireEvent.click(getByText('feedback:useful'))
fireEvent.click(getByText('feedback:send'))
expect(await findByText('feedback:thanksMessage')).toBeTruthy()
diff --git a/web/src/styles/Aside.css b/web/src/styles/Aside.css
new file mode 100644
index 0000000000..bc083e933b
--- /dev/null
+++ b/web/src/styles/Aside.css
@@ -0,0 +1,14 @@
+.aside {
+ position: fixed;
+ top: 35%;
+ width: 100px;
+ left: 1%;
+
+ @media (min-width: 1100px) {
+ left: 10%;
+ }
+
+ &:empty {
+ display: none;
+ }
+}