diff --git a/client/modules/User/components/CollectionItemRow.jsx b/client/modules/User/components/CollectionItemRow.jsx
index e6f3e6d30e..6a6584ccd1 100644
--- a/client/modules/User/components/CollectionItemRow.jsx
+++ b/client/modules/User/components/CollectionItemRow.jsx
@@ -6,6 +6,7 @@ import { useDispatch } from 'react-redux';
import { removeFromCollection } from '../../IDE/actions/collections';
import { formatDateToString } from '../../../utils/formatDate';
import RemoveIcon from '../../../images/close.svg';
+import { Tooltip } from '../../../common/Tooltip';
const CollectionItemRow = ({ collection, item, isOwner }) => {
const { t } = useTranslation();
@@ -48,13 +49,15 @@ const CollectionItemRow = ({ collection, item, isOwner }) => {
{sketchOwnerUsername} |
{isOwner && (
-
+
+
+
)}
|
diff --git a/client/modules/User/components/CollectionItemRow.unit.test.jsx b/client/modules/User/components/CollectionItemRow.unit.test.jsx
new file mode 100644
index 0000000000..933a5e9d07
--- /dev/null
+++ b/client/modules/User/components/CollectionItemRow.unit.test.jsx
@@ -0,0 +1,108 @@
+import React from 'react';
+import thunk from 'redux-thunk';
+import configureStore from 'redux-mock-store';
+import { reduxRender, screen, fireEvent, act } from '../../../test-utils';
+import { initialTestState } from '../../../testData/testReduxStore';
+import CollectionItemRow from './CollectionItemRow';
+
+jest.mock('../../../i18n');
+
+const mockStore = configureStore([thunk]);
+const store = mockStore(initialTestState);
+
+let subjectProps = {
+ collection: {
+ id: 'collection-123',
+ name: 'Test Collection'
+ },
+ item: {
+ createdAt: '2026-01-15T10:30:00.000Z',
+ isDeleted: false,
+ project: {
+ id: 'project-456',
+ name: 'My Sketch',
+ user: { username: 'testuser' },
+ visibility: 'Public'
+ }
+ },
+ isOwner: true
+};
+
+const subject = () => {
+ reduxRender(
+ ,
+ { store }
+ );
+};
+
+describe('', () => {
+ afterEach(() => {
+ store.clearActions();
+ });
+
+ it('renders the sketch name as a link', () => {
+ subject();
+ const link = screen.getByRole('link', { name: 'My Sketch' });
+ expect(link).toBeInTheDocument();
+ expect(link).toHaveAttribute('href', '/testuser/sketches/project-456');
+ });
+
+ it('renders the owner username', () => {
+ subject();
+ expect(screen.getByText('testuser')).toBeInTheDocument();
+ });
+
+ it('shows the remove button when user is the owner', () => {
+ subject();
+ expect(screen.getByRole('button', { name: /remove/i })).toBeInTheDocument();
+ });
+
+ describe('when user is not the owner', () => {
+ beforeAll(() => {
+ subjectProps = { ...subjectProps, isOwner: false };
+ });
+
+ afterAll(() => {
+ subjectProps = { ...subjectProps, isOwner: true };
+ });
+
+ it('does not show the remove button', () => {
+ subject();
+ expect(
+ screen.queryByRole('button', { name: /remove/i })
+ ).not.toBeInTheDocument();
+ });
+ });
+
+ it('wraps the remove button with a tooltip', async () => {
+ subject();
+
+ const button = screen.getByRole('button', { name: /remove/i });
+ await act(async () => {
+ fireEvent.mouseEnter(button);
+ });
+ expect(button).toHaveClass('tooltipped');
+ });
+
+ describe('when the project is deleted', () => {
+ beforeAll(() => {
+ subjectProps = {
+ ...subjectProps,
+ item: {
+ ...subjectProps.item,
+ isDeleted: true,
+ project: undefined
+ }
+ };
+ });
+
+ it('shows the deleted sketch label', () => {
+ subject();
+ expect(screen.getByText('Sketch deleted')).toBeInTheDocument();
+ });
+ });
+});
diff --git a/client/styles/components/_collection.scss b/client/styles/components/_collection.scss
index bc5f9db5db..adfc1caa5c 100644
--- a/client/styles/components/_collection.scss
+++ b/client/styles/components/_collection.scss
@@ -148,6 +148,22 @@
.collection-row__action-column {
width: #{math.div(60, $base-font-size)}rem;
position: relative;
+
+ .tooltip-wrapper {
+ display: inline-flex;
+ width: auto;
+
+ .tooltipped::after {
+ right: 0;
+ left: auto;
+ }
+
+ .tooltipped-n::before,
+ .tooltipped::before {
+ right: #{math.div(10, $base-font-size)}rem;
+ left: auto;
+ }
+ }
}
.collection-row__remove-button {