Skip to main content

Roman Numeral Converter

Roman Numeral Converter Project Mobile UI Preview Figma vs Visual Studio Code Roman Numeral Converter Project Desktop UI Preview Figma vs Visual Studio Code

The Project

Arabic to Roman numeral converter developed with vanilla JavaScript, advanced input validation and component-based architecture. A complete application with Material Design 3 UI and professional commenting system.

Source Code

<!-- DESIGN 
------
* This HTML is characterized by:
* - importing Roboto Slab and Roboto fonts from Google Fonts.
* I chose these fonts because Roboto Slab has classic shapes
* that evoke ancient Rome,
* Roboto (for input and button) provides modernity,
* readability and consistency with Material Design 3
* - a div structure with exception of the card container, where
* I chose <main> for semantic purposes
-->

<!DOCTYPE html>
<html lang="en">
<head>
<title>Roman Numeral Converter</title>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" href="styles.css">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Roboto+Slab:wght@100..900&family=Roboto:ital,wght@0,100..900;1,100..900&display=swap" rel="stylesheet">
</head>

<body>

<!-- * freeCodeCamp instructions:
* - You should have an input element with an id of "number".
* - You should have a button element with an id of "convert-btn".
* - You should have a div, span or p element with an id of output.

* I'll create separate divs to allow me in CSS phase to position
* each component exactly as in Figma

* I must remember to write "number" for type of input to restrict
* input to numeric characters, which is more efficient than using
* regex in JavaScript
* I did some research and found out that input type="number" uses
* browser native validation operating with an underlying C/C++ engine,
* while regex is executed by the JavaScript interpreter.
* However, I still need to use JavaScript to avoid "e" and ","
-->

<main id="card-container">
<div id="title-container">
<h1 id="first-h1">Roman Numeral <span id="second-h1">Converter</span></h1>
</div>
<div id="output-container">
<p id="output"></p>
</div>

<!-- * Adding min/max attributes provides defense in depth.
* Although this approach is typically used in more complex,
* cybersecurity scenarios, it provides a fallback in case JavaScript
* rule validation fails or is disabled.
-->

<div id="input-container">
<input value="" type="number" name="arabic-number-input" class="number" id="number" placeholder="Enter a Number" min="1" max="3999" autocomplete="off">
</div>
<div id="convert-btn-container">
<button id="convert-btn">Convert</button>
</div>
</main>

<script src="script.js"></script>
</body>

</html>

The Art of Comments

Incredibly, I have very few things to say about this project, because I said everything in the comments. Nevertheless, those comments are for programmers who read them, these READMEs are for everyone.
After thoroughly internalizing Salvatore Sanfilippo's article (https://antirez.com/news/124) it's as if in this project I wrote comments for the first time. Previously I only used them in CSS to divide different components. This time I integrated design comments as well as the long introductory comment that explains the file architecture, so that anyone who reads it will have a general overview right from the start. This is useful in long projects, in my case I added this type of comment also in the HTML but I recognize that for such small files it's quite useless, nevertheless, since I want to practice right away, I decided to add it.

The "Why Comments"

I found the "why comments" amazing, as well as all those comments that explain the reasons why one choice was made rather than another and if this is very trivial then explain why it was the best choice at that moment. I say amazing because they forced me to reflect and research a lot in order to affirm certain choices. This gave me an understanding that I could never have received by writing only code.

The "Trivial Comments" with Culture

Then come the trivial comments, which should be all those comments dedicated to concepts that any programmer takes for granted, but which Salvatore Sanfilippo says he loves anyway. I wanted to add a pinch of culture inside.
For example in the HTML at a certain point I state: "I did some research and found out that input type="number" uses browser native validation operating with an underlying C/C++ engine, while regex is executed by the JavaScript interpreter."
Or again: "Adding min/max attributes provides defense in depth. Although this approach is typically used in more complex, cybersecurity scenarios, it provides a fallback in case JavaScript rule validation fails or is disabled."
Two concepts completely useless to include for any programmer, but still concepts worth rereading. For example, I, an absolute beginner, would be very happy to find similar comments in someone else's project.

The "Checklist Comments"

Subsequently I added warning comments, Salvatore calls them "checklist comments" that is, comments that helped me remember exactly what the freeCodeCamp instructions said and I'm not exaggerating if I say that it's precisely thanks to these that I managed to pass a certification project on the first attempt for the first time.

The Design: Material Design 3

Let's now talk about the design of this project. This time I chose to delve into the world of Material Design 3.
I was inspired by the Google Translate application on my smartphone, I've always liked the style, although "acidic" I find its style unique. I started studying this design current and after getting a general overview from a YouTube video, I dedicated myself to exploring the official website. Here I got all the answers, from the style and stylistic choices to a Figma file with all the main components. I took from this the various "shapes", that is all the shapes of Material Design 3 and scattered them on the background, adding an emoji depicting Android, also taken from the Material site.

A New Approach: Side Notes

Here's an image of the notes I wrote alongside the project to help me. I had never adopted this approach. Did Salvatore even manage to change my way of using Figma?

Side Notes Figma Approach

Personal Reinterpretation of the Style

I took the liberty of reinterpreting this style. In fact, for the input box I decided to position the placeholder centered horizontally instead of left-aligned, with a slightly higher opacity than Google would have done and at the same time with a color analogous to the overall theme. I also inserted dashes, precisely 6, which are displayed when opening the application, before getting the output. Google would never have done this, it would have left it empty instead to emphasize that that field would be filled with the call to action by the user (pressing the "Convert" button).

I made all these choices for a mere aesthetic reason, they brought me to the feeling that everything was in the right place.

Typography: Roboto Slab and Roboto

Beyond the style, I also kept the typical consistency pattern that Google dedicates to interactive elements (input, buttons) which must be immediately recognizable. For this reason I opted for the Roboto Slab font for the title and for the output, which had the objective of invoking classic characters, akin to ancient Rome, a sort of "thematic accent". While for input and button the Roboto font that follows modernity, has excellent readability and follows consolidated patterns that the user knows, characteristics central to Google's philosophy.

What I Learned

Advanced CSS Architecture:

  • Component-Based Architecture for organization into components (card, title, output, input, button)
  • Utility-First Variables with centralization in :root
  • Flat Component Hierarchy with ID-based selectors
  • Responsive media queries for mobile

Conversion Algorithm:

  • Array map with Arabic-Roman pairs [[1000, "M"], [900, "CM"]...]
  • .reduce() for result accumulation
  • While loop for iteration on Roman values
  • Array destructuring for concise code

Professional Input Validation:

  • type="number" for native browser validation (C/C++ engine)
  • min/max attributes for defense in depth
  • e.preventDefault() to block non-numeric characters
  • Edge case handling: empty values, NaN, invalid ranges

Event Handling:

  • addEventListener("keydown") for character control
  • Enter key for alternative submit
  • .includes() for blocking specific characters (["e", "E", "+", "-"])

Comment Best Practices:

  • Design comments for general architecture
  • Why comments to explain technical choices
  • Trivial comments with cultural insights
  • Checklist comments for freeCodeCamp requirements

Material Design 3:

  • Shapes and Material components
  • Color system with thematic palettes
  • Typography hierarchy (Roboto Slab + Roboto)
  • Interactive states and transitions

Programming Principles:

  • SRP (Single Responsibility Principle)
  • DRY (Don't Repeat Yourself)
  • Defense in depth approach
  • Semantic HTML

Reflection

Salvatore Sanfilippo taught me that comments are not a burden, but an art. Every technical choice has a reason, every discarded alternative has its why. Documenting this process is not wasting time, after all it led me to pass a certification project on the first attempt for the first time.


Next Project: Learn Regular Expressions by Building a Spam Filter