├── .nvmrc
├── manager.js
├── .husky
└── pre-commit
├── preview.js
├── .releaserc.json
├── .lintstagedrc.json
├── src
├── index.ts
├── constants.ts
├── stories
│ ├── card.css
│ ├── Card.tsx
│ └── Card.stories.ts
├── manager.ts
├── types.ts
├── preview.ts
├── components
│ └── PaddingIcon.tsx
├── helpers.ts
├── withGlobals.ts
└── Tool.tsx
├── demo.gif
├── .gitignore
├── netlify.toml
├── vite.config.ts
├── .prettierrc.json
├── .storybook
├── preview.ts
├── manager.ts
├── main.ts
└── local-preset.cjs
├── icon.svg
├── tsconfig.json
├── LICENSE
├── .github
└── workflows
│ └── main.yml
├── tsup.config.ts
├── README.md
└── package.json
/.nvmrc:
--------------------------------------------------------------------------------
1 | 20
2 |
--------------------------------------------------------------------------------
/manager.js:
--------------------------------------------------------------------------------
1 | import './dist/manager'
2 |
--------------------------------------------------------------------------------
/.husky/pre-commit:
--------------------------------------------------------------------------------
1 | npx --no lint-staged
2 |
--------------------------------------------------------------------------------
/preview.js:
--------------------------------------------------------------------------------
1 | export * from './dist/preview'
2 |
--------------------------------------------------------------------------------
/.releaserc.json:
--------------------------------------------------------------------------------
1 | {
2 | "preset": "conventionalcommits"
3 | }
4 |
--------------------------------------------------------------------------------
/.lintstagedrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "*": "prettier --ignore-unknown --write"
3 | }
4 |
--------------------------------------------------------------------------------
/src/index.ts:
--------------------------------------------------------------------------------
1 | // make it work with --isolatedModules
2 | export default {}
3 |
--------------------------------------------------------------------------------
/demo.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rbardini/storybook-addon-paddings/HEAD/demo.gif
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | dist/
2 | node_modules/
3 | storybook-static/
4 | .DS_Store
5 | .env
6 | .vscode
7 | build-storybook.log
8 |
--------------------------------------------------------------------------------
/netlify.toml:
--------------------------------------------------------------------------------
1 | [build]
2 | command = "npm i && npm run build && npm run build-storybook"
3 | publish = "storybook-static"
4 |
--------------------------------------------------------------------------------
/src/constants.ts:
--------------------------------------------------------------------------------
1 | export const ADDON_ID = 'storybook/paddings'
2 | export const PARAM_KEY = 'paddings'
3 | export const DEFAULT_PADDING = '0'
4 |
--------------------------------------------------------------------------------
/vite.config.ts:
--------------------------------------------------------------------------------
1 | import react from '@vitejs/plugin-react'
2 | import { defineConfig } from 'vite'
3 |
4 | export default defineConfig({
5 | plugins: [react()],
6 | })
7 |
--------------------------------------------------------------------------------
/.prettierrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "arrowParens": "avoid",
3 | "plugins": ["prettier-plugin-packagejson"],
4 | "semi": false,
5 | "singleQuote": true,
6 | "trailingComma": "all"
7 | }
8 |
--------------------------------------------------------------------------------
/.storybook/preview.ts:
--------------------------------------------------------------------------------
1 | import type { Preview } from '@storybook/react-vite'
2 |
3 | const preview: Preview = {
4 | parameters: {
5 | layout: 'fullscreen',
6 | },
7 | tags: ['autodocs'],
8 | }
9 |
10 | export default preview
11 |
--------------------------------------------------------------------------------
/src/stories/card.css:
--------------------------------------------------------------------------------
1 | .card {
2 | background-color: #fff;
3 | border-radius: 1em;
4 | box-shadow: 0 2em 4em rgba(0, 0, 0, 0.2);
5 | display: inline-block;
6 | font-family: sans-serif;
7 | line-height: 1.5;
8 | padding: 4em;
9 | }
10 |
--------------------------------------------------------------------------------
/.storybook/manager.ts:
--------------------------------------------------------------------------------
1 | import { addons } from 'storybook/manager-api'
2 | import { create } from 'storybook/theming/create'
3 |
4 | addons.setConfig({
5 | theme: create({
6 | base: 'light',
7 | brandTitle: 'Storybook Paddings Addon',
8 | }),
9 | })
10 |
--------------------------------------------------------------------------------
/src/stories/Card.tsx:
--------------------------------------------------------------------------------
1 | import React, { type ReactNode } from 'react'
2 | import './card.css'
3 |
4 | interface CardProps {
5 | children?: ReactNode
6 | }
7 |
8 | export const Card = ({ children }: CardProps) => (
9 |
{children}
10 | )
11 |
--------------------------------------------------------------------------------
/.storybook/main.ts:
--------------------------------------------------------------------------------
1 | import { defineMain } from '@storybook/react-vite/node'
2 |
3 | const config = defineMain({
4 | stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|ts|tsx)'],
5 | addons: ['@storybook/addon-docs', './local-preset.cjs'],
6 | framework: '@storybook/react-vite',
7 | })
8 |
9 | export default config
10 |
--------------------------------------------------------------------------------
/.storybook/local-preset.cjs:
--------------------------------------------------------------------------------
1 | function previewAnnotations(entry = []) {
2 | return [...entry, require.resolve('../dist/preview.js')]
3 | }
4 |
5 | function managerEntries(entry = []) {
6 | return [...entry, require.resolve('../dist/manager.js')]
7 | }
8 |
9 | module.exports = {
10 | managerEntries,
11 | previewAnnotations,
12 | }
13 |
--------------------------------------------------------------------------------
/src/manager.ts:
--------------------------------------------------------------------------------
1 | import { addons, types } from 'storybook/manager-api'
2 |
3 | import { ADDON_ID } from './constants'
4 | import { Tool } from './Tool'
5 |
6 | addons.register(ADDON_ID, () => {
7 | addons.add(ADDON_ID, {
8 | title: 'Paddings',
9 | type: types.TOOL,
10 | match: ({ viewMode }) => !!viewMode?.match(/^(story|docs)$/),
11 | render: Tool,
12 | })
13 | })
14 |
--------------------------------------------------------------------------------
/icon.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/types.ts:
--------------------------------------------------------------------------------
1 | import { type ComponentProps } from 'react'
2 | import { TooltipLinkList } from 'storybook/internal/components'
3 |
4 | export type Padding = { name: string; value: string }
5 |
6 | export type PaddingsParameter = {
7 | default?: string
8 | disable?: boolean
9 | values: Padding[]
10 | }
11 |
12 | export type PaddingWithDefault = Padding & { default?: boolean }
13 |
14 | export type Item = Extract<
15 | ComponentProps['links'][number],
16 | Array
17 | >[number]
18 |
19 | export type GlobalState = {
20 | name?: string
21 | selected?: string
22 | }
23 |
--------------------------------------------------------------------------------
/src/preview.ts:
--------------------------------------------------------------------------------
1 | import type { Renderer, ProjectAnnotations } from 'storybook/internal/types'
2 |
3 | import { PARAM_KEY } from './constants'
4 | import { withGlobals } from './withGlobals'
5 |
6 | const preview: ProjectAnnotations = {
7 | decorators: [withGlobals],
8 | initialGlobals: {
9 | [PARAM_KEY]: false,
10 | },
11 | parameters: {
12 | [PARAM_KEY]: {
13 | values: [
14 | { name: 'Small', value: '16px' },
15 | { name: 'Medium', value: '32px' },
16 | { name: 'Large', value: '64px' },
17 | ],
18 | },
19 | },
20 | }
21 |
22 | export default preview
23 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "allowJs": true,
4 | "baseUrl": ".",
5 | "esModuleInterop": true,
6 | "isolatedModules": true,
7 | "jsx": "react",
8 | "lib": ["es2023", "dom", "dom.iterable"],
9 | "module": "preserve",
10 | "moduleDetection": "force",
11 | "moduleResolution": "bundler",
12 | "noImplicitAny": true,
13 | "noImplicitOverride": true,
14 | "noUncheckedIndexedAccess": true,
15 | "resolveJsonModule": true,
16 | "rootDir": "./src",
17 | "skipLibCheck": true,
18 | "strict": true,
19 | "target": "es2023", // Node 20 according to https://github.com/microsoft/TypeScript/wiki/Node-Target-Mapping#node-20
20 | "verbatimModuleSyntax": true
21 | },
22 | "include": ["src/**/*"]
23 | }
24 |
--------------------------------------------------------------------------------
/src/components/PaddingIcon.tsx:
--------------------------------------------------------------------------------
1 | import React, { forwardRef, memo } from 'react'
2 |
3 | interface IconProps extends React.SVGAttributes {
4 | children?: never
5 | color?: string
6 | size?: number
7 | }
8 |
9 | export const PaddingIcon = forwardRef(
10 | ({ color = 'currentColor', size = 14, ...props }, ref) => (
11 |
27 | ),
28 | )
29 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 Rafael Bardini
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/.github/workflows/main.yml:
--------------------------------------------------------------------------------
1 | name: Main
2 | on:
3 | push:
4 | branches:
5 | - main
6 | pull_request:
7 | branches:
8 | - main
9 |
10 | jobs:
11 | test-build-release:
12 | name: Test, build and release
13 | runs-on: ubuntu-latest
14 | steps:
15 | - name: Checkout
16 | uses: actions/checkout@v5
17 |
18 | - name: Setup Node.js
19 | uses: actions/setup-node@v5
20 | with:
21 | node-version: 24
22 |
23 | - name: Install
24 | run: npm ci
25 |
26 | - name: Build
27 | run: npm run build
28 |
29 | - name: Format-check
30 | run: npm run format-check
31 |
32 | - name: Type-check
33 | run: npm run type-check
34 |
35 | - name: Package-check
36 | run: npm run package-check
37 |
38 | - name: Release
39 | uses: cycjimmy/semantic-release-action@v5
40 | with:
41 | semantic_version: 25
42 | extra_plugins: |
43 | conventional-changelog-conventionalcommits
44 | if: github.ref == 'refs/heads/main'
45 | env:
46 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
47 | NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
48 |
--------------------------------------------------------------------------------
/src/helpers.ts:
--------------------------------------------------------------------------------
1 | import { DEFAULT_PADDING } from './constants'
2 | import type { PaddingWithDefault, PaddingsParameter, Padding } from './types'
3 |
4 | export const isEnabled = (values: PaddingWithDefault[]): boolean =>
5 | values.length > 0
6 |
7 | export const isReducedMotionPreferred = (): boolean =>
8 | window.matchMedia('(prefers-reduced-motion: reduce)').matches
9 |
10 | export const normalizeValues = (
11 | parameters: PaddingsParameter | null,
12 | ): PaddingWithDefault[] => {
13 | if (!parameters || parameters.disable || !parameters.values?.length) {
14 | return []
15 | }
16 |
17 | return parameters.values.map((item: Padding) => {
18 | const { name, value } = item
19 | const isDefault = parameters.default === name
20 |
21 | return { name, value, default: isDefault }
22 | })
23 | }
24 |
25 | export const getSelectedPadding = (
26 | values: PaddingWithDefault[],
27 | currentValue: string,
28 | ): string => {
29 | if (currentValue === DEFAULT_PADDING) {
30 | return currentValue
31 | }
32 |
33 | if (values.find(({ value }) => value === currentValue)) {
34 | return currentValue
35 | }
36 |
37 | return values.find(option => option.default)?.value ?? DEFAULT_PADDING
38 | }
39 |
--------------------------------------------------------------------------------
/src/stories/Card.stories.ts:
--------------------------------------------------------------------------------
1 | import type { Meta, StoryObj } from '@storybook/react-vite'
2 |
3 | import { Card } from './Card'
4 |
5 | type Story = StoryObj
6 |
7 | const meta: Meta = {
8 | title: 'Example',
9 | component: Card,
10 | }
11 |
12 | export default meta
13 |
14 | export const PresetOptions: Story = {
15 | args: {
16 | children: 'This story uses preset padding options. (Small, Medium & Large)',
17 | },
18 | }
19 |
20 | export const CustomOptions: Story = {
21 | args: {
22 | children: 'This story uses custom padding options. (xs, sm, md, lg & xl)',
23 | },
24 | parameters: {
25 | paddings: {
26 | values: [
27 | { name: 'xs', value: '8px' },
28 | { name: 'sm', value: '16px' },
29 | { name: 'md', value: '24px' },
30 | { name: 'lg', value: '32px' },
31 | { name: 'xl', value: '48px' },
32 | ],
33 | },
34 | },
35 | }
36 |
37 | export const DefaultOption: Story = {
38 | args: {
39 | children: 'This story sets a default padding option. (Medium)',
40 | },
41 | parameters: {
42 | paddings: { default: 'Medium' },
43 | },
44 | }
45 |
46 | export const Disabled: Story = {
47 | args: {
48 | children: 'This story disables paddings.',
49 | },
50 | parameters: {
51 | paddings: { disable: true },
52 | },
53 | }
54 |
--------------------------------------------------------------------------------
/tsup.config.ts:
--------------------------------------------------------------------------------
1 | import { readFile } from 'fs/promises'
2 | import { globalPackages as globalManagerPackages } from 'storybook/internal/manager/globals'
3 | import { globalPackages as globalPreviewPackages } from 'storybook/internal/preview/globals'
4 | import { defineConfig, type Options } from 'tsup'
5 |
6 | const NODE_TARGET: Options['target'] = 'node20'
7 |
8 | type BundlerConfig = {
9 | bundler?: {
10 | exportEntries?: string[]
11 | managerEntries?: string[]
12 | previewEntries?: string[]
13 | }
14 | }
15 |
16 | export default defineConfig(async options => {
17 | const packageJson = (await readFile('./package.json', 'utf8').then(
18 | JSON.parse,
19 | )) as BundlerConfig
20 |
21 | const {
22 | bundler: {
23 | exportEntries = [],
24 | managerEntries = [],
25 | previewEntries = [],
26 | } = {},
27 | } = packageJson
28 |
29 | const commonConfig: Options = {
30 | splitting: false,
31 | minify: !options.watch,
32 | treeshake: true,
33 | sourcemap: true,
34 | clean: true,
35 | }
36 |
37 | const configs: Options[] = []
38 |
39 | if (exportEntries.length) {
40 | configs.push({
41 | ...commonConfig,
42 | entry: exportEntries,
43 | dts: { resolve: true },
44 | format: ['esm', 'cjs'],
45 | target: NODE_TARGET,
46 | platform: 'neutral',
47 | external: [...globalManagerPackages, ...globalPreviewPackages],
48 | })
49 | }
50 |
51 | if (managerEntries.length) {
52 | configs.push({
53 | ...commonConfig,
54 | entry: managerEntries,
55 | format: ['esm'],
56 | platform: 'browser',
57 | external: globalManagerPackages,
58 | })
59 | }
60 |
61 | if (previewEntries.length) {
62 | configs.push({
63 | ...commonConfig,
64 | entry: previewEntries,
65 | dts: { resolve: true },
66 | format: ['esm', 'cjs'],
67 | platform: 'browser',
68 | external: globalPreviewPackages,
69 | })
70 | }
71 |
72 | return configs
73 | })
74 |
--------------------------------------------------------------------------------
/src/withGlobals.ts:
--------------------------------------------------------------------------------
1 | import type {
2 | Renderer,
3 | PartialStoryFn as StoryFunction,
4 | StoryContext,
5 | } from 'storybook/internal/types'
6 | import { useEffect, useMemo } from 'storybook/preview-api'
7 |
8 | import { DEFAULT_PADDING, PARAM_KEY } from './constants'
9 | import {
10 | getSelectedPadding,
11 | isReducedMotionPreferred,
12 | normalizeValues,
13 | } from './helpers'
14 |
15 | const setStyle = (selector: string, css: string) => {
16 | const existingStyle = document.getElementById(selector)
17 |
18 | if (existingStyle) {
19 | if (existingStyle.innerHTML !== css) {
20 | existingStyle.innerHTML = css
21 | }
22 | } else {
23 | const style = document.createElement('style')
24 | style.setAttribute('id', selector)
25 | style.innerHTML = css
26 |
27 | document.head.appendChild(style)
28 | }
29 | }
30 |
31 | export const withGlobals = (
32 | StoryFn: StoryFunction,
33 | context: StoryContext,
34 | ) => {
35 | const { id, globals, parameters, viewMode } = context
36 | const globalsSelectedPadding = globals[PARAM_KEY]?.value
37 | const paddingsConfig = parameters[PARAM_KEY]
38 | const isInDocs = viewMode === 'docs'
39 | const selector = isInDocs
40 | ? `#anchor--${context.id} .sb-story`
41 | : '#storybook-root'
42 |
43 | const selectedPadding = useMemo(
44 | () =>
45 | getSelectedPadding(
46 | normalizeValues(paddingsConfig),
47 | globalsSelectedPadding,
48 | ) ?? DEFAULT_PADDING,
49 | [paddingsConfig, globalsSelectedPadding],
50 | )
51 |
52 | const paddingStyles = useMemo(
53 | () => `
54 | ${selector} {
55 | margin: 0;
56 | padding: ${selectedPadding} !important;
57 | ${isReducedMotionPreferred() ? '' : 'transition: padding .3s;'}
58 | }
59 |
60 | ${selector} .innerZoomElementWrapper > div {
61 | border-width: 0 !important;
62 | }
63 | `,
64 | [selector, selectedPadding],
65 | )
66 |
67 | useEffect(() => {
68 | const selectorId = isInDocs ? `addon-paddings-docs-${id}` : `addon-paddings`
69 |
70 | setStyle(selectorId, paddingStyles)
71 | }, [id, isInDocs, paddingStyles])
72 |
73 | return StoryFn()
74 | }
75 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Storybook Paddings Addon
2 |
3 | [](https://www.npmjs.com/package/storybook-addon-paddings)
4 | [](https://github.com/rbardini/storybook-addon-paddings/actions)
5 | [](https://libraries.io/npm/storybook-addon-paddings)
6 |
7 | 🔲 A [Storybook](https://storybook.js.org) addon to add different paddings to your preview. Useful for checking how components behave when surrounded with white space.
8 |
9 | 
10 |
11 | [View demo →](https://storybook-addon-paddings.rbrd.in)
12 |
13 | ## Installation
14 |
15 | ```sh
16 | npm install --save-dev storybook-addon-paddings
17 | ```
18 |
19 | ```js
20 | // .storybook/main.js
21 | export default {
22 | addons: ['storybook-addon-paddings'],
23 | }
24 |
25 | // .storybook/preview.js
26 | export default {
27 | parameters: {
28 | layout: 'fullscreen', // remove default Storybook padding
29 | },
30 | }
31 | ```
32 |
33 | ## Configuration
34 |
35 | The paddings toolbar comes with small, medium and large options by default, but you can configure your own set of paddings via the `paddings` [parameter](https://storybook.js.org/docs/react/writing-stories/parameters).
36 |
37 | To configure for all stories, set the `paddings` parameter in [`.storybook/preview.js`](https://storybook.js.org/docs/react/configure/overview#configure-story-rendering):
38 |
39 | ```js
40 | export const parameters = {
41 | paddings: {
42 | values: [
43 | { name: 'Small', value: '16px' },
44 | { name: 'Medium', value: '32px' },
45 | { name: 'Large', value: '64px' },
46 | ],
47 | default: 'Medium',
48 | },
49 | }
50 | ```
51 |
52 | You can also configure on per-story or per-component basis using [parameter inheritance](https://storybook.js.org/docs/react/writing-stories/parameters#component-parameters):
53 |
54 | ```js
55 | // Button.stories.js
56 |
57 | // Set padding options for all Button stories
58 | export default {
59 | title: 'Button',
60 | component: Button,
61 | parameters: {
62 | paddings: {
63 | values: [
64 | { name: 'Small', value: '16px' },
65 | { name: 'Medium', value: '32px' },
66 | { name: 'Large', value: '64px' },
67 | ],
68 | default: 'Large',
69 | },
70 | },
71 | }
72 |
73 | // Disable addon in Button/Large story only
74 | export const Large {
75 | parameters: {
76 | paddings: { disable: true },
77 | },
78 | }
79 | ```
80 |
81 | See other [story examples](./src/stories/Card.stories.ts).
82 |
--------------------------------------------------------------------------------
/src/Tool.tsx:
--------------------------------------------------------------------------------
1 | import React, { memo, useCallback, useMemo } from 'react'
2 | import {
3 | IconButton,
4 | WithTooltip,
5 | TooltipLinkList,
6 | } from 'storybook/internal/components'
7 | import { useParameter, useGlobals } from 'storybook/manager-api'
8 |
9 | import { PaddingIcon } from './components/PaddingIcon'
10 | import { DEFAULT_PADDING, PARAM_KEY } from './constants'
11 | import { getSelectedPadding, normalizeValues, isEnabled } from './helpers'
12 | import type { PaddingWithDefault, Item, GlobalState } from './types'
13 |
14 | const createItem = (
15 | id: string | undefined,
16 | name: string,
17 | value: string,
18 | hasValue: boolean,
19 | active: boolean,
20 | change: (arg: { selected: string; name: string }) => void,
21 | ): Item => ({
22 | id: id || name,
23 | title: name,
24 | onClick: () => change({ selected: value, name }),
25 | active,
26 | right: hasValue ? value : undefined,
27 | })
28 |
29 | const getDisplayedItems = (
30 | list: PaddingWithDefault[],
31 | selected: string,
32 | change: (arg: GlobalState) => void,
33 | ) =>
34 | list.reduce- (
35 | (acc, { name, value }) => (
36 | acc.push(
37 | createItem(undefined, name, value, true, value === selected, change),
38 | ),
39 | acc
40 | ),
41 | selected === DEFAULT_PADDING
42 | ? []
43 | : [
44 | createItem(
45 | 'reset',
46 | 'Clear paddings',
47 | DEFAULT_PADDING,
48 | false,
49 | false,
50 | change,
51 | ),
52 | ],
53 | )
54 |
55 | export const Tool = memo(() => {
56 | const [globals, updateGlobals] = useGlobals()
57 | const options = useParameter(PARAM_KEY, null)
58 | const values = normalizeValues(options)
59 |
60 | const selectedPadding = useMemo(
61 | () => getSelectedPadding(values, globals[PARAM_KEY]?.value),
62 | [globals, values],
63 | )
64 |
65 | const onPaddingChange = useCallback(
66 | (value?: string) =>
67 | updateGlobals({ [PARAM_KEY]: { ...globals[PARAM_KEY], value } }),
68 | [globals, updateGlobals],
69 | )
70 |
71 | return isEnabled(values) ? (
72 | (
76 | {
78 | onPaddingChange(selected)
79 | onHide()
80 | })}
81 | />
82 | )}
83 | closeOnOutsideClick
84 | >
85 |
90 |
91 |
92 |
93 | ) : null
94 | })
95 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "storybook-addon-paddings",
3 | "version": "0.0.0-development",
4 | "description": "Add paddings to view components under different white space settings",
5 | "keywords": [
6 | "storybook-addons",
7 | "style",
8 | "padding",
9 | "margin",
10 | "spacing",
11 | "whitespace"
12 | ],
13 | "homepage": "https://github.com/rbardini/storybook-addon-paddings",
14 | "bugs": {
15 | "url": "https://github.com/rbardini/storybook-addon-paddings/issues"
16 | },
17 | "repository": {
18 | "type": "git",
19 | "url": "https://github.com/rbardini/storybook-addon-paddings.git"
20 | },
21 | "license": "MIT",
22 | "author": {
23 | "name": "Rafael Bardini",
24 | "email": "rafael@rbardini.com",
25 | "url": "https://rbardini.com/"
26 | },
27 | "type": "module",
28 | "exports": {
29 | ".": {
30 | "types": "./dist/index.d.ts",
31 | "import": "./dist/index.js",
32 | "require": "./dist/index.cjs"
33 | },
34 | "./preview": {
35 | "types": "./dist/index.d.ts",
36 | "import": "./dist/preview.js",
37 | "require": "./dist/preview.cjs"
38 | },
39 | "./manager": "./dist/manager.js",
40 | "./package.json": "./package.json"
41 | },
42 | "types": "dist/index.d.ts",
43 | "files": [
44 | "dist/**/*",
45 | "*.js",
46 | "*.d.ts"
47 | ],
48 | "scripts": {
49 | "prebuild": "npm run clean",
50 | "build": "tsup",
51 | "build-storybook": "storybook build",
52 | "build:watch": "npm run build -- --watch",
53 | "clean": "rimraf ./dist",
54 | "format": "prettier --ignore-path .gitignore --write .",
55 | "format-check": "prettier --ignore-path .gitignore --check .",
56 | "package-check": "package-check",
57 | "prepare": "husky",
58 | "start": "concurrently \"npm run build:watch\" \"npm run storybook -- --quiet\"",
59 | "storybook": "storybook dev -p 6006",
60 | "type-check": "tsc --noEmit"
61 | },
62 | "devDependencies": {
63 | "@skypack/package-check": "^0.2.0",
64 | "@storybook/addon-docs": "^9.0.0",
65 | "@storybook/react-vite": "^9.0.0",
66 | "@types/node": "^24.0.0",
67 | "@types/react": "^18.0.0",
68 | "@vitejs/plugin-react": "^5.0.0",
69 | "concurrently": "^9.0.0",
70 | "husky": "^9.0.0",
71 | "lint-staged": "^16.0.0",
72 | "prettier": "^3.1.0",
73 | "prettier-plugin-packagejson": "^2.4.0",
74 | "react": "^18.0.0",
75 | "react-dom": "^18.0.0",
76 | "rimraf": "^6.0.0",
77 | "storybook": "^9.0.0",
78 | "tsup": "^8.0.0",
79 | "typescript": "^5.3.0",
80 | "vite": "^7.0.0"
81 | },
82 | "peerDependencies": {
83 | "storybook": "^9.0.0"
84 | },
85 | "bundler": {
86 | "exportEntries": [
87 | "src/index.ts"
88 | ],
89 | "managerEntries": [
90 | "src/manager.ts"
91 | ],
92 | "previewEntries": [
93 | "src/preview.ts"
94 | ]
95 | },
96 | "storybook": {
97 | "displayName": "Paddings",
98 | "supportedFrameworks": [
99 | "react",
100 | "vue",
101 | "angular",
102 | "web-components",
103 | "ember",
104 | "html",
105 | "svelte",
106 | "preact",
107 | "react-native"
108 | ],
109 | "icon": "https://raw.githubusercontent.com/rbardini/storybook-addon-paddings/HEAD/icon.svg"
110 | }
111 | }
112 |
--------------------------------------------------------------------------------