Skip to content

Conversation

@QuintonJason
Copy link
Contributor

@QuintonJason QuintonJason commented Oct 20, 2025

Description

  • pds-radio - add contained variant
  • add image slot

Fixes DSS-1473

Contained With Image
Screenshot 2025-10-20 at 10 43 36 AM Screenshot 2025-10-20 at 10 43 43 AM

Type of change

  • Bug fix (non-breaking change which fixes an issue)
  • This change requires a documentation update

How Has This Been Tested?

Visit the Radio page, scroll to the With Image and Image Group section and verify

  • unit tests
  • e2e tests

Test Configuration:

  • Pine versions:
  • OS:
  • Browsers:
  • Screen readers:
  • Misc:

Checklist:

If not applicable, leave options unchecked.

  • 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
  • New and existing tests pass locally with my changes
  • Design has QA'ed and approved this PR

@netlify
Copy link

netlify bot commented Oct 20, 2025

Deploy Preview for pine-design-system ready!

Name Link
🔨 Latest commit 0f0c1f5
🔍 Latest deploy log https://app.netlify.com/projects/pine-design-system/deploys/68f91ad5e514d00008ba23a2
😎 Deploy Preview https://deploy-preview-562--pine-design-system.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@github-actions github-actions bot added bug Something isn't working package: core Changes have been made to the Core package labels Oct 20, 2025
@QuintonJason QuintonJason self-assigned this Oct 20, 2025
@QuintonJason QuintonJason changed the title Fix/radio add bordered variant fix(pds-radio): add contained variant and image slot Oct 20, 2025
@QuintonJason QuintonJason force-pushed the fix/radio-add-bordered-variant branch from 5a5e386 to f39b2e1 Compare October 20, 2025 15:49
@QuintonJason QuintonJason marked this pull request as ready for review October 20, 2025 17:34
@QuintonJason
Copy link
Contributor Author

@coderabbitai please review this PR

@coderabbitai
Copy link

coderabbitai bot commented Oct 20, 2025

@QuintonJason: I'll review the changes in this PR, which adds a contained variant and image slot to the pds-radio component.

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai
Copy link

coderabbitai bot commented Oct 20, 2025

📝 Walkthrough

Walkthrough

This pull request extends the PdsRadio component with two new features: a hasBorder boolean property for rendering a bordered radio variant, and support for an "image" slot to enable image-based radio options. Changes include updates to the component's TypeScript implementation to detect and render the image slot, corresponding SCSS styling for the border and image variants, updated type definitions in components.d.ts, documentation additions in the readme and MDX files, a new Storybook story demonstrating the WithBorder variant, and comprehensive end-to-end and unit tests validating the new functionality across various state combinations.

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Description Check ⚠️ Warning The pull request description follows the general structure of the template and includes the required sections, but several key areas are incomplete or missing. The "Description" section lacks an explanation of motivation and context beyond the issue reference, and fails to list any new dependencies or updates. The "Test Configuration" section is present in the template but entirely empty, with no details provided for Pine versions, OS, Browsers, Screen readers, or other configuration specifics. Additionally, most checklist items remain unchecked, including important items like code review, self-review, documentation updates, and design QA approval. While the core information is present (issue reference, type of change selections, basic testing indicators), the description does not fully satisfy the template's requirements for a complete submission. To meet the template requirements, the PR description should be updated to include: (1) a more detailed motivation and context section explaining why the contained variant and image slot were needed, (2) any new dependencies or updates required, (3) specific test configuration details (Pine versions, OS, Browsers, Screen readers, Misc), and (4) completion of the checklist items to confirm code standards, self-review, documentation updates, test coverage, and design QA approval. Additionally, consider whether "New feature" is a more accurate type of change classification than "Bug fix" given that new functionality (hasBorder prop, image slot, new styles) is being added.
✅ Passed checks (2 passed)
Check name Status Explanation
Title Check ✅ Passed The PR title "fix(pds-radio): add contained variant and image slot" directly and clearly summarizes the primary changes in the pull request. It uses the conventional commit format "fix(pds-radio):" and identifies both main features being added: the contained variant (implemented via the hasBorder property) and the image slot. The title is specific and concise, providing meaningful information about what was changed without extraneous details or vague terminology.
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/radio-add-bordered-variant

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🧹 Nitpick comments (3)
libs/core/src/components/pds-radio/pds-radio.scss (2)

83-95: Avoid duplicate visually-hidden definitions.

Both input.visually-hidden and global .visually-hidden implement the same pattern. Keep one utility to reduce drift.

-  /* stylelint-disable-next-line selector-no-qualifying-type */
-  &.visually-hidden {
-    border: 0;
-    clip: rect(0 0 0 0);
-    clip-path: polygon(0 0, 0 0, 0 0);
-    height: 1px;
-    margin: -1px;
-    overflow: hidden;
-    padding: 0;
-    position: absolute;
-    white-space: nowrap;
-    width: 1px;
-  }
+  /* Rely on the global `.visually-hidden` utility */

Also applies to: 159-170


224-253: grid-area has no effect without a grid container.

This block uses grid-area while the parent layout is flex. Remove or introduce a grid container where intended.

libs/core/src/components/pds-radio/pds-radio.tsx (1)

101-109: Make image-slot detection reactive to slot changes.

querySelector('[slot="image"]') won’t trigger re-render when slot content changes. Track state via slotchange.

+import { Component, Host, h, Prop, Event, EventEmitter, Element, State } from '@stencil/core';
...
-  private hasImageSlot(): boolean {
+  @State() private _hasImage = false;
+
+  private hasImageSlot(): boolean {
     const imageSlot = this.el.querySelector('[slot="image"]');
     return !!imageSlot;
   }
 
   private hasImage(): boolean {
-    return this.hasImageSlot();
+    return this._hasImage;
   }
+
+  componentWillLoad() {
+    this._hasImage = this.hasImageSlot();
+  }
...
-        {this.hasImage() && (
+        {this.hasImage() && (
           <div class="pds-radio__image-container" part="image-container">
-            <slot name="image" />
+            <slot name="image" onSlotchange={() => (this._hasImage = this.hasImageSlot())} />
           </div>
         )}

Also applies to: 176-181

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 142716f and f39b2e1.

📒 Files selected for processing (8)
  • libs/core/src/components.d.ts (3 hunks)
  • libs/core/src/components/pds-radio/docs/pds-radio.mdx (2 hunks)
  • libs/core/src/components/pds-radio/pds-radio.scss (4 hunks)
  • libs/core/src/components/pds-radio/pds-radio.tsx (6 hunks)
  • libs/core/src/components/pds-radio/readme.md (2 hunks)
  • libs/core/src/components/pds-radio/stories/pds-radio.stories.js (3 hunks)
  • libs/core/src/components/pds-radio/test/pds-radio.e2e.ts (2 hunks)
  • libs/core/src/components/pds-radio/test/pds-radio.spec.tsx (1 hunks)
🧰 Additional context used
🪛 Biome (2.1.2)
libs/core/src/components/pds-radio/pds-radio.tsx

[error] 136-136: Missing key property for this element in iterable.

The order of the items may change, and having a key can help React identify which item was moved.
Check the React documentation.

(lint/correctness/useJsxKeyInIterable)

🔇 Additional comments (12)
libs/core/src/components.d.ts (3)

1383-1387: Public prop added matches implementation.

hasBorder: boolean looks good and consistent with TSX and docs.


3999-4002: JSX typings updated correctly.

Optional hasBorder?: boolean in LocalJSX is appropriate.


4025-4027: Event doc improvement acknowledged.

Clarified pdsRadioChange payload. No issues.

libs/core/src/components/pds-radio/pds-radio.scss (3)

50-53: Verify :has() support for your browser matrix.

:has() on :host is modern. Confirm support for all target browsers or provide a fallback class.

Would you like a lightweight JS fallback (toggle is-checked class on change) if :has is unavailable?

Also applies to: 202-204


9-9: Host positioning looks good.

position: relative; enables the label overlay to capture clicks. No issues.


174-174: Typography update acknowledged.

Switch to var(--pine-typography-body) is fine.

libs/core/src/components/pds-radio/test/pds-radio.spec.tsx (1)

191-244: Good coverage for hasBorder.

Assertions cover static, dynamic, and combined states.

libs/core/src/components/pds-radio/docs/pds-radio.mdx (1)

85-95: New examples read well.

Bordered and image-slot demos align with the API.

Also applies to: 122-145, 146-179

libs/core/src/components/pds-radio/stories/pds-radio.stories.js (1)

9-9: Story wiring for hasBorder is correct.

Props map and example are good.

Also applies to: 32-33, 77-83

libs/core/src/components/pds-radio/readme.md (1)

16-16: README updates match the public API.

Property, event payload, slot, and part docs look good.

Also applies to: 28-31, 33-38, 40-45

libs/core/src/components/pds-radio/test/pds-radio.e2e.ts (1)

62-117: E2E coverage for has-border looks solid.

Static, absence, toggle, and combo states validated.

libs/core/src/components/pds-radio/pds-radio.tsx (1)

5-8: API/docs annotations look good.

Slot and part JSDoc plus hasBorder prop are consistent.

Also applies to: 46-51

Comment on lines +36 to +69
:host(.has-border) {
align-items: flex-start;
border: var(--pine-border);
border-radius: var(--pine-dimension-125);
column-gap: var(--pine-dimension-xs);
display: flex;
flex: 1;
flex-direction: column;
padding: var(--pine-dimension-md);

&:hover {
border: var(--pine-border-hover);
}

&:has(input:checked) {
box-shadow: 0 0 0 2px var(--pine-color-primary-hover);
}

label {
color: var(--pine-color-text);
font-weight: var(--pine-font-weight-semi-bold);

&::after {
content: "";
cursor: pointer;
height: 100%;
left: 0;
position: absolute;
top: 0;
width: 100%;
z-index: 1;
}
}
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Add visible focus styles for keyboard users when input is visually hidden.

Currently, input:focus-visible won’t be perceptible in bordered/image variants. Mirror focus to the container/host.

:host(.has-border) {
+  /* keyboard focus */
+  &:has(input:focus-visible) {
+    outline: var(--pine-outline-focus);
+    outline-offset: 2px;
+  }
  &:has(input:checked) {
    box-shadow: 0 0 0 2px var(--pine-color-primary-hover);
  }
}

:host(.has-image) {
+  /* keyboard focus */
+  &:has(input:focus-visible) {
+    outline: var(--pine-outline-focus);
+    outline-offset: 2px;
+  }
  &:has(input:checked) {
    box-shadow: 0 0 0 2px var(--pine-color-primary-hover);
  }
}

Also applies to: 189-206

🤖 Prompt for AI Agents
In libs/core/src/components/pds-radio/pds-radio.scss around lines 36 to 69 (and
also apply the same change to lines 189-206), the keyboard focus on the visually
hidden input isn't visible for bordered/image variants—mirror the input's
:focus-visible state to the host/container by adding a selector like
:host(.has-border):has(input:focus-visible) (and equivalent for the image
variant) that applies a clear visible focus style (outline or box-shadow and
optional border-color change) so keyboard users see focus even when the input
itself is visually hidden; ensure the focus style matches existing hover/checked
styles and respects design tokens (e.g., use var(--pine-color-primary-hover) or
a dedicated focus token).

Copy link
Member

@pixelflips pixelflips left a comment

Choose a reason for hiding this comment

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

Non-blocker, but should we add an image story? Otherwise, LGTM! 👍🏼

Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

This PR is being reviewed by Cursor Bugbot

Details

Your team is on the Bugbot Free tier. On this plan, Bugbot will review limited PRs each billing cycle for each member of your team.

To receive Bugbot reviews on all of your PRs, visit the Cursor dashboard to activate Pro and start your 14-day free trial.

>
<pds-icon icon={danger} size="small" />
{this.errorMessage}
)}
Copy link

Choose a reason for hiding this comment

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

Bug: Radio Component Fails to Detect Dynamic Image Content

The pds-radio component's image slot is conditionally rendered. If the component starts without slotted image content, the slot and its onSlotchange handler are not present. This prevents detection of dynamically added image content, as the _hasImage state cannot update.

Fix in Cursor Fix in Web

@QuintonJason QuintonJason merged commit 67848ab into main Oct 22, 2025
19 checks passed
@QuintonJason QuintonJason deleted the fix/radio-add-bordered-variant branch October 22, 2025 18:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working package: core Changes have been made to the Core package

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants