Star Rating Animation - Code
import cn from "classnames";
import styles from "./StarRating.module.scss";
interface RatingStarProps {
id: string;
delayIndex: number;
}
interface RatingRadioProps {
id: string;
}
interface StarRatingAnimationProps {
name?: string;
legend?: string;
className?: string;
}
const RatingStar = ({ id, delayIndex }: RatingStarProps) => (
<label
className={cn(styles.rating__label, styles[`rating__label-${id}`], styles[`rating__label--delay${delayIndex}`])}
htmlFor={`rating-${id}`}
>
<span className="sr-only">{id} stars</span>
<svg className={styles.rating__star} width="32" height="32" viewBox="0 0 32 32" aria-hidden="true">
<g stroke="#C3CCD9" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
<g transform="translate(16,16) rotate(180)">
<polygon
className={styles["rating__star-stroke"]}
points="0,15 4.41,6.07 14.27,4.64 7.13,-2.32 8.82,-12.14 0,-7.5 -8.82,-12.14 -7.13,-2.32 -14.27,4.64 -4.41,6.07"
fill="none"
/>
<polygon
className={styles["rating__star-fill"]}
points="0,15 4.41,6.07 14.27,4.64 7.13,-2.32 8.82,-12.14 0,-7.5 -8.82,-12.14 -7.13,-2.32 -14.27,4.64 -4.41,6.07"
fill="none"
/>
</g>
<g transform="translate(16,16)" strokeDasharray="12 12" strokeDashoffset="12">
<polyline className={styles["rating__star-line"]} transform="rotate(0)" points="0 4,0 16" />
<polyline className={styles["rating__star-line"]} transform="rotate(72)" points="0 4,0 16" />
<polyline className={styles["rating__star-line"]} transform="rotate(144)" points="0 4,0 16" />
<polyline className={styles["rating__star-line"]} transform="rotate(216)" points="0 4,0 16" />
<polyline className={styles["rating__star-line"]} transform="rotate(288)" points="0 4,0 16" />
</g>
</g>
</svg>
</label>
);
const RatingRadio = ({ id }: RatingRadioProps) => (
<input id={`rating-${id}`} className={cn(styles.rating__input, styles[`rating__input-${id}`])} type="radio" name="rating" value={id} />
);
export const StarRatingAnimation = ({ className }: StarRatingAnimationProps) => {
const ratings = ["1", "2", "3", "4", "5"];
return (
<fieldset className={cn(styles.rating, className)}>
<legend className="sr-only">Star rating</legend>
{ratings.map((id) => (
<RatingRadio key={`radio-${id}`} id={id} />
))}
{ratings.map((id, index) => (
<RatingStar key={`star-${id}`} id={id} delayIndex={index} />
))}
</fieldset>
);
};
Star Rating Animation - Preview
3D Media Control Button - Code
import cn from "classnames";
import { useState } from "react";
import styles from "./MediaControlButton.module.scss";
interface MediaControlButtonProps {
iconType: "pause" | "stop";
}
export const MediaControlButton = ({ iconType }: MediaControlButtonProps) => {
const [isActive, setIsActive] = useState(true);
const iconDivCount = iconType === "pause" ? 4 : 2;
const handleClick = () => {
setIsActive(!isActive);
};
return (
<button
type="button"
onClick={handleClick}
aria-pressed={isActive}
aria-label={iconType === "pause" ? (isActive ? "Pause media" : "Play media") : isActive ? "Stop media" : "Start media"}
className={cn(styles["media-control-button"], {
[styles["media-control-button--active"]]: isActive,
[styles["media-control-button--pause-style"]]: iconType === "pause",
[styles["media-control-button--stop-style"]]: iconType === "stop",
})}
>
<div
className={cn(styles["icon-wrapper"], {
[styles["icon-wrapper--active"]]: isActive,
})}
>
{Array.from({ length: iconDivCount }).map((_, index) => (
<div
key={`${iconType}-${index + 1}`}
className={cn(styles.icon, {
[styles["icon--pause-style"]]: iconType === "pause",
[styles["icon--stop-style"]]: iconType === "stop",
})}
/>
))}
</div>
</button>
);
};
3D Media Control Button - Preview
Text Field with Floating Label - Code
import cn from "classnames";
import { useState } from "react";
import styles from "./TextFieldWithFloatingLabel.module.scss";
export const TextFieldWithFloatingLabel = () => {
const [value, setValue] = useState("");
const [isValid, setIsValid] = useState(true);
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const newValue = e.target.value;
setValue(newValue);
const phonePattern = /^[0-9\s\-\(\)\+]*$/;
setIsValid(phonePattern.test(newValue));
};
const hasValue = value.length > 0;
return (
<div
className={cn(styles.textfield, {
[styles["textfield--has-value"]]: hasValue,
[styles["textfield--is-invalid"]]: !isValid,
})}
>
<label
className={cn(styles.textfield__label, {
[styles["textfield__label--has-value"]]: hasValue,
[styles["textfield__label--is-invalid"]]: !isValid,
})}
htmlFor="phone-input"
>
Phone
</label>
<div className={styles.textfield__inputWrapper}>
<input
id="phone-input"
type="tel"
className={cn(styles.textfield__input, {
[styles["textfield__input--has-value"]]: hasValue,
[styles["textfield__input--is-invalid"]]: !isValid,
})}
value={value}
onChange={handleChange}
aria-invalid={!isValid}
placeholder=""
/>
</div>
<p className={cn(styles["help-text"], !isValid && styles["help-text--error"])}>
{isValid && "Please enter your phone number"}
{!isValid && (
<>
<i className="fa-solid fa-circle-exclamation" /> Letters are not allowed in phone numbers
</>
)}
</p>
</div>
);
};
Text Field with Floating Label - Preview
Please enter your phone number
More Examples Coming Soon
Stay tuned for more interactive components, animations, and code snippets.