#app
View Compiled
*
box-sizing border-box
body
min-height 100vh
background linear-gradient(45deg, hsl(0, 0%, 15%), hsl(0, 0%, 70%))
#app
display flex
flex-direction column
align-items center
justify-content center
min-height 100vh
font-size 2rem
font-family sans-serif
& > div
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(245, 229, 27, .25)
--strapBg rgba(254, 241, 96, 1)
View Compiled
const {
React,
React: { 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 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)};
`
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>
)
}
render(<Watch face={AnalogFace} />, ROOT)
View Compiled
This Pen doesn't use any external CSS resources.