Skip to content

Commit

Permalink
add stretch prop to Button (#1971)
Browse files Browse the repository at this point in the history
This is achieved using a private inline CSS variable, which is made available globally to allow setting from all elements.
  • Loading branch information
mayank99 authored Apr 4, 2024
1 parent 5308fa6 commit 3d42bc1
Show file tree
Hide file tree
Showing 8 changed files with 55 additions and 4 deletions.
5 changes: 5 additions & 0 deletions .changeset/thin-eagles-sparkle.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@itwin/itwinui-react": minor
---

Added a new `stretch` prop to `Button` to allow it to span the full width of its container.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
11 changes: 11 additions & 0 deletions apps/react-workshop/src/Button.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -113,3 +113,14 @@ export const AsLink = () => {
</Button>
);
};

export const Stretch = () => {
return <Button stretch>Sign in</Button>;
};
Stretch.decorators = [
(Story: () => React.ReactNode) => (
<div style={{ width: 300, outline: '1px solid', padding: 8 }}>
<Story />
</div>
),
];
1 change: 1 addition & 0 deletions apps/react-workshop/src/Button.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ describe('Button', () => {
'With Icon',
'Call To Action',
'As Link',
'Stretch',
];

tests.forEach((testName) => {
Expand Down
16 changes: 12 additions & 4 deletions apps/website/src/content/docs/button.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,7 @@ thumbnail: Button
Buttons have states and events and should be used when a form is submitted or where the button represents a clear call to action on a page.
In some cases, buttons can also be used in place of href links to draw special attention to that action.

## Variants

### Default
## Usage

The default button should be used in most circumstances. If you are unsure as to what button to use, use this button!

Expand Down Expand Up @@ -65,6 +63,16 @@ There are 3 different sizes available, which can be applied to any button. The m
<AllExamples.ButtonSizeExample client:load />
</LiveExample>

### Stretch

To make a button stretch to the full width of its parent, use the `stretch` prop.

```jsx
<Button stretch>Sign in</Button>
```

This is useful in narrow containers and mobile views. Don't overuse this!

## Button props

<PropsTable path={frontmatter.propsPathDefault} />
Expand Down Expand Up @@ -119,7 +127,7 @@ If the button does obscure anything important, we suggest adding empty space at

<PropsTable path={frontmatter.propsPathIdeasButton} />

## Usage
## Usage guidelines

### Style types

Expand Down
5 changes: 5 additions & 0 deletions packages/itwinui-react/src/core/Buttons/Button.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -215,3 +215,8 @@ it('should render [x]Props correctly', () => {
expect(labelElement).toBeTruthy();
expect(labelElement.style.width).toBe('80px');
});

it('should respect `stretch` prop', () => {
const { container } = render(<Button stretch>Do not click</Button>);
expect(container.querySelector('button')).toHaveStyle('--_iui-width: 100%');
});
13 changes: 13 additions & 0 deletions packages/itwinui-react/src/core/Buttons/Button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,12 @@ export type ButtonProps = {
* Passes props to the end icon.
*/
endIconProps?: React.ComponentProps<'span'>;
/**
* Whether the button should stretch to fill the width of the container.
*
* This is useful on narrow containers and mobile views.
*/
stretch?: boolean;
} & Pick<React.ComponentProps<typeof ButtonBase>, 'htmlDisabled'>;

/**
Expand All @@ -61,6 +67,7 @@ export const Button = React.forwardRef((props, ref) => {
labelProps,
startIconProps,
endIconProps,
stretch,
...rest
} = props;

Expand All @@ -71,6 +78,12 @@ export const Button = React.forwardRef((props, ref) => {
data-iui-variant={styleType !== 'default' ? styleType : undefined}
data-iui-size={size}
{...rest}
style={
{
'--_iui-width': stretch ? '100%' : undefined,
...props.style,
} as React.CSSProperties
}
>
{startIcon && (
<Box
Expand Down
8 changes: 8 additions & 0 deletions packages/itwinui-react/src/styles.js/styles.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,11 @@
--_iui-v3-loaded: yes;
}
}

@layer itwinui {
.iui-root * {
/* When --_iui-width is set, inline-size will use it, otherwise it will be automatically reverted. */
--_iui-width: initial;
inline-size: var(--_iui-width, revert-layer);
}
}

0 comments on commit 3d42bc1

Please sign in to comment.