Skip to content

Commit 3727c4c

Browse files
ElliotLuke BowermanLuke Bowerman
authored
Tree: More style updates and bug fixes (#1196)
* Allow TreeGroup color prop to override default color of child Trees and TreeItems * Added color override test case to TreeGroup * Adjusted Tree indicator gap size to align with TreeItem icon gap * Removed negative margin from ButtonIcon margin calc function * Removed key color from pivot button in FieldPicker exampel * Fixed color override from TreeGroup bug * Updated CHANGELOG * Fixed color test on TreeGroup * Correct Button icon positioning * Removed && pattern * Ship it. Ship it real good * Added color prop to TreeItem Co-authored-by: Luke Bowerman <[email protected]> Co-authored-by: Luke Bowerman <[email protected]>
1 parent 57ba42e commit 3727c4c

File tree

7 files changed

+104
-52
lines changed

7 files changed

+104
-52
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1515
- `FactCheck` icon
1616
- `TreeItem` and `Tree`
1717
- Altered style defaults
18+
- `TreeGroup`
19+
- Added additional test case for color override behavior
1820
- `iconSizes` style function includes `xxsmall` case
1921

2022
### Changed
@@ -37,15 +39,19 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
3739
- `MessageBar`
3840
- MessageBar is dismissable by default. Use prop `noActions` in place of `canDismiss={false}` to hide dismiss button.
3941
- Adds new `visible` prop to toggle display externally
42+
- `Tree` increased gap size between indicator and label to align with sibling `TreeItem`s with icons
43+
- `ButtonBase` removed negative margin from `iconMargins` helper function
4044
- Accepts primary and secondary action overrides and callbacks
4145

4246
### Fixed
4347

4448
- `Select`/`SelectMulti` keyboard navigation when filtering and going from > 100 to < 100 options
4549
- `SelectMulti` with `freeInput` not saving input value on tab key
4650
- `SelectMulti` list not closing on blur
51+
- `TreeGroup` properly overrides color of child `TreeItem` labels and `Tree` labels
4752
- `MenuGroup` now includes icon placeholder spacing if higher `MenuItemContext` has `renderIconPlaceholder === true`
4853

54+
4955
### Removed
5056

5157
- Removed `Modal*` aliases to `Dialog*`

packages/components/src/Button/icon.ts

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -36,31 +36,32 @@ export interface ButtonIconProps {
3636
}
3737

3838
export const iconMargins = (props: ButtonProps) => {
39-
const spacing = { large: 0, small: 0 }
39+
const spacing = { inner: 0, outer: 0 }
4040
switch (props.size) {
41+
case 'xxsmall':
4142
case 'xsmall':
42-
spacing.small = 4
43-
spacing.large = 6
43+
spacing.outer = 4
44+
spacing.inner = 6
4445
break
4546
case 'small':
46-
spacing.small = 8
47-
spacing.large = 8
47+
spacing.outer = 8
48+
spacing.inner = 8
4849
break
4950
case 'large':
5051
default:
51-
spacing.small = 12
52-
spacing.large = 8
52+
spacing.outer = 12
53+
spacing.inner = 8
5354
}
5455

5556
if (props.iconBefore) {
5657
return css`
57-
margin-left: -${rem(spacing.small)};
58-
margin-right: ${rem(spacing.large)};
58+
margin-left: -${rem(spacing.outer)};
59+
margin-right: ${rem(spacing.inner)};
5960
`
6061
} else if (props.iconAfter) {
6162
return css`
62-
margin-left: ${rem(spacing.large)};
63-
margin-right: -${rem(spacing.small)};
63+
margin-left: ${rem(spacing.inner)};
64+
margin-right: -${rem(spacing.outer)};
6465
`
6566
} else {
6667
return false

packages/components/src/Tree/Tree.tsx

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ export interface TreeProps extends AccordionProps {
8181
}
8282

8383
const indicatorProps: AccordionIndicatorProps = {
84-
indicatorGap: 'xxsmall',
84+
indicatorGap: 'xsmall',
8585
indicatorIcons: { close: 'ArrowRight', open: 'ArrowDown' },
8686
indicatorPosition: 'left',
8787
indicatorSize: 'small',
@@ -97,6 +97,7 @@ const TreeLayout: FC<TreeProps> = ({
9797
detailAccessory: propsDetailAccessory,
9898
icon,
9999
label,
100+
className,
100101
visuallyAsBranch,
101102
...restProps
102103
}) => {
@@ -148,25 +149,28 @@ const TreeLayout: FC<TreeProps> = ({
148149
detailHoverDisclosure: hasDetailHoverDisclosure,
149150
}}
150151
>
151-
<TreeStyle border={hasBorder} depth={depth} hovered={isHovered}>
152+
<TreeStyle
153+
className={className}
154+
border={hasBorder}
155+
depth={depth}
156+
hovered={isHovered}
157+
>
152158
{innerAccordion}
153159
</TreeStyle>
154160
</TreeContext.Provider>
155161
)
156162
}
157163

158-
export const Tree = styled(TreeLayout)``
159-
160164
const generateTreeBorder = (depth: number, theme: Theme) => {
161165
const {
162166
colors,
163-
space: { xxsmall, small },
167+
space: { xxsmall, xsmall, small },
164168
} = theme
165169

166170
const itemBorderSize = '1px'
167171
const itemPaddingSize = xxsmall
168172
const indicatorIconSize = small
169-
const indicatorGapSize = xxsmall
173+
const indicatorGapSize = xsmall
170174
const depthSize = `${itemBorderSize} + ${itemPaddingSize} + (${indicatorIconSize} + ${indicatorGapSize}) * ${depth}`
171175
const borderSpacer = `(${small} / 2) + ${depthSize}`
172176

@@ -182,12 +186,12 @@ const generateTreeBorder = (depth: number, theme: Theme) => {
182186

183187
const generateIndent = (depth: number, theme: Theme) => {
184188
const {
185-
space: { xxsmall, small },
189+
space: { xxsmall, xsmall, small },
186190
} = theme
187191

188192
const itemPaddingSize = xxsmall
189193
const indicatorIconSize = small
190-
const indicatorGapSize = xxsmall
194+
const indicatorGapSize = xsmall
191195
const indentCalculation = `${itemPaddingSize} + (${indicatorIconSize} + ${indicatorGapSize}) * ${depth}`
192196

193197
return css`
@@ -202,6 +206,8 @@ interface TreeStyleProps {
202206
}
203207

204208
export const TreeStyle = styled.div<TreeStyleProps>`
209+
color: ${({ theme }) => theme.colors.text2};
210+
205211
& > ${Accordion} {
206212
& > ${AccordionContent} {
207213
${({ border, depth, theme }) =>
@@ -233,3 +239,5 @@ export const TreeStyle = styled.div<TreeStyleProps>`
233239
${({ depth, theme }) => generateIndent(depth + 1, theme)}
234240
}
235241
`
242+
243+
export const Tree = styled(TreeLayout)``

packages/components/src/Tree/TreeGroup.test.tsx

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626

2727
import React from 'react'
2828
import { renderWithTheme } from '@looker/components-test-utils'
29-
import { TreeGroup } from '.'
29+
import { TreeGroup, Tree, TreeItem } from '.'
3030

3131
test('Renders label and children', () => {
3232
const { getByText } = renderWithTheme(
@@ -36,3 +36,19 @@ test('Renders label and children', () => {
3636
getByText('My Tree Group')
3737
getByText('My Children')
3838
})
39+
40+
test('Applies color prop to child Trees and TreeItems', () => {
41+
const { getByText } = renderWithTheme(
42+
<TreeGroup label="My Tree Group" color="red">
43+
<Tree label="My Tree" defaultOpen>
44+
<TreeItem>TreeItem 1</TreeItem>
45+
</Tree>
46+
<TreeItem>TreeItem 2</TreeItem>
47+
</TreeGroup>
48+
)
49+
50+
expect(getByText('My Tree Group')).toHaveStyleRule('color: red')
51+
expect(getByText('My Tree')).toHaveStyleRule('color: red')
52+
expect(getByText('TreeItem 1')).toHaveStyleRule('color: red')
53+
expect(getByText('TreeItem 2')).toHaveStyleRule('color: red')
54+
})

packages/components/src/Tree/TreeGroup.tsx

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@
2727
import React, { FC } from 'react'
2828
import styled from 'styled-components'
2929
import { color, TextColorProps } from '@looker/design-tokens'
30+
import { AccordionDisclosure } from '../Accordion'
31+
import { TreeItemLabel } from './TreeItem'
3032

3133
export interface TreeGroupProps extends TextColorProps {
3234
/**
@@ -47,15 +49,16 @@ const TreeGroupLayout: FC<TreeGroupProps> = ({
4749
</div>
4850
)
4951

50-
export const TreeGroup = styled(TreeGroupLayout)`
51-
${color}
52-
`
53-
5452
export const TreeGroupLabel = styled.div`
5553
/* Border is here to get proper alignment with Tree and TreeItem text */
5654
border: 1px transparent solid;
57-
color: ${({ theme }) => theme.colors.text2};
5855
font-size: ${({ theme }) => theme.fontSizes.xxsmall};
5956
font-weight: ${({ theme }) => theme.fontWeights.semiBold};
6057
padding: ${({ theme: { space } }) => `${space.xsmall} ${space.xxsmall}`};
6158
`
59+
60+
export const TreeGroup = styled(TreeGroupLayout)`
61+
${TreeItemLabel}, ${TreeGroupLabel}, ${AccordionDisclosure} {
62+
${color}
63+
}
64+
`

packages/components/src/Tree/TreeItem.tsx

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,11 @@ import React, {
3636
} from 'react'
3737
import styled from 'styled-components'
3838
import {
39+
color,
40+
CompatibleHTMLProps,
3941
SpacingSizes,
42+
TextColorProps,
4043
uiTransparencyBlend,
41-
CompatibleHTMLProps,
4244
} from '@looker/design-tokens'
4345
import Omit from 'lodash/omit'
4446
import { Space, FlexItem } from '../Layout'
@@ -51,7 +53,9 @@ import {
5153
import { undefinedCoalesce } from '../utils'
5254
import { TreeContext } from './TreeContext'
5355

54-
export interface TreeItemProps extends CompatibleHTMLProps<HTMLDivElement> {
56+
export interface TreeItemProps
57+
extends Omit<CompatibleHTMLProps<HTMLDivElement>, 'color'>,
58+
TextColorProps {
5559
className?: string
5660
/**
5761
* Supplementary element that appears right of the TreeItem's label
@@ -103,6 +107,7 @@ const TreeItemLayout: FC<TreeItemProps> = ({
103107
const [isFocusVisible, setFocusVisible] = useState(false)
104108

105109
const { onBlur, onClick, onKeyDown, onKeyUp, ...restProps } = Omit(props, [
110+
'color',
106111
'detail',
107112
'detailAccessory',
108113
'detailHoverDisclosure',
@@ -203,11 +208,11 @@ const PrimaryIcon = styled(Icon)`
203208
opacity: 0.5;
204209
`
205210

206-
interface TreeItemSpace {
211+
interface TreeItemSpaceProps {
207212
focusVisible: boolean
208213
}
209214

210-
export const TreeItemSpace = styled(Space)<TreeItemSpace>`
215+
export const TreeItemSpace = styled(Space)<TreeItemSpaceProps>`
211216
align-items: center;
212217
border: 1px solid transparent;
213218
border-color: ${({ focusVisible, theme }) =>
@@ -241,5 +246,11 @@ const TreeItemDetail = styled.div<{ detailAccessory: boolean }>`
241246
`
242247

243248
export const TreeItem = styled(TreeItemLayout)`
244-
color: ${({ theme }) => theme.colors.text2};
249+
/*
250+
Note: first-child pseudo-selector is here to give this selector
251+
more specificity over TreeGroup.
252+
*/
253+
${TreeItemLabel}:first-child {
254+
${color}
255+
}
245256
`

storybook/src/Tree/FieldPicker.stories.tsx

Lines changed: 29 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,6 @@ const PickerItem = () => {
6060
<IconButton
6161
icon="Sync"
6262
label="Pivot"
63-
color="key"
6463
tooltipPlacement="top"
6564
onClick={(event) => {
6665
event.stopPropagation()
@@ -73,7 +72,7 @@ const PickerItem = () => {
7372
)
7473

7574
const itemLabel = (
76-
<Space between px="xxsmall">
75+
<Space between>
7776
<span>Cost</span>
7877
{!overlay ? <HoverDisclosure>{pivot}</HoverDisclosure> : pivot}
7978
</Space>
@@ -126,33 +125,41 @@ const PickerItem = () => {
126125
)
127126
}
128127

129-
export const FieldPicker = () => (
130-
<Tree
131-
defaultOpen
132-
detailAccessory
133-
detail={
134-
<ButtonTransparent
135-
size="xxsmall"
136-
iconBefore="Plus"
137-
onClick={() => alert('Hello Mouse')}
138-
onKeyDown={(event) => {
139-
if (event.keyCode === 13) {
140-
event.preventDefault()
141-
alert('Hello Keyboard')
142-
}
143-
}}
144-
>
145-
Add
146-
</ButtonTransparent>
147-
}
148-
label="Custom Fields"
128+
const addButton = (
129+
<ButtonTransparent
130+
size="xxsmall"
131+
iconBefore="Plus"
132+
onClick={() => alert('Hello Mouse')}
133+
onKeyDown={(event) => {
134+
if (event.keyCode === 13) {
135+
event.preventDefault()
136+
alert('Hello Keyboard')
137+
}
138+
}}
149139
>
140+
Add
141+
</ButtonTransparent>
142+
)
143+
144+
export const FieldPicker = () => (
145+
<Tree defaultOpen detailAccessory detail={addButton} label="Custom Fields">
150146
<TreeGroup label="DIMENSIONS">
151147
<PickerItem />
152148
<PickerItem />
153149
<PickerItem />
154150
<PickerItem />
155151
</TreeGroup>
152+
<TreeGroup label="MEASURES" color="keyFocus">
153+
<Tree visuallyAsBranch label="Hello">
154+
<PickerItem />
155+
</Tree>
156+
<TreeItem color="orange" icon="FieldString">
157+
Name
158+
</TreeItem>
159+
<PickerItem />
160+
<PickerItem />
161+
<PickerItem />
162+
</TreeGroup>
156163
</Tree>
157164
)
158165

0 commit comments

Comments
 (0)