Skip to content

feat(config): add defaultPreviewSettings to seed initial preview-pane state#842

Open
arikw wants to merge 2 commits into
histoire-dev:mainfrom
arikw:feat/default-preview-settings
Open

feat(config): add defaultPreviewSettings to seed initial preview-pane state#842
arikw wants to merge 2 commits into
histoire-dev:mainfrom
arikw:feat/default-preview-settings

Conversation

@arikw

@arikw arikw commented May 19, 2026

Copy link
Copy Markdown

Summary

Adds a new top-level config field defaultPreviewSettings: Partial<PreviewSettings> so users can seed the persisted
preview-settings store from histoire.config.js. The primary motivation: change the responsive size picker's initial width away from its hardcoded 720px default so stories can render at their natural width on a first visit.

// histoire.config.js
import { defineConfig } from 'histoire'

export default defineConfig({
  defaultPreviewSettings: {
    responsiveWidth: null, // null → "Auto"
  },
})

Each field of defaultPreviewSettings is optional; omitted fields fall back to the built-in default. Only seeds the store on
first visit — once the user changes a setting via the toolbar, their choice persists and wins on later loads.

Why

The responsive size picker currently always boots at 720px because useStorage is seeded with { responsiveWidth: 720, ... } in packages/histoire-app/src/app/stores/preview-settings.ts. There is no way to change that seed from defineConfig. For projects where the typical primitive is best previewed at its natural width (forms, dialogs, list items) the 720px starting point reads like a bug — every story loads constrained until the user clicks the picker.

The two pre-existing workarounds both have meaningful downsides:

  • defaultStoryProps.responsiveDisabled: true — removes the picker entirely, losing the ability to QA at mobile widths.
  • Custom responsivePresets with a "Full" preset — fails because ResponsivePreset.width is typed number (no null allowed).

This PR exposes the seed directly. The picker UI already handles null (responsiveWidth.value ?? 'Auto' at StoryResponsivePreview.vue:121) so the implementation surface is small.

What changed

  • packages/histoire-shared/src/types/config.ts
    • Added PreviewSettings interface (moved from packages/histoire-app/src/app/types.ts).
    • Added defaultPreviewSettings?: Partial<PreviewSettings> to HistoireConfig.
    • Widened responsiveWidth and responsiveHeight from number to number | null. The runtime already passed null for height; the number-only type was a latent mismatch. Picker UI's ?? 'Auto' fallback only made sense if these were nullable.
  • packages/histoire-app/src/app/types.ts
    • PreviewSettings re-exported from @histoire/shared.
  • packages/histoire-app/src/app/stores/preview-settings.ts
    • useStorage seed merges built-in defaults with histoireConfig.defaultPreviewSettings.
  • docs/reference/config.md
    • New section after defaultStoryProps documenting the field.

Test plan

  • Existing stories still render at 720px when defaultPreviewSettings is omitted (built-in default preserved).
  • Setting defaultPreviewSettings.responsiveWidth: null makes the picker boot at "Auto" on a fresh local-storage state.
  • Once the user picks a different width via the toolbar, the choice persists across reloads (verified by inspecting _histoire-sandbox-settings-v3 in localStorage).

Related

Closes #843

… state

Histoire's preview-settings store is seeded with hardcoded defaults
(notably `responsiveWidth: 720`) the first time it runs. There is
currently no way to change those seeds from `histoire.config.js`, so
every story loads with the responsive picker constrained to 720px
even when the user wants previews to render at their natural width.

This commit exposes a new top-level config field
`defaultPreviewSettings: Partial<PreviewSettings>` that merges into the
useStorage initial value. Each field is optional; omitted fields fall
back to the built-in default. The user-written file `histoire.config.js`
becomes:

  export default defineConfig({
    defaultPreviewSettings: {
      responsiveWidth: null, // null → "Auto"
    },
  })

Only seeds the store on first visit. Once the user changes a setting
via the toolbar, their choice is persisted and wins on later loads.

Type changes:
- `PreviewSettings` moves from `packages/histoire-app/src/app/types.ts`
  to `packages/histoire-shared/src/types/config.ts` so the node-side
  config schema can reference it. The app-side type file re-exports.
- `responsiveWidth` and `responsiveHeight` widen from `number` to
  `number | null` so the picker UI's existing `?? 'Auto'` fallback
  has a typed home (the runtime already passed null for height; the
  number-only type was a latent mismatch).

Docs: new entry under `docs/reference/config.md` after
`defaultStoryProps`.
@bolt-new-by-stackblitz

Copy link
Copy Markdown

Review PR in StackBlitz Codeflow Run & review this pull request in StackBlitz Codeflow.

@codesandbox

codesandbox Bot commented May 19, 2026

Copy link
Copy Markdown

Review or Edit in CodeSandbox

Open the branch in Web EditorVS CodeInsiders

Open Preview

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Code Review

This pull request introduces the defaultPreviewSettings configuration option, allowing users to seed the initial state of the preview pane, such as responsive dimensions and background settings. The PreviewSettings interface was updated to support null values for width and height, representing an 'Auto' sizing mode. Feedback suggests extending this change to the ResponsivePreset interface to maintain type consistency across the configuration and align with existing documentation.

Comment thread packages/histoire-shared/src/types/config.ts
@netlify

netlify Bot commented May 19, 2026

Copy link
Copy Markdown

Deploy Preview for histoire-examples-svelte3 ready!

Name Link
🔨 Latest commit 1b5fee2
🔍 Latest deploy log https://app.netlify.com/projects/histoire-examples-svelte3/deploys/6a0c749e11e7de0008021e90
😎 Deploy Preview https://deploy-preview-842--histoire-examples-svelte3.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
🤖 Make changes Run an agent on this branch

To edit notification comments on pull requests, go to your Netlify project configuration.

@netlify

netlify Bot commented May 19, 2026

Copy link
Copy Markdown

Deploy Preview for histoire-examples-vue3 ready!

Name Link
🔨 Latest commit 1b5fee2
🔍 Latest deploy log https://app.netlify.com/projects/histoire-examples-vue3/deploys/6a0c749e1d29930008334246
😎 Deploy Preview https://deploy-preview-842--histoire-examples-vue3.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
🤖 Make changes Run an agent on this branch

To edit notification comments on pull requests, go to your Netlify project configuration.

@netlify

netlify Bot commented May 19, 2026

Copy link
Copy Markdown

Deploy Preview for histoire-controls ready!

Name Link
🔨 Latest commit 1b5fee2
🔍 Latest deploy log https://app.netlify.com/projects/histoire-controls/deploys/6a0c749e117422000845ca24
😎 Deploy Preview https://deploy-preview-842--histoire-controls.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
🤖 Make changes Run an agent on this branch

To edit notification comments on pull requests, go to your Netlify project configuration.

@netlify

netlify Bot commented May 19, 2026

Copy link
Copy Markdown

Deploy Preview for histoire-site ready!

Name Link
🔨 Latest commit 1b5fee2
🔍 Latest deploy log https://app.netlify.com/projects/histoire-site/deploys/6a0c749e19a2fc0008e52176
😎 Deploy Preview https://deploy-preview-842--histoire-site.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
🤖 Make changes Run an agent on this branch

To edit notification comments on pull requests, go to your Netlify project configuration.

The built-in `responsivePresets` already ship presets with
`height: null` (Laptop Small, Laptop Large, Desktop, 4K — see
packages/histoire/src/node/config.ts) and the documentation reflects
that shape, but the `ResponsivePreset` type declared the fields as
`width: number; height?: number` — a latent mismatch that crashed
TypeScript users who tried to mirror the default presets in their
own `responsivePresets` override.

Widen both fields to `number | null`. No runtime change in core; the
ToolbarResponsiveSize.vue UI is already null-safe (`v-if="preset.width"`,
`v-if="preset.height"`). Updates the docs alongside.

Note: the screenshot plugin (packages/histoire-plugin-screenshot) reads
`preset.width` and `preset.height` directly and passes them to
capture-website. That code path already breaks on the built-in
null-height presets; not regressing it here.

Addresses gemini-code-assist's review comment on PR histoire-dev#842.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Expose a config option to set the initial responsiveWidth (default is hardcoded 720px)

1 participant