Skip to content

Conversation

@tvijay-akamai
Copy link
Contributor

@tvijay-akamai tvijay-akamai commented Jan 12, 2026

Details page for partner referral product

Description 📝

Refactor Marketplace details and Add dynamic product content to each tab for Products details page.

Note

There have been some changes in the approach for Marketplace from the Product. The APIs will no longer be available, and we will fully rely on client-side filtering and client-side management of Marketplace products

Changes 🔄

List any change(s) relevant to the reviewer.

  • Refactor marketplace product details to not use any apis or unnecessary logic. Refactored to frontend static approach as advised by management.
  • Added product details
  • Added product tabs with relevant content received from Product managers.
  • Currently working with the mock data as we are yet to receive actual product content from product managers.

Scope 🚢

Upon production release, changes in this PR will be visible to:

  • All customers
  • Some customers (e.g. in Beta or Limited Availability)
  • No customers / Not applicable

Target release date 🗓️

27 Feb 2026

How to test 🧪

Prerequisites

Reproduction steps

Verification steps

(How to verify changes)

Author Checklists

As an Author, to speed up the review process, I considered 🤔

👀 Doing a self review
❔ Our contribution guidelines
🤏 Splitting feature into small PRs
➕ Adding a changeset
🧪 Providing/improving test coverage
🔐 Removing all sensitive information from the code and PR description
🚩 Using a feature flag to protect the release
👣 Providing comprehensive reproduction steps
📑 Providing or updating our documentation
🕛 Scheduling a pair reviewing session
📱 Providing mobile support
♿ Providing accessibility support


  • I have read and considered all applicable items listed above.

As an Author, before moving this PR from Draft to Open, I confirmed ✅

  • All tests and CI checks are passing
  • TypeScript compilation succeeded without errors
  • Code passes all linting rules

@tvijay-akamai
Copy link
Contributor Author

Ignore the styling for the content received from api in the tabs. Davyd will be providing the styling for different html elements and once we get I add it here accordingly. For now i have added sample styles to make the content look good.

@pmakode-akamai pmakode-akamai changed the title upcoming:[UIE-9818][UIE-9820][UIE-9821][UIE-9822] implemented product details upcoming: [UIE-9818, UIE-9820, UIE-9821, UIE-9822] - Implement product details for Marketplace Jan 14, 2026
Copy link
Contributor

@pmakode-akamai pmakode-akamai left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've left some initial comments and will revisit the PR for a second look

@tvijay-akamai tvijay-akamai requested a review from a team as a code owner January 15, 2026 05:20
@tvijay-akamai tvijay-akamai requested review from fabrice-akamai and removed request for a team January 15, 2026 05:20
Copy link
Contributor

@harsh-akamai harsh-akamai left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Image

The padding inside the details paper is more than what the figma mockup shows.

Comment on lines 153 to 154
fontSize: theme.tokens.font.FontSize.Xs,
lineHeight: theme.tokens.font.LineHeight.Xs,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fontSize and lineHeight is redundant. font covers both the properties

Comment on lines 169 to 170
fontSize: theme.tokens.font.FontSize.Xs,
lineHeight: theme.tokens.font.LineHeight.Xs,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here

<HtmlContentRenderer content={details.overview.description} />
</ContentSection>
<VideoPlaceholder>
<PlayCircleIcon />
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The icon gets hidden in dark mode

Video Icon dark mode Image

Comment on lines 89 to 113
if (details.pricing?.description) {
availableTabs.push({
content: <HtmlContentRenderer content={details.pricing.description} />,
label: 'Pricing',
pendoId: 'Cloud Marketplace Details-Pricing',
});
}

if (details.documentation?.description) {
availableTabs.push({
content: (
<HtmlContentRenderer content={details.documentation.description} />
),
label: 'Documentation',
pendoId: 'Cloud Marketplace Details-Documentation',
});
}

if (details.support?.description) {
availableTabs.push({
content: <HtmlContentRenderer content={details.support.description} />,
label: 'Support',
pendoId: 'Cloud Marketplace Details-Support',
});
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: We could instead have a map containing the pendoId and label instead of defining separate if conditions for non-overview tabs

Comment on lines 10 to 12
paddingLeft: '8px',
paddingRight: '8px',
paddingTop: '8px',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe we can remove this

Copy link
Contributor

@pmakode-akamai pmakode-akamai Feb 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@tvijay-akamai Any update on this if it's required or not? If required, then we should use spacingFunction here and for the gap

@harsh-akamai
Copy link
Contributor

Can we add a changeset for this pr?

@abailly-akamai
Copy link
Contributor

What is the reason for one PR covering 4 tickets and nearing 1000 lined addition to the codebase? From what I can see this is a sensitive feature rendering server side sent HTML? Apart from being quite a suspicious pattern, this kind of work warrants a more careful approach with small bits PRs.

I am already seeing far too many comments and I am concerned about the cleanliness of this feature as a whole, especially when I see the omission of sanitizing HTML that shouldn't be returned by an APIv4 endpoint.

I'd recommend taking a step back - preventing merging for the time being

</table>
<h3>Status Page</h3>
<p>Check the current status of Akamai services at <a href="https://status.akamai.com">status.akamai.com</a></p>
`,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have a fundamental issue if your endpoint is returning this random HTML. Who allowed this design?

@github-project-automation github-project-automation bot moved this from Review to Changes Requested in Cloud Manager Jan 15, 2026
@github-actions
Copy link

This PR is stale because it has been open 15 days with no activity. Please attend to this PR or it will be closed in 5 days

@github-actions github-actions bot added the Stale label Jan 31, 2026

import type { ProductTabDetails } from '.';

const details: ProductTabDetails = {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This feels a bit hard to read as is. Since we're not planning to use separate .md files, maybe we could define overview, pricing, documentation, and support as separate markdown constants above and then reference them here. That would make the file easier to scan and maintain.

Comment on lines 7 to 20
export interface ProductTabDetails {
documentation?: {
description: string;
};
overview?: {
description: string;
};
pricing?: {
description: string;
};
support?: {
description: string;
};
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
export interface ProductTabDetails {
documentation?: {
description: string;
};
overview?: {
description: string;
};
pricing?: {
description: string;
};
support?: {
description: string;
};
}
export interface ProductTabDetails {
documentation?: string;
overview?: string;
pricing?: string;
support?: string;
}

Since this is currently static content and not coming from an API, do we need the extra { description } nesting? Using documentation?: string (and similar for other tabs) will simplify the model.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it might be better to move the data/details package under ProductDetails/ for better organization (and rename it to something like pages). Since these files represent product details page content, a structure like ProductDetails/pages/* would keep them closer to where they're used and make the intent clearer.

* Each product's details are imported statically and available synchronously.
*/
const detailsMap: Record<number, ProductTabDetails> = {
100001: product100001,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This isn't a blocker, but it might be worth checking with Product or UX whether we're okay with using sequential IDs like 100001, 100002, etc., OR if there's a recommended convention. For eg., OneClickApps uses larger non-sequential numeric IDs (e.g. 401697), so it might be worth aligning with that pattern if there's a reason behind it

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As mentioned above, please use slugs

Comment on lines 63 to 64
fontSize: theme.tokens.font.FontSize.Xxxs,
fontFamily: theme.font.bold,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fontFamily doesn't seem to be working here. The text should be bold as per the Figma. I think we can achieve this by setting font and fontSize afterward

  font: theme.font.bold,
  fontSize: theme.tokens.font.FontSize.Xxxs, // Must come after font

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, let's add a changeset for this new icon (PlayCircleIcon) in the ui package

Copy link
Contributor

@harsh-akamai harsh-akamai left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will the Overview Details tab include a video in the near future? Currently, the tab structure assumes only string-based content, and a video placeholder has been hard-coded. If a video is planned, we can add mock data to simulate how the video component would appear.

Overview Tab Image

);

// Tab content is optional. If not present for this product, we still show the page.
const details = getProductTabDetails(numericProductId);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
const details = getProductTabDetails(numericProductId);
const details = React.useMemo( () => getProductTabDetails(numericProductId), [numericProductId]));

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

useMemo Not needed as we're already fetching from map.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also no clarity on video yet, not important for now. we can leave it as is.

Comment on lines +51 to +57
if (!product) {
return (
<ErrorState
errorText={'Unable to load product details. Please try again later.'}
/>
);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe we can move this if-block before the productDetails are fetched?

* This provides consistent styling for all HTML elements across tabs
* Styles follow Figma design specifications
*/
export const StyledHtmlContent = styled('div')(({ theme }) => ({
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
export const StyledHtmlContent = styled('div')(({ theme }) => ({
export const StyledTabContent = styled('div')(({ theme }) => ({

@tvijay-akamai tvijay-akamai added Add'tl Approval Needed Waiting on another approval! and removed Ready for Review labels Feb 3, 2026
Copy link
Contributor

@pmakode-akamai pmakode-akamai left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks @tvijay-akamai -- overall this looks good. I've left a few more comments and questions that need to be looked into.

Comment on lines 10 to 12
paddingLeft: '8px',
paddingRight: '8px',
paddingTop: '8px',
Copy link
Contributor

@pmakode-akamai pmakode-akamai Feb 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@tvijay-akamai Any update on this if it's required or not? If required, then we should use spacingFunction here and for the gap

alignItems: 'flex-start',
alignSelf: 'stretch',
display: 'flex',
gap: '24px',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should use spacingFunction for all gap values in this file

alignItems: 'flex-start',
alignSelf: 'stretch',
display: 'flex',
gap: '24px',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we use spacingFunction here and below as well?

fontStyle: 'normal',
lineHeight: theme.tokens.font.LineHeight.M,
margin: 0,
paddingBottom: theme.tokens.spacing.S16,
Copy link
Contributor

@pmakode-akamai pmakode-akamai Feb 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see that we generally use spacingFunction, and we're already using it in the styles above. I don't think using theme.tokens.spacing.S16 is wrong either, but I'm not sure which way we should standardize on for consistency. @abailly-akamai thoughts?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will indeed result in the same outcome, but for consistency spacingFunction is preferred.

support: supportMarkdown,
};

export default details;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's use named exports

@@ -0,0 +1,55 @@
/**
* Product tab details for id 100001.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we please have IDs as product name slugs?? Static magic numbers are far more confusing and not appropriate for this, especially as your list will grow.

  • Poor URL readability: /catalog/spinkube is more intuitive than /catalog/100001
  • Not self-documenting: Looking at 100001.ts, you have no idea what product it represents without looking it up
  • Developer experience: When debugging or creating new products, you have to constantly look up which ID maps to which product
  • URL sharing: Users sharing links can't tell what product they're sharing

* Each product's details are imported statically and available synchronously.
*/
const detailsMap: Record<number, ProductTabDetails> = {
100001: product100001,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As mentioned above, please use slugs

alignSelf: 'stretch',
display: 'flex',
flexDirection: 'column',
gap: '16px',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use spacingFunction for ALL your gaps

alignItems: 'flex-start',
alignSelf: 'stretch',
display: 'flex',
gap: '24px',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same with gaps

fontSize: theme.tokens.font.FontSize.Xs,
gap: '8px',
lineHeight: theme.tokens.font.LineHeight.Xs,
padding: '12px 16px 12px 12px',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same comment with paddings and gaps

display: 'flex',
flexDirection: 'column',
gap: theme.spacingFunction(8),
height: '202px',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are we ok with a set height here rather than a responsive container?

Also, are we serving videos locally? Pictures is one thing but this is concerning

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No videos will not be served locally. Currently there are no videos in beta.

@linode-gh-bot
Copy link
Collaborator

Cloud Manager UI test results

🎉 865 passing tests on test run #12 ↗︎

❌ Failing✅ Passing↪️ Skipped🕐 Duration
0 Failing865 Passing11 Skipped38m 1s

Copy link
Contributor

@abailly-akamai abailly-akamai left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for your patience, finding a good MVP implementation and addressing a lot of feedback. While this will likely be revisited as the feature grows, this is a good start - to go on my end 👍

@github-project-automation github-project-automation bot moved this from Changes Requested to Approved in Cloud Manager Feb 3, 2026
@tvijay-akamai tvijay-akamai merged commit 819fbef into linode:develop Feb 3, 2026
35 checks passed
@github-project-automation github-project-automation bot moved this from Approved to Merged in Cloud Manager Feb 3, 2026
@tvijay-akamai tvijay-akamai removed the Add'tl Approval Needed Waiting on another approval! label Feb 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Status: Merged

Development

Successfully merging this pull request may close these issues.

6 participants