#app
View Compiled
@import url('https://fonts.googleapis.com/css?family=Exo:900')

*
  box-sizing border-box

body
  min-height 100vh
  background linear-gradient(45deg, hsl(0, 0%, 15%), hsl(0, 0%, 70%))
  display flex
  align-items center
  font-family 'Exo', sans-serif
  justify-content center

#app
  align-items center
  display grid
  grid-gap 1rem
  grid-template-columns repeat(auto-fit, minmax(auto, 150px))
  justify-content center
  justify-items center
  padding 1rem 0
  width 100%

  & > div
    margin 0.5rem
    background repeating-linear-gradient(30deg, var(--strapColor) 0, var(--strapColor) 5px, transparent 5px, transparent 10px) 5px 0 / 90% 100% no-repeat,
      repeating-linear-gradient(-30deg, transparent 0, transparent 5px, var(--strapColor) 5px, var(--strapColor) 10px) 5px 0 / 90% 100% no-repeat, var(--strapBg)
    &:nth-of-type(1)
      --strapColor rgba(165, 55, 253, .25)
      --strapBg rgba(190, 144, 212,1)
    &:nth-of-type(2)
      --strapColor rgba(41, 241, 195, .25)
      --strapBg #29c3b9
    &:nth-of-type(3)
      --strapColor rgba(89, 171, 227, .25)
      --strapBg rgba(129, 207, 224, 1)
    &:nth-of-type(4)
      --strapColor rgba(246, 36, 89, .25)
      --strapBg rgba(226, 106, 106, 1)
    &:nth-of-type(5)
      --strapColor rgba(245, 229, 27, .25)
      --strapBg rgba(254, 241, 96, 1)
View Compiled
const {
  React,
  React: { Fragment, useEffect, useState },
  ReactDOM: { render },
  moment,
  styled,
} = window
const ROOT = document.querySelector('#app')

const clip =
  'polygon(0 5%, 5% 0, 95% 0, 100% 5%, 100% 95%, 95% 100%, 5% 100%, 0 95%)'

const Hand = styled.div`
  width: ${p => (p.type === 'seconds' ? 2 : 5)}px;
  height: ${p => (p.type ? 40 : 20)}px;
  background: white;
  position: absolute;
  top: 50%;
  left: 50%;
  transform-origin: bottom;
  transform: translate(-50%, -100%) rotate(${p => p.value}deg);
`

const Day = styled.div`
  text-transform: uppercase;
  text-align: center;
`

const Strap = styled.div`
  clip-path: ${clip};
  height: 300px;
  overflow: hidden;
  position: relative;
  width: 100px;
`

const Bezel = styled.div`
  background: silver;
  height: 60%;
  left: 50%;
  position: absolute;
  top: 50%;
  transform: translate(-50%, -50%);
  clip-path: ${clip};
  width: 102%;
`
const Screen = styled.div`
  height: 100%;
  position: absolute;
  top: 50%;
  left: 50%;
  overflow: hidden;
  transform: translate(-50%, -50%);
  width: 90%;
  background: #000;
  color: #fff;
`

const Face = styled.div`
  display: flex;
  flex-direction: column;
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
`

const Value = styled.div`
  font-size: ${p => (p.small ? 2 : 3)}rem;
  line-height: ${p => (p.small ? 2 : 3)}rem;
  text-transform: uppercase;
  text-align: center;
  opacity: ${p => (p.opaque ? 0.5 : 1)};
  font-variant: tabular-nums;
`

const DefaultFace = date => (
  <Face>
    <Value>{date.format('HH')}</Value>
    <Value>{date.format('mm')}</Value>
  </Face>
)

const Watch = ({face}) => {
  const [date, setDate] = useState(moment())
  useEffect(() => {
    const TICK = setInterval(() => setDate(moment()), 1000)
    return () => {
      clearInterval(TICK)
    }
  }, [])
  return (
    <Strap>
      <Bezel>
        <Screen>
          {face(date)}
        </Screen>
      </Bezel>
    </Strap>
  )
}

Watch.defaultProps = {
  face: DefaultFace
}

const AnalogFace = date => {
  const seconds = (360 / 60) * date.seconds()
  const minutes = (360 / 60) * date.minutes()
  const hours = (360 / 12) * date.format('h')
  return (
    <Face>
      <Hand type='seconds' value={seconds}/>
      <Hand type='minutes' value={minutes}/>
      <Hand value={hours}/>      
    </Face>
  )
}

const DayFace = date => {
  const hours = date.format('H')
  const minutes = date.format('mm')
  const dayN = date.format('dd')
  const day = date.format('DD')
  return (
    <Face>
      <Value small>{hours}</Value>
      <Value small>{minutes}</Value>
      <Value small opaque>
        {dayN}
      </Value>
      <Value small opaque>
        {day}
      </Value>
    </Face>
  )
}

const DateFace = date => {
  const hours = date.format('HH')
  const minutes = date.format('mm')
  const monthYear = date.format('MMM DD')
  return (
    <Face>
      <Value>{hours}</Value>
      <Day>{monthYear}</Day>
      <Value>{minutes}</Value>
    </Face>
  )
}

const SecondsFace = date => {
  const hours = date.format('HH')
  const minutes = date.format('mm')
  const seconds = date.format('ss')
  return (
    <Face>
      <Value>{hours}</Value>
      <Value>{minutes}</Value>
      <Value>{seconds}</Value>
    </Face>
  )
}

const App = () => (
  <Fragment>
    <Watch face={DayFace} />
    <Watch />
    <Watch face={AnalogFace} />
    <Watch face={DateFace} />
    <Watch face={SecondsFace} />
  </Fragment>
)

render(<App />, ROOT)
View Compiled

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

  1. https://cdnjs.cloudflare.com/ajax/libs/react/16.13.1/umd/react.production.min.js
  2. https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.13.1/umd/react-dom.production.min.js
  3. https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.26.0/moment.min.js
  4. https://unpkg.com/react-is@16.13.1/umd/react-is.production.min.js
  5. https://cdnjs.cloudflare.com/ajax/libs/styled-components/5.1.0/styled-components.min.js