✨(frontend) add slide feature in the IntroSlider
Avoided installing a dependency for such small piece of code. I've implemented a naive component, which allow users explore the slide presenting key feature of our app. User experience should be ok. However, I might need to optimize image format and loading strategy. First 'raw' iteration, gonna optimize it in the future.
This commit is contained in:
committed by
aleb_the_flash
parent
b06880be15
commit
8516782d79
Binary file not shown.
|
Before Width: | Height: | Size: 177 KiB |
BIN
src/frontend/src/assets/intro-slider/1_solo.png
Normal file
BIN
src/frontend/src/assets/intro-slider/1_solo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 635 KiB |
BIN
src/frontend/src/assets/intro-slider/2_multiple.png
Normal file
BIN
src/frontend/src/assets/intro-slider/2_multiple.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 702 KiB |
BIN
src/frontend/src/assets/intro-slider/3_resume.png
Normal file
BIN
src/frontend/src/assets/intro-slider/3_resume.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 599 KiB |
@@ -1,5 +1,13 @@
|
||||
import firstSlide from '@/assets/intro-slider/1.png'
|
||||
import { styled, VStack } from '@/styled-system/jsx'
|
||||
import firstSlide from '@/assets/intro-slider/1_solo.png'
|
||||
import secondSlide from '@/assets/intro-slider/2_multiple.png'
|
||||
import thirdSlide from '@/assets/intro-slider/3_resume.png'
|
||||
|
||||
import { styled } from '@/styled-system/jsx'
|
||||
import { css } from '@/styled-system/css'
|
||||
import { Button } from '@/primitives'
|
||||
import { RiArrowLeftSLine, RiArrowRightSLine } from '@remixicon/react'
|
||||
import { useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
|
||||
const Heading = styled('h2', {
|
||||
base: {
|
||||
@@ -32,18 +40,161 @@ const Image = styled('img', {
|
||||
},
|
||||
})
|
||||
|
||||
// todo - refactor it in a proper slider, only displaying a single slide yet
|
||||
const Dot = styled('div', {
|
||||
base: {
|
||||
borderRadius: '50%',
|
||||
display: 'inline-block',
|
||||
height: '.375rem',
|
||||
margin: '0 .25rem',
|
||||
width: '.375rem',
|
||||
},
|
||||
variants: {
|
||||
selected: {
|
||||
true: {
|
||||
backgroundColor: '#000091',
|
||||
},
|
||||
false: {
|
||||
backgroundColor: '#CACAFB',
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
const Container = styled('div', {
|
||||
base: {
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
width: '100%',
|
||||
justifyContent: 'space-between',
|
||||
textAlign: 'center',
|
||||
},
|
||||
})
|
||||
|
||||
const ButtonVerticalCenter = styled('div', {
|
||||
base: {
|
||||
marginTop: '10.3125rem',
|
||||
transform: 'translateY(-50%)',
|
||||
},
|
||||
})
|
||||
|
||||
const SlideContainer = styled('div', {
|
||||
base: {
|
||||
alignItems: 'stretch',
|
||||
display: 'flex',
|
||||
position: 'relative',
|
||||
},
|
||||
})
|
||||
|
||||
const Slide = styled('div', {
|
||||
base: {
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
alignItems: 'center',
|
||||
gap: '0.5rem',
|
||||
justifyContent: 'start',
|
||||
minHeight: '550px',
|
||||
minWidth: '200px',
|
||||
width: '22.625rem',
|
||||
},
|
||||
variants: {
|
||||
visible: {
|
||||
true: {
|
||||
visibility: 'visible',
|
||||
position: 'static',
|
||||
},
|
||||
false: {
|
||||
visibility: 'hidden',
|
||||
position: 'absolute',
|
||||
},
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
visible: false,
|
||||
},
|
||||
})
|
||||
|
||||
type Slide = {
|
||||
key: string
|
||||
img: string
|
||||
}
|
||||
|
||||
// todo - optimize how images are imported
|
||||
const SLIDES: Slide[] = [
|
||||
{
|
||||
key: 'slide1',
|
||||
img: firstSlide,
|
||||
},
|
||||
{
|
||||
key: 'slide2',
|
||||
img: secondSlide,
|
||||
},
|
||||
{
|
||||
key: 'slide3',
|
||||
img: thirdSlide,
|
||||
},
|
||||
]
|
||||
|
||||
export const IntroSlider = () => {
|
||||
const [slideIndex, setSlideIndex] = useState(0)
|
||||
const { t } = useTranslation('home', { keyPrefix: 'introSlider' })
|
||||
const NUMBER_SLIDES = SLIDES.length
|
||||
|
||||
return (
|
||||
<>
|
||||
<Image src={firstSlide} alt="" />
|
||||
<VStack justify={'center'} gap={0.5}>
|
||||
<Heading>Essayez Visio pour simplifier votre quotidien</Heading>
|
||||
<Body>
|
||||
Découvrez une solution intuitive et accessible, conçue pour tous les
|
||||
agents publics et leurs partenaires, et bien plus encore.
|
||||
</Body>
|
||||
</VStack>
|
||||
</>
|
||||
<Container>
|
||||
<div
|
||||
className={css({
|
||||
display: 'flex',
|
||||
flexGrow: 1,
|
||||
justifyContent: 'center',
|
||||
})}
|
||||
>
|
||||
<div>
|
||||
<ButtonVerticalCenter>
|
||||
<Button
|
||||
square
|
||||
invisible
|
||||
aria-label={t('previous.label')}
|
||||
tooltip={t('previous.tooltip')}
|
||||
onPress={() => setSlideIndex(slideIndex - 1)}
|
||||
isDisabled={slideIndex == 0}
|
||||
>
|
||||
<RiArrowLeftSLine />
|
||||
</Button>
|
||||
</ButtonVerticalCenter>
|
||||
</div>
|
||||
<SlideContainer>
|
||||
{SLIDES.map((slide, index) => (
|
||||
<Slide visible={index == slideIndex}>
|
||||
<Image src={slide.img} alt={t(`${slide.key}.imgAlt`)} />
|
||||
<Heading>{t(`${slide.key}.title`)}</Heading>
|
||||
<Body>{t(`${slide.key}.body`)}</Body>
|
||||
</Slide>
|
||||
))}
|
||||
</SlideContainer>
|
||||
<div>
|
||||
<ButtonVerticalCenter>
|
||||
<Button
|
||||
square
|
||||
invisible
|
||||
aria-label={t('next.label')}
|
||||
tooltip={t('next.tooltip')}
|
||||
onPress={() => setSlideIndex(slideIndex + 1)}
|
||||
isDisabled={slideIndex == NUMBER_SLIDES - 1}
|
||||
>
|
||||
<RiArrowRightSLine />
|
||||
</Button>
|
||||
</ButtonVerticalCenter>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className={css({
|
||||
marginTop: '0.5rem',
|
||||
})}
|
||||
>
|
||||
{SLIDES.map((_, index) => (
|
||||
<Dot key={index} selected={index == slideIndex} />
|
||||
))}
|
||||
</div>
|
||||
</Container>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -23,5 +23,30 @@
|
||||
"copy": "",
|
||||
"copied": "",
|
||||
"permissions": ""
|
||||
},
|
||||
"introSlider": {
|
||||
"previous": {
|
||||
"label": "",
|
||||
"tooltip": ""
|
||||
},
|
||||
"next": {
|
||||
"label": "",
|
||||
"tooltip": ""
|
||||
},
|
||||
"slide1": {
|
||||
"title": "",
|
||||
"body": "",
|
||||
"imgAlt": ""
|
||||
},
|
||||
"slide2": {
|
||||
"title": "",
|
||||
"body": "",
|
||||
"imgAlt": ""
|
||||
},
|
||||
"slide3": {
|
||||
"title": "",
|
||||
"body": "",
|
||||
"imgAlt": ""
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,5 +23,30 @@
|
||||
"copy": "Copy the meeting link",
|
||||
"copied": "Link copied to clipboard",
|
||||
"permissions": "People with this link do not need your permission to join this meeting."
|
||||
},
|
||||
"introSlider": {
|
||||
"previous": {
|
||||
"label": "previous",
|
||||
"tooltip": "previous"
|
||||
},
|
||||
"next": {
|
||||
"label": "next",
|
||||
"tooltip": "next"
|
||||
},
|
||||
"slide1": {
|
||||
"title": "Try Visio to simplify your daily tasks",
|
||||
"body": "Discover an intuitive and accessible solution, designed for all public agents, their partners, and much more.",
|
||||
"imgAlt": "Illustration of a user-friendly and accessible collaboration platform"
|
||||
},
|
||||
"slide2": {
|
||||
"title": "Host group calls without limits",
|
||||
"body": "Unlimited time meetings, up to 15 participants, with smooth and high-quality communication, no matter the group size.",
|
||||
"imgAlt": "Image of a virtual meeting with multiple participants collaborating seamlessly"
|
||||
},
|
||||
"slide3": {
|
||||
"title": "Transform your meetings with AI",
|
||||
"body": "Get accurate and actionable transcripts to boost your productivity. Feature in beta—try it now!",
|
||||
"imgAlt": "Illustration of AI-powered note-taking in a virtual meeting"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,5 +23,30 @@
|
||||
"copy": "Copier le lien de la réunion",
|
||||
"copied": "Lien copié dans le presse-papiers",
|
||||
"permissions": "Les personnes disposant de ce lien n'ont pas besoin de votre autorisation pour rejoindre cette réunion."
|
||||
},
|
||||
"introSlider": {
|
||||
"previous": {
|
||||
"label": "précédent",
|
||||
"tooltip": "précédent"
|
||||
},
|
||||
"next": {
|
||||
"label": "suivant",
|
||||
"tooltip": "suivant"
|
||||
},
|
||||
"slide1": {
|
||||
"title": "Essayez Visio pour simplifier votre quotidien",
|
||||
"body": "Découvrez une solution intuitive et accessible, conçue pour tous les agents publics et leurs partenaires, et bien plus encore.",
|
||||
"imgAlt": "Illustration d'une plateforme de collaboration simple et accessible"
|
||||
},
|
||||
"slide2": {
|
||||
"title": "Organisez des appels de groupe sans limite",
|
||||
"body": "Réunions sans limite de temps, jusqu'à 15 participants, avec une communication fluide et de haute qualité, quel que soit le nombre.",
|
||||
"imgAlt": "Image d'une réunion virtuelle avec plusieurs participants collaborant efficacement"
|
||||
},
|
||||
"slide3": {
|
||||
"title": "Transformez vos réunions avec l'IA",
|
||||
"body": "Obtenez des transcriptions précises et actionnables, pour booster votre productivité. Fonctionnalité en beta, essayez-la maintenant !",
|
||||
"imgAlt": "Illustration de prise de notes assistée par l'IA dans une réunion virtuelle"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user