From 8680aaecf122266dd10acf0215371539487583ce Mon Sep 17 00:00:00 2001 From: fabrice-akamai Date: Fri, 26 Sep 2025 10:40:03 -0400 Subject: [PATCH 01/12] Added missing padding around the Managed dashboard card --- .../Managed/ManagedDashboardCard/ManagedDashboardCard.styles.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/manager/src/features/Managed/ManagedDashboardCard/ManagedDashboardCard.styles.tsx b/packages/manager/src/features/Managed/ManagedDashboardCard/ManagedDashboardCard.styles.tsx index aac50be3668..37a315b01a3 100644 --- a/packages/manager/src/features/Managed/ManagedDashboardCard/ManagedDashboardCard.styles.tsx +++ b/packages/manager/src/features/Managed/ManagedDashboardCard/ManagedDashboardCard.styles.tsx @@ -18,6 +18,7 @@ export const StyledOuterContainerGrid = styled(Grid, { background: theme.bg.bgPaper, flexDirection: 'column', margin: '-8px', + padding: theme.spacing(2), [theme.breakpoints.up('sm')]: { flexDirection: 'row', flexWrap: 'nowrap', From d53e3f63d283531199921ea176b39e57633f6131 Mon Sep 17 00:00:00 2001 From: fabrice-akamai Date: Fri, 26 Sep 2025 13:46:44 -0400 Subject: [PATCH 02/12] changed spacing to spacingFunction --- .../ManagedDashboardCard/ManagedDashboardCard.styles.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/manager/src/features/Managed/ManagedDashboardCard/ManagedDashboardCard.styles.tsx b/packages/manager/src/features/Managed/ManagedDashboardCard/ManagedDashboardCard.styles.tsx index 37a315b01a3..9d03064cd63 100644 --- a/packages/manager/src/features/Managed/ManagedDashboardCard/ManagedDashboardCard.styles.tsx +++ b/packages/manager/src/features/Managed/ManagedDashboardCard/ManagedDashboardCard.styles.tsx @@ -18,7 +18,7 @@ export const StyledOuterContainerGrid = styled(Grid, { background: theme.bg.bgPaper, flexDirection: 'column', margin: '-8px', - padding: theme.spacing(2), + padding: theme.spacingFunction(12), [theme.breakpoints.up('sm')]: { flexDirection: 'row', flexWrap: 'nowrap', From 408d904b85039e4dbfb55dd9e2960c2874886a41 Mon Sep 17 00:00:00 2001 From: fabrice-akamai Date: Tue, 31 Mar 2026 12:22:44 -0400 Subject: [PATCH 03/12] Implement basic sharegroup create form --- .../ShareGroupsCreate.test.tsx | 140 ++++++++++++++++++ .../ShareGroupsCreate/ShareGroupsCreate.tsx | 122 +++++++++++++++ .../ShareGroupsCreateContainer.tsx | 24 +++ .../ShareGroupsCreateLazyRoute.tsx | 9 ++ packages/manager/src/routes/images/index.ts | 10 ++ packages/queries/src/images/sharegroups.ts | 27 +++- 6 files changed, 331 insertions(+), 1 deletion(-) create mode 100644 packages/manager/src/features/Images/ImagesLanding/v2/ShareGroups/ShareGroupsCreate/ShareGroupsCreate.test.tsx create mode 100644 packages/manager/src/features/Images/ImagesLanding/v2/ShareGroups/ShareGroupsCreate/ShareGroupsCreate.tsx create mode 100644 packages/manager/src/features/Images/ImagesLanding/v2/ShareGroups/ShareGroupsCreate/ShareGroupsCreateContainer.tsx create mode 100644 packages/manager/src/features/Images/ImagesLanding/v2/ShareGroups/ShareGroupsCreate/ShareGroupsCreateLazyRoute.tsx diff --git a/packages/manager/src/features/Images/ImagesLanding/v2/ShareGroups/ShareGroupsCreate/ShareGroupsCreate.test.tsx b/packages/manager/src/features/Images/ImagesLanding/v2/ShareGroups/ShareGroupsCreate/ShareGroupsCreate.test.tsx new file mode 100644 index 00000000000..1230675017b --- /dev/null +++ b/packages/manager/src/features/Images/ImagesLanding/v2/ShareGroups/ShareGroupsCreate/ShareGroupsCreate.test.tsx @@ -0,0 +1,140 @@ +import { imageSharegroupFactory } from '@linode/utilities'; +import { userEvent } from '@testing-library/user-event'; +import React from 'react'; + +import { renderWithTheme } from 'src/utilities/testHelpers'; + +import { ShareGroupsCreate } from './ShareGroupsCreate'; + +const queryMocks = vi.hoisted(() => ({ + useCreateShareGroupMutation: vi.fn().mockReturnValue({}), + useNavigate: vi.fn().mockReturnValue(vi.fn()), +})); + +vi.mock('@linode/queries', async () => { + const actual = await vi.importActual('@linode/queries'); + return { + ...actual, + useCreateShareGroupMutation: queryMocks.useCreateShareGroupMutation, + }; +}); + +vi.mock('@tanstack/react-router', async () => { + const actual = await vi.importActual('@tanstack/react-router'); + return { + ...actual, + useNavigate: queryMocks.useNavigate, + }; +}); + +describe('ShareGroupsCreate', () => { + let mockNavigate: ReturnType; + let mockMutateAsync: ReturnType; + + beforeEach(() => { + mockNavigate = vi.fn(); + mockMutateAsync = vi.fn(); + + queryMocks.useNavigate.mockReturnValue(mockNavigate); + queryMocks.useCreateShareGroupMutation.mockReturnValue({ + mutateAsync: mockMutateAsync, + isLoading: false, + error: null, + }); + }); + + afterEach(() => { + vi.clearAllMocks(); + }); + + it('should render the form with all fields, titles, and buttons in their default state', () => { + const { getByRole, getByText } = renderWithTheme(); + + expect(getByText('Share group details')).toBeVisible(); + expect(getByText('Images')).toBeVisible(); + expect(getByText('Selected images (0)')).toBeVisible(); + + expect( + getByText( + 'Add a name and description for your share group. These details are visible to all group members.' + ) + ).toBeVisible(); + + const labelField = getByRole('textbox', { name: /Label/i }); + expect(labelField).toBeVisible(); + expect(labelField).toHaveValue(''); + + const descriptionField = getByRole('textbox', { name: /Description/i }); + expect(descriptionField).toBeVisible(); + expect(descriptionField).toHaveValue(''); + + const submitButton = getByText('Create Share Group').closest('button'); + expect(submitButton).toBeVisible(); + expect(submitButton).toBeEnabled(); + }); + + it('should submit the form with valid data', async () => { + const shareGroup = imageSharegroupFactory.build(); + + mockMutateAsync.mockResolvedValue(shareGroup); + + const { getByRole, getByText } = renderWithTheme(); + + const labelField = getByRole('textbox', { name: /Label/i }); + const descriptionField = getByRole('textbox', { name: /Description/i }); + const submitButton = getByText('Create Share Group').closest('button'); + + await userEvent.type(labelField, 'My Share Group'); + await userEvent.type(descriptionField, 'Test Description'); + await userEvent.click(submitButton!); + + expect(mockMutateAsync).toHaveBeenCalledWith({ + label: 'My Share Group', + description: 'Test Description', + }); + + expect(mockNavigate).toHaveBeenCalledWith({ + search: expect.any(Function), + to: '/images/share-groups', + }); + }); + + it('should submit the form with only label (description is optional)', async () => { + const shareGroup = imageSharegroupFactory.build(); + + mockMutateAsync.mockResolvedValue(shareGroup); + + const { getByRole, getByText } = renderWithTheme(); + + const labelField = getByRole('textbox', { name: /Label/i }); + const submitButton = getByText('Create Share Group').closest('button'); + + await userEvent.type(labelField, 'My Share Group'); + await userEvent.click(submitButton!); + + expect(mockMutateAsync).toHaveBeenCalledWith({ + label: 'My Share Group', + }); + }); + + it('should display field-specific errors from API', async () => { + const apiError = [ + { + field: 'label', + reason: 'Label must be unique', + }, + ]; + + mockMutateAsync.mockRejectedValue(apiError); + + const { getByRole, getByText } = renderWithTheme(); + + const labelField = getByRole('textbox', { name: /Label/i }); + const submitButton = getByText('Create Share Group').closest('button'); + + await userEvent.type(labelField, 'Duplicate Label'); + await userEvent.click(submitButton!); + + expect(getByText('Label must be unique')).toBeVisible(); + }); +}); diff --git a/packages/manager/src/features/Images/ImagesLanding/v2/ShareGroups/ShareGroupsCreate/ShareGroupsCreate.tsx b/packages/manager/src/features/Images/ImagesLanding/v2/ShareGroups/ShareGroupsCreate/ShareGroupsCreate.tsx new file mode 100644 index 00000000000..22669ea0d9d --- /dev/null +++ b/packages/manager/src/features/Images/ImagesLanding/v2/ShareGroups/ShareGroupsCreate/ShareGroupsCreate.tsx @@ -0,0 +1,122 @@ +import { useCreateShareGroupMutation } from '@linode/queries'; +import { + Box, + Button, + Divider, + Notice, + Paper, + Stack, + TextField, + Typography, +} from '@linode/ui'; +import { useNavigate } from '@tanstack/react-router'; +import { useSnackbar } from 'notistack'; +import * as React from 'react'; +import { Controller, useForm } from 'react-hook-form'; + +import type { CreateSharegroupPayload } from '@linode/api-v4'; + +export const ShareGroupsCreate = () => { + const navigate = useNavigate(); + + const { mutateAsync: createShareGroup } = useCreateShareGroupMutation(); + + const { enqueueSnackbar } = useSnackbar(); + + const { control, handleSubmit, setError } = + useForm(); + + const selectedImages = []; + + const onSubmit = handleSubmit(async (values) => { + try { + await createShareGroup(values); + + enqueueSnackbar('Sharegroup scheduled for creation', { + variant: 'info', + }); + + navigate({ + search: () => ({}), + to: '/images/share-groups', + }); + } catch (errors) { + for (const error of errors) { + if (error.field) { + setError(error.field, { message: error.reason }); + } else { + setError('root', { message: error.reason }); + } + } + } + }); + return ( +
+ + + Share group details + + Add a name and description for your share group. These details are + visible to all group members. + + ( + + field.onChange( + e.target.value === '' ? undefined : e.target.value + ) + } + value={field.value ?? ''} + /> + )} + /> + ( + + field.onChange( + e.target.value === '' ? undefined : e.target.value + ) + } + rows={1} + value={field.value ?? ''} + /> + )} + /> + + + + Images + Images table is coming soon... + + + + + Selected images ({selectedImages.length}) + + Selected images is coming soon... + + + + + +
+ ); +}; diff --git a/packages/manager/src/features/Images/ImagesLanding/v2/ShareGroups/ShareGroupsCreate/ShareGroupsCreateContainer.tsx b/packages/manager/src/features/Images/ImagesLanding/v2/ShareGroups/ShareGroupsCreate/ShareGroupsCreateContainer.tsx new file mode 100644 index 00000000000..2c298112a3b --- /dev/null +++ b/packages/manager/src/features/Images/ImagesLanding/v2/ShareGroups/ShareGroupsCreate/ShareGroupsCreateContainer.tsx @@ -0,0 +1,24 @@ +import Grid from '@mui/material/Grid'; +import * as React from 'react'; + +import { DocumentTitleSegment } from 'src/components/DocumentTitle/DocumentTitle'; +import { LandingHeader } from 'src/components/LandingHeader/LandingHeader'; + +import { ShareGroupsCreate } from './ShareGroupsCreate'; + +export const ShareGroupsCreateContainer = () => { + return ( + <> + + + + + + + ); +}; diff --git a/packages/manager/src/features/Images/ImagesLanding/v2/ShareGroups/ShareGroupsCreate/ShareGroupsCreateLazyRoute.tsx b/packages/manager/src/features/Images/ImagesLanding/v2/ShareGroups/ShareGroupsCreate/ShareGroupsCreateLazyRoute.tsx new file mode 100644 index 00000000000..5cd1ac095fe --- /dev/null +++ b/packages/manager/src/features/Images/ImagesLanding/v2/ShareGroups/ShareGroupsCreate/ShareGroupsCreateLazyRoute.tsx @@ -0,0 +1,9 @@ +import { createLazyRoute } from '@tanstack/react-router'; + +import { ShareGroupsCreateContainer } from './ShareGroupsCreateContainer'; + +export const shareGroupsCreateLazyRoute = createLazyRoute( + '/images/share-groups/create' +)({ + component: ShareGroupsCreateContainer, +}); diff --git a/packages/manager/src/routes/images/index.ts b/packages/manager/src/routes/images/index.ts index 0e48c5b2c2a..0d566188a0f 100644 --- a/packages/manager/src/routes/images/index.ts +++ b/packages/manager/src/routes/images/index.ts @@ -315,6 +315,15 @@ const shareGroupsTypeRoute = createRoute({ validateSearch: (search: ImagesSearchParams) => search, }); +const shareGroupsCreateRoute = createRoute({ + getParentRoute: () => imagesRoute, + path: 'share-groups/create', +}).lazy(() => + import( + 'src/features/Images/ImagesLanding/v2/ShareGroups/ShareGroupsCreate/ShareGroupsCreateLazyRoute' + ).then((m) => m.shareGroupsCreateLazyRoute) +); + export const imagesRouteTree = imagesRoute.addChildren([ imagesIndexRoute.addChildren([imageActionRoute]), imageLibraryLandingRoute.addChildren([ @@ -324,6 +333,7 @@ export const imagesRouteTree = imagesRoute.addChildren([ ]), shareGroupsLandingRoute.addChildren([ shareGroupsIndexRoute.addChildren([shareGroupsTypeRoute]), + shareGroupsCreateRoute, ]), imagesCreateRoute.addChildren([ imagesCreateIndexRoute, diff --git a/packages/queries/src/images/sharegroups.ts b/packages/queries/src/images/sharegroups.ts index e03fc06eb1c..655cce4f495 100644 --- a/packages/queries/src/images/sharegroups.ts +++ b/packages/queries/src/images/sharegroups.ts @@ -1,14 +1,21 @@ -import { getSharegroup, getSharegroups } from '@linode/api-v4'; +import { + createSharegroup, + getSharegroup, + getSharegroups, +} from '@linode/api-v4'; import { getAll } from '@linode/utilities'; import { createQueryKeys } from '@lukemorales/query-key-factory'; import { keepPreviousData, useInfiniteQuery, + useMutation, useQuery, + useQueryClient, } from '@tanstack/react-query'; import type { APIError, + CreateSharegroupPayload, Filter, Params, ResourcePage, @@ -95,3 +102,21 @@ export const useShareGroupsInfiniteQuery = ( initialPageParam: 1, retry: false, }); + +export const useCreateShareGroupMutation = () => { + const queryclient = useQueryClient(); + + return useMutation({ + mutationFn: createSharegroup, + onSuccess(shareGroup) { + queryclient.invalidateQueries({ + queryKey: shareGroupsQueries.sharegroups._ctx.paginated._def, + }); + queryclient.setQueryData( + shareGroupsQueries.sharegroups._ctx.sharegroup(shareGroup.id.toString()) + .queryKey, + shareGroup, + ); + }, + }); +}; From 1befb7354f5935d8929a1271af45a4eddd35dd97 Mon Sep 17 00:00:00 2001 From: fabrice-akamai Date: Tue, 31 Mar 2026 12:28:01 -0400 Subject: [PATCH 04/12] Added changeset: Implement the basic share group create page --- .../.changeset/pr-13550-upcoming-features-1774974481770.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 packages/manager/.changeset/pr-13550-upcoming-features-1774974481770.md diff --git a/packages/manager/.changeset/pr-13550-upcoming-features-1774974481770.md b/packages/manager/.changeset/pr-13550-upcoming-features-1774974481770.md new file mode 100644 index 00000000000..f10eb8d3673 --- /dev/null +++ b/packages/manager/.changeset/pr-13550-upcoming-features-1774974481770.md @@ -0,0 +1,5 @@ +--- +"@linode/manager": Upcoming Features +--- + +Implement the basic share group create page ([#13550](https://github.com/linode/manager/pull/13550)) From 2c3f4dc246ab84870327e9f00f647d101a8d14e9 Mon Sep 17 00:00:00 2001 From: fabrice-akamai Date: Tue, 31 Mar 2026 13:03:44 -0400 Subject: [PATCH 05/12] update unit test --- .../ShareGroupsCreate.test.tsx | 33 ++++++++++--------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/packages/manager/src/features/Images/ImagesLanding/v2/ShareGroups/ShareGroupsCreate/ShareGroupsCreate.test.tsx b/packages/manager/src/features/Images/ImagesLanding/v2/ShareGroups/ShareGroupsCreate/ShareGroupsCreate.test.tsx index 1230675017b..88df9069ac9 100644 --- a/packages/manager/src/features/Images/ImagesLanding/v2/ShareGroups/ShareGroupsCreate/ShareGroupsCreate.test.tsx +++ b/packages/manager/src/features/Images/ImagesLanding/v2/ShareGroups/ShareGroupsCreate/ShareGroupsCreate.test.tsx @@ -28,6 +28,9 @@ vi.mock('@tanstack/react-router', async () => { }); describe('ShareGroupsCreate', () => { + const shareGroupLabel = 'My Share Group'; + const shareGroupDescription = 'Test Description'; + let mockNavigate: ReturnType; let mockMutateAsync: ReturnType; @@ -68,7 +71,7 @@ describe('ShareGroupsCreate', () => { expect(descriptionField).toBeVisible(); expect(descriptionField).toHaveValue(''); - const submitButton = getByText('Create Share Group').closest('button'); + const submitButton = getByRole('button', { name: /Create Share Group/i }); expect(submitButton).toBeVisible(); expect(submitButton).toBeEnabled(); }); @@ -78,19 +81,19 @@ describe('ShareGroupsCreate', () => { mockMutateAsync.mockResolvedValue(shareGroup); - const { getByRole, getByText } = renderWithTheme(); + const { getByRole } = renderWithTheme(); const labelField = getByRole('textbox', { name: /Label/i }); const descriptionField = getByRole('textbox', { name: /Description/i }); - const submitButton = getByText('Create Share Group').closest('button'); + const submitButton = getByRole('button', { name: /Create Share Group/i }); - await userEvent.type(labelField, 'My Share Group'); - await userEvent.type(descriptionField, 'Test Description'); - await userEvent.click(submitButton!); + await userEvent.type(labelField, shareGroupLabel); + await userEvent.type(descriptionField, shareGroupDescription); + await userEvent.click(submitButton); expect(mockMutateAsync).toHaveBeenCalledWith({ - label: 'My Share Group', - description: 'Test Description', + label: shareGroupLabel, + description: shareGroupDescription, }); expect(mockNavigate).toHaveBeenCalledWith({ @@ -104,16 +107,16 @@ describe('ShareGroupsCreate', () => { mockMutateAsync.mockResolvedValue(shareGroup); - const { getByRole, getByText } = renderWithTheme(); + const { getByRole } = renderWithTheme(); const labelField = getByRole('textbox', { name: /Label/i }); - const submitButton = getByText('Create Share Group').closest('button'); + const submitButton = getByRole('button', { name: /Create Share Group/i }); - await userEvent.type(labelField, 'My Share Group'); - await userEvent.click(submitButton!); + await userEvent.type(labelField, shareGroupLabel); + await userEvent.click(submitButton); expect(mockMutateAsync).toHaveBeenCalledWith({ - label: 'My Share Group', + label: shareGroupLabel, }); }); @@ -130,10 +133,10 @@ describe('ShareGroupsCreate', () => { const { getByRole, getByText } = renderWithTheme(); const labelField = getByRole('textbox', { name: /Label/i }); - const submitButton = getByText('Create Share Group').closest('button'); + const submitButton = getByRole('button', { name: /Create Share Group/i }); await userEvent.type(labelField, 'Duplicate Label'); - await userEvent.click(submitButton!); + await userEvent.click(submitButton); expect(getByText('Label must be unique')).toBeVisible(); }); From 007e94dc945b6239f8fba8cf90d01e723513811a Mon Sep 17 00:00:00 2001 From: fabrice-akamai Date: Tue, 31 Mar 2026 14:41:37 -0400 Subject: [PATCH 06/12] Update packages/manager/.changeset/pr-13550-upcoming-features-1774974481770.md Co-authored-by: Dajahi Wiley <114682940+dwiley-akamai@users.noreply.github.com> --- .../.changeset/pr-13550-upcoming-features-1774974481770.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/manager/.changeset/pr-13550-upcoming-features-1774974481770.md b/packages/manager/.changeset/pr-13550-upcoming-features-1774974481770.md index f10eb8d3673..0dee27b3bb8 100644 --- a/packages/manager/.changeset/pr-13550-upcoming-features-1774974481770.md +++ b/packages/manager/.changeset/pr-13550-upcoming-features-1774974481770.md @@ -2,4 +2,4 @@ "@linode/manager": Upcoming Features --- -Implement the basic share group create page ([#13550](https://github.com/linode/manager/pull/13550)) +Private Image Sharing: Implement basic structure of Share Group Create page ([#13550](https://github.com/linode/manager/pull/13550)) From 2dbdb37b823ef21bb05ceaa6d60507a7db67f027 Mon Sep 17 00:00:00 2001 From: fabrice-akamai Date: Tue, 31 Mar 2026 15:32:19 -0400 Subject: [PATCH 07/12] Update the createShareGroup query --- .../v2/ShareGroups/ShareGroupsCreate/ShareGroupsCreate.tsx | 7 ------- packages/queries/src/images/sharegroups.ts | 6 ++++++ 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/packages/manager/src/features/Images/ImagesLanding/v2/ShareGroups/ShareGroupsCreate/ShareGroupsCreate.tsx b/packages/manager/src/features/Images/ImagesLanding/v2/ShareGroups/ShareGroupsCreate/ShareGroupsCreate.tsx index 22669ea0d9d..1a0fef28bec 100644 --- a/packages/manager/src/features/Images/ImagesLanding/v2/ShareGroups/ShareGroupsCreate/ShareGroupsCreate.tsx +++ b/packages/manager/src/features/Images/ImagesLanding/v2/ShareGroups/ShareGroupsCreate/ShareGroupsCreate.tsx @@ -10,7 +10,6 @@ import { Typography, } from '@linode/ui'; import { useNavigate } from '@tanstack/react-router'; -import { useSnackbar } from 'notistack'; import * as React from 'react'; import { Controller, useForm } from 'react-hook-form'; @@ -21,8 +20,6 @@ export const ShareGroupsCreate = () => { const { mutateAsync: createShareGroup } = useCreateShareGroupMutation(); - const { enqueueSnackbar } = useSnackbar(); - const { control, handleSubmit, setError } = useForm(); @@ -32,10 +29,6 @@ export const ShareGroupsCreate = () => { try { await createShareGroup(values); - enqueueSnackbar('Sharegroup scheduled for creation', { - variant: 'info', - }); - navigate({ search: () => ({}), to: '/images/share-groups', diff --git a/packages/queries/src/images/sharegroups.ts b/packages/queries/src/images/sharegroups.ts index 655cce4f495..3191acdf9df 100644 --- a/packages/queries/src/images/sharegroups.ts +++ b/packages/queries/src/images/sharegroups.ts @@ -112,6 +112,12 @@ export const useCreateShareGroupMutation = () => { queryclient.invalidateQueries({ queryKey: shareGroupsQueries.sharegroups._ctx.paginated._def, }); + queryclient.invalidateQueries({ + queryKey: shareGroupsQueries.sharegroups._ctx.all._def, + }); + queryclient.invalidateQueries({ + queryKey: shareGroupsQueries.sharegroups._ctx.infinite._def, + }); queryclient.setQueryData( shareGroupsQueries.sharegroups._ctx.sharegroup(shareGroup.id.toString()) .queryKey, From aabb130245256c1fca422aac3af6c1a8cfcd8293 Mon Sep 17 00:00:00 2001 From: fabrice-akamai Date: Wed, 1 Apr 2026 18:39:30 -0400 Subject: [PATCH 08/12] Update description cell to truncate the text overflow and use tooltips --- .../v2/ShareGroups/ShareGroupRow.tsx | 39 +++++++++++++++---- .../v2/ShareGroups/shareGroupsTabsConfig.tsx | 8 ++-- 2 files changed, 37 insertions(+), 10 deletions(-) diff --git a/packages/manager/src/features/Images/ImagesLanding/v2/ShareGroups/ShareGroupRow.tsx b/packages/manager/src/features/Images/ImagesLanding/v2/ShareGroups/ShareGroupRow.tsx index 6ac9015479d..279d99b9bd7 100644 --- a/packages/manager/src/features/Images/ImagesLanding/v2/ShareGroups/ShareGroupRow.tsx +++ b/packages/manager/src/features/Images/ImagesLanding/v2/ShareGroups/ShareGroupRow.tsx @@ -1,5 +1,5 @@ import { usePreferences, useProfile } from '@linode/queries'; -import { Hidden, LinkButton } from '@linode/ui'; +import { Hidden, LinkButton, Tooltip } from '@linode/ui'; import { TableCell, TableRow } from 'akamai-cds-react-components/Table'; import React from 'react'; @@ -37,6 +37,13 @@ export const ShareGroupRow = (props: Props) => { tableStripingPreference ); + const TableCellOverflowStyle: React.CSSProperties = { + textOverflow: 'ellipsis', + whiteSpace: 'nowrap', + overflow: 'hidden', + display: 'block', + }; + return ( { rowborder={!isTableStripingEnabled} zebra={isTableStripingEnabled} > - - {}}>{label} - - {description} + + + {}} + sx={{ + ...TableCellOverflowStyle, + }} + > + {label} + + + + + + {description} + + {members_count} {images_count} - + {created && formatDate(created, { timezone: profile?.timezone, @@ -61,7 +86,7 @@ export const ShareGroupRow = (props: Props) => { - + {updated !== null ? formatDate(updated, { timezone: profile?.timezone }) : '–'} diff --git a/packages/manager/src/features/Images/ImagesLanding/v2/ShareGroups/shareGroupsTabsConfig.tsx b/packages/manager/src/features/Images/ImagesLanding/v2/ShareGroups/shareGroupsTabsConfig.tsx index b8a1b5f391b..add78267d91 100644 --- a/packages/manager/src/features/Images/ImagesLanding/v2/ShareGroups/shareGroupsTabsConfig.tsx +++ b/packages/manager/src/features/Images/ImagesLanding/v2/ShareGroups/shareGroupsTabsConfig.tsx @@ -60,10 +60,14 @@ export const shareGroupsSubTabs: ImageSubTab[] = [ ]; const OWNED_GROUPS_TABLE_COLUMNS: ShareGroupsViewTableColConfig[] = [ - { name: 'Group', sortableProps: { label: 'label' } }, + { + name: 'Group', + sortableProps: { label: 'label' }, + }, { name: 'Description', sortableProps: { label: 'description' }, + style: { flex: 2 }, }, { name: '# of members', @@ -76,13 +80,11 @@ const OWNED_GROUPS_TABLE_COLUMNS: ShareGroupsViewTableColConfig[] = [ name: 'Created', sortableProps: { label: 'created' }, hidden: 'lgDown', - style: { whiteSpace: 'nowrap' }, }, { name: 'Updated', sortableProps: { label: 'updated' }, hidden: 'lgDown', - style: { whiteSpace: 'nowrap' }, }, ]; From f099e814a7660449ff2386e0809036a68bab0027 Mon Sep 17 00:00:00 2001 From: fabrice-akamai Date: Thu, 2 Apr 2026 17:52:40 -0400 Subject: [PATCH 09/12] Update table design and tooltip appearance --- .../v2/ImageLibrary/ImagesTable.styles.ts | 4 + .../v2/ShareGroups/ShareGroupRow.tsx | 47 +++++----- .../v2/ShareGroups/ShareGroupsTable.tsx | 88 ++++++++++--------- .../v2/ShareGroups/shareGroupsTabsConfig.tsx | 28 +++++- 4 files changed, 102 insertions(+), 65 deletions(-) diff --git a/packages/manager/src/features/Images/ImagesLanding/v2/ImageLibrary/ImagesTable.styles.ts b/packages/manager/src/features/Images/ImagesLanding/v2/ImageLibrary/ImagesTable.styles.ts index c61583d2128..8f4eea5e6aa 100644 --- a/packages/manager/src/features/Images/ImagesLanding/v2/ImageLibrary/ImagesTable.styles.ts +++ b/packages/manager/src/features/Images/ImagesLanding/v2/ImageLibrary/ImagesTable.styles.ts @@ -37,4 +37,8 @@ export const StyledImageTableContainer = styled(Box, { '& cds-table-row:last-child:not([rowborder])': { borderBottom: `1px solid ${theme.tokens.component.Table.Row.Border}`, }, + + '& cds-table-header-cell, & cds-table-cell': { + boxSizing: 'border-box', + }, })); diff --git a/packages/manager/src/features/Images/ImagesLanding/v2/ShareGroups/ShareGroupRow.tsx b/packages/manager/src/features/Images/ImagesLanding/v2/ShareGroups/ShareGroupRow.tsx index 279d99b9bd7..dc72820c828 100644 --- a/packages/manager/src/features/Images/ImagesLanding/v2/ShareGroups/ShareGroupRow.tsx +++ b/packages/manager/src/features/Images/ImagesLanding/v2/ShareGroups/ShareGroupRow.tsx @@ -1,13 +1,22 @@ import { usePreferences, useProfile } from '@linode/queries'; import { Hidden, LinkButton, Tooltip } from '@linode/ui'; -import { TableCell, TableRow } from 'akamai-cds-react-components/Table'; +import { truncateEnd } from '@linode/utilities'; +import { TableRow } from 'akamai-cds-react-components/Table'; import React from 'react'; import { getIsTableStripingEnabled } from 'src/features/Profile/Settings/TableStriping.utils'; import { formatDate } from 'src/utilities/formatDate'; import { ShareGroupActionMenu } from './ShareGroupActionMenu'; -import { StyledActionMenuWrapper } from './ShareGroupTable.styles'; +import { + StyledActionMenuWrapper, + StyledCreatedCell, + StyledDescriptionCell, + StyledGroupCell, + StyledImageCountCell, + StyledMemberCountCell, + StyledUpdatedCell, +} from './ShareGroupTable.styles'; import type { Sharegroup } from '@linode/api-v4'; @@ -49,48 +58,44 @@ export const ShareGroupRow = (props: Props) => { data-qa-sharegroup-row={id} key={id} rowborder={!isTableStripingEnabled} + style={{ padding: 0 }} zebra={isTableStripingEnabled} > - - + 32 ? label : ''}> + {}} sx={{ ...TableCellOverflowStyle, }} > - {label} + {truncateEnd(label, 32)} - + - - - {description} - + 50 ? description : ''}> + + {truncateEnd(description, 50)} + - {members_count} + {members_count} - {images_count} + {images_count} - + {created && formatDate(created, { timezone: profile?.timezone, })} - + - + {updated !== null ? formatDate(updated, { timezone: profile?.timezone }) : '–'} - + diff --git a/packages/manager/src/features/Images/ImagesLanding/v2/ShareGroups/ShareGroupsTable.tsx b/packages/manager/src/features/Images/ImagesLanding/v2/ShareGroups/ShareGroupsTable.tsx index 8aaf6da3bb4..2c9395f7888 100644 --- a/packages/manager/src/features/Images/ImagesLanding/v2/ShareGroups/ShareGroupsTable.tsx +++ b/packages/manager/src/features/Images/ImagesLanding/v2/ShareGroups/ShareGroupsTable.tsx @@ -28,6 +28,7 @@ import { StyledImageTableSubheader, } from '../ImageLibrary/ImagesTable.styles'; import { ShareGroupRow } from './ShareGroupRow'; +import { StyledShareGroupsTableHeader } from './ShareGroupTable.styles'; import type { ShareGroupsViewTableColConfig } from './shareGroupsTabsConfig'; import type { APIError, Sharegroup } from '@linode/api-v4'; @@ -132,49 +133,52 @@ export const ShareGroupsTable = (props: ShareGroupsTableProps) => { )} - - - - {columns.map((col, idx) => { - const cell = col.sortableProps ? ( - - handleOrderChange( - col.sortableProps?.label ?? col.name, - order === 'asc' ? 'desc' : 'asc' - ) - } - sortable - sorted={ - orderBy === col.sortableProps?.label ? order : undefined - } - style={{ ...col.style }} - > - {col.name} - - ) : ( - - {col.name} - - ); +
+ + + + {columns.map((col, idx) => { + const cell = col.sortableProps ? ( + + handleOrderChange( + col.sortableProps?.label ?? col.name, + order === 'asc' ? 'desc' : 'asc' + ) + } + sortable + sorted={ + orderBy === col.sortableProps?.label ? order : undefined + } + style={{ ...col.style }} + > + {col.name} + + ) : ( + + {col.name} + + ); + + return col.hidden ? ( + + {cell} + + ) : ( + cell + ); + })} + + + + - return col.hidden ? ( - - {cell} - - ) : ( - cell - ); - })} - - - {!error && shareGroups.length === 0 && ( diff --git a/packages/manager/src/features/Images/ImagesLanding/v2/ShareGroups/shareGroupsTabsConfig.tsx b/packages/manager/src/features/Images/ImagesLanding/v2/ShareGroups/shareGroupsTabsConfig.tsx index add78267d91..9adcbe71319 100644 --- a/packages/manager/src/features/Images/ImagesLanding/v2/ShareGroups/shareGroupsTabsConfig.tsx +++ b/packages/manager/src/features/Images/ImagesLanding/v2/ShareGroups/shareGroupsTabsConfig.tsx @@ -1,7 +1,7 @@ import React from 'react'; import type { APIError } from '@linode/api-v4'; -import type { HiddenProps } from '@linode/ui'; +import type { HiddenProps, SxProps } from '@linode/ui'; import type { ImageSubTab, ShareGroupsType } from 'src/features/Images/utils'; export interface ShareGroupsViewTableColConfig { @@ -59,32 +59,56 @@ export const shareGroupsSubTabs: ImageSubTab[] = [ }, ]; +const COLUMN_WIDTHS = { + group: '20%', + description: '25%', + membersCount: '10%', + imagesCount: '10%', + created: '15%', + updated: '15%', + action: '5%', +}; + +const tableStyles: SxProps = { + flex: { + lg: '0 1 30%', + md: '0 1 20%', + sm: '100%', + }, +}; + + const OWNED_GROUPS_TABLE_COLUMNS: ShareGroupsViewTableColConfig[] = [ { name: 'Group', sortableProps: { label: 'label' }, + style: { flex: '0 1 20%' }, }, { name: 'Description', sortableProps: { label: 'description' }, - style: { flex: 2 }, + style: { flex: '0 1 25%' }, }, { name: '# of members', + style: { flex: '0 1 10%' }, }, { name: '# of images', hidden: 'smDown', + style: { flex: '0 1 10%' }, }, { name: 'Created', sortableProps: { label: 'created' }, hidden: 'lgDown', + style: { whiteSpace: 'nowrap', flex: '0 1 15%' }, }, { name: 'Updated', sortableProps: { label: 'updated' }, hidden: 'lgDown', + style: { whiteSpace: 'nowrap', flex: '0 1 15%' }, }, ]; From e23162c4c5d2a328218381681df5c679b70e8eee Mon Sep 17 00:00:00 2001 From: fabrice-akamai Date: Thu, 2 Apr 2026 18:13:55 -0400 Subject: [PATCH 10/12] Update table cell styling --- .../v2/ShareGroups/ShareGroupTable.styles.ts | 77 ++++++++++++++++++- 1 file changed, 76 insertions(+), 1 deletion(-) diff --git a/packages/manager/src/features/Images/ImagesLanding/v2/ShareGroups/ShareGroupTable.styles.ts b/packages/manager/src/features/Images/ImagesLanding/v2/ShareGroups/ShareGroupTable.styles.ts index 947a50512ea..86a18a4f1c4 100644 --- a/packages/manager/src/features/Images/ImagesLanding/v2/ShareGroups/ShareGroupTable.styles.ts +++ b/packages/manager/src/features/Images/ImagesLanding/v2/ShareGroups/ShareGroupTable.styles.ts @@ -7,7 +7,7 @@ export const StyledActionMenuWrapper = styled(TableCell, { justifyContent: 'flex-end', display: 'flex', alignItems: 'center', - maxWidth: 40, + flex: '0 1 5%', '& button': { padding: 0, color: theme.tokens.alias.Content.Icon.Primary.Default, @@ -18,3 +18,78 @@ export const StyledActionMenuWrapper = styled(TableCell, { color: theme.tokens.alias.Content.Icon.Primary.Hover, }, })); + +export const StyledGroupCell = styled(TableCell, { + label: 'StyledGroupCell', +})(({ theme }) => ({ + whiteSpace: 'nowrap', + flex: '0 1 20%', + [theme.breakpoints.down('lg')]: { + flex: '0 1 30%', + }, + [theme.breakpoints.down('sm')]: { + width: '20%', + }, +})); + +export const StyledDescriptionCell = styled(TableCell, { + label: 'StyledDescriptionCell', +})(({ theme }) => ({ + flex: '0 1 25%', + textOverflow: 'ellipsis', + whiteSpace: 'nowrap', + overflow: 'hidden', + display: 'block', + + [theme.breakpoints.down('lg')]: { + flex: '0 1 35%', + }, + [theme.breakpoints.down('sm')]: { + width: '25%', + }, +})); + +export const StyledMemberCountCell = styled(TableCell, { + label: 'StyledMemberCountCell', +})(({ theme }) => ({ + whiteSpace: 'nowrap', + flex: '0 1 10%', + [theme.breakpoints.down('lg')]: { + flex: '0 1 15%', + }, +})); + +export const StyledImageCountCell = styled(TableCell, { + label: 'StyledImageCountCell', +})(({ theme }) => ({ + whiteSpace: 'nowrap', + width: '10%', + flex: '0 1 10%', + [theme.breakpoints.down('lg')]: { + flex: '0 1 15%', + }, +})); + +export const StyledCreatedCell = styled(TableCell, { + label: 'StyledCreatedCell', +})(({ theme }) => ({ + whiteSpace: 'nowrap', + width: '15%', + flex: '0 1 15%', +})); + +export const StyledUpdatedCell = styled(TableCell, { + label: 'StyledUpdatedCell', +})(({ theme }) => ({ + whiteSpace: 'nowrap', + width: '15%', + flex: '0 1 15%', +})); + +export const StyledShareGroupsTableHeader = styled('div', { + label: 'StyledShareGroupsTableHeader', +})(({ theme }) => ({ + '& div.row': { + padding: 0, + }, +})); \ No newline at end of file From 15f2a0e299c32b725ca0f4d7904f3569d4880182 Mon Sep 17 00:00:00 2001 From: fabrice-akamai Date: Mon, 6 Apr 2026 15:51:39 -0400 Subject: [PATCH 11/12] Update the share groups table columns and add tooltips --- .../v2/ShareGroups/ShareGroupRow.tsx | 47 +++---- .../v2/ShareGroups/ShareGroupTable.styles.ts | 116 ++++++++---------- .../v2/ShareGroups/ShareGroupsTable.tsx | 100 +++++++-------- .../v2/ShareGroups/shareGroupsTabsConfig.tsx | 37 ++---- 4 files changed, 132 insertions(+), 168 deletions(-) diff --git a/packages/manager/src/features/Images/ImagesLanding/v2/ShareGroups/ShareGroupRow.tsx b/packages/manager/src/features/Images/ImagesLanding/v2/ShareGroups/ShareGroupRow.tsx index dc72820c828..b99743e2b5d 100644 --- a/packages/manager/src/features/Images/ImagesLanding/v2/ShareGroups/ShareGroupRow.tsx +++ b/packages/manager/src/features/Images/ImagesLanding/v2/ShareGroups/ShareGroupRow.tsx @@ -1,22 +1,14 @@ import { usePreferences, useProfile } from '@linode/queries'; import { Hidden, LinkButton, Tooltip } from '@linode/ui'; import { truncateEnd } from '@linode/utilities'; -import { TableRow } from 'akamai-cds-react-components/Table'; +import { TableCell, TableRow } from 'akamai-cds-react-components/Table'; import React from 'react'; import { getIsTableStripingEnabled } from 'src/features/Profile/Settings/TableStriping.utils'; import { formatDate } from 'src/utilities/formatDate'; import { ShareGroupActionMenu } from './ShareGroupActionMenu'; -import { - StyledActionMenuWrapper, - StyledCreatedCell, - StyledDescriptionCell, - StyledGroupCell, - StyledImageCountCell, - StyledMemberCountCell, - StyledUpdatedCell, -} from './ShareGroupTable.styles'; +import { StyledActionMenuWrapper } from './ShareGroupTable.styles'; import type { Sharegroup } from '@linode/api-v4'; @@ -46,13 +38,6 @@ export const ShareGroupRow = (props: Props) => { tableStripingPreference ); - const TableCellOverflowStyle: React.CSSProperties = { - textOverflow: 'ellipsis', - whiteSpace: 'nowrap', - overflow: 'hidden', - display: 'block', - }; - return ( { zebra={isTableStripingEnabled} > 32 ? label : ''}> - + {}} sx={{ - ...TableCellOverflowStyle, + textOverflow: 'ellipsis', + whiteSpace: 'nowrap', + overflow: 'hidden', + display: 'block', }} > {truncateEnd(label, 32)} - + 50 ? description : ''}> - + {truncateEnd(description, 50)} - + - {members_count} + {members_count} - {images_count} + {images_count} - + {created && formatDate(created, { timezone: profile?.timezone, })} - + - + {updated !== null ? formatDate(updated, { timezone: profile?.timezone }) : '–'} - + diff --git a/packages/manager/src/features/Images/ImagesLanding/v2/ShareGroups/ShareGroupTable.styles.ts b/packages/manager/src/features/Images/ImagesLanding/v2/ShareGroups/ShareGroupTable.styles.ts index 86a18a4f1c4..407595c6300 100644 --- a/packages/manager/src/features/Images/ImagesLanding/v2/ShareGroups/ShareGroupTable.styles.ts +++ b/packages/manager/src/features/Images/ImagesLanding/v2/ShareGroups/ShareGroupTable.styles.ts @@ -7,7 +7,7 @@ export const StyledActionMenuWrapper = styled(TableCell, { justifyContent: 'flex-end', display: 'flex', alignItems: 'center', - flex: '0 1 5%', + maxWidth: '5%', '& button': { padding: 0, color: theme.tokens.alias.Content.Icon.Primary.Default, @@ -19,77 +19,63 @@ export const StyledActionMenuWrapper = styled(TableCell, { }, })); -export const StyledGroupCell = styled(TableCell, { - label: 'StyledGroupCell', -})(({ theme }) => ({ - whiteSpace: 'nowrap', - flex: '0 1 20%', - [theme.breakpoints.down('lg')]: { - flex: '0 1 30%', - }, - [theme.breakpoints.down('sm')]: { - width: '20%', - }, -})); - -export const StyledDescriptionCell = styled(TableCell, { - label: 'StyledDescriptionCell', -})(({ theme }) => ({ - flex: '0 1 25%', +const TABLE_CELL_BASE_STYLES: React.CSSProperties = { + boxSizing: 'border-box', +}; +const TABLE_CELL_OVERFLOW_STYLES: React.CSSProperties = { textOverflow: 'ellipsis', whiteSpace: 'nowrap', overflow: 'hidden', display: 'block', +}; - [theme.breakpoints.down('lg')]: { - flex: '0 1 35%', +export const StyledShareGroupsTableContainer = styled('div', { + label: 'StyledShareGroupsTable', +})(({ theme }) => ({ + '& .group-column': { + minWidth: '20%', + ...TABLE_CELL_BASE_STYLES, + [theme.breakpoints.down('sm')]: { + minWidth: '30%', + }, }, - [theme.breakpoints.down('sm')]: { - width: '25%', + '& .description-column': { + minWidth: '25%', + ...TABLE_CELL_OVERFLOW_STYLES, + ...TABLE_CELL_BASE_STYLES, + [theme.breakpoints.down('lg')]: { + minWidth: '45%', + }, + [theme.breakpoints.down('sm')]: { + minWidth: '40%', + }, }, -})); - -export const StyledMemberCountCell = styled(TableCell, { - label: 'StyledMemberCountCell', -})(({ theme }) => ({ - whiteSpace: 'nowrap', - flex: '0 1 10%', - [theme.breakpoints.down('lg')]: { - flex: '0 1 15%', + '& .membersCount-column': { + minWidth: '11%', + ...TABLE_CELL_BASE_STYLES, + [theme.breakpoints.down('lg')]: { + minWidth: '15%', + }, }, -})); - -export const StyledImageCountCell = styled(TableCell, { - label: 'StyledImageCountCell', -})(({ theme }) => ({ - whiteSpace: 'nowrap', - width: '10%', - flex: '0 1 10%', - [theme.breakpoints.down('lg')]: { - flex: '0 1 15%', + '& .imagesCount-column': { + minWidth: '9%', + ...TABLE_CELL_BASE_STYLES, + [theme.breakpoints.down('lg')]: { + minWidth: '15%', + }, }, -})); - -export const StyledCreatedCell = styled(TableCell, { - label: 'StyledCreatedCell', -})(({ theme }) => ({ - whiteSpace: 'nowrap', - width: '15%', - flex: '0 1 15%', -})); - -export const StyledUpdatedCell = styled(TableCell, { - label: 'StyledUpdatedCell', -})(({ theme }) => ({ - whiteSpace: 'nowrap', - width: '15%', - flex: '0 1 15%', -})); - -export const StyledShareGroupsTableHeader = styled('div', { - label: 'StyledShareGroupsTableHeader', -})(({ theme }) => ({ - '& div.row': { - padding: 0, + '& .created-column': { + minWidth: '15%', + ...TABLE_CELL_BASE_STYLES, + whiteSpace: 'nowrap', }, -})); \ No newline at end of file + '& .updated-column': { + minWidth: '15%', + ...TABLE_CELL_BASE_STYLES, + whiteSpace: 'nowrap', + }, + '& .action-column': { + maxWidth: '5%', + ...TABLE_CELL_BASE_STYLES, + }, +})); diff --git a/packages/manager/src/features/Images/ImagesLanding/v2/ShareGroups/ShareGroupsTable.tsx b/packages/manager/src/features/Images/ImagesLanding/v2/ShareGroups/ShareGroupsTable.tsx index 2c9395f7888..b6548f9ba01 100644 --- a/packages/manager/src/features/Images/ImagesLanding/v2/ShareGroups/ShareGroupsTable.tsx +++ b/packages/manager/src/features/Images/ImagesLanding/v2/ShareGroups/ShareGroupsTable.tsx @@ -28,7 +28,7 @@ import { StyledImageTableSubheader, } from '../ImageLibrary/ImagesTable.styles'; import { ShareGroupRow } from './ShareGroupRow'; -import { StyledShareGroupsTableHeader } from './ShareGroupTable.styles'; +import { StyledShareGroupsTableContainer } from './ShareGroupTable.styles'; import type { ShareGroupsViewTableColConfig } from './shareGroupsTabsConfig'; import type { APIError, Sharegroup } from '@linode/api-v4'; @@ -133,8 +133,8 @@ export const ShareGroupsTable = (props: ShareGroupsTableProps) => { )} -
- + +
{ {columns.map((col, idx) => { const cell = col.sortableProps ? ( handleOrderChange( @@ -161,7 +162,11 @@ export const ShareGroupsTable = (props: ShareGroupsTableProps) => { {col.name} ) : ( - + {col.name} ); @@ -174,55 +179,54 @@ export const ShareGroupsTable = (props: ShareGroupsTableProps) => { cell ); })} - + - - - - {!error && shareGroups.length === 0 && ( - - - ({ + + {!error && shareGroups.length === 0 && ( + + - - {emptyMessage.main} - {!query && emptyMessage.instruction && ( - - {emptyMessage.instruction} - - )} - - - - )} - {error && query && ( - - - - - - )} + ({ + display: 'flex', + flexDirection: 'column', + alignItems: 'center', + gap: theme.spacingFunction(4), + p: `${theme.spacingFunction(24)} ${theme.spacingFunction(32)}`, + width: '100%', + })} + > + + {emptyMessage.main} + {!query && emptyMessage.instruction && ( + + {emptyMessage.instruction} + + )} + + + + )} + {error && query && ( + + + + + + )} - {shareGroups.map((sharegroup) => ( - - ))} - -
+ {shareGroups.map((sharegroup) => ( + + ))} + + + {pagination.count > DEFAULT_PAGE_SIZES[0] && ( ; /* Column name */ name: string; - /* Provide sortableProps to enable sorting for this column. */ sortableProps?: { /* API field used for sorting this column */ @@ -59,56 +61,37 @@ export const shareGroupsSubTabs: ImageSubTab[] = [ }, ]; -const COLUMN_WIDTHS = { - group: '20%', - description: '25%', - membersCount: '10%', - imagesCount: '10%', - created: '15%', - updated: '15%', - action: '5%', -}; - -const tableStyles: SxProps = { - flex: { - lg: '0 1 30%', - md: '0 1 20%', - sm: '100%', - }, -}; - - const OWNED_GROUPS_TABLE_COLUMNS: ShareGroupsViewTableColConfig[] = [ { name: 'Group', sortableProps: { label: 'label' }, - style: { flex: '0 1 20%' }, + className: 'group-column', }, { name: 'Description', sortableProps: { label: 'description' }, - style: { flex: '0 1 25%' }, + className: 'description-column', }, { name: '# of members', - style: { flex: '0 1 10%' }, + className: 'membersCount-column', }, { name: '# of images', hidden: 'smDown', - style: { flex: '0 1 10%' }, + className: 'imagesCount-column', }, { name: 'Created', sortableProps: { label: 'created' }, hidden: 'lgDown', - style: { whiteSpace: 'nowrap', flex: '0 1 15%' }, + className: 'created-column', }, { name: 'Updated', sortableProps: { label: 'updated' }, hidden: 'lgDown', - style: { whiteSpace: 'nowrap', flex: '0 1 15%' }, + className: 'updated-column', }, ]; From 1f3b935bda16bb56f07821014ca2a1b4592728d8 Mon Sep 17 00:00:00 2001 From: fabrice-akamai Date: Mon, 6 Apr 2026 17:25:50 -0400 Subject: [PATCH 12/12] Update description column width --- .../v2/ShareGroups/ShareGroupTable.styles.ts | 13 +++++-------- .../v2/ShareGroups/shareGroupsTabsConfig.tsx | 2 +- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/packages/manager/src/features/Images/ImagesLanding/v2/ShareGroups/ShareGroupTable.styles.ts b/packages/manager/src/features/Images/ImagesLanding/v2/ShareGroups/ShareGroupTable.styles.ts index 407595c6300..154dd1d947e 100644 --- a/packages/manager/src/features/Images/ImagesLanding/v2/ShareGroups/ShareGroupTable.styles.ts +++ b/packages/manager/src/features/Images/ImagesLanding/v2/ShareGroups/ShareGroupTable.styles.ts @@ -22,12 +22,6 @@ export const StyledActionMenuWrapper = styled(TableCell, { const TABLE_CELL_BASE_STYLES: React.CSSProperties = { boxSizing: 'border-box', }; -const TABLE_CELL_OVERFLOW_STYLES: React.CSSProperties = { - textOverflow: 'ellipsis', - whiteSpace: 'nowrap', - overflow: 'hidden', - display: 'block', -}; export const StyledShareGroupsTableContainer = styled('div', { label: 'StyledShareGroupsTable', @@ -41,10 +35,13 @@ export const StyledShareGroupsTableContainer = styled('div', { }, '& .description-column': { minWidth: '25%', - ...TABLE_CELL_OVERFLOW_STYLES, + textOverflow: 'ellipsis', + whiteSpace: 'nowrap', + overflow: 'hidden', + display: 'block', ...TABLE_CELL_BASE_STYLES, [theme.breakpoints.down('lg')]: { - minWidth: '45%', + minWidth: '40%', }, [theme.breakpoints.down('sm')]: { minWidth: '40%', diff --git a/packages/manager/src/features/Images/ImagesLanding/v2/ShareGroups/shareGroupsTabsConfig.tsx b/packages/manager/src/features/Images/ImagesLanding/v2/ShareGroups/shareGroupsTabsConfig.tsx index 038502e046c..e748a38e719 100644 --- a/packages/manager/src/features/Images/ImagesLanding/v2/ShareGroups/shareGroupsTabsConfig.tsx +++ b/packages/manager/src/features/Images/ImagesLanding/v2/ShareGroups/shareGroupsTabsConfig.tsx @@ -136,7 +136,7 @@ export const SHAREGROUPS_CONFIG: Record< }, columns: OWNED_GROUPS_TABLE_COLUMNS, emptyMessage: { - main: 'No Share groups to display', + main: 'No share groups to display', instruction: 'Click \u2018Create Share Group\u2019 to create your first share group and share your custom images with other accounts.', },