Skip to content

Commit 60001cd

Browse files
committed
feat(ui-table): add setHoverStateTo to control the hover state of the Table's row
INSTUI-4622
1 parent 4e9f486 commit 60001cd

File tree

3 files changed

+184
-11
lines changed

3 files changed

+184
-11
lines changed

cypress/component/Table.cy.tsx

Lines changed: 164 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,30 @@ import 'cypress-real-events'
2727

2828
import { Table } from '@instructure/ui'
2929

30-
describe('<Table/>', () =>
30+
describe('<Table/>', () => {
31+
const TestTable = ({
32+
setHoverStateTo,
33+
hover
34+
}: {
35+
setHoverStateTo?: boolean
36+
hover?: boolean
37+
}) => (
38+
<Table caption="Test table" hover={hover}>
39+
<Table.Head>
40+
<Table.Row data-testid="target-row" setHoverStateTo={setHoverStateTo}>
41+
<Table.ColHeader id="foo">ColHeader</Table.ColHeader>
42+
<Table.ColHeader id="bar">Bar-header</Table.ColHeader>
43+
</Table.Row>
44+
</Table.Head>
45+
<Table.Body>
46+
<Table.Row data-testid="control-row">
47+
<Table.RowHeader>RowHeader</Table.RowHeader>
48+
<Table.Cell>Cell</Table.Cell>
49+
</Table.Row>
50+
</Table.Body>
51+
</Table>
52+
)
53+
3154
it('can render table head as a combobox when in stacked layout', async () => {
3255
const sortFoo = cy.stub()
3356
cy.mount(
@@ -56,4 +79,143 @@ describe('<Table/>', () =>
5679
cy.get('[role="option"]').first().click()
5780

5881
cy.wrap(sortFoo).should('have.been.calledOnce')
59-
}))
82+
})
83+
84+
it('should highlight row when setHoverStateTo is set to true', () => {
85+
cy.mount(<TestTable />)
86+
87+
cy.get('[data-testid="target-row"]')
88+
.invoke('css', 'border-left-color')
89+
.then((initialTargetColor) => {
90+
cy.get('[data-testid="control-row"]')
91+
.invoke('css', 'border-left-color')
92+
.then((initialControlColor) => {
93+
cy.mount(<TestTable setHoverStateTo={true} />)
94+
95+
cy.get('[data-testid="target-row"]').should(
96+
'not.have.css',
97+
'border-left-color',
98+
initialTargetColor
99+
)
100+
101+
cy.get('[data-testid="control-row"]').should(
102+
'have.css',
103+
'border-left-color',
104+
initialControlColor
105+
)
106+
})
107+
})
108+
})
109+
110+
it('should not highlight row when setHoverStateTo is set to false', () => {
111+
cy.mount(<TestTable />)
112+
113+
cy.get('[data-testid="target-row"]')
114+
.invoke('css', 'border-left-color')
115+
.then((initialTargetColor) => {
116+
cy.get('[data-testid="control-row"]')
117+
.invoke('css', 'border-left-color')
118+
.then((initialControlColor) => {
119+
cy.mount(<TestTable setHoverStateTo={false} />)
120+
121+
cy.get('[data-testid="target-row"]').should(
122+
'have.css',
123+
'border-left-color',
124+
initialTargetColor
125+
)
126+
127+
cy.get('[data-testid="control-row"]').should(
128+
'have.css',
129+
'border-left-color',
130+
initialControlColor
131+
)
132+
})
133+
})
134+
})
135+
136+
it('should not highlight table row when hover is true but setHoverStateTo is false', () => {
137+
cy.mount(<TestTable setHoverStateTo={false} hover={true} />)
138+
139+
cy.get('[data-testid="target-row"]').then(($row) => {
140+
const initialBorderColor = $row.css('border-left-color')
141+
142+
cy.wrap($row)
143+
.realHover()
144+
.and('have.css', 'border-left-color', initialBorderColor)
145+
})
146+
147+
cy.get('[data-testid="control-row"]').then(($row) => {
148+
const initialBorderColor = $row.css('border-left-color')
149+
150+
cy.wrap($row)
151+
.realHover()
152+
.should('not.have.css', 'border-left-color', initialBorderColor)
153+
})
154+
})
155+
156+
it('should highlight table row when hover is false but setHoverStateTo is true', () => {
157+
cy.mount(<TestTable />)
158+
159+
cy.get('[data-testid="target-row"]')
160+
.invoke('css', 'border-left-color')
161+
.then((initialTargetColor) => {
162+
cy.get('[data-testid="control-row"]')
163+
.invoke('css', 'border-left-color')
164+
.then((initialControlColor) => {
165+
cy.mount(<TestTable setHoverStateTo={true} hover={false} />)
166+
167+
cy.get('[data-testid="target-row"]').should(
168+
'not.have.css',
169+
'border-left-color',
170+
initialTargetColor
171+
)
172+
173+
cy.get('[data-testid="control-row"]').should(
174+
'have.css',
175+
'border-left-color',
176+
initialControlColor
177+
)
178+
})
179+
})
180+
})
181+
182+
it('should highlight table row when hover is true but setHoverStateTo is undefined', () => {
183+
cy.mount(<TestTable setHoverStateTo={undefined} hover={true} />)
184+
185+
cy.get('[data-testid="target-row"]').then(($row) => {
186+
const initialBorderColor = $row.css('border-left-color')
187+
188+
cy.wrap($row)
189+
.realHover()
190+
.should('not.have.css', 'border-left-color', initialBorderColor)
191+
})
192+
193+
cy.get('[data-testid="control-row"]').then(($row) => {
194+
const initialBorderColor = $row.css('border-left-color')
195+
196+
cy.wrap($row)
197+
.realHover()
198+
.should('not.have.css', 'border-left-color', initialBorderColor)
199+
})
200+
})
201+
202+
it('should not highlight table row when hover is false and setHoverStateTo is undefined', () => {
203+
cy.mount(<TestTable setHoverStateTo={undefined} hover={false} />)
204+
205+
cy.get('[data-testid="target-row"]').then(($row) => {
206+
const initialBorderColor = $row.css('border-left-color')
207+
208+
cy.wrap($row)
209+
.realHover()
210+
.should('have.css', 'border-left-color', initialBorderColor)
211+
})
212+
213+
cy.get('[data-testid="control-row"]').then(($row) => {
214+
const initialBorderColor = $row.css('border-left-color')
215+
216+
cy.wrap($row)
217+
.realHover()
218+
.should('have.css', 'border-left-color', initialBorderColor)
219+
})
220+
})
221+
})

packages/ui-table/src/Table/Row/props.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,13 @@ type TableRowOwnProps = {
4040
* By default `Table.ColHeader` or `Table.RowHeader` or `Table.Cell`
4141
*/
4242
children?: React.ReactElement | React.ReactElement[]
43+
44+
/**
45+
* Controls the hover state of the row.
46+
* When set to true, the row will appear highlighted even when not hovered.
47+
* When set to false, the row will not highlight on hover even if the hover prop is set to true.
48+
*/
49+
setHoverStateTo?: boolean
4350
}
4451

4552
type PropKeys = keyof TableRowOwnProps
@@ -53,10 +60,11 @@ type TableRowProps = TableRowOwnProps &
5360
type TableRowStyle = ComponentStyle<'row'>
5461

5562
const propTypes: PropValidators<PropKeys> = {
56-
children: PropTypes.node
63+
children: PropTypes.node,
64+
setHoverStateTo: PropTypes.bool
5765
}
5866

59-
const allowedProps: AllowedPropKeys = ['children']
67+
const allowedProps: AllowedPropKeys = ['children', 'setHoverStateTo']
6068

6169
export type { TableRowProps, TableRowStyle }
6270
export { propTypes, allowedProps }

packages/ui-table/src/Table/Row/styles.ts

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,16 @@ import type { TableRowProps, TableRowStyle } from './props'
3737
*/
3838
const generateStyle = (
3939
componentTheme: TableRowTheme,
40-
_props: TableRowProps,
40+
props: TableRowProps,
4141
extraArgs: { isStacked: boolean; hover: boolean }
4242
): TableRowStyle => {
43+
const { setHoverStateTo } = props
44+
45+
const hoverStyles = {
46+
borderLeftColor: componentTheme.hoverBorderColor,
47+
borderRightColor: componentTheme.hoverBorderColor
48+
}
49+
4350
return {
4451
row: {
4552
label: 'row',
@@ -53,14 +60,10 @@ const generateStyle = (
5360
borderBottomWidth: '0.0625rem',
5461
borderBottomColor: componentTheme.borderColor,
5562

56-
...(extraArgs.hover && {
63+
...((setHoverStateTo ?? extraArgs.hover) && {
5764
borderLeft: '0.1875rem solid transparent',
5865
borderRight: '0.1875rem solid transparent',
59-
60-
'&:hover': {
61-
borderLeftColor: componentTheme.hoverBorderColor,
62-
borderRightColor: componentTheme.hoverBorderColor
63-
}
66+
...(setHoverStateTo === true ? hoverStyles : { '&:hover': hoverStyles })
6467
}),
6568

6669
...(extraArgs.isStacked && { padding: componentTheme.padding })

0 commit comments

Comments
 (0)