Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: animated checkbox icons #57

Merged
merged 3 commits into from
Dec 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 19 additions & 36 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,29 @@ 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"
"ink:data-checked:bg-button-primary",
"ink:data-indeterminate:bg-button-primary",
"ink:flex ink:items-center",
"ink:text-button-primary ink:data-checked:text-text-on-primary ink:data-indeterminate:text-text-on-primary"
)}
>
<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:animate-svg-path 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: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
32 changes: 32 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,26 @@
@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.1s;
--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;
}
}
Loading