🚸(frontend) follow antoine's remarks on homepage and header

- show the header on homepage. Not sure we want any header on this app
actually but I guess he's right since we have one it feels more
consistent to have it everywhere
- show logged in email in header. ditched it because i didn't quite get
the value of showing it all the time in this app but i guess it's better
than nothing
- remove user info from settings. Since they are back in the header, no
need
This commit is contained in:
Emmanuel Pelletier
2024-07-25 14:39:34 +02:00
parent d15fb0a19b
commit 668523aa8b
19 changed files with 117 additions and 76 deletions

View File

@@ -181,6 +181,7 @@ const config: Config = {
active: { value: '{colors.gray.300}' },
text: { value: '{colors.default.text}' },
border: { value: '{colors.gray.500}' },
subtle: { value: '{colors.gray.400}' },
},
primary: {
DEFAULT: { value: '{colors.blue.700}' },

View File

@@ -4,7 +4,6 @@ import { Button, Div, Text, VerticallyOffCenter } from '@/primitives'
import { HStack } from '@/styled-system/jsx'
import { authUrl, useUser } from '@/features/auth'
import { navigateToNewRoom } from '@/features/rooms'
import { SettingsButton } from '@/features/settings'
import { Screen } from '@/layout/Screen'
import { JoinMeetingDialog } from '../components/JoinMeetingDialog'
@@ -12,7 +11,7 @@ export const Home = () => {
const { t } = useTranslation('home')
const { isLoggedIn } = useUser()
return (
<Screen type="splash">
<Screen>
<VerticallyOffCenter>
<Div margin="auto" width="fit-content">
<Text as="h1" variant="display">
@@ -41,8 +40,6 @@ export const Home = () => {
</Button>
<JoinMeetingDialog />
</DialogTrigger>
<SettingsButton />
</HStack>
</Div>
</VerticallyOffCenter>

View File

@@ -11,7 +11,14 @@ export const Join = ({
return (
<Box title={t('join.heading')} withBackButton>
<PreJoin persistUserChoices onSubmit={onSubmit} />
<PreJoin
persistUserChoices
onSubmit={onSubmit}
micLabel={t('join.micLabel')}
camLabel={t('join.camlabel')}
joinLabel={t('join.joinLabel')}
userLabel={t('join.userLabel')}
/>
</Box>
)
}

View File

@@ -1,36 +1,12 @@
import { Trans, useTranslation } from 'react-i18next'
import { useTranslation } from 'react-i18next'
import { useLanguageLabels } from '@/i18n/useLanguageLabels'
import { A, Badge, Dialog, Field, H, P } from '@/primitives'
import { authUrl, logoutUrl, useUser } from '@/features/auth'
import { Dialog, Field, H } from '@/primitives'
export const SettingsDialog = () => {
const { t, i18n } = useTranslation('settings')
const { user, isLoggedIn } = useUser()
const { languagesList, currentLanguage } = useLanguageLabels()
return (
<Dialog title={t('dialog.heading')}>
<H lvl={2}>{t('account.heading')}</H>
{isLoggedIn ? (
<>
<P>
<Trans
i18nKey="settings:account.currentlyLoggedAs"
values={{ user: user?.email }}
components={[<Badge />]}
/>
</P>
<P>
<A href={logoutUrl()}>{t('logout', { ns: 'global' })}</A>
</P>
</>
) : (
<>
<P>{t('account.youAreNotLoggedIn')}</P>
<P>
<A href={authUrl()}>{t('login', { ns: 'global' })}</A>
</P>
</>
)}
<H lvl={2}>{t('language.heading')}</H>
<Field
type="select"

View File

@@ -2,20 +2,23 @@ import { Link } from 'wouter'
import { css } from '@/styled-system/css'
import { Stack } from '@/styled-system/jsx'
import { useTranslation } from 'react-i18next'
import { Text } from '@/primitives'
import { A, Button, Popover, PopoverList, Text } from '@/primitives'
import { SettingsButton } from '@/features/settings'
import { authUrl, logoutUrl, useUser } from '@/features/auth'
export const Header = () => {
const { t } = useTranslation()
const isHome = window.location.pathname === '/'
const { user, isLoggedIn } = useUser()
return (
<div
className={css({
backgroundColor: 'primary.text',
color: 'primary',
borderBottomColor: 'box.border',
borderBottomWidth: 1,
borderBottomStyle: 'solid',
padding: 1,
paddingY: 1,
paddingX: 1,
flexShrink: 0,
})}
>
@@ -26,7 +29,32 @@ export const Header = () => {
</Text>
</header>
<nav>
<SettingsButton />
<Stack gap={1} direction="row" align="center">
{isLoggedIn === false && !isHome && (
<A href={authUrl()}>{t('login')}</A>
)}
{!!user && (
<Popover aria-label={t('logout')}>
<Button
size="sm"
invisible
tooltip={t('loggedInUserTooltip')}
tooltipType="delayed"
>
{user.email}
</Button>
<PopoverList
items={[{ value: 'logout', label: t('logout') }]}
onAction={(value) => {
if (value === 'logout') {
window.location.href = logoutUrl()
}
}}
/>
</Popover>
)}
<SettingsButton />
</Stack>
</nav>
</Stack>
</div>

View File

@@ -3,7 +3,7 @@ import { useTranslation } from 'react-i18next'
import { BoxScreen } from './BoxScreen'
import { Screen } from './Screen'
import { VerticallyOffCenter } from '@/primitives'
import { Center, Container } from '@/styled-system/jsx'
import { Center } from '@/styled-system/jsx'
export const LoadingScreen = ({
asBox = false,

View File

@@ -14,6 +14,7 @@
"popoverLabel": ""
},
"loading": "",
"loggedInUserTooltip": "",
"login": "Anmelden",
"logout": "",
"notFound": {

View File

@@ -1,5 +1,9 @@
{
"join": {
"heading": ""
"camlabel": "",
"heading": "",
"joinLabel": "",
"micLabel": "",
"userLabel": ""
}
}

View File

@@ -1,9 +1,4 @@
{
"account": {
"currentlyLoggedAs": "",
"heading": "",
"youAreNotLoggedIn": ""
},
"dialog": {
"heading": ""
},

View File

@@ -14,6 +14,7 @@
"popoverLabel": "Choose language"
},
"loading": "Loading…",
"loggedInUserTooltip": "Logged in as…",
"login": "Login",
"logout": "Logout",
"notFound": {

View File

@@ -1,5 +1,9 @@
{
"join": {
"heading": "Verify your settings before joining"
"camlabel": "Camera",
"heading": "Join the meeting",
"joinLabel": "Join",
"micLabel": "Microphone",
"userLabel": "Your name"
}
}

View File

@@ -1,11 +1,6 @@
{
"account": {
"currentlyLoggedAs": "You are currently logged in as <0>{{user}}</0>",
"heading": "Account",
"youAreNotLoggedIn": "You are not logged in."
},
"dialog": {
"heading": "Account and settings"
"heading": "Settings"
},
"language": {
"heading": "Language",

View File

@@ -14,6 +14,7 @@
"popoverLabel": "Choix de la langue"
},
"loading": "Chargement…",
"loggedInUserTooltip": "Connecté en tant que…",
"login": "Se connecter",
"logout": "Se déconnecter",
"notFound": {

View File

@@ -1,5 +1,9 @@
{
"join": {
"heading": "Vérifiez vos paramètres"
"camlabel": "Webcam",
"heading": "Rejoindre la réunion",
"joinLabel": "Rejoindre",
"micLabel": "Micro",
"userLabel": "Votre nom"
}
}

View File

@@ -1,11 +1,6 @@
{
"account": {
"currentlyLoggedAs": "Vous êtes actuellement connecté en tant que <0>{{user}}</0>",
"heading": "Compte",
"youAreNotLoggedIn": "Vous n'êtes pas connecté."
},
"dialog": {
"heading": "Compte et paramètres"
"heading": "Paramètres"
},
"language": {
"heading": "Langue",

View File

@@ -7,6 +7,7 @@ const link = cva({
textUnderlineOffset: '2',
cursor: 'pointer',
borderRadius: 2,
transition: 'all 0.2s',
'&[data-hovered]': {
textDecoration: 'none',
},

View File

@@ -7,7 +7,7 @@ import {
LinkProps,
} from 'react-aria-components'
import { cva, type RecipeVariantProps } from '@/styled-system/css'
import { Tooltip, TooltipArrow } from './Tooltip'
import { Tooltip } from './Tooltip'
const button = cva({
base: {
@@ -76,7 +76,7 @@ const button = cva({
backgroundColor: 'none!',
'&[data-hovered]': {
backgroundColor: 'none!',
borderColor: 'currentcolor',
borderColor: 'colorPalette.active!',
},
'&[data-pressed]': {
borderColor: 'currentcolor',
@@ -93,6 +93,7 @@ const button = cva({
type Tooltip = {
tooltip?: string
tooltipType?: 'instant' | 'delayed'
}
export type ButtonProps = RecipeVariantProps<typeof button> &
RACButtonsProps &
@@ -102,17 +103,21 @@ type LinkButtonProps = RecipeVariantProps<typeof button> & LinkProps & Tooltip
type ButtonOrLinkProps = ButtonProps | LinkButtonProps
export const Button = ({ tooltip, ...props }: ButtonOrLinkProps) => {
export const Button = ({
tooltip,
tooltipType = 'instant',
...props
}: ButtonOrLinkProps) => {
const [variantProps, componentProps] = button.splitVariantProps(props)
if ((props as LinkButtonProps).href !== undefined) {
return (
<TooltipWrapper tooltip={tooltip}>
<TooltipWrapper tooltip={tooltip} tooltipType={tooltipType}>
<Link className={button(variantProps)} {...componentProps} />
</TooltipWrapper>
)
}
return (
<TooltipWrapper tooltip={tooltip}>
<TooltipWrapper tooltip={tooltip} tooltipType={tooltipType}>
<RACButton
className={button(variantProps)}
{...(componentProps as RACButtonsProps)}
@@ -123,18 +128,15 @@ export const Button = ({ tooltip, ...props }: ButtonOrLinkProps) => {
const TooltipWrapper = ({
tooltip,
tooltipType,
children,
}: {
tooltip?: string
children: ReactNode
}) => {
} & Tooltip) => {
return tooltip ? (
<TooltipTrigger delay={300}>
<TooltipTrigger delay={tooltipType === 'instant' ? 300 : 1000}>
{children}
<Tooltip>
<TooltipArrow />
{tooltip}
</Tooltip>
<Tooltip>{tooltip}</Tooltip>
</TooltipTrigger>
) : (
children

View File

@@ -14,10 +14,20 @@ const ListItem = styled(Button, {
width: 'full',
borderRadius: 4,
cursor: 'pointer',
color: 'primary',
color: 'box.text',
border: '1px solid transparent',
'&[data-selected]': {
fontWeight: 'bold',
},
'&[data-focused]': {
color: 'primary.text',
backgroundColor: 'primary',
outline: 'none!',
},
'&[data-hovered]': {
color: 'primary.subtle-text',
backgroundColor: 'primary.subtle',
color: 'primary.text',
backgroundColor: 'primary',
outline: 'none!',
},
},
})

View File

@@ -1,4 +1,9 @@
import { OverlayArrow, Tooltip as RACTooltip } from 'react-aria-components'
import { type ReactNode } from 'react'
import {
OverlayArrow,
Tooltip as RACTooltip,
TooltipProps,
} from 'react-aria-components'
import { styled } from '@/styled-system/jsx'
/**
@@ -9,7 +14,7 @@ import { styled } from '@/styled-system/jsx'
*
* Style taken from example at https://react-spectrum.adobe.com/react-aria/Tooltip.html
*/
export const Tooltip = styled(RACTooltip, {
const StyledTooltip = styled(RACTooltip, {
base: {
boxShadow: '0 8px 20px rgba(0 0 0 / 0.1)',
borderRadius: '4px',
@@ -18,7 +23,9 @@ export const Tooltip = styled(RACTooltip, {
forcedColorAdjust: 'none',
outline: 'none',
padding: '2px 8px',
maxWidth: '150px',
maxWidth: '200px',
textAlign: 'center',
fontSize: 14,
transform: 'translate3d(0, 0, 0)',
'&[data-placement=top]': {
marginBottom: '8px',
@@ -63,7 +70,7 @@ const StyledOverlayArrow = styled(OverlayArrow, {
},
})
export const TooltipArrow = () => {
const TooltipArrow = () => {
return (
<StyledOverlayArrow>
<svg width={8} height={8} viewBox="0 0 8 8">
@@ -72,3 +79,15 @@ export const TooltipArrow = () => {
</StyledOverlayArrow>
)
}
export const Tooltip = ({
children,
...props
}: Omit<TooltipProps, 'children'> & { children: ReactNode }) => {
return (
<StyledTooltip {...props}>
<TooltipArrow />
{children}
</StyledTooltip>
)
}