Skip to content

arlagonix/todo-app

Repository files navigation

Todo App

Coded with HTML, SCSS, TypeScript

Built with Webpack

ℹ️ About

This is a solution to the Todo app challenge on Frontend Mentor.

The challenge is to build out a todo list and get it looking as close to the design as possible.

See task.md for more details about the task.

Users should be able to:

  • View the optimal layout for the app depending on their device's screen size
  • See hover states for all interactive elements on the page
  • Add new todos to the list
  • Mark todos as complete
  • Delete todos from the list
  • Filter by all/active/complete todos
  • Clear all completed todos
  • Toggle light and dark mode
  • Bonus: Drag and drop to reorder items on the list

⚙️ Tools

  • HTML5
    • Semantic HTML
  • SASS
    • Flexbox
    • BEM methodology
    • Responsive design
    • Desktop first
  • NodeJS
  • TypeScript
  • Webpack
  • Github Pages
    • Hosting

🔨 Build project

Command Description
npm install Installs required npm packages. Run it before building the project
npm start Builds application in development mode, launches a server that opens in a new browser tab
npm run dev Builds application in development mode, results may be found in ./build folder
npm run build Builds application in production mode, results may be found in ./build folder. Files are minimized, hash added to filenames to help when dealing with caching
npm run lint Doesn't build anything. Checks code quality

📁 File Structure

Path Description
build Folder with files generated by Webpack
static Folder with static assets (images, favicon)
__tests__ Folder with Gherkin tests (manual, no automation)
src Source files needed for application development
src / index.scss Main styles
src / index.ts Main file with TS
src / scripts Definition of TS classes
docs Folder with additional information, documentation
docs / design Folder with images of how the interface must look like
docs / results Folder with screenshots of how the application works after being fully developed
docs / unused assets Folder with assets from initial FrontendMentor archive that I didn't use
docs / README-template.md Template for README.md, don't use it (from FrontendMentor)
docs / style-guide.md Style information: color palette, fonts, etc. (from FrontendMentor)
docs / task.md Detailed task description (from FrontendMentor)
docs / todo-app-main.zip Initial archive provided by Frontend Mentor
LICENSE MIT License
package-lock.json JSON file that keeps track of the exact version of every package that is installed so that a product is 100% reproducible in the same way even if packages are updated by their maintainers
package.json JSON file that holds various metadata relevant to the project. This file is used to give information to npm that allows it to identify the project as well as handle the project's dependencies
tsconfig.json JSON file that holds different compiler options for TypeScript
.prettierrc Config for Prettier VS Code plugin
.eslintrc.js Config for ESlint
webpack.common.js Contains configuration common for build and dev configs
webpack.dev.js Contains configuration for development mode
webpack.prod.js Contains configuration for production mode

📦 NPM Packages

Package Comment
webpack Module bundler
webpack-cli Required for work of webpack with v4 or later
webpack-merge Helps to merge configs (webpack.common.js + webpack.dev.js for example)
webpack-dev-server Launches developer server that automatically applies all changes in code
typescript Is used by ts-loader, compiles ts into js
ts-loader Is used by Webpack, compiles ts into js, resolves imports
node-sass Is used by sass-loader, compiles sass/scss into css
sass-loader Is used by Webpack, compiles sass/scss into css
css-loader Is used by Webpack, resolves assets imported in css files, unites them in one file
css‑minimizer‑webpack‑plugin Is used by Webpack, minifies css
mini-css-extract-plugin Extracts transpiled css in a separate css file
html-loader Is used by Webpack, resolves assets in html files. (Mode production works perfectly without it, but development mode for some reason sometimes loses some assets referred in html...)
html‑webpack‑plugin Is used by Webpack, generates a html file from a template. Minifies html, adds links to js, css
terser-webpack-plugin Is used by Webpack, minifies js (comes with webpack, no need to install it separately)
eslint Checks code quality
eslint-config-prettier Removes formatting checks that contradict to the standards of prettier
eslint-config-standard-with-typescript
eslint-plugin-import
eslint-plugin-n
eslint-plugin-promise
Come with ESLint

💡 Details

Working with Webpack

Yeah, baby! I configured Webpack. That's a module bundler. It took much time, comparable with the time required to code the todo list itself.

Now it takes all my ts files and compiles them into one js file. Then it minifies the js file

Also it transpiles scss files into css, resolves all imports, generates hashes for all imports, and adds styles in style tag of index.html

Also it turns my template html into index.html, adds there links to js file, resolves all relative imports to assets with hash names

Also it works differently depending on mode. In production mode it minifies everything. In development it doesn't

Also it places all built files in a build folder. And clears the results of the previous build after every build

Also now it launches the server and automatically opens it in a new tab and automatically tracks all changes in files. Just use "npm run start"

Also it took many hours of reading articles, watching videos in order to properly configure it

I'm fully satisfied

P.S. Tried to make Webpack place all generated assets (images, svg, webp) in a separate folder inside of build. Used file-loader, but it ocurred that it's outdated, works with errors. I couldn't find any alternatives, so everything is placed automatically now in one place: in build folder.


Legendary Todo list

I have finally accomplised the task, that every beginner frontend developer must complete. Todo list! With many, many features


What you can do with todo list

You can

  • Add new items + submit validation
  • Check / Uncheck items
  • Delete individual items
  • Delete all completed (checked) items
  • Display all, active, completed items
  • Drag and drop items

Save to local storage

Theme is saved in local storage. Initially, if there is no theme in the storage, I use the prefers-color-scheme to define the system theme of a user.

// If the theme is saved in local storage take it from there
const isDarkModeFromStorage = JSON.parse(
  localStorage.getItem('isDarkMode') ?? 'null'
);
if (isDarkModeFromStorage) this._isDarkMode = isDarkModeFromStorage;
// Otherwise use theme from user's system settings
else
  this._isDarkMode =
    window.matchMedia &&
    window.matchMedia('(prefers-color-scheme: dark)').matches;

I also save the todo list items and their order in local storage. Thus after page refresh data doesn't disappear.


Dark theme, Light theme

Users can toggle dark and light theme. The default theme is defined using prefers-color-scheme.

Classic CSS class toggle on/of to enable/disable dark theme.


Figma prototype

I use a free version of FrontendMentor. Thus I don't have access to Figma prototypes. But that's not a problem - I made my own one

Here it is: https://www.figma.com/file/4dFzGRjZoRp0v3ed84Xrci/Todo-App

That helped me to make the application look quite appealing and to experiment with elements to come up with the best looking variant


Gherkin syntax

I thought about including Jest to add unit test my scripts, but in this case it seems redundant. All functions are tightly related to the DOM elements and depend on their state. Thus it's extremely difficult to test this functions in isolations.

So instead I decided to add Gherkin "Given When Then" scenarios to describe the business logic. I wrote them prior to coding the implemenation. They describe how the interface must work with as few as possible interface details like "press button" and so on.

Feature: Switch a theme

  In order to see the theme I like
  As a User
  I want to be able to switch themes

  Scenario Outline: Switch theme
  Given Current theme is <CurrentTheme>
  When User switches a theme
  Then System shows a <NewTheme>

  Examples:
      | CurrentTheme          | NewTheme    |
      |-----------------------|-------------|
      | light theme (default) | dark theme  |
      | dark theme            | light theme |

Other notes

  • Submit button is disabled when input is empty
  • Hover effect on items
  • Theme changing icon changes depending on the current theme
  • Added nice background, minified it by converting images to webp format. From 1.5 md it went to about 50 Kb!
  • The interface lags for some reason when there are more than 10 items on the screen. Don't know why it happens. Even hover animation lags! Inexplicable
  • Item height adapts to the length of content, so a user may input strings of any length. Don't think there is any validation needed in this case.
  • If the list is empty the block "No items to display" is shown
  • Added a nice frosted ice effect from IOS
  • Changed the initial design of application described in the task, using Figma

🔗 Useful resources

👤 Author