import type {ComponentProps} from 'react'; import styled from '@emotion/styled'; import Link from 'sentry/components/links/link'; import {IconFile} from 'sentry/icons'; import {space} from 'sentry/styles/space'; import {useLocation} from 'sentry/utils/useLocation'; import type {StoriesQuery} from 'sentry/views/stories/types'; interface Props extends ComponentProps<'div'> { files: string[]; } export default function StoryTree({files, style}: Props) { const tree = toTree(files); return ( ); } function FolderContent({path, content}: {content: TreeMapping; path: string}) { const location = useLocation(); const currentFile = location.query.name; // sort folders to the top const entries = Object.entries(content).sort( (a, b) => Number(!!Object.keys(b[1]).length) - Number(!!Object.keys(a[1]).length) ); return ( {entries.map(([name, children]) => { const childPath = toPath(path, name); if (Object.keys(children).length === 0) { const isCurrent = childPath === currentFile ? true : undefined; const to = `/stories/?name=${childPath}`; return ( {name} ); } return ( {name} ); })} ); } interface TreeMapping extends Record {} function toTree(files: string[]): TreeMapping { const root: Record = {}; for (const file of files) { const parts = file.split('/'); let tree = root; for (const part of parts) { if (!(part in tree)) { tree[part] = {}; } tree = tree[part]; } } return root; } function toPath(path: string, name: string) { return [path, name].filter(Boolean).join('/'); } const UnorderedList = styled('ul')` margin: 0; padding: 0; list-style: none; `; const ListItem = styled('li')` position: relative; &[aria-current] { background: ${p => p.theme.blue300}; color: ${p => p.theme.white}; font-weight: ${p => p.theme.fontWeightBold}; } &[aria-current] a:before { background: ${p => p.theme.blue300}; content: ''; left: -100%; position: absolute; right: 0; top: 0; z-index: -1; bottom: 0; } `; const Folder = styled('details')` cursor: pointer; padding-left: ${space(2)}; position: relative; &:before { content: '⏵'; position: absolute; left: ${space(0.5)}; top: ${space(0.25)}; } &[open]:before { content: '⏷'; } `; const FolderName = styled('summary')` padding: ${space(0.25)}; color: inherit; &:hover { color: inherit; } &:hover:before { background: ${p => p.theme.blue100}; content: ''; left: -100%; position: absolute; right: 0; top: 0; z-index: -1; bottom: 0; } `; const FolderLink = styled(Link)` display: grid; grid-template-columns: max-content 1fr; align-items: baseline; gap: ${space(0.5)}; padding: ${space(0.25)}; white-space: nowrap; color: inherit; &:hover { color: inherit; } &:hover:before { background: ${p => p.theme.blue100}; content: ''; left: -100%; position: absolute; right: 0; top: 0; z-index: -1; bottom: 0; } `;