Skip to content

Commit f4f592f

Browse files
authored
Merge pull request #2807 from codecrafters-io/arpan/cc-1698-add-rive-animation-for-gleam-icon
Animation on hover w/ Gleam Logo
2 parents 9132652 + 6ad0f70 commit f4f592f

File tree

13 files changed

+260
-2
lines changed

13 files changed

+260
-2
lines changed

app/components/rive-animation.hbs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
<canvas {{did-insert this.handleDidInsert}} {{will-destroy this.handleWillDestroy}} class="w-full h-full block max-w-full" ...attributes></canvas>

app/components/rive-animation.ts

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
import { action } from '@ember/object';
2+
import Component from '@glimmer/component';
3+
import { tracked } from '@glimmer/tracking';
4+
import { Fit, Layout, Rive } from '@rive-app/canvas';
5+
import * as Sentry from '@sentry/ember';
6+
7+
interface Signature {
8+
Element: HTMLCanvasElement;
9+
Args: {
10+
src: string;
11+
};
12+
}
13+
14+
export default class RiveAnimationComponent extends Component<Signature> {
15+
resizeObserver: ResizeObserver | null = null;
16+
@tracked riveInstance: Rive | null = null;
17+
18+
@action
19+
handleDidInsert(element: HTMLCanvasElement) {
20+
// Set up ResizeObserver to handle canvas resizing
21+
this.resizeObserver = new ResizeObserver(() => {
22+
if (this.riveInstance) {
23+
this.riveInstance.resizeDrawingSurfaceToCanvas();
24+
}
25+
});
26+
27+
// Observe the canvas element itself
28+
this.resizeObserver.observe(element);
29+
30+
try {
31+
this.riveInstance = new Rive({
32+
src: this.args.src,
33+
canvas: element,
34+
stateMachines: 'Default',
35+
autoplay: true,
36+
automaticallyHandleEvents: true,
37+
layout: new Layout({
38+
fit: Fit.Contain,
39+
}),
40+
onLoad: async () => {
41+
if (this.riveInstance) {
42+
// Initial resize
43+
this.riveInstance.resizeDrawingSurfaceToCanvas();
44+
}
45+
},
46+
});
47+
} catch (error: unknown) {
48+
console.error('Error setting up Rive:', error);
49+
Sentry.captureException(error);
50+
}
51+
}
52+
53+
@action
54+
handleWillDestroy() {
55+
if (this.resizeObserver) {
56+
this.resizeObserver.disconnect();
57+
this.resizeObserver = null;
58+
}
59+
60+
if (this.riveInstance) {
61+
this.riveInstance.stop();
62+
this.riveInstance = null;
63+
}
64+
}
65+
}
66+
67+
declare module '@glint/environment-ember-loose/registry' {
68+
export default interface Registry {
69+
RiveAnimation: typeof RiveAnimationComponent;
70+
}
71+
}

app/components/track-page/header/index.hbs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,11 @@
66
{{@language.name}}.
77
</h1>
88
<div class="flex md:hidden h-12 w-12 flex-shrink-0">
9-
<LanguageLogo @language={{@language}} @variant="color" class="dark:opacity-90" />
9+
{{#if (eq @language.name "Gleam")}}
10+
<RiveAnimation @src="/assets/animations/gleam_logo_animation.riv" />
11+
{{else}}
12+
<LanguageLogo @language={{@language}} @variant="color" class="dark:opacity-90" />
13+
{{/if}}
1014
</div>
1115
</div>
1216

@@ -54,6 +58,10 @@
5458
{{/if}}
5559
</div>
5660
<div class="ml-4 hidden md:flex h-36 w-36 flex-shrink-0">
57-
<LanguageLogo @language={{@language}} @variant="color" class="dark:opacity-90" />
61+
{{#if (eq @language.name "Gleam")}}
62+
<RiveAnimation @src="/assets/animations/gleam_logo_animation.riv" />
63+
{{else}}
64+
<LanguageLogo @language={{@language}} @variant="color" class="dark:opacity-90" />
65+
{{/if}}
5866
</div>
5967
</div>

app/router.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,5 +111,6 @@ Router.map(function () {
111111
this.route('dark-mode-toggle');
112112
this.route('file-contents-card');
113113
this.route('file-diff-card');
114+
this.route('rive-animation');
114115
});
115116
});

app/routes/demo/rive-animation.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import Route from '@ember/routing/route';
2+
import RouteInfoMetadata, { RouteColorScheme } from 'codecrafters-frontend/utils/route-info-metadata';
3+
4+
export default class DemoRiveAnimationRoute extends Route {
5+
buildRouteInfoMetadata() {
6+
return new RouteInfoMetadata({ colorScheme: RouteColorScheme.Both });
7+
}
8+
}

app/templates/demo.hbs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,16 @@
4949
class={{if (eq this.router.currentRouteName "demo.dark-mode-toggle") "font-medium text-teal-500" "text-gray-600 dark:text-gray-200"}}
5050
>DarkModeToggle</span>
5151
</LinkTo>
52+
<LinkTo
53+
@route="demo.rive-animation"
54+
role="button"
55+
class="flex flex-shrink-0 items-center px-3 py-2 mr-2 border-b-2 text-sm
56+
{{if (eq this.router.currentRouteName 'demo.rive-animation') 'border-teal-500' 'border-gray-100 dark:border-gray-700'}}"
57+
>
58+
<span
59+
class={{if (eq this.router.currentRouteName "demo.rive-animation") "font-medium text-teal-500" "text-gray-600 dark:text-gray-200"}}
60+
>RiveAnimation</span>
61+
</LinkTo>
5262
</div>
5363

5464
{{outlet}}

app/templates/demo/rive-animation.hbs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
{{page-title "Rive Animation Demo"}}
2+
3+
<div class="space-y-8">
4+
<div class="bg-white dark:bg-gray-800 rounded-lg p-6 shadow-sm">
5+
<h2 class="text-xl font-semibold text-gray-700 dark:text-gray-200 mb-4">Default Size</h2>
6+
<div class="flex justify-center h-[400px]">
7+
<RiveAnimation @src="/assets/animations/gleam_logo_animation.riv" />
8+
</div>
9+
</div>
10+
11+
<div class="bg-white dark:bg-gray-800 rounded-lg p-6 shadow-sm">
12+
<h2 class="text-xl font-semibold text-gray-700 dark:text-gray-200 mb-4">Custom Size (200px)</h2>
13+
<div class="flex justify-center h-[200px]">
14+
<RiveAnimation @src="/assets/animations/gleam_logo_animation.riv" />
15+
</div>
16+
</div>
17+
18+
<div class="bg-white dark:bg-gray-800 rounded-lg p-6 shadow-sm">
19+
<h2 class="text-xl font-semibold text-gray-700 dark:text-gray-200 mb-4">Small Size (100px)</h2>
20+
<div class="flex justify-center h-[100px]">
21+
<RiveAnimation @src="/assets/animations/gleam_logo_animation.riv" />
22+
</div>
23+
</div>
24+
25+
{{! Test pig_cuddly.riv }}
26+
<div class="bg-white dark:bg-gray-800 rounded-lg p-6 shadow-sm">
27+
<h2 class="text-xl font-semibold text-gray-700 dark:text-gray-200 mb-4">Test pig_cuddly.riv</h2>
28+
<div class="flex justify-center h-[400px]">
29+
<RiveAnimation @src="/assets/animations/pig_cuddly.riv" />
30+
</div>
31+
</div>
32+
33+
{{! Test capy_walking.riv }}
34+
<div class="bg-white dark:bg-gray-800 rounded-lg p-6 shadow-sm">
35+
<h2 class="text-xl font-semibold text-gray-700 dark:text-gray-200 mb-4">Test capy_walking.riv</h2>
36+
<div class="flex justify-center h-[400px]">
37+
<RiveAnimation @src="/assets/animations/capy_walking.riv" />
38+
</div>
39+
</div>
40+
</div>

package-lock.json

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,7 @@
202202
},
203203
"dependencies": {
204204
"@rails/actioncable": "^8.0.200",
205+
"@rive-app/canvas": "^2.27.0",
205206
"@stripe/stripe-js": "^5.5.0",
206207
"@tailwindcss/container-queries": "^0.1.1",
207208
"@tailwindcss/typography": "^0.5.16",
6.84 KB
Binary file not shown.

0 commit comments

Comments
 (0)