Skip to content

Commit

Permalink
feat: animated checkbox icons
Browse files Browse the repository at this point in the history
  • Loading branch information
fran-ink committed Dec 4, 2024
1 parent 1d3a19d commit d6bb7f2
Show file tree
Hide file tree
Showing 6 changed files with 52 additions and 35 deletions.
48 changes: 15 additions & 33 deletions src/components/Checkbox/Checkbox.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Checkbox as HeadlessCheckbox } from "@headlessui/react";
import { classNames } from "../../util/classes";
import { InkIcon } from "../..";

export interface CheckboxProps {
checked: boolean;
Expand All @@ -20,47 +21,28 @@ export const Checkbox: React.FC<CheckboxProps> = ({
className={classNames(
"ink:group ink:relative ink:flex ink:items-center ink:justify-center ink:size-3 ink:shrink-0 ink:cursor-pointer ink:rounded-xs ink:box-border",
"ink:transition-colors ink:transition-default-animation",
"ink:border-2 ink:border-transparent ink:bg-background-container ink:shadow-xs",
"ink:bg-background-container ink:shadow-xs",
"ink:ring-text-on-secondary ink:focus-visible:outline-none ink:focus-visible:text-on-primary ink:focus-visible:ring-2 ink:focus-visible:ring-offset-2",
"ink:data-checked:bg-button-primary ink:data-checked:hover:bg-button-primary-hover",
"ink:data-indeterminate:bg-button-primary ink:data-indeterminate:hover:bg-button-primary-hover",
"ink:flex ink:items-center"
)}
>
<div className="ink:absolute ink:inset-0 ink:flex ink:items-center ink:justify-center">
{/** See if those SVGs should be icons in our standard icon library. */}
<svg
className="ink:size-1.5 ink:text-text-on-primary ink:group-data-indeterminate:opacity-0 ink:transition-opacity ink:transition-default-animation ink:opacity-100 ink:starting:opacity-0"
width="12"
height="12"
viewBox="0 0 12 12"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M11.5905 0.748484C12.0362 1.07459 12.1332 1.70028 11.8071 2.14601L5.30384 11.0349C5.14317 11.2545 4.89996 11.3992 4.6303 11.4355C4.36064 11.4718 4.08781 11.3967 3.87476 11.2274L0.378025 8.44967C-0.0544173 8.10614 -0.126496 7.47709 0.217033 7.04465C0.560562 6.6122 1.18961 6.54013 1.62205 6.88365L4.30408 9.01423L10.193 0.965086C10.5191 0.519357 11.1448 0.422381 11.5905 0.748484Z"
fill="currentColor"
/>
</svg>
<div className="ink:absolute ink:inset-0 ink:flex ink:items-center ink:justify-center ink:box-border">
<InkIcon.Check
className={classNames(
"ink:size-3 ink:text-text-on-primary",
"ink:animate-svg-path ink:group-hover:not-in-data-indeterminate:animate-svg-path-start ink:in-data-checked:not-in-data-indeterminate:animate-svg-path-start"
)}
/>
</div>

<svg
className="ink:size-1.5 ink:text-text-on-primary ink:group-not-data-indeterminate:opacity-0 ink:transition-opacity ink:transition-default-animation ink:opacity-100 ink:starting:opacity-0"
width="12"
height="2"
viewBox="0 0 12 2"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M0 1C0 0.447715 0.447715 0 1 0H11C11.5523 0 12 0.447715 12 1C12 1.55228 11.5523 2 11 2H1C0.447715 2 0 1.55228 0 1Z"
fill="currentColor"
/>
</svg>
<InkIcon.Minus
className={classNames(
"ink:size-3 ink:text-text-on-primary",
"ink:animate-svg-path ink:in-data-indeterminate:animate-svg-path-start"
)}
/>
</HeadlessCheckbox>
);
};
2 changes: 1 addition & 1 deletion src/components/FieldLabel/FieldLabel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export const FieldLabel: React.FC<FieldLabelProps> = ({
children,
}) => {
return (
<Field className="ink:flex ink:flex-col ink:font-default">
<Field className="ink:flex ink:flex-col ink:font-default ink:group">
<div className="ink:flex ink:items-center ink:gap-1">
{children}
<Label className="ink:cursor-pointer ink:h-3 ink:flex ink:items-center ink:justify-center ink:text-body-2 ink:text-text-default">
Expand Down
2 changes: 1 addition & 1 deletion src/icons/Type=Check.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions src/icons/Type=Minus.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions src/icons/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export { default as Error } from "./Type=Error.svg?react";
export { default as Home } from "./Type=Home.svg?react";
export { default as Loading } from "./Type=Loading.svg?react";
export { default as Menu } from "./Type=Menu.svg?react";
export { default as Minus } from "./Type=Minus.svg?react";
export { default as Moon } from "./Type=Moon.svg?react";
export { default as Profile } from "./Type=Profile.svg?react";
export { default as Search } from "./Type=Search.svg?react";
Expand Down
31 changes: 31 additions & 0 deletions src/tailwind.css
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,15 @@
/** Required for Safari to have proper font weights */
font-synthesis: none;
}

@keyframes svg-path-dash {
from {
stroke-dashoffset: var(--svg-path-dash-offset);
}
to {
stroke-dashoffset: 0;
}
}
}

@theme {
Expand Down Expand Up @@ -177,3 +186,25 @@
@utility transition-default-animation {
@apply ink:duration-200 ink:ease-in-out;
}

/**
* For this animation to work, the SVG path must have a stroke attribute.
* Set `animate-svg-path` on the Icon element, then apply `animate-svg-path-start` when you want the animation to play (e.g. on hover).
*/
@utility animate-svg-path {
--svg-path-dash-duration: 0.25s;
--svg-path-dash-offset: 24;
--svg-path-dash-delay: 0.2s;
--svg-path-dash-easing: ease-in-out;

> path[stroke] {
stroke-dasharray: var(--svg-path-dash-offset);
stroke-dashoffset: var(--svg-path-dash-offset);
}
}

@utility animate-svg-path-start {
> path[stroke] {
animation: svg-path-dash var(--svg-path-dash-duration) var(--svg-path-dash-delay) var(--svg-path-dash-easing) forwards;
}
}

0 comments on commit d6bb7f2

Please sign in to comment.