diff --git a/packages/shared/src/components/cards/squad/SquadList.tsx b/packages/shared/src/components/cards/squad/SquadList.tsx
index 76215eab919..a8b9294fa45 100644
--- a/packages/shared/src/components/cards/squad/SquadList.tsx
+++ b/packages/shared/src/components/cards/squad/SquadList.tsx
@@ -40,7 +40,7 @@ export const SquadList = ({
return (
,
};
}) ?? [];
diff --git a/packages/shared/src/components/squads/SquadFavoriteButton.spec.tsx b/packages/shared/src/components/squads/SquadFavoriteButton.spec.tsx
new file mode 100644
index 00000000000..f0c0eefc5d8
--- /dev/null
+++ b/packages/shared/src/components/squads/SquadFavoriteButton.spec.tsx
@@ -0,0 +1,75 @@
+import React from 'react';
+import { render, screen } from '@testing-library/react';
+import userEvent from '@testing-library/user-event';
+import { SquadFavoriteButton } from './SquadFavoriteButton';
+import { useSquadFavorite } from '../../hooks/squads/useSquadFavorite';
+import { generateTestSquad } from '../../../__tests__/fixture/squads';
+import type { Squad } from '../../graphql/sources';
+
+jest.mock('../../hooks/squads/useSquadFavorite', () => ({
+ useSquadFavorite: jest.fn(),
+}));
+
+const toggleFavorite = jest.fn();
+
+const renderButton = (overrides: Partial = {}) =>
+ render();
+
+describe('SquadFavoriteButton', () => {
+ beforeEach(() => {
+ jest.clearAllMocks();
+ jest.mocked(useSquadFavorite).mockReturnValue({
+ toggleFavorite,
+ isPending: false,
+ });
+ });
+
+ it('renders an unpressed star with the correct aria label when not favorited', () => {
+ renderButton({ favoritedAt: null });
+
+ const button = screen.getByRole('button', { name: 'Favorite squad' });
+ expect(button).toBeInTheDocument();
+ expect(button).toHaveAttribute('aria-pressed', 'false');
+ });
+
+ it('renders a pressed star with the unfavorite aria label when favorited', () => {
+ renderButton({ favoritedAt: '2025-01-01T00:00:00.000Z' });
+
+ const button = screen.getByRole('button', { name: 'Unfavorite squad' });
+ expect(button).toBeInTheDocument();
+ expect(button).toHaveAttribute('aria-pressed', 'true');
+ });
+
+ it('calls toggleFavorite with the squad when clicked', async () => {
+ const squad = generateTestSquad({ favoritedAt: null });
+ render();
+
+ await userEvent.click(
+ screen.getByRole('button', { name: 'Favorite squad' }),
+ );
+
+ expect(toggleFavorite).toHaveBeenCalledWith(squad);
+ });
+
+ it('applies hover-reveal classes when the squad is not favorited', () => {
+ renderButton({ favoritedAt: null });
+
+ const button = screen.getByRole('button', { name: 'Favorite squad' });
+ expect(button).toHaveClass('laptop:opacity-0');
+ expect(button).toHaveClass('laptop:group-hover/squad-row:opacity-100');
+ expect(button).toHaveClass(
+ 'laptop:group-focus-within/squad-row:opacity-100',
+ );
+ });
+
+ it('does not apply hover-reveal classes when the squad is already favorited', () => {
+ renderButton({ favoritedAt: '2025-01-01T00:00:00.000Z' });
+
+ const button = screen.getByRole('button', { name: 'Unfavorite squad' });
+ expect(button).not.toHaveClass('laptop:opacity-0');
+ expect(button).not.toHaveClass('laptop:group-hover/squad-row:opacity-100');
+ expect(button).not.toHaveClass(
+ 'laptop:group-focus-within/squad-row:opacity-100',
+ );
+ });
+});
diff --git a/packages/shared/src/components/squads/SquadFavoriteButton.tsx b/packages/shared/src/components/squads/SquadFavoriteButton.tsx
index 80138ee553f..ae54876b1da 100644
--- a/packages/shared/src/components/squads/SquadFavoriteButton.tsx
+++ b/packages/shared/src/components/squads/SquadFavoriteButton.tsx
@@ -38,6 +38,8 @@ export const SquadFavoriteButton = ({
onClick={onClick}
className={classNames(
'relative z-1 flex items-center justify-center disabled:opacity-50',
+ !isFavorited &&
+ 'laptop:opacity-0 laptop:transition-opacity laptop:group-focus-within/squad-row:opacity-100 laptop:group-hover/squad-row:opacity-100',
className,
)}
>