DEV Community

loading...
Cover image for Coding 15 Dynamic Time-Based Icons for Notion

Coding 15 Dynamic Time-Based Icons for Notion

supernaturval profile image val 🧙‍♂️ ・3 min read

Hi everyone! Val from Optemization here. We just shipped Dynamic Calendar Icons for Notion on Product Hunt - it's basically a bunch of different calendar icons that update based on current time and serve users icons based on their timezone.

Icon preview in a Cloudflare Worker

It was a simple project, but a fun one to implement.
Notion doesn't allow to embed any complex iFrames or code inside the tool, so I had to work around this limitation and learn how to add dynamic content to basic SVG.

Code for assembling SVG based on icon type

In the end I built it all as a single Cloudflare Worker. The code features a function that serves different icons based on a request URL (where the route includes icon type and the timezone).

Icons are generated at the time the request comes in - a Javascript worker assembles an icon, taking some dynamic variables (e.g. one calculating the date for this week's Monday, or another one calculating the current year, or quarter), and taking a timezone into account.

Emoji icon previews in a widget

Because icons have light mode, dark mode and emoji versions, worker also assembles different SVG code based on what icon is requested - e.g. emoji icon is made via SVG paths, while simple dark icons are just text blocks in a square-shaped container.
There's a couple constant SVG parts added as variables - e.g. the opening part, declaring document type and the size of the icon, and a closing part

Here's an example:

 function iconContents(iconParameters, fontSize, contents){
   return `<g><text id="contents" x="${iconParameters.x}" y="${iconParameters.y}" fill="${iconParameters.fill}" font-family="San Francisco" font-size="${fontSize}" style="text-anchor: middle" class="dynamic">${contents}</text></g>`
 };
Enter fullscreen mode Exit fullscreen mode

This function takes in coordinates to place the text (date, usually) in inside the icon, it's fill color, font size and the actual contents.

Icon contents are generated with code blocks similar to the one below:

  let day = d.getDay(),
  diff = d.getDate() - day + (day == 0 ? -6:1); // the last part is for adjusting depending on whether it's a Sunday
  let DD_monday = new Date(d.setDate(diff)).toLocaleString(locale, {day: "numeric", timeZone: zone });
  let MMShort_monday = new Date(d.setDate(diff)).toLocaleString(locale, {month:   "short", timeZone: zone}).toUpperCase();
Enter fullscreen mode Exit fullscreen mode

Thanks to kind people posting snippets like the first two lines in the block above on StackOverflow! There was a lot of date- and time-crunching here -- e.g. the icon above gets the monday of the current week. We also have icons that get you the first day of the next month, the last quarter, or that tell what date is tomorrow.

You can find the icons and see some previews here - https://optemization.com/dynamic-icons.
Along with these icons, my teammate and founder of Optemization Tem (shout-out for this!) assembled a fresh, no-code checkout workflow, allowing users to view a gallery with icons served using Firebase via an Indify widget, and then buy icons by selecting their timezone by typing it in, picking one of the icon packs, and paying with Stripe. The whole checkout flow was made with Paperform.

Previewing and picking an icon set in Paperform

Now we're going to add some more options, like icons with colored backgrounds, and think how to account for the dark mode automatically. After this is done - and I clean up my spaghetti code a bit - we'll open-source this on Github for everyone to check out!

If you created icons like this in the past or know a thing or two about generating dynamic SVGs, drop a comment in the thread - let's make these icons better and cover more use cases together.

Discussion (0)

pic
Editor guide