Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Deprecate utility components #1316

Merged
merged 40 commits into from
Jul 22, 2021
Merged
Show file tree
Hide file tree
Changes from 31 commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
e97fdc7
add utility props to Box
VanAnderson Jun 22, 2021
4ccefb0
update box docs
VanAnderson Jun 22, 2021
26d08f6
export box props
VanAnderson Jun 22, 2021
29e6d9f
update snapshots
VanAnderson Jun 22, 2021
64adf68
Create green-worms-nail.md
VanAnderson Jun 22, 2021
6556f3f
AvatarStack story in storybook
VanAnderson Jun 22, 2021
ca4884f
Deprecate components with JSDoc
VanAnderson Jun 22, 2021
eddac82
Update documentation
VanAnderson Jun 22, 2021
50aa394
Create metal-swans-allow.md
VanAnderson Jun 22, 2021
3a04406
deprecate utility components
VanAnderson Jun 28, 2021
5d76285
deprecate utility components
VanAnderson Jun 28, 2021
07d6f51
fix linter errors
VanAnderson Jun 28, 2021
4c4e183
fix build errors
VanAnderson Jun 28, 2021
a1d3c9f
fix build errors
VanAnderson Jun 28, 2021
2b93818
progress
VanAnderson Jun 29, 2021
3b3ccd7
code mode for deprecating utility components
VanAnderson Jun 30, 2021
aa3e8ea
Merge remote-tracking branch 'origin/main' into VanAnderson/deprecate…
colebemis Jul 20, 2021
4cf24a2
Update snapshots
colebemis Jul 20, 2021
699250b
BorderBox and additional test cases for codemod
VanAnderson Jul 21, 2021
2c61036
changeset documentation for utility component deprecation
VanAnderson Jul 21, 2021
7d0edf5
update codemod and test coverage
VanAnderson Jul 21, 2021
d696220
deprecate BorderBox
VanAnderson Jul 21, 2021
0b3d5db
better deprecation comments
VanAnderson Jul 21, 2021
96bc59d
correct codemod in changeset docs
VanAnderson Jul 21, 2021
d8ae367
run codemod on stories folder
VanAnderson Jul 21, 2021
9b96c60
complete borderBox deprecation
VanAnderson Jul 21, 2021
fc37baf
remove duplicate identifier
VanAnderson Jul 21, 2021
0b383df
border box is deprecated in docs
VanAnderson Jul 21, 2021
b1ca888
Update src/Grid.tsx
VanAnderson Jul 21, 2021
651b574
adjust codemod changeset docs
VanAnderson Jul 21, 2021
e192a0a
safe nav operator for codemod find operation
VanAnderson Jul 21, 2021
de80479
Update src/Position.tsx
VanAnderson Jul 22, 2021
90e5885
Update .changeset/metal-swans-allow.md
VanAnderson Jul 22, 2021
87def33
Update src/Popover.tsx
VanAnderson Jul 22, 2021
9d5e8b4
Update .changeset/metal-swans-allow.md
colebemis Jul 22, 2021
47f3a2e
Update snapshot
colebemis Jul 22, 2021
997286f
Edit changeset
colebemis Jul 22, 2021
a1408d1
Merge branch 'main' into VanAnderson/deprecate-utility-components
colebemis Jul 22, 2021
4b67a09
Update deprecated docs
colebemis Jul 22, 2021
1965269
Merge branch 'VanAnderson/deprecate-utility-components' of github.com…
colebemis Jul 22, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .changeset/green-worms-nail.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
"@primer/components": minor
'@primer/components': minor
---

`Box` now accepts all [styled system props](https://styled-system.com/table/).
30 changes: 30 additions & 0 deletions .changeset/metal-swans-allow.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
---
'@primer/components': minor
---

Deprecate utility components in favor of using Box.

The following components will be deprecated:

Flex
Grid
Position
Absolute
Fixed
Relative
Sticky
BorderBox
colebemis marked this conversation as resolved.
Show resolved Hide resolved

In place of these components, you may now use `Box`, which accepts all system props. There is a codemod availible to effectively handle these deprecations.

First, install jscodeshift:

`npm install -g jscodeshift`

Then, run the codemod using the appropriate command (examples given from the primer/components root directory)

typescript example:
`jscodeshift -t codemods/deprecateUtilityComponents.js --parser=tsx path/to/workspace/src/*.tsx`

babel example:
`jscodeshift -t codemods/deprecateUtilityComponents.js --parser=babel path/to/workspace/src/*.jsx`
VanAnderson marked this conversation as resolved.
Show resolved Hide resolved
200 changes: 200 additions & 0 deletions codemods/__tests__/deprecateUtilityComponents.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,200 @@
import {defineInlineTest} from 'jscodeshift/dist/testUtils'
import deprecateUtilityComponents from '../deprecateUtilityComponents'

defineInlineTest(
deprecateUtilityComponents,
{},
`
import {Flex} from '@primer/components'
export default () => (
<Flex>
<div />
</Flex>
)
`.trim(),
`
import {Box} from '@primer/components'
export default () => (
<Box display="flex">
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we test that other props are preserved? Example:

- <Flex flexDirection="column">
+ <Box display="flex" flexDirection="column">

<div />
</Box>
)
`.trim(),
'deprecateUtilityComponents'
)

defineInlineTest(
deprecateUtilityComponents,
{},
`
import {Grid} from '@primer/components'
export default () => (
<Grid>
<div />
</Grid>
)
`.trim(),
`
import {Box} from '@primer/components'
export default () => (
<Box display="grid">
<div />
</Box>
)
`.trim(),
'deprecateUtilityComponents'
)

defineInlineTest(
deprecateUtilityComponents,
{},
`
import {Position} from '@primer/components'
export default () => (
<Position>
<div />
</Position>
)
`.trim(),
`
import {Box} from '@primer/components'
export default () => (
<Box>
<div />
</Box>
)
`.trim(),
'deprecateUtilityComponents'
)

defineInlineTest(
deprecateUtilityComponents,
{},
`
import {Absolute} from '@primer/components'
export default () => (
<Absolute>
<div />
</Absolute>
)
`.trim(),
`
import {Box} from '@primer/components'
export default () => (
<Box position="absolute">
<div />
</Box>
)
`.trim(),
'deprecateUtilityComponents'
)

defineInlineTest(
deprecateUtilityComponents,
{},
`
import {Relative} from '@primer/components'
export default () => (
<Relative>
<div />
</Relative>
)
`.trim(),
`
import {Box} from '@primer/components'
export default () => (
<Box position="relative">
<div />
</Box>
)
`.trim(),
'deprecateUtilityComponents'
)

defineInlineTest(
deprecateUtilityComponents,
{},
`
import {Fixed} from '@primer/components'
export default () => (
<Fixed>
<div />
</Fixed>
)
`.trim(),
`
import {Box} from '@primer/components'
export default () => (
<Box position="fixed">
<div />
</Box>
)
`.trim(),
'deprecateUtilityComponents'
)

defineInlineTest(
deprecateUtilityComponents,
{},
`
import {Sticky} from '@primer/components'
export default () => (
<Sticky>
<div />
</Sticky>
)
`.trim(),
`
import {Box} from '@primer/components'
export default () => (
<Box position="sticky">
<div />
</Box>
)
`.trim(),
'deprecateUtilityComponents'
)

defineInlineTest(
deprecateUtilityComponents,
{},
`
import {BorderBox} from '@primer/components'
export default () => (
<BorderBox borderColor="border.secondary" borderRadius={1}>
<div />
</BorderBox>
)
`.trim(),
`
import {Box} from '@primer/components'
export default () => (
<Box borderColor="border.secondary" borderRadius={1} borderWidth="1px" borderStyle="solid">
<div />
</Box>
)
`.trim(),
'deprecateUtilityComponents'
)

defineInlineTest(
deprecateUtilityComponents,
{},
`
import {Flex} from '@primer/components'
export default () => (
<Flex p={2} m={1}>
<div />
</Flex>
)
`.trim(),
`
import {Box} from '@primer/components'
export default () => (
<Box p={2} m={1} display="flex">
<div />
</Box>
)
`.trim(),
'deprecateUtilityComponents'
)
111 changes: 111 additions & 0 deletions codemods/deprecateUtilityComponents.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
const prettify = require('./lib/prettify')

module.exports = (file, api) => {
const j = api.jscodeshift
const ast = j(file.source)

deprecateComponents(ast, j, '@primer/components', {
Flex: {
identifier: 'Box',
attributes: {
display: 'flex'
}
},
Grid: {
identifier: 'Box',
attributes: {
display: 'grid'
}
},
Position: {
identifier: 'Box',
attributes: {}
},
Absolute: {
identifier: 'Box',
attributes: {
position: 'absolute'
}
},
Relative: {
identifier: 'Box',
attributes: {
position: 'relative'
}
},
Fixed: {
identifier: 'Box',
attributes: {
position: 'fixed'
}
},
Sticky: {
identifier: 'Box',
attributes: {
position: 'sticky'
}
},
BorderBox: {
identifier: 'Box',
attributes: {
borderWidth: '1px',
borderStyle: 'solid',
borderColor: 'border.primary',
borderRadius: 2
}
}
})

return prettify(ast, file)
}

function deprecateComponents(ast, j, importSource, importMap) {
const imports = ast.find(j.ImportDeclaration, {source: {value: importSource}})
const importsByName = {}

imports.forEach(decl => {
j(decl)
.find(j.ImportSpecifier)
.forEach(spec => {
importsByName[spec.node.imported.name] = spec
})
})

for (const [from, to] of Object.entries(importMap)) {
rewriteImport(from, to.identifier, to.attributes)
}

function rewriteImport(from, to, attributes) {
imports.forEach(decl => {
j(decl)
.find(j.ImportSpecifier, {imported: {name: from}})
.forEach(spec => {
if (importsByName[to]) {
// if the destination import already exists and there are members
// in this identifier, then this one is a dupe
j(spec).remove()
} else {
// otherwise, we can safely rename this one to the new identifier
spec.node.imported.name = to
importsByName[to] = spec
}
})
})

ast.find(j.JSXOpeningElement, {name: {name: from}}).forEach(nodePath => {
for (const [attr, value] of Object.entries(attributes || {})) {
const expression = typeof value === 'string' ? j.literal(value) : j.jsxExpressionContainer(j.literal(value))
const attrExists = nodePath.value.attributes.find(a => a?.name?.name === attr)
if (!attrExists) {
nodePath.value.attributes.push(j.jsxAttribute(j.jsxIdentifier(attr), expression))
}
}
})

// replace all of the rewritten identifiers with member expressions
ast
.find(j.Identifier, {name: from})
.filter(id => id.parent.node.type !== 'ImportSpecifier')
.replaceWith(j.jsxIdentifier(to))
}
}
2 changes: 1 addition & 1 deletion codemods/lib/prettify.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ module.exports = function prettify(ast, file) {
source,
Object.assign(
{
parser: 'babylon',
parser: 'typescript',
filepath: file.path
},
config
Expand Down
12 changes: 4 additions & 8 deletions docs/content/AnchoredOverlay.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -15,23 +15,19 @@ The overlay can be opened and navigated using keyboard or mouse.
const closeOverlay = React.useCallback(() => setIsOpen(false), [setIsOpen])
return (
<AnchoredOverlay
renderAnchor={(anchorProps) => (
<DropdownButton {...anchorProps}>
Click me to open
</DropdownButton>
)}
renderAnchor={anchorProps => <DropdownButton {...anchorProps}>Click me to open</DropdownButton>}
open={isOpen}
onOpen={openOverlay}
onClose={closeOverlay}
>
<Flex flexDirection="column" maxWidth="300px" padding={2}>
<Box display="flex" flexDirection="column" maxWidth="300px" padding={2}>
<p>
This menu automatically receives a focus trap and focus zone. Use up/down keys to navigate between buttons
This menu automatically receives a focus trap and focus zone. Use up/down keys to navigate between buttons
</p>
<Button mb={1}>Button 1</Button>
<Button mb={1}>Button 2</Button>
<Button>Button 3</Button>
</Flex>
</Box>
</AnchoredOverlay>
)
}}
Expand Down
Loading