Create a French Flashcard Carousel in an evening
Tags: vue, vite, vercel, tutorial
Published: 2023-10-22 22:01:05

---
title: Create a French Flashcard Carousel in an evening
published: true
tags: Vue,Vite,Vercel,Tutorial
cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/b90igvpzvdxsr8nzikwj.gif
series: Create a Flashcard Carousel using Vue.js
---
Hello internet! This is my first blog post and we will be building a mobile friendly French Flashcard application [(try it here)](https://flashcard-tutorial.vercel.app/). If you are learning a language or gearing up for travel this simple tool is for you.

### Introduction to Vue, Vite & Vercel

[Vue 3](https://v3.vuejs.org/), in it's own words: _is a progressive framework for building user interfaces_. Vue enables developers to create dynamic Single-page Applications (SPA) that rewrite the current web page with new data from the application's web server. This approach to web development sees us advance from creating many HTML pages and loading them with our web server ultimately producing an increasingly seamless process more akin to a native app.

What is [Vite](https://vitejs.dev/) I hear you ask, Vite is french for 'quick' and is a build tool we will use to bundle and serve our application. If you are familiar with Webpack, the Vue-CLI or even Create-React-App this will feel like a Concorde amongst Pigeons!

Last but not least, [Vercel](https://vercel.com/) is a platform that boasts the ability to provide a frictionless developer experience when deploying and serving our application's content. This is what we will use to host our application.

### Prerequesites
Before we get started it is important to note that this article assumes a good grasp of JavaScript. You will need both [Node version >=12.0.0.](https://nodejs.org/en/) and [NPM](https://www.npmjs.com/) installed. A familiarity with Vue is helpful but not essential though worry not, we'll have code samples galore and an accompanying repo available [here](https://github.com/Menilek/flashcard-tutorial). Now let's get started!

### Scaffolding our App
First we need to scaffold our Vue app with Vite. Use the following command and select Vue.
```
npm init vite@latest
```
We will go ahead and use Vue without TypeScript for now.
![Vite CLI steps to create a Vue application](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ai961v84phcv0c73avos.png)

Once we've completed the above we can navigate into our application's directory, run `npm install` and top it off with `npm run dev`. Your browser should popup displaying boilerplate output like so:
![Boilerplate Vue 3 application generated using Vite](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/h8bgq0twk44vrb3ko257.png)

### Installing Vue3-Carousel
We will use the awesome [Vue3-Carousel](https://ismail9k.github.io/vue3-carousel/) to create our flashcard Carousel. First, we need to install it using:
```
npm install vue3-carousel
```
Next up we want to create a `carousel.css` file in the assets folder within the src directory. This will style all of our carousels, go ahead and paste the following inside it:
```
.carousel__slide>.carousel__item {
  transform: scale(1);
  opacity: 0.5;
  transition: 0.5s;
}
.carousel__slide--visible>.carousel__item {
  opacity: 1;
  transform: rotateY(0);
}
.carousel__slide--next>.carousel__item {
  transform: scale(0.9) translate(-10px);
}
.carousel__slide--prev>.carousel__item {
  transform: scale(0.9) translate(10px);
}
.carousel__slide--active>.carousel__item {
  transform: scale(1.1);
}
.carousel__item {
  min-height: 200px;
  width: 100%;
  background-color: var(--vc-clr-primary);
  color: var(--vc-clr-white);
  font-size: 20px;
  border-radius: 8px;
  display: flex;
  justify-content: center;
  align-items: center;
}
```

### Creating our Carousel
Vue 3 components allow us to define JavaScript functions, templates for rendering our page and styles all in one place! Go ahead and create a `Days.vue` component within the components directory like so:
![Days Vue component](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lsas7ay9nn6tap5m5yup.png)

This component will be responsible for rendering the French words for Monday through to Sunday. We need to import the newly created `carousel.css` file as well as some Components from Vue3-carousel using the below snippets then we can begin defining our functions and rendering the Carousel. We will need to add the following to our `Days.vue` component within the script tags:
```
import { Carousel, Slide, Pagination, Navigation } from 'vue3-carousel';
import 'vue3-carousel/dist/carousel.css';
import '../assets/carousel.css';
```

Within Vue components we can use the content defined within the Script tags to help us render output within our Template tags.

Now, our application requires some French content (feel free to deviate and put a Spanish/Mandarin/Amharic spin on this)! We shall begin by creating an object that will hold the day in English as a key and the day in French as the corresponding value. Let's call it FrenchDays and define it using the sample below:
```
const FrenchDays = {
    Monday: "Lundi",
    Tuesday: "Mardi",
    Wednesday: "Mercredi",
    Thursday: "Jeudi",
    Friday: "Vendredi",
    Saturday: "Samedi",
    Sunday: "Dimanche"
}
```
Congrats! You've made it to the fun part where we get into the cool parts of Vue.js and render our Carousel. We've got our FrenchDays object (or whichever language you've chosen you cheeky polyglot!) and we want to loop through these and create a _slide_ for each word aka value in our object.

Vue has a special _directive_ just for this called `v-for`, see more [here](https://v3.vuejs.org/guide/list.html#v-for-with-an-object). This directive allows us to iterate through the properties of an object. There is a lot going on in the code below so we shall dissect it step by step:
```
    <h2>Days</h2>
    <Carousel :itemsToShow="2" :wrapAround="true">
        <Slide v-for="day in FrenchDays" :key="day">
            <div class="carousel__item">{{ day }}</div>
        </Slide>
        <template #addons>
            <Navigation />
            <Pagination />
        </template>
    </Carousel>
```
Let's examine the Slide component. This is using the `v-for` directive to iteratively create Slides for each property in our `FrenchDays` object. You might also notice this: `:key="day"` what this does is give each Slide a unique key. This key helps Vue determine what has changed within the virtual Document Object Model (DOM) and what hasn't.

If you are interested in learning what the Navigation and Pagination components are or what the itemsToShow and wrapAround props are feel free to play with their values or refer to the Vue3-Carousel docs [here](https://ismail9k.github.io/vue3-carousel/getting-started.html).

Ok, we've done a lot of work, what do we have to show for it so far? We'll need to render our Days component to see what all the fuss is about first! In the `App.vue` file within the root of our /src directory we want to make some changes as this currently renders the boilerplate HelloWorld.vue component generated by Vite. Instead we want to import and render the Days component and we will do this with the following:
```
<script setup>
  import Days from './components/Days.vue'
</script>

<template>
  <Days />
</template>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>
```
After we save, Vite will quickly pull in our changes and our browser should show us:
![Carousel showing Days of the week in French](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/60yazl1n46ncctm1tn0f.png)

### Toggling the Language
We are nearing the final hurdle. How do we toggle between French and English? There are many ways in which this can be implemented (and I am curious how you might have done it; please do share in the comments 🤓) but we will always require a user clicking/tapping on a Slide within our Carousel to kick off the change. As always, Vue has a [directive for that](https://v3.vuejs.org/guide/events.html) named `v-on:click` or better yet `@click`.

Essentially, we require a _click_ event that will trigger a function that toggles our French word into English and vice-versa. We also need a way of knowing which word is being shown so that we know which word to show when clicked. Let's update our Slide component within `Days.vue` by adding the click directive and a function we want to trigger.
```
<Slide v-for="day in FrenchDays" :key="day">
    <div class="carousel__item" @click="toggle(day)">{{ day }}</div>
</Slide>
```
We also need a way to determine whether a flash card shows English or French. This will allow a single flashcard to toggle without toggling all of the flashcards - this will ensure we don't spoil our language learning fun!

We will track the _state_ of a flashcard using a Ref. Refs let us create variables enriched with the power of _reactive and mutable reference objects_, what that means is that if there is a change to the value of such a variable it will be detected and trickle down to anywhere else that uses that variable, notifying it of the new value. One thing we need to note is that with the introduction of reactive variables in Vue3 using ref, we must use `.value` to access their values inside our script block, though this is not the case inside our template (we'll see this in action later).

First we need to import `ref` from Vue like so: `import { ref } from 'vue';` within the script tags in our `Days.vue` file. 

To make use of `ref` we can define the following:
```
const MondayRevealed = ref(false);
const TuesdayRevealed = ref(false);
const WednesdayRevealed = ref(false);
const ThursdayRevealed = ref(false);
const FridayRevealed = ref(false);
const SaturdayRevealed = ref(false);
const SundayRevealed = ref(false);
```
So far so good, time to begin defining the toggle function. The purpose of the toggle function is to invert or toggle the boolean value of a flashcard. Currently, these have all been set to false by default.

This could be implemented in a number of ways. Using if/else statements or a switch statement are viable options but I recently stumbled upon a way to achieve this succinctly using object literals! I will link to a very handy article [here](https://dev.to/lukyhenson/replace-your-switch-statement-and-multiple-if-and-else-using-object-literals-en-us-1dec).

Depending on which day/card a user clicks determines which day/card we want to toggle; thereby toggling the boolean value for that day e.g MondayRevealed now equals true.
```
const toggle = (day) => {
    const dayMap = {
        Lundi: () => MondayRevealed.value = MondayRevealed.value ? false : true,
        Mardi: () => TuesdayRevealed.value = TuesdayRevealed.value ? false : true,
        Mercredi: () => WednesdayRevealed.value = WednesdayRevealed.value ? false : true,
        Jeudi: () => ThursdayRevealed.value = ThursdayRevealed.value ? false : true,
        Vendredi: () => FridayRevealed.value = FridayRevealed.value ? false : true,
        Samedi: () => SaturdayRevealed.value = SaturdayRevealed.value ? false : true,
        Dimanche: () => SundayRevealed.value = SundayRevealed.value ? false : true
    }
    dayMap[day]()
}
```
Let's break down some of these lines:
> `Lundi: () => MondayRevealed.value = MondayRevealed.value ? false : true`

This lines run if the day clicked on is Lundi (French for Monday) then the value for MondayRevealed is updated with the use of a [ternary operator](https://www.freecodecamp.org/news/how-the-question-mark-works-in-javascript/).
> `dayMap[day]()`

On the line above we are invoking the function that corresponds to the value of the key equal to the day passed as an argument. E.g if we were to pass in Jeudi this would match the following
`() => ThursdayRevealed.value = ThursdayRevealed.value ? false : true`

We now have our Carousel and a toggle function; the only thing that remains is a way to show the translated word. This will involve retrieving the English day for a given French day and rendering this within our template.
Luckily enough we have an object named FrenchDays consisting of the days in French and English and must now create a function that will return the English word for a given French day.

To retrieve the corresponding English key for a French value within the FrenchDays object we have to...
```
const findKey = (obj, value) => {
    return Object.keys(obj).find(key => obj[key] === value);
}
```
Now that we can find the English word for a French word in our FrenchDays object we can move onto figuring out how we can render this in our template. This is where the use of our boolean variables comes in handy. To illustrate, imagine we click on Mardi (Tuesday in French), this will toggle the value of TuesdayRevealed to true and if this value is true we want to show the English for that word.
To implement this we can use an object literal again. This time we can accept the day value and map it to the corresponding boolean value.
```
const isWordRevealed = (day) => {
    const revealMap = {
        Lundi: MondayRevealed.value,
        Mardi: TuesdayRevealed.value,
        Mercredi: WednesdayRevealed.value,
        Jeudi: ThursdayRevealed.value,
        Vendredi: FridayRevealed.value,
        Samedi: SaturdayRevealed.value,
        Dimanche: SundayRevealed.value
    }
    return revealMap[day];
}
```
We can now use `isWordRevealed` to render the correct word within our Carousel like so:
```
<Slide v-for="day in FrenchDays" :key="day">
    <div class="carousel__item" @click="toggle(day)">{{ !isWordRevealed(day) ? day : findKey(FrenchDays, day); }}</div>
</Slide>
```
We can go one step further to tidy up our template expression as there is a lot going on within the curly braces. Instead we can store the value within a variable and render that variable within our template like so:
```
const dayToShow = (day) => !isWordRevealed(day) ? day : findKey(FrenchDays, day);
```
```
<Slide v-for="day in FrenchDays" :key="day">
    <div class="carousel__item red" @click="toggle(day)">{{ dayToShow(day) }}</div>
</Slide>
```
You should now be able to toggle each flash card independent of the others! 🎉
![A working French flashcard deck](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/b90igvpzvdxsr8nzikwj.gif)
A little challenge would be to add flashcards for months, numbers and the seasons! In the gif above you can see I've gone ahead and added months in already.

### Deploying our Flashcard application

The final piece of the puzzle is to deploy the application. We will do this using [Vercel](https://vercel.com/). Before we do this, ensure that you've committed and pushed all your changes to a repository in your Source Control Management provider of choice (Github, Gitlab, Bitbucket etc).

If you don't already have a Vercel account sign up using the link [here](https://vercel.com/signup) and then select your Git provider. By connecting to your git provider instead of using your email you can smoothly deploy your project in a couple of clicks.

![Import your app in Vercel](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7fgx5g5rtymu8tg3cnhf.png)

After selecting your git provider, you will be prompted to select your project to deploy. Select your flashcard application then you'll be prompted by a screen to configure the application. There is no special configuration required for this simple app so we will be good to go with the default options. Click the Deploy button and behold the magic!


![App deployment configuration screen](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jqwmecrzgdgr5bhp9uff.png)


Congratulations! You have now deployed your flashcard application. Continue to the Dashboard and click the Visit button to see your work in all it's glory.
![Successful deployment of the flashcard app](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8co135mbnken8xwkw13r.png)

This concludes the tutorial! Thanks for reading and following along. I would love to hear your thoughts, how you used this project and any potential changes you added in the comments. Merci beaucoup 😁

Stay tuned for the next post in the flashcard series where we will turn this app into a Progressive Web App (PWA)! Suggestions on further extensions to the app are more than welcome. Au revoir😊