Skip to content

Commit

Permalink
feat: prettier plugin options (#24)
Browse files Browse the repository at this point in the history
* feat: pandaStylePropsFirst/pandaSortOtherProps options

* feat: pandaGroupOrder
  • Loading branch information
astahmer authored Feb 29, 2024
1 parent a4469de commit c68aade
Show file tree
Hide file tree
Showing 7 changed files with 241 additions and 57 deletions.
5 changes: 5 additions & 0 deletions .changeset/little-apples-sin.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@pandabox/prettier-plugin-panda': patch
---

Add `pandaStylePropsFirst` / `pandaSortOtherProps` / `pandaGroupOrder` options
3 changes: 1 addition & 2 deletions .prettierrc
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,5 @@
"jsxSingleQuote": false,
"proseWrap": "always",
"semi": false,
"tabWidth": 2,
"plugins": ["@pandabox/prettier-plugin-panda"]
"tabWidth": 2
}
146 changes: 121 additions & 25 deletions packages/prettier-plugin-panda/README.md
Original file line number Diff line number Diff line change
@@ -1,28 +1,114 @@
# prettier-plugin-panda
# @pandabox/prettier-plugin-panda

Prettier plugin for Panda CSS.

Will sort style props based on your local `panda.config.ts`:

- in any Panda function like `css({ ... })` or `stack({ ... })`
- in the `css` prop of any JSX component

## Installation

```bash
pnpm add -D prettier prettier-plugin-panda
pnpm add -D prettier @pandabox/prettier-plugin-panda
```

## Usage

```json
{
"plugins": ["prettier-plugin-panda"]
"plugins": ["@pandabox/prettier-plugin-panda"],
"pandaFirstProps": ["as", "layerStyle", "textStyle"],
"pandaLastProps": [],
"pandaOnlyComponents": false,
"pandaOnlyIncluded": false,
"pandaStylePropsFirst": true,
"pandaSortOtherProps": true
}
```

## Options
## Sorting

### `pandaConfigPath`
The plugin will dynamically resolve your `panda.config.ts` file and sort the style properties based on your
[`utilities`](https://panda-css.com/docs/customization/utilities) (keys and shorthands) and their associated `group`.

The path to the panda config file.
Each utility in the [`@pandacss/preset-base`](https://github.com/chakra-ui/panda/pull/2269/files) has a group name.

### `pandaCwd`
The
[group names and their order](https://github.com/astahmer/pandakit/blob/5e3d5cb6c5bbed211c3bf608b69b307568cdff06/packages/prettier-plugin-panda/src/get-priority-index.ts#L7)
are:

```ts
const groupNames = [
'System',
'Container',
'Display',
'Visibility',
'Position',
'Transform',
'Flex Layout',
'Grid Layout',
'Layout',
'Border',
'Border Radius',
'Width',
'Height',
'Margin',
'Padding',
'Color',
'Typography',
'Background',
'Shadow',
'Table',
'List',
'Scroll',
'Interactivity',
'Transition',
'Effect',
'Other',
]
```

- [Conditions](https://panda-css.com/docs/concepts/conditional-styles) (`_hover`, `_dark`...) will be sorted after
`Other` and are always sorted in the same order as in the generated CSS
- [Arbitrary conditions](https://panda-css.com/docs/concepts/conditional-styles#arbitrary-selectors) will be sorted
after `Conditions`
- `Css` will be sorted after `Arbitrary conditions`, since the JSX `css` prop will override any other JSX style prop
with JSX patterns / `styled` factory

The current working directory from which the config file will be searched for.
Finally, other (non-style) props will be sorted alphabetically.

## Extending

You can extend the `utilities` in your `panda.config.ts` and bind (or re-bind an existing) them to a `group` name so
that they will be sorted with the other utilities in that group.

```ts
export default defineConfig({
utilities: {
boxSize: {
values: 'sizes',
group: 'Width',
transform: (value) => {
return {
width: value,
height: value,
}
},
},
},
})

// will be sorted near the `width` prop
css({
position: 'relative',
boxSize: '2xl',
width: '100%',
fontSize: '2xl',
})
```

## Options

### `pandaFirstProps`

Expand All @@ -32,21 +118,31 @@ The first props to sort. Defaults to `['as', 'layerStyle', 'textStyle']`.

The last props to sort. Defaults to `[]`.

## Example
### `pandaOnlyComponents`

```json
{
"plugins": ["prettier-plugin-panda"],
"overrides": [
{
"files": "*.{ts,tsx}",
"options": {
"pandaConfigPath": "./panda.config.ts",
"pandaCwd": "./packages/my-package",
"pandaFirstProps": ["as"],
"pandaLastProps": ["css"],
}
}
]
}
```
Only sort props in known Panda components (JSX patterns and `<styled.xxx /> factory`). Defaults to `false`.

### `pandaOnlyIncluded`

Only sort props in files that are included in the config. Defaults to `false`.

### `pandaStylePropsFirst`

Whether to sort the style props before the component props. Defaults to `true`.

### `pandaSortOtherProps`

Whether to sort the other props alphabetically. Defaults to `true`.

### `pandaGroupOrder`

The order of the style groups. Defaults to:
`['System', 'Container', 'Display', 'Visibility', 'Position', 'Transform', 'Flex Layout', 'Grid Layout', 'Layout', 'Border', 'Border Radius', 'Width', 'Height', 'Margin', 'Padding', 'Color', 'Typography', 'Background', 'Shadow', 'Table', 'List', 'Scroll', 'Interactivity', 'Transition', 'Effect', 'Other', 'Conditions', 'Arbitrary conditions', 'Css']`

### `pandaConfigPath`

The path to the panda config file. Only relevant when used programatically.

### `pandaCwd`

The current working directory from which the config file will be searched for. Only relevant when used programatically.
Original file line number Diff line number Diff line change
Expand Up @@ -1081,4 +1081,65 @@ describe('call expression specifics', () => {
"
`)
})

test('custom pandaGroupOrder', async () => {
const code = `
import { Box } from "../styled-system/jsx";
const App = ({ onClick }: { onClick: () => void }) => {
return (
<Box bgColor="red" p="4" mx="2" width="120" mt="4">
Hello
</Box>
);
}
`

expect(
await run(code, {
pandaGroupOrder: [
'Padding', // changed
'System',
'Container',
'Display',
'Visibility',
'Position',
'Transform',
'Flex Layout',
'Grid Layout',
'Layout',
'Border',
'Border Radius',
'Background', // changed
'Margin', // changed
'Height',
'Color',
'Typography',
'Shadow',
'Table',
'List',
'Scroll',
'Interactivity',
'Transition',
'Effect',
'Other',
'Conditions',
'Arbitrary conditions',
'Css',
'Width', // changed
],
}),
).toMatchInlineSnapshot(`
"import { Box } from "../styled-system/jsx";
const App = ({ onClick }: { onClick: () => void }) => {
return (
<Box p="4" bgColor="red" mx="2" mt="4" width="120">
Hello
</Box>
);
};
"
`)
})
})
23 changes: 7 additions & 16 deletions packages/prettier-plugin-panda/src/get-priority-index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import type { CssSemanticGroup } from '@pandacss/types'
import type { PluginOptions } from './options'

export const groupNames = [
export const defaultGroupNames = [
'System',
'Container',
'Display',
Expand Down Expand Up @@ -36,17 +36,9 @@ export const groupNames = [
'Css',
] as const

export type PriorityGroupName = CssSemanticGroup | (typeof groupNames)[number]
export type PriorityGroupName = CssSemanticGroup | (typeof defaultGroupNames)[number]

export const groupPriorities = groupNames.reduce(
(acc, key, index) => {
acc[key] = index + 1
return acc
},
{} as Record<PriorityGroupName, number>,
)

type Priority = typeof groupPriorities
type Priority = Record<PriorityGroupName, number>

export type PriorityGroup = {
name: PriorityGroupName
Expand Down Expand Up @@ -111,14 +103,13 @@ const calcPriorityFromIndex = (index: Index, config: PluginOptions, priorityGrou

// Perhaps we may want to handle -1 as error in some future.
// Therefore I set the priority to numbers greater than or equal to zero.
// const isComponentSpecBeforeStyle = config.isCompPropsBeforeStyleProps
const isComponentSpecBeforeStyle = true
const basePriorities = {
firstProps: 0,
styleProps: 20000,
componentSpecificProps: isComponentSpecBeforeStyle ? 10000 : 30000,
otherProps: 40000,
lastProps: 50000,
styleProps: config.pandaStylePropsFirst ? 20_000: 45_000 ,
componentSpecificProps: isComponentSpecBeforeStyle ? 10_000 : 30_000,
otherProps: 40_000,
lastProps: 50_000,
}

switch (index.type) {
Expand Down
33 changes: 24 additions & 9 deletions packages/prettier-plugin-panda/src/options.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { Plugin, SupportOption } from 'prettier'
import type { SupportOption } from 'prettier'

export interface PluginOptions {
pandaConfigPath?: string
Expand All @@ -8,7 +8,9 @@ export interface PluginOptions {
pandaLastProps: string[]
pandaOnlyComponents: boolean
pandaOnlyIncluded: boolean
// isCompPropsBeforeStyleProps: boolean
pandaStylePropsFirst: boolean
pandaSortOtherProps: boolean
pandaGroupOrder: string[]
// componentSpecificProps: string[] | undefined
}

Expand Down Expand Up @@ -43,7 +45,7 @@ export const options = {
pandaOnlyComponents: {
type: 'boolean',
category: 'Panda',
description: 'Only sort props in Panda components (JSX patterns and `<styled.xxx /> factory`)',
description: 'Only sort props in known Panda components (JSX patterns and `<styled.xxx /> factory`)',
default: false,
},
pandaOnlyIncluded: {
Expand All @@ -52,12 +54,25 @@ export const options = {
description: 'Only sort props in files that are included in the config',
default: false,
},
// isCompPropsBeforeStyleProps: {
// type: 'boolean',
// category: 'Panda',
// description: 'Whether to sort the style props before the component props',
// default: true,
// },
pandaStylePropsFirst: {
type: 'boolean',
category: 'Panda',
description: 'Whether to sort the style props before the component props',
default: true,
},
pandaSortOtherProps: {
type: 'boolean',
category: 'Panda',
description: 'Whether to sort the other props alphabetically',
default: true,
},
pandaGroupOrder: {
array: true,
type: 'string',
category: 'Panda',
description: "The order of the style groups. Defaults to: ['System', 'Container', 'Display', 'Visibility', 'Position', 'Transform', 'Flex Layout', 'Grid Layout', 'Layout', 'Border', 'Border Radius', 'Width', 'Height', 'Margin', 'Padding', 'Color', 'Typography', 'Background', 'Shadow', 'Table', 'List', 'Scroll', 'Interactivity', 'Transition', 'Effect', 'Other', 'Conditions', 'Arbitrary conditions', 'Css']",
default: [{ value: [] }],
},
// componentSpecificProps: {
// array: true,
// type: 'string',
Expand Down
Loading

0 comments on commit c68aade

Please sign in to comment.