DEV Community

ziga
ziga

Posted on

I build date and range picker from scratch so you don't have to

Don't you hate to repeat yourself? For example, I hate working on anything related to user authentication or authorization that isn't directly related to the system I'm working on. I see it as necessary evil, an accidental complexity.

Fortunately, web components are coming and soon we'll get to choose from even more and better UI components and we won't need to reinvent common components from scratch all the time. We are reinventing components because we're always switching to new JS frameworks.

As Ben Issa puts it: assemblers first, crafts people second.

Motivation

  • must be significantly smaller than moment.js + jQuery combo or even moment.js + custom elements combo
    • ~170 kB (~140 kB for moment + ~30 kB for jQuery, not including calendar library size at all) vs 4.2 kB for nanocal
  • must be reusable anywhere on web
    • use it with or without frameworks
    • use it with or without build tools

Decisions

  • I used svelte because it compiles down to plain javascript which makes this library able to run with no runtime or build tool dependencies
  • I ripped-off Airbnb's style, because I am no designer nor I wanted to spend time re-inventing calendar style
  • For testing I use tape (and not jest or ava) because I want to run tests inside real browser which is targeted runtime

Future plans

  • once web components are available everywhere ™, I'll probably rewrite front-end part into custom element or use svelte's compile to custom elements
  • add more style customizations or remove some

I hope my UI decisions will work for some of you. I build this library for myself, documented and open-sourced it for you.

Here's the repo: ⭐️ https://github.com/zigomir/nanocal ⭐️

Top comments (11)

Collapse
 
tracker1 profile image
Michael J. Ryan

No way to jump to another year/month.

Collapse
 
ziga profile image
ziga

how come? you should see forward and backward buttons, if not please provide more details.

Collapse
 
tracker1 profile image
Michael J. Ryan • Edited

Go to December 30. 1974 ... How many backs do you have to click?

Not every date entry is the near future or past.

Thread Thread
 
ziga profile image
ziga

It's not good UX for birthday picking, that's for sure. Main reason why I build it was for range picking (same as in AirBnb). Anyhow, if you want to open a calendar at specific year/month you can specify year and month as documented here.

Collapse
 
tracker1 profile image
Michael J. Ryan

I think, except for the size, Ms Ajax toolkit had the best date picked ux ever. Even if I hated the toolkit itself

Collapse
 
aks0510 profile image
Ankit Singhaniya

Any reason why you used Svelte and not Stencil? Cool project by the way. I'm really pissed with the large ~300kb bundle of react-date. Will give it a try.

Is it possible to add presets? I'll add the question to the repo as well.

Collapse
 
ziga profile image
ziga

Yeah! I actually knew about Stencil at the time I started, but I liked Svelte more. Even now I see Stencil is marketing it has 6kb runtime, while whole nanocal weights less than that. So I guess no runtime still beats a minimal runtime for me :)

Collapse
 
jorgutdev profile image
jorgutdev

Wow this is very good! Also the usage is simple and well implemented! Nice work :)

Collapse
 
mbocoder profile image
Mohamed BinOthman

it will be better if you provide demo to see how this date-picker look

Collapse
 
ziga profile image
ziga

you can see live examples on repo's readme: github.com/zigomir/nanocal#example... ;)

Collapse
 
pothureddypalli profile image
Pothureddypalli • Edited

Hi am very new to this Date Range Picker and am done Date Range Picker in Type script showing single month but I need to show two months, Please help me in building the calendar showing two months

This is the code I had done to show calendar for one month but I need two months to show please help me .

public createCalender(month) {
const firstDay = moment(month).startOf('M');
const days = Array.apply(null, {length: month.daysInMonth()})
.map(Number.call, Number)
.map((n) => {
return moment(firstDay).add(n, 'd');
});
for (let n = 0; n < firstDay.weekday(); n++) {
days.unshift(null);
}
return days;
}