💄(frontend) update feedback button to banner with context

Refactored the feedback alert button into a more discreet and polished banner.
The banner provides additional context about Visio being under construction.
Also updated the link to the feedback form.
This commit is contained in:
lebaudantoine
2024-11-17 15:26:19 +01:00
committed by aleb_the_flash
parent 24e819a533
commit 061f12e7e2
6 changed files with 126 additions and 94 deletions

View File

@@ -1,25 +0,0 @@
import { css } from '@/styled-system/css'
import { RiExternalLinkLine } from '@remixicon/react'
import { useTranslation } from 'react-i18next'
import { LinkButton } from '@/primitives'
export const Feedback = () => {
const { t } = useTranslation()
return (
<LinkButton
href="https://grist.incubateur.net/o/docs/forms/1YrfNP1QSSy8p2gCxMFnSf/4"
variant="success"
target="_blank"
>
<span className={css({ marginRight: 0.5 })} aria-hidden="true">
💡
</span>
{t('feedbackAlert')}
<RiExternalLinkLine
size={16}
className={css({ marginLeft: 0.5 })}
aria-hidden="true"
/>
</LinkButton>
)
}

View File

@@ -0,0 +1,46 @@
import { css } from '@/styled-system/css'
import { RiErrorWarningLine, RiExternalLinkLine } from '@remixicon/react'
import { useTranslation } from 'react-i18next'
import { Text, A } from '@/primitives'
const GRIST_FORM =
'https://grist.numerique.gouv.fr/o/docs/forms/1YrfNP1QSSy8p2gCxMFnSf/4'
export const FeedbackBanner = () => {
const { t } = useTranslation()
return (
<div
className={css({
width: '100%',
backgroundColor: '#E8EDFF',
color: '#0063CB',
display: { base: 'none', sm: 'flex' },
justifyContent: 'center',
padding: '0.5rem 0',
})}
>
<div
className={css({
display: 'inline-flex',
gap: '0.5rem',
alignItems: 'center',
})}
>
<RiErrorWarningLine size={20} />
<Text as="p">{t('feedback.context')}</Text>
<div
className={css({
display: 'flex',
alignItems: 'center',
gap: 0.25,
})}
>
<A href={GRIST_FORM} target="_blank">
{t('feedback.cta')}
</A>
<RiExternalLinkLine size={16} aria-hidden="true" />
</div>
</div>
</div>
)
}

View File

@@ -6,7 +6,7 @@ import { Text, Button } from '@/primitives'
import { SettingsButton } from '@/features/settings'
import { logoutUrl, useUser } from '@/features/auth'
import { useMatchesRoute } from '@/navigation/useMatchesRoute'
import { Feedback } from '@/components/Feedback'
import { FeedbackBanner } from '@/components/FeedbackBanner.tsx'
import { Menu } from '@/primitives/Menu'
import { MenuList } from '@/primitives/MenuList'
import { ProConnectButton } from '@/components/ProConnectButton'
@@ -20,77 +20,79 @@ export const Header = () => {
const { user, isLoggedIn } = useUser()
return (
<div
className={css({
paddingY: 1,
paddingX: 1,
flexShrink: 0,
})}
>
<>
<FeedbackBanner />
<div
className={css({
display: 'flex',
flexDirection: 'column',
rowGap: 1,
md: {
rowGap: 0,
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
},
paddingY: 1,
paddingX: 1,
flexShrink: 0,
})}
>
<header>
<Stack gap={2.25} direction="row" align="center">
<Text bold variant="h1" margin={false}>
<Link
onClick={(event) => {
if (
isRoom &&
!window.confirm(t('leaveRoomPrompt', { ns: 'rooms' }))
) {
event.preventDefault()
}
}}
to="/"
>
{t('app')}
</Link>
</Text>
<Feedback />
</Stack>
</header>
<nav>
<Stack gap={1} direction="row" align="center">
{isLoggedIn === false && !isHome && (
<ProConnectButton hint={false} />
)}
{!!user && (
<Menu>
<Button
size="sm"
invisible
tooltip={t('loggedInUserTooltip')}
tooltipType="delayed"
>
{user?.full_name || user?.email}
</Button>
<MenuList
items={[{ value: 'logout', label: t('logout') }]}
onAction={(value) => {
if (value === 'logout') {
terminateAnalyticsSession()
terminateSupportSession()
window.location.href = logoutUrl()
<div
className={css({
display: 'flex',
flexDirection: 'column',
rowGap: 1,
md: {
rowGap: 0,
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
},
})}
>
<header>
<Stack gap={2.25} direction="row" align="center">
<Text bold variant="h1" margin={false}>
<Link
onClick={(event) => {
if (
isRoom &&
!window.confirm(t('leaveRoomPrompt', { ns: 'rooms' }))
) {
event.preventDefault()
}
}}
/>
</Menu>
)}
<SettingsButton />
</Stack>
</nav>
to="/"
>
{t('app')}
</Link>
</Text>
</Stack>
</header>
<nav>
<Stack gap={1} direction="row" align="center">
{isLoggedIn === false && !isHome && (
<ProConnectButton hint={false} />
)}
{!!user && (
<Menu>
<Button
size="sm"
invisible
tooltip={t('loggedInUserTooltip')}
tooltipType="delayed"
>
{user?.full_name || user?.email}
</Button>
<MenuList
items={[{ value: 'logout', label: t('logout') }]}
onAction={(value) => {
if (value === 'logout') {
terminateAnalyticsSession()
terminateSupportSession()
window.location.href = logoutUrl()
}
}}
/>
</Menu>
)}
<SettingsButton />
</Stack>
</nav>
</div>
</div>
</div>
</>
)
}

View File

@@ -6,7 +6,10 @@
"error": {
"heading": ""
},
"feedbackAlert": "",
"feedback": {
"context": "",
"cta": ""
},
"forbidden": {
"heading": ""
},

View File

@@ -6,7 +6,10 @@
"error": {
"heading": "An error occurred while loading the page"
},
"feedbackAlert": "Give us feedback",
"feedback": {
"context": "Visio is still evolving—your input matters!",
"cta": "Share your feedback"
},
"forbidden": {
"heading": "You don't have the permission to view this page"
},

View File

@@ -6,7 +6,10 @@
"error": {
"heading": "Une erreur est survenue lors du chargement de la page"
},
"feedbackAlert": "Donnez-nous votre avis",
"feedback": {
"context": "Visio est en pleine construction — votre avis compte !",
"cta": "Partagez votre avis"
},
"forbidden": {
"heading": "Accès interdit"
},