storybookjs / storybook

Storybook is the industry standard workshop for building, documenting, and testing UI components in isolation
https://storybook.js.org
MIT License
83.59k stars 9.16k forks source link

Default tab is always canvas on first load #13128

Open AndreasNH opened 3 years ago

AndreasNH commented 3 years ago

Describe the bug I'm trying to change the default storybook tab following the method described in #12111 . On initial load of the storybook always land on the canvas page. (locally that would be http://localhost:6006/?path=/story/<pathToStory>). If i click on another story, its defaults to the docs page as intended. eg: http://localhost:6006/?path=/docs/<pathToStory>

To Reproduce

  1. Add viewMode: 'docs',to parameter in preview.js
  2. Run and open storybook. (eg localhost:6006 )
  3. See that its defaults to the canvas tab. 4 In you click at any other story after initial load, its defaults to docs as intended.

Expected behavior Even on initial load, the tab should default to the one set in preview.js

System System: OS: macOS 10.15.6 CPU: (12) x64 Intel(R) Core(TM) i7-8850H CPU @ 2.60GHz Binaries: Node: 12.18.1 - ~/.nvm/versions/node/v12.18.1/bin/node Yarn: 1.22.4 - /usr/local/bin/yarn npm: 6.14.5 - ~/.nvm/versions/node/v12.18.1/bin/npm Browsers: Chrome: 88.0.4315.5 Safari: 14.0 npmPackages: @storybook/addon-actions: ^6.0.26 => 6.0.27 @storybook/addon-essentials: ^6.0.26 => 6.0.27 @storybook/addon-links: ^6.0.26 => 6.0.27 @storybook/addons: ^6.0.26 => 6.0.27 @storybook/node-logger: ^6.0.26 => 6.0.27 @storybook/preset-create-react-app: ^3.1.4 => 3.1.4 @storybook/react: ^6.0.26 => 6.0.27

stale[bot] commented 3 years ago

Hi everyone! Seems like there hasn't been much going on in this issue lately. If there are still questions, comments, or bugs, please feel free to continue the discussion. Unfortunately, we don't have time to get to every issue. We are always open to contributions so please send us a pull request if you would like to help. Inactive issues will be closed after 30 days. Thanks!

sdaconceicao commented 3 years ago

I'm experiencing the same issue with 6.1.11.

shilman commented 3 years ago

Do you have a repro repo you can share? Not able to repro in the monorepo.

sdaconceicao commented 3 years ago

https://github.com/sdaconceicao/local-storage Run npm run storybook, and you'll see it takes you to the canvas page initially. If you click on any story, including going back to the first story, it will then correctly load the doc page.

shilman commented 3 years ago

@sdaconceicao there is a whitespace error in your MDX:

## Cookies
<Story name="Example">
  <Cookies />
</Story>

When I add a newline between ## Cookies and the JSX, the problem is fixed. I don't understand why this triggers the bug you're seeing.

There's a bigger issue here which is whitespace handling in MDX: doing the right thing or at least making weirdo errors like this more visible. I hope to revisit that that when MDX v2 comes out (hopefully soon).

Hope that helps!

sdaconceicao commented 3 years ago

@shilman I added in a newline after cookies, but I'm still seeing the issue unfortunately. Chrome 87.0.4280.88 and FF 83.0 What I've noticed is you have to specifically go to just the bare base url. That will redirect you to this url http://localhost:6006/?path=/story/cookies--example If I click to another story and back to the cookies story again, the url changes to http://localhost:6006/?path=/docs/cookies--example That url is the correct one, and if you reload after that your initial load will be fine.

DylanCulfogienis commented 3 years ago

Does anyone have a workaround for this in the meanwhile?

marceloadsj commented 3 years ago

You can add this to preview.js. On first load, it will click on Docs btn and switch tabs.

A bit hacky but... :)

// Hacky way of clicking on Docs button on first load of page.
// https://github.com/storybookjs/storybook/issues/13128
function clickDocsButtonOnFirstLoad() {
  window.removeEventListener("load", clickDocsButtonOnFirstLoad);

  try {
    const docsButtonSelector = window.parent.document.evaluate(
      "//button[contains(., 'Docs')]",
      window.parent.document,
      null,
      XPathResult.ANY_TYPE,
      null
    );

    const button = docsButtonSelector.iterateNext();

    button.click();
  } catch (error) {
    // Do nothing if it wasn't able to click on Docs button.
  }
}

window.addEventListener("load", clickDocsButtonOnFirstLoad);
jeffersondev commented 3 years ago

Thank you for sharing @marceloadsj ;) It worked like a charm until there is not a solution to this by configuration!

bbellmyers commented 3 years ago

My workaround is to create this React component which I include in my home page MDX:

import { useContext } from 'react';
import { DocsContext } from '@storybook/addon-docs/blocks';
import addons from '@storybook/addons';
import { NAVIGATE_URL } from '@storybook/core-events';

const SwitchToDocs = () => {
  const context = useContext(DocsContext);
  window.setTimeout(() => {
    if (!context.storyStore.getSelection().viewMode!== 'docs') {
      addons.getChannel().emit(NAVIGATE_URL, `?path=/docs/${context.id}`);
    }
  }, 0);
  return null;
}

export default SwitchToDocs;
zorfling commented 3 years ago

I'm also seeing this same problem, not in MDX docs.

MustafaHaddara commented 2 years ago

I have the same problem, MDX docs, Storybook 6.3.7 and @storybook/addon-essentials v6.3.7 as well

kate-hall commented 2 years ago

I have the same problem, MDX docs, Storybook 6.3.7 and @storybook/addon-essentials v6.3.7 as well

Same here.

IndProgo commented 2 years ago

The same. I'm using storyStoreV7 feature and viewMode: 'docs'. Storybook 6.5.0-alpha.5 for React.

For initial load (without path), it always opens in canvas view, even if canvas panel is hidden. If the current page is in the canvas view, then the next page initial load will open in canvas as well, but if the page has been loaded before, it will open in docs mode (so clicking on some new story in sidebar twice will first open in canvas, then docs). Only if current page is in docs view, then the next page will initially load in docs view

jonsalvas commented 2 years ago

confirmed

sndrs commented 2 years ago

just in case this helps anyone, we have a concept of playground and chromatic story types for our design system (one for consumers to explore the component with, the other for visual regression testing) and got around it in 6.4 by updating the links in the nav as they're written to the DOM:

<!-- manager-head.html -->
<script>
    window.onload = () => {
        const observer = new MutationObserver((mutationsList) => {
            for (const mutation of mutationsList) {
                mutation.addedNodes.forEach((addedNode) => {
                    const links = addedNode.querySelectorAll(
                        '[href$="--playground"]',
                    );
                    links.forEach((link) => {
                        link.href = link.href.replace(
                            'path=/story/',
                            'path=/docs/',
                        );
                        if (link.dataset.selected) {
                            link.click();
                        }
                    });
                });
            }
        });

        observer.observe(document.body, { childList: true, subtree: true });
    };
</script>

it's a bit of a hack but it works for now (edit: inspired by https://github.com/storybookjs/storybook/issues/13128#issuecomment-798927176 above)

MilesWellsSVT commented 2 years ago

I was going to open a new issue, but this one seems relevant enough. I noticed there wasn't a proper reproduction per the documentation so here's that:

Describe the bug If the first story in a Storybook has viewMode: 'docs' set the canvas still shows first upon initial navigation to the Storybook. The viewMode parameter works as expected if you're already in the storybook on a story's canvas and navigate to another story with the parameter set to 'docs'.

To Reproduce Reproduction repo: https://github.com/MilesWellsSVT/sb-bug-repro

All I did was remove the introduction story and add viewMode: 'docs' to the Button's Meta.

Reproduction on Chromatic: https://621e8cdd02c715003a880928-mqdlloaofg.chromatic.com

System System: OS: macOS 12.2.1 CPU: (12) x64 Intel(R) Core(TM) i7-9750H CPU @ 2.60GHz Binaries: Node: 16.13.2 - ~/.nvm/versions/node/v16.13.2/bin/node Yarn: 3.2.0 - /usr/local/bin/yarn npm: 8.1.2 - ~/.nvm/versions/node/v16.13.2/bin/npm Browsers: Chrome: 98.0.4758.109 Edge: 98.0.1108.62 Firefox: 97.0.1 Safari: 15.3 npmPackages: @storybook/addon-actions: ^6.5.0-alpha.45 => 6.5.0-alpha.45 @storybook/addon-docs: ^6.5.0-alpha.45 => 6.5.0-alpha.45 @storybook/addon-essentials: ^6.5.0-alpha.45 => 6.5.0-alpha.45 @storybook/addon-interactions: ^6.5.0-alpha.45 => 6.5.0-alpha.45 @storybook/addon-links: ^6.5.0-alpha.45 => 6.5.0-alpha.45 @storybook/builder-webpack5: ^6.5.0-alpha.45 => 6.5.0-alpha.45 @storybook/manager-webpack5: ^6.5.0-alpha.45 => 6.5.0-alpha.45 @storybook/node-logger: ^6.5.0-alpha.45 => 6.5.0-alpha.45 @storybook/preset-create-react-app: ^4.0.1 => 4.0.1 @storybook/react: ^6.5.0-alpha.45 => 6.5.0-alpha.45 @storybook/testing-library: ^0.0.9 => 0.0.9

Additional context The behavior is the same when the canvas is hidden via:

parameters: {
    viewMode: 'docs',
    previewTabs: {
    canvas: {
        hidden: true,
    },
    },
}

Which I suppose makes sense because this parameter simply hides the tab. The canvas is still manually navigable.

singhinderpal commented 1 year ago

do we have anyluck on this? I am facing the same issue...

singhinderpal commented 1 year ago

You can add this to preview.js. On first load, it will click on Docs btn and switch tabs.

A bit hacky but... :)

// Hacky way of clicking on Docs button on first load of page.
// https://github.com/storybookjs/storybook/issues/13128
function clickDocsButtonOnFirstLoad() {
  window.removeEventListener("load", clickDocsButtonOnFirstLoad);

  try {
    const docsButtonSelector = window.parent.document.evaluate(
      "//button[contains(., 'Docs')]",
      window.parent.document,
      null,
      XPathResult.ANY_TYPE,
      null
    );

    const button = docsButtonSelector.iterateNext();

    button.click();
  } catch (error) {
    // Do nothing if it wasn't able to click on Docs button.
  }
}

window.addEventListener("load", clickDocsButtonOnFirstLoad);

I just tried it, didn't work for me.

hannasage commented 1 year ago

BUMP

Still seems like an issue. There doesn't appear to be an option to prevent it from going to the Docs page when you navigate to a new story, either. The behavior sought is to load on the Docs tab by default, but maintain the tab state when swapping stories.

joshwreford commented 1 year ago

Yeah, I'm experiencing the same issue. I have viewMode: 'docs' set in my parameters object export in preview.tsx. Canvas is still loaded initially, but then clicking any other story switches to 'docs'. If I then manually switch back to Canvas I would expect it to then stay on Canvas mode until I manually switch back to docs. However, it will automatically switch back to Docs every time I select a new story from the side bar.

jordan-cutler commented 1 year ago

Hey all, I think you can do this: https://github.com/storybookjs/storybook/blob/v6.5.15/addons/docs/docs/recipes.md#reordering-docs-tab-first

// preview.js
export const parameters = {
  // Resets the view to the docs when the user navigates
  // https://github.com/storybookjs/storybook/blob/master/addons/docs/docs/recipes.md#controlling-a-storys-view-mode
  viewMode: "docs",
  https://github.com/storybookjs/storybook/blob/v6.5.15/addons/docs/docs/recipes.md#reordering-docs-tab-first
  previewTabs: { "storybook/docs/panel": { index: -1 } },
};

Edit: Nevermind... it still starts out at the canvas tab

sperro commented 1 year ago

You can add this to preview.js. On first load, it will click on Docs btn and switch tabs. A bit hacky but... :)

// Hacky way of clicking on Docs button on first load of page.
// https://github.com/storybookjs/storybook/issues/13128
function clickDocsButtonOnFirstLoad() {
  window.removeEventListener("load", clickDocsButtonOnFirstLoad);

  try {
    const docsButtonSelector = window.parent.document.evaluate(
      "//button[contains(., 'Docs')]",
      window.parent.document,
      null,
      XPathResult.ANY_TYPE,
      null
    );

    const button = docsButtonSelector.iterateNext();

    button.click();
  } catch (error) {
    // Do nothing if it wasn't able to click on Docs button.
  }
}

window.addEventListener("load", clickDocsButtonOnFirstLoad);

I just tried it, didn't work for me.

@singhinderpal It worked for me after adding a short timeout delay with setTimeout().

I also added a combination with this to reset the tab again when clicking the sidebar to navigate to another story if a different tab was selected.

(function() {
  try {
    var button = window.parent.document.getElementsByClassName('sidebar-item');
    for (var i = 0; i < button.length; i++) {
      button[i].addEventListener("click", function(){ 
        const docsButtonSelector = window.parent.document.evaluate(
          "//button[contains(., 'Docs')]",
          window.parent.document,
          null,
          XPathResult.ANY_TYPE,
          null
        );
        const tab = docsButtonSelector.iterateNext();
        tab.click();
      })
    }
  } catch (error) {
    // Do nothing if it wasn't able to click on Docs button.
  }
})();