DEV Community

Cover image for Create a French Flashcard Carousel in an evening
Menilek Techane
Menilek Techane

Posted on • Edited on

Create a French Flashcard Carousel in an evening

Hello internet! This is my first blog post and we will be building a mobile friendly French Flashcard application (try it here). If you are learning a language or gearing up for travel this simple tool is for you.

Introduction to Vue, Vite & Vercel

Vue 3, 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 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 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. and NPM 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. 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
Enter fullscreen mode Exit fullscreen mode

We will go ahead and use Vue without TypeScript for now.
Vite CLI steps to create a Vue application

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

Installing Vue3-Carousel

We will use the awesome Vue3-Carousel to create our flashcard Carousel. First, we need to install it using:

npm install vue3-carousel
Enter fullscreen mode Exit fullscreen mode

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;
}
Enter fullscreen mode Exit fullscreen mode

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

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';
Enter fullscreen mode Exit fullscreen mode

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"
}
Enter fullscreen mode Exit fullscreen mode

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. 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>
Enter fullscreen mode Exit fullscreen mode

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.

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>
Enter fullscreen mode Exit fullscreen mode

After we save, Vite will quickly pull in our changes and our browser should show us:
Carousel showing Days of the week in French

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 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>
Enter fullscreen mode Exit fullscreen mode

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);
Enter fullscreen mode Exit fullscreen mode

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.

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]()
}
Enter fullscreen mode Exit fullscreen mode

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.

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);
}
Enter fullscreen mode Exit fullscreen mode

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];
}
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

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);
Enter fullscreen mode Exit fullscreen mode
<Slide v-for="day in FrenchDays" :key="day">
    <div class="carousel__item red" @click="toggle(day)">{{ dayToShow(day) }}</div>
</Slide>
Enter fullscreen mode Exit fullscreen mode

You should now be able to toggle each flash card independent of the others! 🎉
A working French flashcard deck
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. 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 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

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

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

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😊

Top comments (5)

Collapse
 
wimadev profile image
Lukas Mauser

cool! I recently created a similar post, but without using any libs: dev.to/nuxt-wimadev/create-an-inst...

Collapse
 
menilek profile image
Menilek Techane

Just checked out your post, it's great!

Collapse
 
wimadev profile image
Lukas Mauser

Thank you! 😊

Collapse
 
melphindev profile image
MelphinDev

Thank you for the tutorial! I will try this out in the evening.

Collapse
 
menilek profile image
Menilek Techane

Awesome! Let me know how it goes