github.com/tilt-dev/tilt@v0.33.15-0.20240515162809-0a22ed45d8a0/web/src/HeaderBar.tsx (about)

     1  import React from "react"
     2  import { Link } from "react-router-dom"
     3  import styled from "styled-components"
     4  import { AnalyticsType } from "./analytics"
     5  import { ReactComponent as DetailViewSvg } from "./assets/svg/detail-view-icon.svg"
     6  import { ReactComponent as LogoWordmarkSvg } from "./assets/svg/logo-wordmark.svg"
     7  import { ReactComponent as TableViewSvg } from "./assets/svg/table-view-icon.svg"
     8  import { CustomNav } from "./CustomNav"
     9  import { GlobalNav, GlobalNavProps } from "./GlobalNav"
    10  import { usePathBuilder } from "./PathBuilder"
    11  import {
    12    AllResourceStatusSummary,
    13    ResourceStatusSummaryRoot,
    14  } from "./ResourceStatusSummary"
    15  import { useSnapshotAction } from "./snapshot"
    16  import { SnapshotBar } from "./SnapshotBar"
    17  import { AnimDuration, Color, Font, FontSize, SizeUnit } from "./style-helpers"
    18  import { showUpdate } from "./UpdateDialog"
    19  
    20  const HeaderBarRoot = styled.nav`
    21    display: flex;
    22    align-items: center;
    23    padding-left: ${SizeUnit(1)};
    24    background-color: ${Color.gray10};
    25  
    26    ${ResourceStatusSummaryRoot} {
    27      justify-self: center;
    28      flex-grow: 1;
    29      justify-content: center;
    30    }
    31  `
    32  
    33  const Logo = styled(LogoWordmarkSvg)`
    34    justify-self: flex-start;
    35    & .fillStd {
    36      transition: fill ${AnimDuration.short} ease;
    37      fill: ${Color.grayLightest};
    38    }
    39    &:hover .fillStd,
    40    &.isSelected .fillStd {
    41      fill: ${Color.gray70};
    42    }
    43    display: block;
    44  `
    45  
    46  const HeaderDivider = styled.div`
    47    border-left: 1px solid ${Color.gray40};
    48    height: ${SizeUnit(0.7)};
    49    margin: ${SizeUnit(0.5)};
    50  `
    51  
    52  const ViewLinkText = styled.span`
    53    bottom: 0;
    54    color: ${Color.gray70};
    55    font-family: ${Font.monospace};
    56    font-size: ${FontSize.smallest};
    57    opacity: 0;
    58    position: absolute;
    59    transition: opacity ${AnimDuration.default} ease;
    60    white-space: nowrap;
    61    width: 100%;
    62  `
    63  
    64  const viewLinkIconMixin = `
    65    display: flex;
    66    transition: fill ${AnimDuration.default} ease;
    67    height: 100%;
    68    padding: ${SizeUnit(0.65)} 0;
    69    fill: ${Color.gray50};
    70  
    71    &.isCurrent {
    72      fill: ${Color.gray70};
    73    }
    74  `
    75  
    76  const TableViewIcon = styled(TableViewSvg)`
    77    ${viewLinkIconMixin}
    78    /* "Hack" to right-align text */
    79    padding-left: ${SizeUnit(0.5)};
    80  `
    81  
    82  const DetailViewIcon = styled(DetailViewSvg)`
    83    ${viewLinkIconMixin}
    84  `
    85  
    86  const ViewLink = styled(Link)`
    87    position: relative;
    88  
    89    &:is(:hover, :focus, :active) {
    90      ${ViewLinkText} {
    91        opacity: 1;
    92      }
    93  
    94      ${TableViewIcon}, ${DetailViewIcon} {
    95        fill: ${Color.blue};
    96      }
    97    }
    98  `
    99  
   100  const ViewLinkSection = styled.div`
   101    align-items: center;
   102    display: flex;
   103    margin-left: ${SizeUnit(1)};
   104    margin-right: ${SizeUnit(1)};
   105  `
   106  
   107  type HeaderBarProps = {
   108    view: Proto.webviewView
   109    isSocketConnected: boolean
   110    currentPage?: AnalyticsType.Detail | AnalyticsType.Grid
   111  }
   112  
   113  export default function HeaderBar({
   114    view,
   115    currentPage,
   116    isSocketConnected,
   117  }: HeaderBarProps) {
   118    let isSnapshot = usePathBuilder().isSnapshot()
   119    let snapshot = useSnapshotAction()
   120    let session = view?.uiSession?.status
   121    let runningBuild = session?.runningTiltBuild
   122    let suggestedVersion = session?.suggestedTiltVersion
   123    let resources = view?.uiResources || []
   124  
   125    let globalNavProps: GlobalNavProps = {
   126      isSnapshot,
   127      snapshot,
   128      showUpdate: showUpdate(view),
   129      suggestedVersion,
   130      runningBuild,
   131      clusterConnections: view.clusters,
   132    }
   133  
   134    const pb = usePathBuilder()
   135  
   136    const tableViewLinkClass =
   137      currentPage === AnalyticsType.Grid ? "isCurrent" : ""
   138    const detailViewLinkClass =
   139      currentPage === AnalyticsType.Detail ? "isCurrent" : ""
   140  
   141    // TODO (lizz): Consider refactoring nav to use more semantic pattern of ul + li
   142    return (
   143      <>
   144        <SnapshotBar className={`is-${currentPage}`} />
   145        <HeaderBarRoot aria-label="Dashboard menu">
   146          <Link to="/overview" aria-label="Tilt home">
   147            <Logo width="57px" />
   148          </Link>
   149          <ViewLinkSection>
   150            <ViewLink
   151              to="/overview"
   152              aria-label="Table view"
   153              aria-current={currentPage === AnalyticsType.Grid}
   154            >
   155              <TableViewIcon className={tableViewLinkClass} role="presentation" />
   156              <ViewLinkText>Table</ViewLinkText>
   157            </ViewLink>
   158            <HeaderDivider role="presentation" />
   159            <ViewLink
   160              to={pb.encpath`/r/(all)/overview`}
   161              aria-label="Detail view"
   162              aria-current={currentPage === AnalyticsType.Detail}
   163            >
   164              <DetailViewIcon
   165                className={detailViewLinkClass}
   166                role="presentation"
   167              />
   168              <ViewLinkText>Detail</ViewLinkText>
   169            </ViewLink>
   170          </ViewLinkSection>
   171          <AllResourceStatusSummary
   172            displayText="Resources"
   173            labelText="Status summary for all resources"
   174            resources={resources}
   175            isSocketConnected={isSocketConnected}
   176          />
   177          <CustomNav view={view} />
   178          <GlobalNav {...globalNavProps} />
   179        </HeaderBarRoot>
   180      </>
   181    )
   182  }