Skip to content

Commit

Permalink
feat: Introduce an add-on interface
Browse files Browse the repository at this point in the history
* Add manager export and a preview module
* Adapt the example.
* Adapt the documentation

The modification of preview.js is still needed, unfortunately.
  • Loading branch information
prantlf committed May 14, 2023
1 parent 4a52fb1 commit ce08cef
Show file tree
Hide file tree
Showing 16 changed files with 830 additions and 825 deletions.
14 changes: 9 additions & 5 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
# [2.0.0](https://github.com/prantlf/storybook-multilevel-sort/compare/v1.2.1...v2.0.0) (2023-05-14)

# [2.0.0-next.2](https://github.com/prantlf/storybook-multilevel-sort/compare/v2.0.0-next.1...v2.0.0-next.2) (2023-05-14)

### Features

* Support Storybook 7 and docs pages ([#10](https://github.com/prantlf/storybook-multilevel-sort/issues/10)) ([1065337](https://github.com/prantlf/storybook-multilevel-sort/commit/10653377d94d46763e3c0885bc2386bf42a5d8d2))
* Describe how to modify preview.js maually, unfortunately ([9695988](https://github.com/prantlf/storybook-multilevel-sort/commit/9695988cdef4e6b5894c7f9d32d61b90a9dbc060))

# [2.0.0-next.1](https://github.com/prantlf/storybook-multilevel-sort/compare/v2.0.0-next.0...v2.0.0-next.1) (2023-05-08)

### BREAKING CHANGES
### Bug Fixes

* Make sortOrder option not mandatory, add tests ([ff2417a](https://github.com/prantlf/storybook-multilevel-sort/commit/ff2417a473de31cda9fe258c0534006ca22f25c5))

### Features

* Only Storybook 7 is supported. If you use Storybook 6 or older, stay with the versions 1.x. Also, the minimum supported version of Node.js is 16. Except for the version requirements, the configuration of the custom sorting needs to be specified by a different interface. See the documentation about migration for more information.
* Introduce an add-on interface ([4bdbd77](https://github.com/prantlf/storybook-multilevel-sort/commit/4bdbd77b8cdaf77bc6f59f9e3a0566d511eaaa7e))

# [2.0.0-next.0](https://github.com/prantlf/storybook-multilevel-sort/compare/v1.2.0...v2.0.0-next.0) (2023-05-07)

Expand Down
2 changes: 0 additions & 2 deletions LICENSE
Original file line number Diff line number Diff line change
Expand Up @@ -32,5 +32,3 @@ Our license allows you to use the content:
* For an unlimited number of times without interruption
* Anywhere in the world
* To make changes and create derivative works

See also docs/icon-license.pdf.
224 changes: 105 additions & 119 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@

Applies specific sort order to more than two levels of chapters and stories in a [storybook].

**Warning**: This is an experimental branch trying to simpler interface to set up the custom sorting using add-on properties. Unfortunately, it doesn't work yet. The change in `preview.js`, copied & pasted to each Storybook project, wasn't supposed to be needed. This branch remains open to be able to look at the problem once more. There's more about this in the [open issue].

**Attention**: Versions `2.x` of this package will support Storybook 7 only. If you use Storybook 6 or older, look for the [versions `1.x` of this package]. If you upgrade Storybook to the verion 7, you vill need a version `2.x` of this package too. See the [documentation about how to migrate] from a version `1.x` to a version `2.x` of this package.

See also an [example of a Storybook project using this package].
Expand Down Expand Up @@ -78,25 +80,30 @@ Components
When using the following code in `.storybook/main.js`:

```js
import { configureSort } from 'storybook-multilevel-sort'

configureSort({
storyOrder: {
articles: null,
elements: {
'*': { default: null }
},
components: {
navigation: {
header: {
default: null,
'with search': null
}
const storyOrder = {
articles: null,
elements: {
'*': { default: null }
},
components: {
navigation: {
header: {
default: null,
'with search': null
}
},
'**': { default: null }
}
})
}
},
'**': { default: null }
}

export default {
addons: [
{
name: 'storybook-multilevel-sort',
options: { storyOrder }
}
]
}
```

And the following code in `.storybook/preview.js`:
Expand All @@ -115,7 +122,7 @@ export default {
A simpler configuration using nested wildcards:

```js
{
const storyOrder = {
articles: null,
elements: null,
components: {
Expand All @@ -133,47 +140,30 @@ A simpler configuration using nested wildcards:
This module can be installed in your project using [NPM], [PNPM] or [Yarn]. Make sure, that you use [Node.js] version 16 or newer.

```sh
npm i -D storybook-multilevel-sort
pnpm i -D storybook-multilevel-sort
yarn add storybook-multilevel-sort
npm i -D storybook-multilevel-sort@2.0.0-next.2
pnpm i -D storybook-multilevel-sort@2.0.0-next.2
yarn add storybook-multilevel-sort@2.0.0-next.2
```

## API

This package exports a function to configure the custom sorting:

```js
import { configureSort } from 'storybook-multilevel-sort'
```

The function is supposed to be executed in `.storybook/main.js` and expects an object with the sorting configuration:

```js
configureSort({
typeOrder: ...
storyOrder: ...
compareNames: ...
})
```

It prepares a global function, which will be called in the `storySort` callback with the two stories to compare, implemented in`.storybook/preview.js`:
This package contains a Storybook add-on setting up the custom sorting: It is supposed to be added to `.storybook/main.js` and expects an object with the sorting configuration:

```js
export default {
parameters: {
options: {
storySort: (story1, story2) =>
globalThis['storybook-multilevel-sort:storySort'](story1, story2)
addons: [
{
name: 'storybook-multilevel-sort',
options: {
typeOrder: ...
storyOrder: ...
compareNames: ...
}
}
}
]
}
```

This package can be imported to CJS projects too:

```js
const { configureSort } = require('storybook-multilevel-sort')
```
## Configuration

The object expected by the `configureSort` function may include the following properties:
Expand All @@ -187,16 +177,14 @@ The object expected by the `configureSort` function may include the following pr
The sorting configuration is an object set by the `sortOrder` property. Keys are titles of groups and stories. Values are objects with the next level of groups or stories. Nesting of the objects follows the slash-delimited story paths set to the `title` attribute:

```js
configureSort({
storyOrder: {
elements: {
link: null, // Elements/Link/...
button: null // Elements/Button/...
},
components: null // Components/Card/...
// Components/Header/...
}
})
const storyOrder = {
elements: {
link: null, // Elements/Link/...
button: null // Elements/Button/...
},
components: null // Components/Card/...
// Components/Header/...
}
```

**Keys in the sorting objects have to be lower-case.** If a value is `null` or an empty object, that level will be sorted alphabetically. Names of groups or stories missing among the object keys will be sorted alphabetically, behind the names that are listed as keys.
Expand All @@ -221,12 +209,10 @@ story1.storyName = 'With Search'
When you refer to such groups or stories on the ordering configuration, use the displayable name (with spaces) lower-case, for example:

```js
{
storyOrder: {
'*': {
default: null,
'with search': null
}
const storyOrder = {
'*': {
default: null,
'with search': null
}
}
```
Expand All @@ -238,51 +224,45 @@ When you refer to such groups or stories on the ordering configuration, use the
If you want to skip explicit sorting at one level and specify the next level, use `*` instead of names, for which you want to specify the next level. The `*` matches any name, which is not listed explicitly at the same level:

```js
{
storyOrder: {
'*': {
default: null // Link/Default
} // Link/Active
} // Link/Visited
}
const storyOrder = {
'*': {
default: null // Link/Default
} // Link/Active
} // Link/Visited
```

### Nested Wildcards

If you want to enable implicit sorting at multiple levels, you would have to repeat the `*` selector on each level:

```js
{
storyOrder: {
elements: {
'*': {
default: null // Link/Default
} // Link/Active
}, // Link/Visited
components: {
'*': {
default: null // Header/Default
} // Header/Collapsed
} // Header/Expanded
}
const storyOrder = {
elements: {
'*': {
default: null // Link/Default
} // Link/Active
}, // Link/Visited
components: {
'*': {
default: null // Header/Default
} // Header/Collapsed
} // Header/Expanded
}
```

you can use a nested wildcard `**` to specify default for the current and deeper levels. The `**` matches any name, which is not listed explicitly at the same level and if there is no `*` wildcard selector at that level:

```js
{
storyOrder: {
elements: null,
components: null,
'**': {
default: null // Link/Default
} // Link/Active
} // Link/Visited
// Header/Default
// Header/Collapsed
// Header/Expanded
}
const storyOrder = {
elements: null,
components: null,
'**': {
default: null // Link/Default
} // Link/Active
} // Link/Visited
// Header/Default
// Header/Collapsed
// Header/Expanded
```

The precedence of the selectors at a particular level:
Expand All @@ -296,19 +276,24 @@ The precedence of the selectors at a particular level:
Names of groups and stories on one level are compared alphabetically according to the current locale by default. If you need a different comparison, you can specify it by using the optional `compareNames` parameter:

```js
{
storyOrder: ...

compareNames: (name1, name2, context) {
// name1 - the string with the name on the left side of the comparison
// name2 - the string with the name on the right side of the comparison
// context - additional information
// context.path1 - an array of strings with the path of groups
// down to the left compared group or story name (name1)
// context.path2 - an array of strings with the path of groups
// down to the right compared group or story name (name2)
return name1.localeCompare(name2, { numeric: true })
}
const compareNames: (name1, name2, context) {
// name1 - the string with the name on the left side of the comparison
// name2 - the string with the name on the right side of the comparison
// context - additional information
// context.path1 - an array of strings with the path of groups
// down to the left compared group or story name (name1)
// context.path2 - an array of strings with the path of groups
// down to the right compared group or story name (name2)
return name1.localeCompare(name2, { numeric: true })
}

export default {
addons: [
{
name: 'storybook-multilevel-sort',
options: { compareNames }
}
]
}
```

Expand All @@ -321,10 +306,15 @@ Storybook 7 introduced a new type of pages, which can appear among the stories -
Storybook inserts the links to the "Docs" pages before the first story of a particular component. This custom sorting will retain it by default, because the "Docs" page usually contains an overview of the component's usage. But you can change it by the `typeOrder` property. This is the default value, which groups all pages of the `docs` type before all pages of the `story` type:

```js
{
storyOrder: ...
const typeOrder = ['docs', 'story']

typeOrder: ['docs', 'story']
export default {
addons: [
{
name: 'storybook-multilevel-sort',
options: { typeOrder }
}
]
}
```

Expand All @@ -333,11 +323,7 @@ The order of types in he array will be the order of the page groups. If you spec
If you want to handle the `docs` pages like any other stories and sort all the pages only by their names, you can pass an empty array to `typeOrder` to disable the gouping by type:

```js
{
storyOrder: ...

typeOrder: []
}
const typeOrder = []
```

## Motivation
Expand Down Expand Up @@ -426,7 +412,7 @@ Licensed under the [Icon Free License (with attribution)](./docs/icon-license.pd
[storybook]: https://storybook.js.org/
[sorting configuration supported by Storybook]: https://storybook.js.org/docs/react/writing-stories/naming-components-and-hierarchy#sorting-stories
[algorithm how Storybook generates the names of stories]: https://storybook.js.org/docs/react/api/csf#named-story-exports
[example of a Storybook project using this package]: ./example
[example of a Storybook project]: ./example
[versions `1.x` of this package]: https://github.com/prantlf/storybook-multilevel-sort/tree/v1.x#readme
[open issue]: https://github.com/prantlf/storybook-multilevel-sort/issues/8#issuecomment-1537507235
[documentation about how to migrate]: ./docs/MIGRATION.md
Expand Down
Loading

0 comments on commit ce08cef

Please sign in to comment.