Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions changelog.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
Version x.x.x - xth July, 2026
- Improvement: Atom - Radio Button: Added reverse position support.

Version 1.7.13 - 11th June, 2026
- Fix: Resolved `patch-package: command not found` install failure when the library is consumed as a git dependency. `patch-package` is now a runtime dependency so the bundled Lexical Shadow DOM patches are applied in consumer projects, which is required for the Editor Input mention menu Shadow DOM fix to work.

Expand Down
75 changes: 75 additions & 0 deletions src/components/radio-button/radio-button.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,81 @@ RadioWithBorderSmallSize.args = {
size: 'sm',

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

What: Consider adding comments to describe the purpose of new story components such as RadioWithBorderReversePosition and SwitchWithBorderReversePosition. It's not immediately clear what these stories are demonstrating or why they are useful.

Why: Adding comments will help other developers (or future you) understand the intended use and functionality of these stories, improving maintainability and clarity.

How: For instance, add comments like // Story demonstrating the reverse position for bordered RadioButton above each story definition.

};

const RadioWithBorderReversePositionTemplate: StoryFn<RadioButtonGroupProps> = (
args
) => {
const [ value, setValue ] = useState( args.value || args.defaultValue );

return (

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

What: In the new templates, you're repeating the setup code for RadioButton and Switch components. Consider creating a reusable function to encapsulate this logic.

Why: Duplicating code can lead to maintenance issues since a change in one instance would require a change in all. It decreases readability and increases potential for bugs.

How: You can create a helper function that returns the RadioButton.Group setup and just modify it as necessary for different scenarios.

<RadioButton.Group
value={ value }
columns={ args.columns ?? 3 }
onChange={ ( val ) => {
setValue( val as string );
} }
{ ...args }
>
{ [ 1, 2, 3, 4, 5, 6 ].map( ( num ) => (
<RadioButton.Button
key={ num }
value={ `option${ num }` }
label={ {
heading: `Option ${ num }`,
} }

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

What: The new RadioButton stories have added complexity with monitoring state management. Ensure that the initial state is handled carefully to avoid unintentional mutations or leaks in state management.

Why: Improper handling of component state can lead to bugs that are difficult to trace and can affect usability and performance.

How: Consider using functional updates to set state or utilizing React's useReducer for complex state logic to prevent inadvertent state bugs.

disabled={ args.disabled }
borderOn={ true }
reversePosition={ true }
/>
) ) }
</RadioButton.Group>
);
};

export const RadioWithBorderReversePosition =
RadioWithBorderReversePositionTemplate.bind( {} );
RadioWithBorderReversePosition.args = {
size: 'md',
};

const SwitchWithBorderReversePositionTemplate: StoryFn<
RadioButtonGroupProps
> = ( args ) => {
const [ value, setValue ] = useState<string[]>( [] );

return (
<RadioButton.Group
value={ value }
columns={ args.columns ?? 2 }
multiSelection={ true }
onChange={ ( val ) => {
setValue( val as string[] );
} }
{ ...args }
>
{ [ 1, 2, 3, 4 ].map( ( num ) => (
<RadioButton.Button
key={ num }
value={ `option${ num }` }
label={ {
heading: `Option ${ num }`,
description: `Description ${ num }`,
} }
disabled={ args.disabled }
borderOn={ true }
reversePosition={ true }
useSwitch={ true }
/>
) ) }
</RadioButton.Group>
);
};

export const SwitchWithBorderReversePosition =
SwitchWithBorderReversePositionTemplate.bind( {} );
SwitchWithBorderReversePosition.args = {
size: 'md',
};

const defaultRadioButtonGroupData = [
{
id: '1',
Expand Down
22 changes: 14 additions & 8 deletions src/components/radio-button/radio-button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ export interface RadioButtonProps extends RadioButtonCommonProps {
inlineIcon?: boolean;
/** Hides the selection indicator */
hideSelection?: boolean;
/** Reverses the position of icon and label */
/** Places the selection control (radio/switch) on the left and the label on the right. Works with the bordered variant (`borderOn`) */
reversePosition?: boolean;
/** Adds a border around the button */
borderOn?: boolean;
Expand Down Expand Up @@ -340,7 +340,6 @@ export const RadioButtonComponent = (
'space-y-3': size === 'sm',
'space-y-4': size === 'md',
},
reversePosition && ( useSwitch ? 'ml-10' : 'ml-4' ),
inlineIcon && 'flex gap-2',
inlineIcon && ! label.description && 'items-center'
) }
Expand All @@ -358,7 +357,7 @@ export const RadioButtonComponent = (
>
<p

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

What: Using [overflow-wrap:anywhere] in your class names may introduce non-standard handling of overflow that could affect performance in rare scenarios or introduce browser inconsistencies.

Why: Maintaining a balance between CSS standards and performance is crucial. Overly broad or non-standard CSS can lead to unexpected behavior across different browsers, which can also potentially influence performance.

How: Consider using a more standard CSS approach for overflowing text, such as setting overflow-wrap: break-word; in a dedicated CSS class or style instead.

className={ cn(
'text-text-primary font-medium m-0',
'text-text-primary font-medium m-0 [overflow-wrap:anywhere]',
textSizeClassNames[
size as keyof typeof textSizeClassNames
],
Expand All @@ -368,7 +367,7 @@ export const RadioButtonComponent = (
{ label.heading }
</p>
{ label.description && (
<p className="text-text-tertiary text-sm font-normal leading-5 m-0">
<p className="text-text-tertiary text-sm font-normal leading-5 m-0 [overflow-wrap:anywhere]">
{ label.description }
</p>
) }
Expand Down Expand Up @@ -405,6 +404,13 @@ export const RadioButtonComponent = (
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

What: The conditional assignment of controlSpacingClass can be optimized for readability and maintainability.

Why: Improving conditional logic for class assignment can enhance code legibility and decrease potential for errors when toggling classes, especially as components evolve.

How: Consider using the ternary operator directly in the class list like this: const controlSpacingClass = reversePosition ? (useSwitch ? 'pl-16' : 'pl-12') : 'pr-12'; This reduces the need for an additional block of code and keeps related logic together.

};

// Reserve space on the control side. Default: control on the right (pr-12).
// Reversed: control on the left; the switch needs more room than the radio.
let controlSpacingClass = 'pr-12';
if ( reversePosition ) {
controlSpacingClass = useSwitch ? 'pl-16' : 'pl-12';
}

const paddingClasses = {
'pl-3.5 pr-2.5 py-2.5': size === 'sm' && ! ( icon && useSwitch ),
'p-3': size === 'sm' && ( ( icon && useSwitch ) || ( icon && badgeItem ) ),
Expand All @@ -425,7 +431,7 @@ export const RadioButtonComponent = (
checkedValue &&
'outline-border-interactive',
paddingClasses,
'pr-12',
controlSpacingClass,
isDisabled && 'cursor-not-allowed opacity-40',
buttonWrapperClasses
) }
Expand Down Expand Up @@ -457,10 +463,10 @@ export const RadioButtonComponent = (
) }
<label
className={ cn(
'absolute mr-0.5 right-3 flex items-center cursor-pointer rounded-full gap-2',
reversePosition && 'left-0',
'absolute flex items-center cursor-pointer rounded-full gap-2',
reversePosition ? 'left-3 ml-0.5' : 'right-3 mr-0.5',
isDisabled && 'cursor-not-allowed',
inlineIcon && 'mr-3'
inlineIcon && ( reversePosition ? 'ml-3' : 'mr-3' )
) }
onClick={ handleLabelClick }
>
Expand Down
1 change: 1 addition & 0 deletions src/theme/default-config.js
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,7 @@ const defaultTheme = {
},
borderWidth: {
0.5: '0.5px',
1.5: '1.5px',
},
},
},
Expand Down
Loading