Skip to content
Open
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
8 changes: 8 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,11 @@ pnpm-debug.log*

# jetbrains setting folder
.idea/

# astro setting folder
.astro/

# Lock file
package-lock.json
yarn.lock
pnpm-lock.yaml
9 changes: 9 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"workbench.colorCustomizations": {
"titleBar.activeForeground": "#283a22",
"titleBar.inactiveForeground": "#82bf72",
"titleBar.activeBackground": "#77bb65",
"titleBar.inactiveBackground": "#49713e"
},
"editor.tabSize": 4
}
40 changes: 20 additions & 20 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,38 +11,38 @@
},
"dependencies": {
"@astrojs/check": "^0.9.4",
"@astrojs/react": "4.1.1",
"@astrojs/starlight": "^0.30.3",
"@astrojs/tailwind": "5.1.3",
"@astrojs/react": "4.1.5",
"@astrojs/starlight": "^0.31.1",
"@astrojs/tailwind": "5.1.4",
"@heroicons/react": "^2.2.0",
"@splinetool/react-spline": "^4.0.0",
"@splinetool/runtime": "^1.9.48",
"@splinetool/runtime": "^1.9.59",
"@types/react": "^18.3.12",
"@types/react-dom": "^18.3.1",
"astro": "5.1.0",
"astro": "5.1.7",
"clsx": "^2.1.1",
"motion": "^11.12.0",
"motion": "^11.18.1",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"tailwindcss": "^3.4.15",
"typescript": "^5.7.2"
"tailwindcss": "^3.4.17",
"typescript": "^5.7.3"
},
"devDependencies": {
"@eslint/js": "^9.15.0",
"@eslint/js": "^9.18.0",
"@phosphor-icons/react": "^2.1.7",
"@typescript-eslint/parser": "^8.16.0",
"eslint": "^9.15.0",
"eslint-config-prettier": "^9.1.0",
"@typescript-eslint/parser": "^8.20.0",
"eslint": "^9.18.0",
"eslint-config-prettier": "^10.0.1",
"eslint-plugin-astro": "^1.3.1",
"eslint-plugin-jsx-a11y": "^6.10.2",
"eslint-plugin-prettier": "^5.2.1",
"eslint-plugin-react": "^7.37.2",
"eslint-plugin-react-hooks": "^5.0.0",
"eslint-plugin-tailwindcss": "^3.17.5",
"prettier": "^3.4.1",
"eslint-plugin-prettier": "^5.2.3",
"eslint-plugin-react": "^7.37.4",
"eslint-plugin-react-hooks": "^5.1.0",
"eslint-plugin-tailwindcss": "^3.18.0",
"prettier": "^3.4.2",
"prettier-plugin-astro": "^0.14.1",
"sass": "^1.81.0",
"tailwind-merge": "^2.5.5",
"typescript-eslint": "^8.16.0"
"sass": "^1.83.4",
"tailwind-merge": "^2.6.0",
"typescript-eslint": "^8.20.0"
}
}
138 changes: 138 additions & 0 deletions src/components/Animations/BackrollCubes/BackrollCubes.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
$grid-size: 5; // sqrt of number of cubes
$cube-size: 4em; // cube edge length
$faces: 6; // number of cube faces
$edges: 4; // number of square edges
$color: #ddd;
$brightness-percent: 10%;
$gap: 0.25 * $cube-size;
$middle: 0.5 * ($grid-size - 1);
$distance: $cube-size + $gap;
$animation-distance: 3 * $distance;
$edge-angle: 360deg/$edges;
$duration: 2.8s;
$breakpoint: 50%/$grid-size;

@mixin background($color, $angle, $percent) {
background: darken($color, (1 - cos($angle)) * $percent);
}

@for $i from 0 through $grid-size {
.animate-backrollcubes-cube:nth-child(n) {
&[data-movement="#{$i}"] {
animation-name: animate-backrollcubes-movement-#{$i};

div:before {
animation-name: animate-backrollcubes-fade-#{$i};
}
}
}

@keyframes animate-backrollcubes-movement-#{$i} {
#{$i * $breakpoint} {
transform: none;
}
#{($i + 2) * $breakpoint}, 100% {
transform: translateZ(-$animation-distance) rotateX($edge-angle);
}
}

@keyframes animate-backrollcubes-fade-#{$i} {
#{$i * $breakpoint} {
opacity: 0.999;
}
#{($i + 2) * $breakpoint}, 100% {
opacity: 0.001;
}
}
}

.animate-backrollcubes-assembly {
position: absolute;
top: 50%;
left: 50%;
transform-style: preserve-3d;
animation: animate-backrollcubes-assembly $duration linear infinite;
}

@keyframes animate-backrollcubes-assembly {
to {
transform: translateZ($animation-distance);
}
}

.animate-backrollcubes-cube {
position: absolute;
top: 50%;
left: 50%;
transform-style: preserve-3d;
animation: animate-backrollcubes-phase $duration cubic-bezier(0.65, 0.05, 0.35, 1) infinite;

@for $i from 0 to $grid-size {
$y: ($i - $middle) * $distance;
$q1: abs($i - $middle);

@for $j from 0 to $grid-size {
$x: ($j - $middle) * $distance;
$idx: $i * $grid-size + $j + 1;
$q2: abs($j - $middle);
$s: $q1 + $q2 + max(0, max($q1, $q2) - 1);

&:nth-child(#{$idx}) {
margin: $y $x;
animation-name: animate-backrollcubes-movement-#{$s};

div:before {
animation-name: animate-backrollcubes-fade-#{$s};
}
}
}
}
}

.animate-backrollcubes-cube__face {
position: absolute;
top: 50%;
left: 50%;
margin: -0.5 * $cube-size;
width: $cube-size;
height: $cube-size;
backface-visibility: hidden;

&:nth-child(-n + 4):before {
position: absolute;
width: inherit;
height: inherit;
animation: animate-backrollcubes-phase $duration ease-in-out infinite;
content: '';
}

&:nth-child(n + 5) {
background: darken($color, 3 * $brightness-percent);
}

@for $i from 0 to $faces {
$angle: $i * $edge-angle;
$prev-angle: ($i - 1) * $edge-angle;

&:nth-child(#{$i + 1}) {
transform: if($i < $edges,
rotateX($angle),
rotateY(pow(-1, $i) * $edge-angle)
) translateZ(0.5 * $cube-size);

@if $i < $edges {
@include background($color, $angle, $brightness-percent);

&:before {
@include background($color, $prev-angle, $brightness-percent);
}
}
}
}
}

@keyframes animate-backrollcubes-phase {
from, to {
transform: none;
}
}
15 changes: 15 additions & 0 deletions src/components/Animations/BackrollCubes/BackrollCubes.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import styles from './BackrollCubes.module.scss';

export const BackrollCubes = () => {
return (
<div className={styles['animate-backrollcubes-assembly']}>
{Array.from({ length: 25 }, (_, i) => (
<div key={i} className={styles['animate-backrollcubes-cube']}>
{Array.from({ length: 6 }, (_, j) => (
<div key={j} className={styles['animate-backrollcubes-cube__face']} />
))}
</div>
))}
</div>
);
};
102 changes: 102 additions & 0 deletions src/components/Animations/CubeAssembly/CubeAssembly.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
$palette: #1c6c3e #dd7ca9; // Using our theme colors
$n-items: 6;
$edge-length: 3.125em;
$inradius: .5 * $edge-length;
$s: .2; // minimum scale factor
$t: .6s; // animation duration
$p: 7%; // difference between face shades

@mixin c($c, $p: $p) {
color: lighten(saturate($c, $p), $p);
}

.wrapper {
width: 100%;
height: 100%;
position: relative;
}

.assembly {
position: absolute;
top: 50%;
left: 50%;
transform-style: preserve-3d;
transform: rotateX(-35deg) rotateY(-45deg) translateZ($inradius);
}

.item {
position: absolute;
margin: -$inradius;
width: $edge-length;
height: $edge-length;
transform-style: preserve-3d;
transform-origin: 50% 50% (-1 * $inradius);
animation: s $t cubic-bezier(.45, .03, .51, .95) infinite alternate;

// Front face
background: currentColor;
box-shadow: 0 0 .125em currentColor;
transform-style: preserve-3d;

// Top face
&:before {
position: absolute;
content: '';
width: 100%;
height: $edge-length;
background: currentColor;
transform: rotateX(90deg) translateY(-100%);
transform-origin: top;
box-shadow: inherit;
}

// Left side face
&:after {
position: absolute;
content: '';
width: $edge-length;
height: 100%;
background: currentColor;
transform: rotateY(-90deg) translateX(-100%);
transform-origin: left;
box-shadow: inherit;
}

// Right side face
div {
position: absolute;
width: $edge-length;
height: 100%;
background: currentColor;
transform: rotateY(90deg) translateX(100%);
transform-origin: right;
box-shadow: inherit;
}

@for $i from 0 through ($n-items - 1) {
$n: $n-items - 1;
$c: mix(nth($palette, 1), nth($palette, 2), $i/$n * 100%);

&:nth-child(#{$i + 1}) {
margin-top: (.5 * $n - $i - .5) * $edge-length;
color: $c;
animation-delay: ($i/$n-items - 1) * 2 * $t;

&:before {
@include c($c, 2 * $p);
}
&:after {
@include c($c);
filter: brightness(0.85);
}
div {
@include c($c);
filter: brightness(0.7);
}
}
}
}

@keyframes s {
to { transform: scale3d($s, $s, $s); }
}
15 changes: 15 additions & 0 deletions src/components/Animations/CubeAssembly/CubeAssembly.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import styles from './CubeAssembly.module.scss';

export const CubeAssembly = () => {
return (
<div className={styles.wrapper}>
<div className={styles.assembly}>
{Array.from({ length: 6 }, (_, index) => (
<div key={index} className={styles.item}>
<div />
</div>
))}
</div>
</div>
);
};
Loading