crutch12

Breadcrumb.tsx

Dec 8th, 2021
761
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. import * as React from 'react';
  2. import { refSetter } from '#/components/common/utils/refSetter';
  3. import styled from 'styled-components';
  4. import { typography } from '#/components/Typography';
  5.  
  6. import { InverseTooltip } from './InverseTooltip';
  7.  
  8. export const Crumb = styled.li`
  9.   display: flex;
  10.   align-items: center;
  11.   white-space: nowrap;
  12.   ${typography['Additional/M']}
  13.  
  14.   [data-dimension='m'] & {
  15.     ${typography['Additional/XS']}
  16.   }
  17.   [data-dimension='s'] & {
  18.     ${typography['Caption/XS']}
  19.   }
  20. `;
  21.  
  22. export const Content = styled.span`
  23.   width: 100%;
  24.   height: 100%;
  25.   padding: 4px;
  26.   display: flex;
  27.   align-items: center;
  28. `;
  29.  
  30. export const CrumbAnchor = styled.a`
  31.   display: flex;
  32.   align-items: center;
  33.   text-decoration: none;
  34.   position: relative;
  35.   color: ${({ theme }) => theme.color.text.secondary};
  36.  
  37.   [aria-current='page'] & {
  38.     pointer-events: none;
  39.   }
  40.  
  41.   &:hover {
  42.     color: ${({ theme }) => theme.color.basic.hover};
  43.   }
  44.   &:active {
  45.     color: ${({ theme }) => theme.color.basic.press};
  46.   }
  47.  
  48.   &:focus {
  49.     &:before {
  50.       position: absolute;
  51.       content: '';
  52.       border: 2px solid ${({ theme }) => theme.color.basic.hover};
  53.       border-radius: 4px;
  54.       top: 0;
  55.       left: 0;
  56.       bottom: 0;
  57.       right: 0;
  58.     }
  59.   }
  60.   &:focus,
  61.   & > ${Content} {
  62.     outline: none;
  63.   }
  64. `;
  65.  
  66. export interface BreadcrumbProps extends React.HTMLAttributes<HTMLLIElement> {
  67.   /** Текст хлебной крошки */
  68.   text: string;
  69.   /** Url хлебной крошки (href атрибут, используемый во внутреннем Anchor) */
  70.   url?: string;
  71.   /** Позволяет вместо внутреннего Anchor отрендерить любой другой компонент (https://styled-components.com/docs/api#as-polymorphic-prop) */
  72.   linkAs?: React.ElementType;
  73.   /** Дополнительные параметры, которые можно передать во внутренний Anchor */
  74.   linkProps?: { [key: string]: string };
  75. }
  76.  
  77. export const Breadcrumb = React.forwardRef<HTMLLIElement, BreadcrumbProps>(
  78.   ({ text, url = '#', linkAs, linkProps, children, ...props }, ref) => {
  79.     const tooltip = text.length > 40;
  80.     const crumbRef = React.useRef<HTMLLIElement>(null);
  81.  
  82.     return tooltip ? (
  83.       <Crumb ref={refSetter(ref, crumbRef)} {...props}>
  84.         <CrumbAnchor href={url} as={linkAs} {...linkProps}>
  85.           <Content tabIndex={-1} role="link">
  86.             <InverseTooltip renderContent={() => text}>{text.slice(0, 37) + '...'}</InverseTooltip>
  87.             {children}
  88.           </Content>
  89.         </CrumbAnchor>
  90.       </Crumb>
  91.     ) : (
  92.       <Crumb ref={refSetter(ref, crumbRef)} {...props}>
  93.         <CrumbAnchor href={url} as={linkAs} {...linkProps}>
  94.           <Content tabIndex={-1} role="link">
  95.             {text}
  96.             {children}
  97.           </Content>
  98.         </CrumbAnchor>
  99.       </Crumb>
  100.     );
  101.   },
  102. );
  103.  
RAW Paste Data