index.tsx 2.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. import styled from '@emotion/styled';
  2. import Link from 'sentry/components/links/link';
  3. import getRouteStringFromRoutes from 'sentry/utils/getRouteStringFromRoutes';
  4. import recreateRoute from 'sentry/utils/recreateRoute';
  5. import Crumb from 'sentry/views/settings/components/settingsBreadcrumb/crumb';
  6. import Divider from 'sentry/views/settings/components/settingsBreadcrumb/divider';
  7. import OrganizationCrumb from 'sentry/views/settings/components/settingsBreadcrumb/organizationCrumb';
  8. import ProjectCrumb from 'sentry/views/settings/components/settingsBreadcrumb/projectCrumb';
  9. import TeamCrumb from 'sentry/views/settings/components/settingsBreadcrumb/teamCrumb';
  10. import {useBreadcrumbsPathmap} from './context';
  11. import {RouteWithName} from './types';
  12. const MENUS = {
  13. Organization: OrganizationCrumb,
  14. Project: ProjectCrumb,
  15. Team: TeamCrumb,
  16. } as const;
  17. type Props = {
  18. params: {[param: string]: string | undefined};
  19. route: any;
  20. routes: RouteWithName[];
  21. className?: string;
  22. };
  23. function SettingsBreadcrumb({className, routes, params}: Props) {
  24. const pathMap = useBreadcrumbsPathmap();
  25. const lastRouteIndex = routes.map(r => !!r.name).lastIndexOf(true);
  26. return (
  27. <Breadcrumbs className={className}>
  28. {routes.map((route, i) => {
  29. if (!route.name) {
  30. return null;
  31. }
  32. const pathTitle = pathMap[getRouteStringFromRoutes(routes.slice(0, i + 1))];
  33. const isLast = i === lastRouteIndex;
  34. const createMenu = MENUS[route.name];
  35. const Menu = typeof createMenu === 'function' && createMenu;
  36. const hasMenu = !!Menu;
  37. const CrumbItem = hasMenu
  38. ? Menu
  39. : () => (
  40. <Crumb>
  41. <CrumbLink to={recreateRoute(route, {routes, params})}>
  42. {pathTitle || route.name}{' '}
  43. </CrumbLink>
  44. <Divider isLast={isLast} />
  45. </Crumb>
  46. );
  47. return (
  48. <CrumbItem
  49. key={`${route.name}:${route.path}`}
  50. routes={routes}
  51. params={params}
  52. route={route}
  53. isLast={isLast}
  54. />
  55. );
  56. })}
  57. </Breadcrumbs>
  58. );
  59. }
  60. export default SettingsBreadcrumb;
  61. const CrumbLink = styled(Link)`
  62. display: block;
  63. &.focus-visible {
  64. outline: none;
  65. box-shadow: ${p => p.theme.blue300} 0 2px 0;
  66. }
  67. color: ${p => p.theme.subText};
  68. &:hover {
  69. color: ${p => p.theme.textColor};
  70. }
  71. `;
  72. export {CrumbLink};
  73. const Breadcrumbs = styled('div')`
  74. display: flex;
  75. align-items: center;
  76. `;