Skip to content

Commit 0eaa872

Browse files
committed
feat(ui-flex): add order prop to Flex.Item
INSTUI-4663
1 parent 0cc2f76 commit 0eaa872

File tree

4 files changed

+95
-4
lines changed

4 files changed

+95
-4
lines changed

cypress/component/FlexItem.cy.tsx

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
/*
2+
* The MIT License (MIT)
3+
*
4+
* Copyright (c) 2015 - present Instructure, Inc.
5+
*
6+
* Permission is hereby granted, free of charge, to any person obtaining a copy
7+
* of this software and associated documentation files (the "Software"), to deal
8+
* in the Software without restriction, including without limitation the rights
9+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
* copies of the Software, and to permit persons to whom the Software is
11+
* furnished to do so, subject to the following conditions:
12+
*
13+
* The above copyright notice and this permission notice shall be included in all
14+
* copies or substantial portions of the Software.
15+
*
16+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22+
* SOFTWARE.
23+
*/
24+
25+
import { Flex } from '@instructure/ui'
26+
27+
describe('<Flex.Item/>', () => {
28+
it('visually reorders items when order prop is set', () => {
29+
cy.mount(
30+
<Flex data-testid="flex-container-default">
31+
<Flex.Item data-testid="item-1-default">FOO</Flex.Item>
32+
<Flex.Item data-testid="item-2-default">BOO</Flex.Item>
33+
</Flex>
34+
)
35+
36+
cy.get('[data-testid="flex-container-default"]').then(($container) => {
37+
const firstItem = $container.find('[data-testid="item-1-default"]')[0]
38+
const secondItem = $container.find('[data-testid="item-2-default"]')[0]
39+
const firstRect = firstItem.getBoundingClientRect()
40+
const secondRect = secondItem.getBoundingClientRect()
41+
42+
expect(firstRect.left).to.be.lessThan(secondRect.left)
43+
})
44+
45+
// set order prop
46+
cy.mount(
47+
<Flex data-testid="flex-container-ordered">
48+
<Flex.Item order={2} data-testid="item-1-ordered">
49+
FOO
50+
</Flex.Item>
51+
<Flex.Item order={1} data-testid="item-2-ordered">
52+
BOO
53+
</Flex.Item>
54+
</Flex>
55+
)
56+
57+
cy.get('[data-testid="flex-container-ordered"]').then(($container) => {
58+
const firstItem = $container.find('[data-testid="item-1-ordered"]')[0]
59+
const secondItem = $container.find('[data-testid="item-2-ordered"]')[0]
60+
const firstRect = firstItem.getBoundingClientRect()
61+
const secondRect = secondItem.getBoundingClientRect()
62+
63+
expect(secondRect.left).to.be.lessThan(firstRect.left)
64+
})
65+
})
66+
})

packages/ui-flex/src/Flex/Item/__tests__/FlexItem.test.tsx

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
* SOFTWARE.
2323
*/
2424

25-
import { render, waitFor } from '@testing-library/react'
25+
import { render, waitFor, screen } from '@testing-library/react'
2626
import { vi } from 'vitest'
2727

2828
import '@testing-library/jest-dom'
@@ -57,4 +57,18 @@ describe('<Item />', () => {
5757

5858
expect(axeCheck).toBe(true)
5959
})
60+
61+
describe('order prop', () => {
62+
it('should apply `order` CSS when passed', () => {
63+
render(<Item order={2}>Item with order</Item>)
64+
const item = screen.getByText('Item with order')
65+
expect(item).toHaveStyle('order: 2')
66+
})
67+
68+
it('should not apply `order` CSS when prop is undefined', () => {
69+
render(<Item>Item without order</Item>)
70+
const item = screen.getByText('Item without order')
71+
expect(item).not.toHaveStyle({ order: expect.anything() })
72+
})
73+
})
6074
})

packages/ui-flex/src/Flex/Item/props.ts

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,14 @@ type FlexItemOwnProps = {
110110
* Places dashed lines around the component's borders to help debug your layout
111111
*/
112112
withVisualDebug?: boolean
113+
/**
114+
* Specifies the order of the `Flex.Item` inside the `Flex` component.
115+
*
116+
* Items with the same order revert to source order.
117+
*
118+
* Utilizes the order flex CSS property. Default order CSS value is 0.
119+
*/
120+
order?: string | number
113121
}
114122

115123
type PropKeys = keyof FlexItemOwnProps
@@ -136,7 +144,8 @@ const propTypes: PropValidators<PropKeys> = {
136144
shouldGrow: PropTypes.bool,
137145
shouldShrink: PropTypes.bool,
138146
size: PropTypes.string,
139-
withVisualDebug: PropTypes.bool
147+
withVisualDebug: PropTypes.bool,
148+
order: PropTypes.oneOfType([PropTypes.string, PropTypes.number])
140149
}
141150

142151
const allowedProps: AllowedPropKeys = [
@@ -153,7 +162,8 @@ const allowedProps: AllowedPropKeys = [
153162
'shouldGrow',
154163
'shouldShrink',
155164
'size',
156-
'withVisualDebug'
165+
'withVisualDebug',
166+
'order'
157167
]
158168

159169
export type { FlexItemProps, FlexItemStyle }

packages/ui-flex/src/Flex/Item/styles.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ const generateStyle = (
3838
_componentTheme: null,
3939
props: FlexItemProps
4040
): FlexItemStyle => {
41-
const { shouldGrow, shouldShrink, align, size } = props
41+
const { shouldGrow, shouldShrink, align, size, order } = props
4242

4343
const alignSelfValues = {
4444
start: 'flex-start',
@@ -53,6 +53,7 @@ const generateStyle = (
5353
boxSizing: 'border-box',
5454
minWidth: '0.0625rem',
5555
flexBasis: size,
56+
...(order !== undefined && { order }),
5657
// initial value is 1, but we want 0 as our default,
5758
// so users can opt in to shrink like they do grow
5859
flexShrink: shouldShrink ? 1 : 0,

0 commit comments

Comments
 (0)