Skip to content

Storybook: Move debug UI mobile/RTL toggles to the toolbar - #4241

Merged
jeremywiebe merged 4 commits into
mainfrom
jer/debug-ui-toolbar-switches
Sep 17, 2026
Merged

jeremywiebe merged 4 commits into
mainfrom
jer/debug-ui-toolbar-switches

Conversation

@jeremywiebe

@jeremywiebe jeremywiebe commented Sep 16, 2026

Copy link
Copy Markdown
Collaborator

Summary:

Today, our widget stories, use a mix of ServerItemRendererWithDebugUI and QuestionRendererForStories. In #4217 I attempted to unify the component we use for all widget stories, but it hits Storybook play test failures. This is because the ServerItemRendererWithDebugUI has two switches in the header which are the first things that receive focus plus they add switch role elements to the DOM that confuse selection of elements.

So, this PR moves these two debug header items to be true Storybook toolbar toggles. This removes them from the Storybook canvas and will eliminate the confounding elements for #4217.

image

Note that the Mobile toggle may not be what you think. It controls the isMobile flag that we pass to apiOptions. It's not a statement of viewport width (use the built-in Viewport Storybook toolbar item for that). I've chosen not to entwine these because you can have a wide viewport (tablet) and still have isMobile enabled and (unfortunately) you can have a narrow viewport (such as when Perseus is embedded in a narrow panel) and still have isMobile: false.

Issue: LEMS-4611

Test plan:

pnpm start
Navigate to the Dropdown widget story. Change the mobile toggle and test. Chagne the Viewport widgth and test.

@github-actions

Copy link
Copy Markdown
Contributor

npm Snapshot

Want to try this PR's changes before it merges? Comment /snapshot below and we'll publish an npm snapshot you can install right away.

@jeremywiebe
jeremywiebe marked this pull request as ready for review September 16, 2026 17:14
@github-actions

Copy link
Copy Markdown
Contributor

Size Change: 0 B

Total Size: 499 kB

ℹ️ View Unchanged
Filename Size
packages/kas/dist/es/index.js 20.6 kB
packages/keypad-context/dist/es/index.js 1 kB
packages/kmath/dist/es/index.js 6.31 kB
packages/math-input/dist/es/index.js 98.5 kB
packages/math-input/dist/es/strings.js 1.63 kB
packages/perseus-core/dist/es/index.js 29.2 kB
packages/perseus-editor/dist/es/index.js 105 kB
packages/perseus-linter/dist/es/index.js 10.4 kB
packages/perseus-score/dist/es/index.js 9.91 kB
packages/perseus-utils/dist/es/index.js 403 B
packages/perseus/dist/es/index.js 196 kB
packages/perseus/dist/es/strings.js 12.9 kB
packages/pure-markdown/dist/es/index.js 1.39 kB
packages/simple-markdown/dist/es/index.js 6.12 kB

compressed-size-action

Comment thread .storybook/preview.tsx
Comment on lines +188 to +189
"Treat the host as a phone or tablet (Perseus isMobile). Pair " +
"with a phone Viewport for the full experience.",

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.

Pair with a phone Viewport for the full experience.

No action needed: I wonder if we could do this automagically in the future by rewiring some Storybook stuff 🤔

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

👍 I thought about this too. It was tricky to do right as each toggled back and forth, so instead of making it more complicated, I opted for simplicity to start. We can adjust this further or "tie" the two settings together in a future PR.

Also, in the future as we refactor layout to be responsive based on container sizing and untangle our "we do this special thing on mobile" (for no good reason), I think we'll have less and less need for this special "isMobile" toggle).


// The toolbar's "story default" leaves per-story apiOptions in charge so
// that mobile stories stay mobile.
const isMobile = mobileOverride ?? apiOptions.isMobile ?? false;

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.

I'm not sure what to do about this, but it seems like this could be a little bit confusing. Like what if you wanted to turn off isMobile for a story that had it enabled in apiOptions.

Again, not sure if there's anything worth doing right now though. We can see if it becomes an issue in the future (I'm guessing it won't be).

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Agree!

Right now, it looks like we use this primarily to build a Mobile-specific version of a story. I think now that this has become a Storybook setting, it might be possible to provide these two stories somewhat automatically.

onToggleMobile,
onToggleRtl,
}: DebugHeaderProps): React.ReactElement => {
export const DebugHeader = ({title}: DebugHeaderProps): React.ReactElement => {

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.

Do we even need a DebugHeader if it's basically not doing anything anymore? Is it even a "debug header" at this point?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

You're right. We have a title in this component, but the only thing we ever pass to it is Widget and "". I've deleted the file and cleaned up the usages.

onToggleMobile={toggleMobile}
/>
{/* Title */}
<DebugHeader title={title} />

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.

Yeah, I dunno. Doesn't seem to warrant being its own component.

@@ -0,0 +1,16 @@
import * as React from "react";

type StorybookViewOptions = {

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.

What if we wanted to follow this pattern for other Storybook options. Would we need to make a separate context? Or could this just be StorybookOptions and StorybookOptionsContext?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

That's a good callout! We already have another Perseus-specific options context in StorybookFeatureFlagsContext.

I wonder if it's better to break contexts apart to specific concerns or to group them?

I'm going to land this PR, but I can open another PR to do a bit of unifying of these.

@jeremywiebe
jeremywiebe force-pushed the jer/debug-ui-toolbar-switches branch from 896bf75 to 00a84f1 Compare September 17, 2026 16:38
@jeremywiebe
jeremywiebe merged commit ceb93bc into main Sep 17, 2026
12 checks passed
@jeremywiebe
jeremywiebe deleted the jer/debug-ui-toolbar-switches branch September 17, 2026 16:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants