Skip to content

Commit

Permalink
fix: Fix InputGroup inner end width calculations (#2984)
Browse files Browse the repository at this point in the history
Fixes `InputGroup.InnerEnd` `width` and positioning calculations. Without this change, `InnerEnd` elements are rendered in the wrong location.

[category:Components]
  • Loading branch information
NicholasBoll authored Oct 14, 2024
1 parent 23aaa97 commit b361815
Show file tree
Hide file tree
Showing 4 changed files with 78 additions and 24 deletions.
4 changes: 3 additions & 1 deletion cypress/component/Autocomplete.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,9 @@ describe('Autocomplete', () => {

context('when the clear button is clicked', () => {
beforeEach(() => {
cy.get('[data-testid=clear]').click();
// Force click because Cypress gets confused if an element had `pointer-events; none` at any point
// in time, even if it doesn't at the point the click was attempted.
cy.get('[data-testid=clear]').click({force: true});
});

it('should clear the combobox', () => {
Expand Down
6 changes: 2 additions & 4 deletions modules/react/text-input/lib/InputGroup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ export const useInputGroupInput = createElemPropsHook(useInputGroupModel)((model

return {
ref: elementRef,
placeholder: '', // Make sure a placeholder attribute always exists for `:placeholder-shown`
};
});

Expand Down Expand Up @@ -172,7 +173,6 @@ export const useClearButton = createElemPropsHook(useInputGroupModel)(model => {
// This will clear the input's value
dispatchInputEvent(model.state.inputRef.current, '');
},
placeholder: '', // Make sure a placeholder attribute always exists for `:placeholder-shown`
} as const;
});

Expand Down Expand Up @@ -211,8 +211,6 @@ export const inputGroupStencil = createStencil({
// Clear Button
'& :has([data-part="input-group-clear-button"])': {
transition: 'opacity 300ms ease',
opacity: 1,
pointerEvents: 'auto',
},

// Clear Button when a placeholder is being shown (no value)
Expand Down Expand Up @@ -311,7 +309,7 @@ export const InputGroup = createContainer('div')({
});
}
if (child.type === InputGroupInnerEnd) {
const offset = wrapInCalc(offsetsEnd.slice(indexEnd, -1)) || '0px';
const offset = wrapInCalc(offsetsEnd.slice(indexEnd + 1, offsetsEnd.length)) || '0px';
indexEnd++;

return React.cloneElement(child, {
Expand Down
3 changes: 2 additions & 1 deletion modules/react/text-input/stories/TextInput.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,8 @@ and will be semantically correct in left-to-right and right-to-left languages.
`InputGroup.InnerStart` and `InputGroup.InnerEnd` subcomponents can handle any child elements, but
are built for icons. The default width is `40px`, which is perfect for icons. If you need to use
something else, be sure to set the `width` property of `InputGroup.InnerStart` or
`InputGroup.InnerEnd` to match the intended width of the element.
`InputGroup.InnerEnd` to match the intended width of the element. Do not use the `cs` prop or any
method to change width. The `width` prop is used to correctly position other inner elements.

<ExampleCodeBlock code={Icons} />

Expand Down
89 changes: 71 additions & 18 deletions modules/react/text-input/stories/visualTesting.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -90,29 +90,66 @@ export const InputGroupStates = () => (
<StaticStates>
<ComponentStatesTable
rowProps={[
{label: 'Start', props: {start: [<SystemIcon icon={searchIcon} size="small" />]}},
{
label: 'Start',
props: {
start: [
<InputGroup.InnerStart>
<SystemIcon icon={searchIcon} size="small" />
</InputGroup.InnerStart>,
],
},
},
{
label: 'End',
props: {
end: [
<TertiaryButton role="presentation" icon={xSmallIcon} size="small" tabIndex={-1} />,
<InputGroup.InnerEnd>
<TertiaryButton role="presentation" icon={xSmallIcon} size="small" tabIndex={-1} />
</InputGroup.InnerEnd>,
],
},
},
{
label: 'Both',
props: {
start: [<SystemIcon icon={searchIcon} size="small" />],
start: [
<InputGroup.InnerStart>
<SystemIcon icon={searchIcon} size="small" />
</InputGroup.InnerStart>,
],
end: [
<TertiaryButton role="presentation" icon={xSmallIcon} size="small" tabIndex={-1} />,
<InputGroup.InnerEnd>
<TertiaryButton role="presentation" icon={xSmallIcon} size="small" tabIndex={-1} />
</InputGroup.InnerEnd>,
],
},
},
{
label: 'Multiple',
props: {
start: [<span>1</span>, <span>2</span>, <span>3</span>],
end: [<span>4</span>, <span>5</span>, <span>6</span>],
start: [
<InputGroup.InnerStart>
<span>1</span>
</InputGroup.InnerStart>,
<InputGroup.InnerStart>
<span>2</span>
</InputGroup.InnerStart>,
<InputGroup.InnerStart>
<span>3</span>
</InputGroup.InnerStart>,
],
end: [
<InputGroup.InnerEnd>
<span>4</span>
</InputGroup.InnerEnd>,
<InputGroup.InnerEnd>
<span>5</span>
</InputGroup.InnerEnd>,
<InputGroup.InnerEnd>
<span>6</span>
</InputGroup.InnerEnd>,
],
},
},
{
Expand All @@ -121,7 +158,11 @@ export const InputGroupStates = () => (
placeholder: 'Placeholder',
value: 'Some Value',
start: [],
end: [<InputGroup.ClearButton />],
end: [
<InputGroup.InnerEnd>
<InputGroup.ClearButton />
</InputGroup.InnerEnd>,
],
},
},
{
Expand All @@ -130,7 +171,27 @@ export const InputGroupStates = () => (
placeholder: '',
value: '',
start: [],
end: [<InputGroup.ClearButton />],
end: [
<InputGroup.InnerEnd>
<InputGroup.ClearButton />
</InputGroup.InnerEnd>,
],
},
},
{
label: 'Variable Width',
props: {
end: [
<InputGroup.InnerEnd width="10px" backgroundColor="blueberry200">
<span>1</span>
</InputGroup.InnerEnd>,
<InputGroup.InnerEnd width="20px" backgroundColor="cantaloupe200">
<span>2</span>
</InputGroup.InnerEnd>,
<InputGroup.InnerEnd width="30px" backgroundColor="greenApple200">
<span>3</span>
</InputGroup.InnerEnd>,
],
},
},
]}
Expand All @@ -142,20 +203,12 @@ export const InputGroupStates = () => (
{({value, placeholder, ...props}) => (
<CanvasProvider theme={{canvas: {direction: props.dir}}}>
<InputGroup width={300}>
{props.start &&
props.start.map((start, index) => (
<InputGroup.InnerStart key={index} pointerEvents="none">
{start}
</InputGroup.InnerStart>
))}
{props.start}
<InputGroup.Input
placeholder={placeholder}
value={value ?? 'Very Long Text. Very Long Text. Very Long Text.'}
/>
{props.end &&
props.end.map((end, index) => (
<InputGroup.InnerEnd key={index}>{end}</InputGroup.InnerEnd>
))}
{props.end}
</InputGroup>
</CanvasProvider>
)}
Expand Down

0 comments on commit b361815

Please sign in to comment.