Skip to content

Instantly share code, notes, and snippets.

@trozzelle
Created April 6, 2023 15:59
Show Gist options
  • Save trozzelle/1a601c48e4adceb1f1df8e7fa429b544 to your computer and use it in GitHub Desktop.
Save trozzelle/1a601c48e4adceb1f1df8e7fa429b544 to your computer and use it in GitHub Desktop.
Countdown Component for Framer Hosted
import { useEffect, useRef } from "react"
import { motion, useInView, useMotionValue, useSpring } from "framer-motion"
import type { ComponentType } from "react"
import { addPropertyControls, ControlType } from "framer"
/**
* These annotations control how your component sizes
* Learn more: https://www.framer.com/docs/guides/auto-sizing
*
* @framerSupportedLayoutWidth auto
* @framerSupportedLayoutHeight auto
*/
export default function Counter({ counterValue, direction, typography }) {
const ref = useRef<HTMLSpanElement>(null)
const countdownValue = counterValue ? counterValue : 100
const motionValue = useMotionValue(
direction === "down" ? countdownValue : 0
)
const springValue = useSpring(motionValue, {
damping: 100,
stiffness: 100,
})
const isInView = useInView(ref, { once: true, margin: "-100px" })
useEffect(() => {
if (isInView) {
motionValue.set(direction === "down" ? 0 : countdownValue)
}
}, [motionValue, isInView])
useEffect(
() =>
springValue.on("change", (latest) => {
if (ref.current) {
ref.current.textContent = Intl.NumberFormat("en-US").format(
latest.toFixed(0)
)
}
}),
[springValue]
)
const itemStyle: React.CSSProperties = {
font: `${typography.weight} ${typography.size}px/1 ${typography.font}`,
color: typography.color,
letterSpacing: typography.letter,
lineHeight: typography.line,
textTransform: typography.transform,
width: "100%",
display: "inline-flex",
flexDirection: "column",
alignItems: "center",
justifyContent: "center",
textAlign: "center",
backdropFilter: `blur(${blur}px)`,
}
// style="color:#000;font-size:72px;"
return (
<motion.div style={itemStyle}>
<span ref={ref} />
</motion.div>
)
}
export function CounterC(props) {}
CounterC.defaultProps = {
value: 0,
direction: "up",
}
addPropertyControls(Counter, {
counterValue: {
title: "Value",
type: ControlType.String,
},
direction: {
title: "Direction",
type: ControlType.Enum,
defaultValue: "up",
options: ["up", "down"],
optionTitles: ["Up", "Down"],
},
typography: {
type: ControlType.Object,
controls: {
font: { type: ControlType.String, defaultValue: "Inter" },
weight: {
type: ControlType.Enum,
defaultValue: "400",
options: [
"200",
"italic 200",
"300",
"italic 300",
"400",
"italic 400",
"500",
"italic 500",
"600",
"italic 600",
"700",
"italic 700",
"800",
"italic 800",
],
optionTitles: [
"Extra Light",
"Extra Light Italic",
"Light",
"Light Italic",
"Regular",
"Italic",
"Medium",
"Medium Italic",
"Semibold",
"Semibold Italic",
"Bold",
"Bold Italic",
"Extra Bold",
"Extra Bold Italic",
],
},
color: {
title: "Color",
type: ControlType.Color,
},
size: {
type: ControlType.Number,
defaultValue: 16,
unit: "px",
step: 1,
displayStepper: true,
},
letter: {
type: ControlType.Number,
defaultValue: 0,
max: 10,
unit: "%",
step: 1,
displayStepper: true,
},
line: {
type: ControlType.Number,
defaultValue: 1,
max: 3,
unit: "em",
step: 0.1,
displayStepper: true,
},
transform: {
type: ControlType.Enum,
defaultValue: "none",
options: ["none", "capitalize", "uppercase", "lowercase"],
optionTitles: ["None", "Capitalize", "Uppercase", "Lowercase"],
},
},
},
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment