diff --git a/frontend/src/stories/How to add tabs to a scene.stories.mdx b/frontend/src/stories/How to add tabs to a scene.stories.mdx new file mode 100644 index 0000000000000..328bd664e7cb2 --- /dev/null +++ b/frontend/src/stories/How to add tabs to a scene.stories.mdx @@ -0,0 +1,129 @@ +import { Meta } from '@storybook/addon-docs' + + + +# How to add tabs to a scene? + +This guide follows on from ["How to build a scene"](/docs/how-to-build-a-scene--page) – we'll be adding tabs to that guide's Dashboards scene. + +1. Add an enum to `frontend/src/types.ts` to define the tabs: + +```ts title="frontend/src/types.ts" +export enum DashboardsTabs { + First = 'first', + Second = 'second', +} +``` + +2. Update the URL in `frontend/src/scenes/urls.ts` to handle tabs: + +```ts title="frontend/src/scenes/urls.ts" +dashboards: (tab: DashboardsTabs = DashboardsTabs.First): string => `/dashboards/${tab}` +``` + +3. Add entries to routes per tab in `frontend/src/scenes/scenes.ts`: + +```ts title="frontend/src/scenes/scenes.ts" + // One entry for every available tab + ...Object.fromEntries( + Object.values(DashboardsTabs).map((tab) => [urls.dashboards(tab), Scene.Dashboards]) + ) as Record, +``` + +4. Update `dashboardsLogic` to handle tab changes in `frontend/src/scenes/dashboards/dashboardsLogic.ts`: + +```ts title="frontend/src/scenes/dashboards/dashboardsLogic.ts" +import { kea, reducers, path, actions, selectors } from 'kea' +import { actionToUrl, urlToAction } from 'kea-router' + +import { Breadcrumb, DashboardsTabs } from '~/types' +import { urls } from 'scenes/urls' + +export const DASHBOARDS_TAB_TO_NAME: Record = { + [DashboardsTabs.First]: 'First', + [DashboardsTabs.Second]: 'Second', +} + +export const dashboardsLogic = kea([ + path(['scenes', 'dashboard', 'dashboardsLogic']), + actions({ + setCurrentTab: (tab: DashboardsTabs = DashboardsTabs.First) => ({ tab }), + }), + reducers({ + currentTab: [ + DashboardsTabs.First as DashboardsTabs, + { + setCurrentTab: (_, { tab }) => tab, + }, + ], + }), + selectors(() => ({ + breadcrumbs: [ + // Optional if you'd like the breadcrumbs to show the current tab + (s) => [s.currentTab], + (tab): Breadcrumb[] => { + const breadcrumbs: Breadcrumb[] = [{ name: 'Dashboards' }] + breadcrumbs.push({ + name: DASHBOARDS_TAB_TO_NAME[tab], + }) + + return breadcrumbs + }, + ], + })), + actionToUrl(({ values }) => { + return { + setCurrentTab: () => [urls.dashboards(values.currentTab)], + } + }), + urlToAction(({ actions, values }) => ({ + '/dashboards/:tab': ({ tab }) => { + if (tab !== values.currentTab) { + actions.setCurrentTab(tab as DashboardsTabs) + } + }, + })), +]) +``` + +5. Update `frontend/src/scenes/dashboards/Dashboards.tsx` to render the tabs: + +```tsx title="frontend/src/scenes/dashboards/Dashboards.tsx" +import { useValues } from 'kea' +import { router } from 'kea-router' +import { DashboardsTabs } from '~/types' +import { SceneExport } from 'scenes/sceneTypes' +import { PageHeader } from 'lib/components/PageHeader' +import { LemonTabs } from 'lib/lemon-ui/LemonTabs/LemonTabs' +import { urls } from 'scenes/urls' +import { dashboardsLogic, humanFriendlyTabName } from './dashboardsLogic' + +const DASHBOARDS_TAB_TO_CONTENT: Record = { + [DashboardsTabs.First]:
First tab content
, + [DashboardsTabs.Second]:
Second tab content
, +} + +export const scene: SceneExport = { + component: Dashboards, + logic: dashboardsLogic, +} + +export function Dashboards(): JSX.Element { + const { currentTab } = useValues(dashboardsLogic) + + return ( +
+ + router.actions.push(urls.dashboards(tab as DashboardsTabs))} + tabs={Object.values(DashboardsTabs).map((tab) => ({ + label: DASHBOARDS_TAB_TO_NAME[tab], + key: tab, + content: DASHBOARDS_TAB_TO_CONTENT[tab], + }))} + /> +
+ ) +} +``` diff --git a/frontend/src/stories/How to build a scene.stories.mdx b/frontend/src/stories/How to build a scene.stories.mdx index 2ddd3573c517e..7bd650313eeeb 100644 --- a/frontend/src/stories/How to build a scene.stories.mdx +++ b/frontend/src/stories/How to build a scene.stories.mdx @@ -279,3 +279,4 @@ export function NewDashboard (): JSX.Element { Read next: - [How to use components](/docs/how-to-use-components--page) - [How to build a form](/docs/how-to-build-a-form--page) +- [How to add tabs to a scene](/docs/how-to-add-tabs-to-a-scene--page)