Skip to content

Feature:SPLaSK compliance on link and button component(SSD-168) #320

Open
4fn4n wants to merge 4 commits into
developfrom
feature/SSD-168-splask-compliance-button-and-link
Open

Feature:SPLaSK compliance on link and button component(SSD-168) #320
4fn4n wants to merge 4 commits into
developfrom
feature/SSD-168-splask-compliance-button-and-link

Conversation

@4fn4n
Copy link
Copy Markdown

@4fn4n 4fn4n commented Oct 4, 2025

Summarise the feature

Issue ticket # 168, 194, 195, 196

  • 168 [FE][MyDS] SPLaSK compliance components, part 2
  • 194 [FE][MyDS] SPLaSK compliance - Broadcast, PrivacyPolicy, Freedom Information
  • 195 [FE][MyDS] SPLaSK compliance - Number of Online Services + Online Procurement Announcement + E-Participation
  • 196 [FE][MyDS] SPLaSK compliance - E-Participation

Description:
SPLaSK compliance - Broadcast, Number of online services, Freedom of Information, Online Procurement Announcement, E-participation, privacy policy on link component and E-participation on button component

Type of change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • This change requires a documentation update

Affected endpoints

none

Checklist

  • My code follows the style guidelines of this project
  • I have performed a self-review of my code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings
  • I have added tests that prove my fix is effective or that my feature works

…vices, Freedom of Information, Online Procurement Announcement, E-participation, privacy policy on link component and E-participation on button component
@4fn4n 4fn4n requested review from Copilot and zaidaiman October 4, 2025 05:39
@4fn4n 4fn4n self-assigned this Oct 4, 2025
@4fn4n 4fn4n added the Feature label Oct 4, 2025
@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented Oct 4, 2025

🦋 Changeset detected

Latest commit: 26c54c7

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 4 packages
Name Type
@govtechmy/myds-react Patch
@govtechmy/myds-docs Patch
@govtechmy/kd-standard Patch
@govtechmy/myds-storybook Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@vercel
Copy link
Copy Markdown

vercel Bot commented Oct 4, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
myds Ready Ready Preview, Comment Feb 12, 2026 3:57am
myds-storybook Ready Ready Preview, Comment Feb 12, 2026 3:57am

Request Review

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR adds SPLaSK (Social Platform for Learning and Sharing Knowledge) compliance support to the Link and Button components by introducing wrapper attributes that conditionally wrap components with custom HTML elements.

  • Added JSX type declarations for SPLaSK custom elements in the Link component
  • Implemented conditional wrapper logic for both Link and Button components based on SPLaSK attributes
  • Added support for 7 SPLaSK variants in Link component and 1 in Button component

Reviewed Changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.

File Description
packages/react/src/components/link.tsx Added JSX declarations for SPLaSK elements and conditional wrapper logic with 7 SPLaSK attribute variants
packages/react/src/components/button.tsx Added SplaskOnlineEParticipation attribute with conditional wrapper for e-participation compliance
.changeset/lemon-tables-beam.md Added changeset entry documenting the SPLaSK compliance feature

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

Comment on lines +137 to +145
const buttonElement = (
<Comp
ref={ref}
className={clx(button_cva({ variant, size, className, iconOnly }))}
{...props}
>
{children}
</Comp>
);
Copy link

Copilot AI Oct 4, 2025

Choose a reason for hiding this comment

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

The ButtonContext.Provider wrapper has been removed, which will break components that depend on the button context (like ButtonIcon or ButtonText). The context should be preserved around the button element.

Copilot uses AI. Check for mistakes.
Comment on lines +150 to +152
<div splwpk-online-e-participation="splwpk-online-e-participation">
{buttonElement}
</div>
Copy link

Copilot AI Oct 4, 2025

Choose a reason for hiding this comment

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

The SPLaSK attribute should use the JSX type declaration pattern from the Link component. Add the custom element declaration and use the proper JSX element instead of a div with custom attributes.

Suggested change
<div splwpk-online-e-participation="splwpk-online-e-participation">
{buttonElement}
</div>
<splask-online-e-participation>
{buttonElement}
</splask-online-e-participation>

Copilot uses AI. Check for mistakes.
Comment thread packages/react/src/components/link.tsx Outdated
* @example
* <Link href="https://design.digital.gov.my" newTab primary underline="always">MYDS</Link>
* @see {@link https://design.digital.gov.my/?path=/docs/myds-react-link--docs}
* <Link href="https://design.digital.gov.my" newTab primary underline="always" SplaskBroadcast>
Copy link

Copilot AI Oct 4, 2025

Choose a reason for hiding this comment

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

The example documentation shows SplaskBroadcast as a boolean prop, but it should include the proper value assignment (SplaskBroadcast={true}) to demonstrate correct usage.

Suggested change
* <Link href="https://design.digital.gov.my" newTab primary underline="always" SplaskBroadcast>
* <Link href="https://design.digital.gov.my" newTab primary underline="always" SplaskBroadcast={true}>

Copilot uses AI. Check for mistakes.
@4fn4n 4fn4n requested review from Copilot and harrisazmi February 12, 2026 03:53
@4fn4n
Copy link
Copy Markdown
Author

4fn4n commented Feb 12, 2026

Updated @harrisazmi

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated 7 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread packages/react/src/components/link.tsx Outdated
Comment on lines +118 to +130
// collect Splask attributes
const attrs: Record<string, string> = {};
if (SplaskBroadcast) attrs["splwpk-broadcast"] = "splwpk-broadcast";
if (SplaskOnlineServices) attrs["splwpk-online-services"] = "splwpk-online-services";
if (SplaskOnlineEParticipation) attrs["splwpk-online-e-participation"] = "splwpk-online-e-participation";
if (SplaskPrivacyPolicy) attrs["splwpk-privacy-policy"] = "splwpk-privacy-policy";
if (SplaskProcurement) attrs["splwpk-procurement"] = "splwpk-procurement";
if (SplaskFreedom) attrs["splwpk-freedom"] = "splwpk-freedom";
if (SplaskFaqs) attrs["splwpk-faqs"] = "splwpk-faqs";

if (Object.keys(attrs).length === 0) return linkElement;

return <div {...attrs}>{linkElement}</div>;
Copy link

Copilot AI Feb 12, 2026

Choose a reason for hiding this comment

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

Spreading Record<string, string> into a JSX element typically fails TypeScript checks because it implies every possible prop name (e.g. onClick) is a string, which is incompatible with React’s event handler prop types. Also, the keys like "splwpk-broadcast" are being used as custom attributes on a div, but the earlier JSX.IntrinsicElements augmentation declares them as custom elements (tags), not attributes, so it doesn’t address the typing issue. Consider rendering actual wrapper custom elements (e.g. <splwpk-broadcast>...</splwpk-broadcast>) or switching to data-* attributes (which are supported/typable), and avoid using a generic Record<string,string> spread as JSX props.

Suggested change
// collect Splask attributes
const attrs: Record<string, string> = {};
if (SplaskBroadcast) attrs["splwpk-broadcast"] = "splwpk-broadcast";
if (SplaskOnlineServices) attrs["splwpk-online-services"] = "splwpk-online-services";
if (SplaskOnlineEParticipation) attrs["splwpk-online-e-participation"] = "splwpk-online-e-participation";
if (SplaskPrivacyPolicy) attrs["splwpk-privacy-policy"] = "splwpk-privacy-policy";
if (SplaskProcurement) attrs["splwpk-procurement"] = "splwpk-procurement";
if (SplaskFreedom) attrs["splwpk-freedom"] = "splwpk-freedom";
if (SplaskFaqs) attrs["splwpk-faqs"] = "splwpk-faqs";
if (Object.keys(attrs).length === 0) return linkElement;
return <div {...attrs}>{linkElement}</div>;
const hasSplaskAttrs =
SplaskBroadcast ||
SplaskOnlineServices ||
SplaskOnlineEParticipation ||
SplaskPrivacyPolicy ||
SplaskProcurement ||
SplaskFreedom ||
SplaskFaqs;
if (!hasSplaskAttrs) return linkElement;
return (
<div
splwpk-broadcast={
SplaskBroadcast ? "splwpk-broadcast" : undefined
}
splwpk-online-services={
SplaskOnlineServices ? "splwpk-online-services" : undefined
}
splwpk-online-e-participation={
SplaskOnlineEParticipation
? "splwpk-online-e-participation"
: undefined
}
splwpk-privacy-policy={
SplaskPrivacyPolicy ? "splwpk-privacy-policy" : undefined
}
splwpk-procurement={
SplaskProcurement ? "splwpk-procurement" : undefined
}
splwpk-freedom={SplaskFreedom ? "splwpk-freedom" : undefined}
splwpk-faqs={SplaskFaqs ? "splwpk-faqs" : undefined}
>
{linkElement}
</div>
);

Copilot uses AI. Check for mistakes.
Comment thread packages/react/src/components/link.tsx Outdated

if (Object.keys(attrs).length === 0) return linkElement;

return <div {...attrs}>{linkElement}</div>;
Copy link

Copilot AI Feb 12, 2026

Choose a reason for hiding this comment

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

Wrapping Link in a div changes the component’s default inline behavior and can produce invalid HTML in common cases (e.g., a link used inside text/paragraph flow). If a wrapper is required, prefer an inline wrapper (span) or the actual SPLaSK custom wrapper element so layout/semantics remain consistent.

Suggested change
return <div {...attrs}>{linkElement}</div>;
return <span {...attrs}>{linkElement}</span>;

Copilot uses AI. Check for mistakes.
Comment thread packages/react/src/components/link.tsx Outdated
Comment on lines +7 to +38
declare global {
namespace JSX {
interface IntrinsicElements {
"splwpk-broadcast": React.DetailedHTMLProps<
React.HTMLAttributes<HTMLElement>,
HTMLElement
>;
"splwpk-online-services": React.DetailedHTMLProps<
React.HTMLAttributes<HTMLElement>,
HTMLElement
>;
"splwpk-online-e-participation": React.DetailedHTMLProps<
React.HTMLAttributes<HTMLElement>,
HTMLElement
>;
"splwpk-privacy-policy": React.DetailedHTMLProps<
React.HTMLAttributes<HTMLElement>,
HTMLElement
>;
"splwpk-procurement": React.DetailedHTMLProps<
React.HTMLAttributes<HTMLElement>,
HTMLElement
>;
"splwpk-freedom": React.DetailedHTMLProps<
React.HTMLAttributes<HTMLElement>,
HTMLElement
>;
"splwpk-faqs": React.DetailedHTMLProps<
React.HTMLAttributes<HTMLElement>,
HTMLElement
>;
}
Copy link

Copilot AI Feb 12, 2026

Choose a reason for hiding this comment

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

The declare global JSX augmentation is embedded in the component file, which makes the component responsible for global type setup and can lead to duplication/ordering issues as custom tags grow. Prefer moving this to a dedicated *.d.ts (e.g. splask-elements.d.ts) in the React package so it’s clearly global typing, easier to maintain, and doesn’t mix type plumbing with component logic.

Suggested change
declare global {
namespace JSX {
interface IntrinsicElements {
"splwpk-broadcast": React.DetailedHTMLProps<
React.HTMLAttributes<HTMLElement>,
HTMLElement
>;
"splwpk-online-services": React.DetailedHTMLProps<
React.HTMLAttributes<HTMLElement>,
HTMLElement
>;
"splwpk-online-e-participation": React.DetailedHTMLProps<
React.HTMLAttributes<HTMLElement>,
HTMLElement
>;
"splwpk-privacy-policy": React.DetailedHTMLProps<
React.HTMLAttributes<HTMLElement>,
HTMLElement
>;
"splwpk-procurement": React.DetailedHTMLProps<
React.HTMLAttributes<HTMLElement>,
HTMLElement
>;
"splwpk-freedom": React.DetailedHTMLProps<
React.HTMLAttributes<HTMLElement>,
HTMLElement
>;
"splwpk-faqs": React.DetailedHTMLProps<
React.HTMLAttributes<HTMLElement>,
HTMLElement
>;
}
declare namespace JSX {
interface IntrinsicElements {
"splwpk-broadcast": React.DetailedHTMLProps<
React.HTMLAttributes<HTMLElement>,
HTMLElement
>;
"splwpk-online-services": React.DetailedHTMLProps<
React.HTMLAttributes<HTMLElement>,
HTMLElement
>;
"splwpk-online-e-participation": React.DetailedHTMLProps<
React.HTMLAttributes<HTMLElement>,
HTMLElement
>;
"splwpk-privacy-policy": React.DetailedHTMLProps<
React.HTMLAttributes<HTMLElement>,
HTMLElement
>;
"splwpk-procurement": React.DetailedHTMLProps<
React.HTMLAttributes<HTMLElement>,
HTMLElement
>;
"splwpk-freedom": React.DetailedHTMLProps<
React.HTMLAttributes<HTMLElement>,
HTMLElement
>;
"splwpk-faqs": React.DetailedHTMLProps<
React.HTMLAttributes<HTMLElement>,
HTMLElement
>;

Copilot uses AI. Check for mistakes.
Comment thread packages/react/src/components/link.tsx Outdated
Comment on lines +50 to +57
// Splask attributes
SplaskBroadcast?: boolean;
SplaskOnlineServices?: boolean;
SplaskOnlineEParticipation?: boolean;
SplaskPrivacyPolicy?: boolean;
SplaskProcurement?: boolean;
SplaskFreedom?: boolean;
SplaskFaqs?: boolean;
Copy link

Copilot AI Feb 12, 2026

Choose a reason for hiding this comment

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

The new prop names are PascalCase (SplaskBroadcast, etc.), which is atypical for React props and can read like components. Consider renaming to camelCase (e.g. splaskBroadcast, splaskOnlineServices, …) for consistency with common React conventions.

Copilot uses AI. Check for mistakes.
Comment on lines +123 to +127
const ButtonContext = createContext<VariantProps<typeof button_cva>>({
variant: "primary-fill",
size: "small",
iconOnly: false,
});
Copy link

Copilot AI Feb 12, 2026

Choose a reason for hiding this comment

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

ButtonContext is typed as VariantProps<typeof button_cva>, but the default value and provider value include iconOnly. Since iconOnly is declared on ButtonProps separately (not as a button_cva variant in this diff), this is very likely a TypeScript type error. Fix by changing the context type to include iconOnly explicitly (e.g. a dedicated interface/type that includes variant, size, and iconOnly) or by making iconOnly an actual button_cva variant if that’s the intent.

Copilot uses AI. Check for mistakes.
return (
<ButtonContext.Provider value={{ variant, size }}>
const buttonElement = (
<ButtonContext.Provider value={{ variant, size, iconOnly }}>
Copy link

Copilot AI Feb 12, 2026

Choose a reason for hiding this comment

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

ButtonContext is typed as VariantProps<typeof button_cva>, but the default value and provider value include iconOnly. Since iconOnly is declared on ButtonProps separately (not as a button_cva variant in this diff), this is very likely a TypeScript type error. Fix by changing the context type to include iconOnly explicitly (e.g. a dedicated interface/type that includes variant, size, and iconOnly) or by making iconOnly an actual button_cva variant if that’s the intent.

Copilot uses AI. Check for mistakes.
if (!SplaskOnlineEParticipation) return buttonElement;

return (
<div splwpk-online-e-participation="splwpk-online-e-participation">
Copy link

Copilot AI Feb 12, 2026

Choose a reason for hiding this comment

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

splwpk-online-e-participation is a non-standard DOM attribute; React may pass it through at runtime, but TypeScript’s JSX typings typically reject it on a div. Align this with the approach used for custom elements by wrapping with a real custom element tag (e.g. <splwpk-online-e-participation>...</splwpk-online-e-participation>) or use a data-* attribute (e.g. data-splwpk-online-e-participation) to keep it valid/typable.

Suggested change
<div splwpk-online-e-participation="splwpk-online-e-participation">
<div data-splwpk-online-e-participation="splwpk-online-e-participation">

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants