Git Product home page Git Product logo

yuschick / horologist Goto Github PK

View Code? Open in Web Editor NEW
24.0 2.0 0.0 4.11 MB

Horologist is a JavaScript library for animating DOM elements to represent time in the same ways as many of the world's greatest haute horologist watchmakers

Home Page: https://www.horologist.dev

License: MIT License

JavaScript 0.54% Shell 0.06% TypeScript 93.98% CSS 5.41%
animation css horology javascript svg typescript watchmaking ticktock-js haute ticktock

horologist's Introduction

Daniel Yuschick speaking at HelsinkiJS about building components in React and TypeScript.

Hey y'all 🤘 I'm Daniel.

Frontend, Design Systems, HTML, CSS, JavaScript, TypeScript, React, Accessibility, UI/UX, Mentor, Empathy

I'm a senior frontend developer, author, and speaker originally from the US but now calling Helsinki, Finland home. You can catch me sharing insights on platforms like Smashing Magazine, LogRocket and formerly CSS Tricks. Whether it's at conferences, meetups, or consulting with local companies, I love diving into topics like web accessibility (a11y) and design systems. Back in the US, I used to teach frontend engineering to career changers, and that passion for helping others continues today through my volunteer work with the Helsinki chapter of CodeBar.

I'm most passionate about great chocolate, beautiful tattoos and bridging design and development to create accessible and resilient design systems. Catch me at a local metal show, drinking hot chocolate at a cafe, gaming or sporting (basketball, squash, climbing).

Speaking

Date Event Title
02.11.2024 Moldova DevCon Approach With Care - Making Digital Accessibility Feel Natural
27.11.2024 Turku ❤️ Frontend It's Alive! Facing The Monsters Of Accessible Live Regions
18.12.2024 Turku ❤️ Frontend Get Lost, JavaScript: Just Kidding — But HTML & CSS Do More Now

Past Speaking Events

Date Event Title
29.05.2024 Hive Helsinki Approach With Care - Making Digital Accessibility Feel Natural
07.05.2024 enterJS The Keys to an Accessibility Mindset
04.04.2024 TampereJS Building Better Components — A Journey to a More Resilient Frontend
22.03.2024 Michigan Technology Conference The Keys to an Accessibility Mindset
21.03.2024 Michigan Technology Conference Building Better Components — A Journey to a More Resilient Frontend
29.02.2024 HelsinkiJS Building Better Components — A Journey to a More Resilient Frontend
28.02.2024 Turku ❤️ Frontend Building Better Components — A Journey to a More Resilient Frontend
29.09.2023 RenderCon Nairobi The Keys to an Accessibility Mindset
13.09.2023 StackConf Berlin The Keys to an Accessibility Mindset
31.05.2023 Turku ❤️ Frontend The Keys to an Accessibility Mindset
04.05.2023 TampereJS The Keys to an Accessibility Mindset
26.04.2023 ResQ Club The Keys to an Accessibility Mindset
04.04.2023 Integrify The Keys to an Accessibility Mindset
28.03.2023 HelsinkJS The Keys to an Accessibility Mindset
10.03.2023 Meru Health The Keys to an Accessibility Mindset
21.02.2023 FiksuRuoka The Keys to an Accessibility Mindset

horologist's People

Contributors

dependabot[bot] avatar yuschick avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

horologist's Issues

Allow Passing an ID into the Main Watch Class

ID Support in Watch Class

In the event there are multiple watches on one page, allowing the primary Watch class to support the passing of a parent ID can help easily scope functionality to the correct watch as opposed to always needing explicitly named elements for each watch.

Specs

  • The Watch class should support an optional ID parameter which would then be used when creating all the additional complications
  • This will likely entail updating all document.getElementById calls to document.querySelector in order to preface all complication elements with the parent Watch ID
const demo = new Watch(settings, [parent-id]);

indicators in external sphere as option too

Thanks for your work

I would suggest indicators in external sphere as option too.

Sun raise/down and Moon rise/down, would be nice to be able to setup as markers in a external 24h sphere.
Also a dot showing the actual 24h/ day percentage (as the failed internet time) time
And other layer with weather, rains, winds, and temperature changes.
More or less all you did with small spheres able to be implemented too, as an option, in external spheres.

Consider Tri-Pusher for Rattrapante Complication

Rattrapante Tri-Pusher Support

While currently, the Rattrapante complication works with two pushers, like the chronograph, many versions of this complication consist of three pushers.

Specs

  • This functionality should exist within the existing Chronograph.js module
  • The tri-pusher functionality should be assumed by the logic whenever a 3rd button is passed into the settings with rattrapante: true.

Functionality

The tri-pusher rattrapante should function as follows:

  1. Pusher 1: Starts the time
  2. Pusher 2: Pauses the break second hand
  3. Pusher 2: Resets the break second hand back to constant second hand
  4. Pusher 3: Stops all hands
  5. Pusher 1: Resets all hands to original position

Considerations

  • Given the preferred implementation being within the existing Chronograph complication, a restructuring or renaming of the existing btns props will likely be needed. Currently start and reset, while effective for the existing Chronograph and dual-pusher Rattrapante, aren't appropriate names for a tri-pusher model.
    • Naming ideas:
      • primary, secondary, tertiary
      • run, step, stop
  • Naming must convey proper meaning for all chronograph variations (standard, flyback, rattrapante dual/tri-pusher)

Update API for some Components

For some complications, such as day, date, and month, the API is overcomplicated. Currently, the Object structure would look as follows for any of these components:

date: {
  id: 'element-id'
}

This seems excessive.

Solution
For elements that can work by only providing an ID should have the ability to accept a string or object as its value. For example:

date: 'date-indicator'

or

date: {
  id: 'date-indicator',
  invert: true
}

This will clean up the code needed to run some complications and expand upon the flexibility of the API.

Components

  • day
  • date
  • month
  • week
  • year
  • moonphase
  • day night indicator
  • crown
  • eqTime

Include a Calendar Week Complication

Calendar Week

The calendar week display helps you plan your week’s activities by displaying the number of the calendar week on the watch dial. The week changes at midnight between Sunday and Monday, in parallel with the date change.

Learn more here.

Specs

Much like other calendar complications, the week indicator should only require an element ID to rotate, whether this is a hand or a dial. Optionally, supporting the ability to set the beginning of the week between Sunday or Monday. Default to Monday.

Review Moment Docs here.

Tentatively:

week: {
  id: string,
  [start: 'sun/mon'],
  [invert: true]
}

Functionality

Assume the indicator will be designed at the 1st week, leverage Moment to determine the current week based on the locale (per Moment docs above). Rotate the indicator element 6.92deg (360/52).

Considerations

  • Consider the optional start value. This could conflict with locale settings in Moment. Using Moment would be the most consistent functionality but providing start values could create conflicts. This will need to be reviewed and tested.

Support Split Display for Hours

Split Displays

Split displays consist of two discs that rotate in unison to depict the desired value. In this case, two discs rotate to show the hour - one disc for 0-2 (tenth hours) and a second disc 0-9 (single hours).

See an example here.

Specs

  • The updates should live in the current Dials.js module
dials: {
  hands: {
    minute: [string]
  },
  split: {
    hour: {
      ones: [string],
      tenths: [string]
    }
  }
}

Functionality

The ones disc will rotate every hour while the tenths disc will rotate every ten.

Considerations

  • How will this affect manual time setting and how should this feature be supported
  • The hours can be displayed in both 12 and 24 hour formats
  • Split displays cannot be paired with any other display type
    • If an hour hand is passed into the split property, no other hour hand should exist in the settings

Allow Manual Setting of Complications

Manual Setting

Most complications in watches can be manually set. This includes moonphase, calendar complications, and day/night indicators for example. The ability to manually set these complications within TickTock should be included.

Specs

  • The work will reside in the appropriate complication's module

  • Complications to include:

  • Moonphase

  • Calendar

    • Day
    • Date
    • Month
    • Year
    • Week
  • Day Night Indicator

Functionality

By default, TickTock will add an event listener for the right arrow key to toggle between dials to manually set the time. Leveraging this, the complications that support manual setting should be included in the array that the right arrow traverses. This designation will likely be done within the primary Watch Class to store the complications.

Each complication should move relative to its own degree intervals. For example, the day complication should rotate 51.43deg (306 / 7) with each step. Following the boolean flags used within the dials to denote manually set time, these additional complications should work similarly.

The main Watch class contains this.activeDial and this.dialInstances into which dial references are stored. By incrementing this.activeDial that determines on which dial to run rotateHands(). These values will likely need to be updated to this.activeComplication and this.manualComplications. Each complication (except Dials) will need to have its rotateHands() method updated to support forward and backward setting as well as boolean manualtime flags.

Clean Up Babel Presets

Remove the es2015 preset and use the env preset (or just the react one). In any event, the es2015 preset is deprecated, so drop that ish.

Update Docs Section to Remove Overview Links

On the Docs section of the TickTock website, each component has an Overview section. This is very redundant. Instead, remove the Overview links and when clicking on a component header, such as Minute Repeater, the menu expands while the user is taken to the Minute Repeater Overview section by default.

Support Monopusher Chronograph Functionality

Monopusher Chronograph

The monopusher chronograph is another variation on the traditional chronograph complication. As the name suggests, it allows one pusher to control the full chronograph.

Specs

  • Given the additional issue regarding support for a tripusher chronograph, this could possibly turn into a slight chronograph re-write.

Tripusher Issue: #12

chronograph: {
  buttons: {
    primary: ...
    secondary: ...
    tertiary: ...
  }
}

Functionality

A monopusher cycles through three functions.

  1. Click to start
  2. Click to pause
  3. Click to reset

Considerations

  • Should this and the tripusher be handled simultaneously?
  • This will likely emphasise the need for a rewrite to the chronograph API and naming
  • By following the primary, secondary, and tertiary naming convention, the N-pusher functionality could be determined based upon the amount of supplies buttons.
    • If only primary is defined, it should function as a mono-pusher
    • If primary and secondary it should function as a traditional two pusher
    • If all three are set, function as a tripusher
      • Should error checking be implemented if the hands are not provided in order? (ie: primary, tertiary) Or should the functionality be applied to the number of hands, not necessarily their key?

Include an Equation of Time Complication

Equation of Time

An equation of time watch shows the difference between "true" solar time (that of Nature) and "mean" solar time (that of Man). This rare and poetic complication is usually combined with other astronomical indications.

Learn more here.

Specs

Will need to review several implementations of this complication to find the common habits. Should this be a retrograde hand, should it be a dial; finding the common display habits will help scope the specs.

Tentatively:

eot: {
  id: string,
  range: [number, number]
}

Functionality

Assuming the indicator will likely be designed at 0 to begin, a range of values would ned to be provided - a min for when the time is -15 minutes and a max for when the time is +15 minutes. The difference would need to be found between the range to evenly position the hand.

Considerations

  • What would be the most common implementation of this complication? As it's such an obscure complication, building to its most common implementation would be fine.

Fine Tune the Seconds Hand

There are two areas where the second hand should be improved.

  1. The default ticking behaviour should be updated to tick at twice the rate but half the rotation value. The current behaviour functions more like a one hertz / jumping seconds watch which should be its own feature.
  • When separating the jumping seconds functionality out to its own feature, this will require a slight API change, so consider how this should be handled.
dials: [{
  hands: {
    ...
    second: 'split-second-hand',
  },
  jumpingSeconds: true
}]
  1. When sweeping, get off your ass and finally clean up the transition from 59 seconds to 0. It currently drops the transition at 59 seconds and jumps to 0, then sweeps again. Fix that, ya bum!

Sweeping Seconds Do Not Sweep

Describe the bug

When using the sweep property for the seconds hand, the hand still ticks.

To Reproduce

Visit any of the showcase pieces, such as the Velsheda, to see the sweeping seconds ticking.

Expected behavior

The sweep property should make the second hand sweep smoothly around the dial.

Support Retrograde Minutes

Retrograde Hours

“Retrograde” hands sweep a segment of a circle before springing back to their initial position to begin their movement again. Their endless choreography is an inspiration for innovative and highly spectacular dials.

Learn more here
Watch it live here

Specs

  • The functionality should exist within the existing Dials.js module
  • Discussion: How best to include the property in the existing Dials object?
dials: [{
        hands: {
          hour: 'retrograde-sec-hour-hand',
          second: 'retrograde-sec-second-hand',
        },
        retrograde: {
          minute: {
            id: 'retrograde-minute-hand-one',
            max: 180,
            duration: 10
          }
        }
      },
    ]

Functionality

TickTock will assume the retrograde hand will be designed in its beginning position, 0 degrees. Be defining a max value, the minutes will be evenly divided amongst that range. Upon reaching the end of the range, the hand will reset back to its original position.

Considerations

  • When manually winding the watch, how can the retrograde be added cleanly allowing manual winding to reset and jump accordingly.
  • How to easily handle the flags needed when keeping time from a manually set position. For example, manually winding the watch to 11:59 and then the watch is set to then keep time on its own, knowing to reset at 12:00
  • Watches contain retrograde hours, minutes, and seconds. Building a solution that can be leveraged for all three is the goal
    • Does this possibly warrant a separate Module?

Support Split Display for Minutes

Split Displays

Split displays consist of two discs that rotate in unison to depict the desired value. In this case, two discs rotate to show the hour - one disc for 0-5 (tenth minutes) and a second disc 0-9 (single minutes).

See an example here.

Specs

  • The updates should live in the current Dials.js module
dials: {
  hands: {
    hour: [string]
  },
  split: {
    minute: {
      ones: [string],
      tenths: [string]
    }
  }
}

Functionality

The ones disc will rotate every minute while the tenths disc will rotate every ten.

Considerations

  • How will this affect manual time setting and how should this feature be supported
  • Split displays cannot be paired with any other display type
    • If a minute hand is passed into the split property, no other minute hand should exist in the settings

Clean Master Branch and Build Scripts

Currently, the master branch contains some unnecessary and cumbersome processes. Update this branch and workflow.

  • Update build scripts
    • Remove the manual step of having to update /index.js imports from ./modules/* to ./dist/modules/*
    • Remove manual process of replacing ./dist/modules with ./dist/src/modules
    • Remove the creation of ./dist/src/
  • Restructure NPM scripts to be more efficient
  • Store root svg files into /src/svg/

Looking to make these improvements to not only make my workflow easier but to ease the burden of entry for others who may wish to contribute.

Deprecate the Offset Property in the Dial Class

Currently, TickTock supports both the offset and timezone properties, though it displays timezone options at a greater priority. In lieu of the inclusion of Moment Timezone and the timezone property in the Dial class, finally remove support and deprecate the offset property.

Support Retrograde Seconds

Retrograde Hours

“Retrograde” hands sweep a segment of a circle before springing back to their initial position to begin their movement again. Their endless choreography is an inspiration for innovative and highly spectacular dials.

Learn more here
Watch it live here

Specs

  • The functionality should exist within the existing Dials.js module
  • Discussion: How best to include the property in the existing Dials object?
dials: [{
        hands: {
          hour: 'retrograde-sec-hour-hand',
          minute: 'retrograde-sec-minute-hand',
        },
        retrograde: {
          second: {
            id: 'retrograde-second-hand-one',
            max: 180,
            duration: 10
          }
        }
      },
    ]

Functionality

TickTock will assume the retrograde hand will be designed in its beginning position, 0 degrees. Be defining a max value, the seconds will be evenly divided amongst that range. Upon reaching the end of the range, the hand will reset back to its original position.

Considerations

  • Watches contain retrograde hours, minutes, and seconds. Building a solution that can be leveraged for all three is the goal
    • Does this possibly warrant a separate Module?

Remove Manual Wind Complication

After debating pros and cons of having the manual wind complication, I believe I have settled on removing it in lieu of a much more simplified Dials complication. Removing this will clean up a lot of jumbled logic within the components, remove automatic keybindings attached to every Watch class, and simplify the inclusion of additional display types, such as retrograde hours and minutes.

Wandering Hours Complication

Is your feature request related to a problem? Please describe.
No

Describe the solution you'd like
The Arnold & Son Wandering Hours complication provides a unique, and beautiful, challenge. This would be a terrific feature to support in Horologist. Wandering hours would also unlock the ability to recreate many Urwerk pieces.

Describe alternatives you've considered
N/A

Additional context

image

image

Update the Minute Repeater Chime Patterns

Minute Repeater

Coming Soon...

Specs

  • The work will consist of reworking the existing logic within the existing MinuteRepeater.js module
  • The settings object should be updated to support the existing format (until v3) but be modified to focus on accepting only two chimes.
repeater: {
  chimes: {
    hour: [string path],
    minute: [string path]
  }
}

Functionality

Most repeaters work off of two chimes.

Hours are denoted by the striking of Chime 1.
Quarter Hours are denoted by striking Chime 1 and right after striking Chime 2
Minutes are denoted by the striking of Chime 2

The two chimes representing the quarter hours should overlap when played, approximately striking chime 2 half way through chime 1's duration.

Add a Linter File

Add a linter file with rules in place to help others looking to contribute (and myself, obviously)

Improve Testing Coverage

Write additional tests for individual components. It doesn't have to be extensive but having only one total test for this whole thing is pretty shameful. Shame. Shame. Shame!

Implement a Foudroyante Complication Module

Foudroyante Complication

A foudroyante is also called a jumping seconds hand. What it mostly does is move very quickly on a watch dial in steps (not sweeping). Depending on the speed of the movement, the foudroyante hand makes a few very brief stops as it makes a full revolution each second. For example a hand may make six stops each second, and runs continuously as opposed to being part of a chronograph.

Learn more here.
Watch a live version here.

Specs

  • The complication should function as its own separate module, Foudroyante.js
  • The behaviour should be tied to the overall Watch interval and Power Reserve
  • The settings property structure should look at follows:
foudroyante: {
  id: [string],
  steps: [number]
}

Functionality

Based upon the amount in the steps property, the target element (defined by id) will jump [steps] amount of times around its dial per second. For example, if steps is set to 6, the hand will jump 60 (360 / 6) degrees every 1/6 of a second.

Support Retrograde Hours

Retrograde Hours

“Retrograde” hands sweep a segment of a circle before springing back to their initial position to begin their movement again. Their endless choreography is an inspiration for innovative and highly spectacular dials.

Learn more here
Watch it live here

Specs

  • The functionality should exist within the existing Dials.js module
  • Discussion: How best to include the property in the existing Dials object?
dials: [{
        hands: {
          minute: 'retrograde-sec-minute-hand',
        },
        retrograde: {
          hour: {
            id: 'retrograde-house-hand-one',
            max: 180,
            duration: 10
          }
        }
      },
    ]

Functionality

TickTock will assume the retrograde hand will be designed in its beginning position, 0 degrees. Be defining a max value, the hours will be evenly divided amongst that range. Upon reaching the end of the range, the hand will reset back to its original position.

Considerations

  • When manually winding the watch, how can the retrograde be added cleanly allowing manual winding to reset and jump accordingly.
  • How to easily handle the flags needed when keeping time from a manually set position. For example, manually winding the watch to 11:59 and then the watch is set to then keep time on its own, knowing to reset at 12:00
  • TickTock supports both 12 and 24 hour time. This format will have to be taken into consideration when originally processing the max range provided.
  • Watches contain retrograde hours, minutes, and seconds. Building a solution that can be leveraged for all three is the goal
    • Does this possibly warrant a separate Module?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.