Skip to main content
Glama

@arizeai/phoenix-mcp

Official
by Arize-ai
Navbar.tsx8.8 kB
import { PropsWithChildren, ReactNode, useMemo } from "react"; import { Button, Pressable } from "react-aria-components"; import { Link, NavLink as RRNavLink } from "react-router"; import { css } from "@emotion/react"; import { Flex, Icon, Icons, Menu, MenuItem, MenuTrigger, Popover, PopoverArrow, Text, Tooltip, TooltipTrigger, } from "@phoenix/components"; import { GitHubStarCount } from "@phoenix/components/nav/GitHubStarCount"; import { isProviderThemeMode, useTheme, useViewer } from "@phoenix/contexts"; import { assertUnreachable } from "@phoenix/typeUtils"; import { Logo, LogoText } from "./Logo"; const topNavCSS = css` padding: var(--ac-global-dimension-static-size-100); background-color: var(--ac-global-color-grey-100); flex: none; display: flex; flex-direction: row; justify-content: flex-start; align-items: center; gap: var(--ac-global-dimension-static-size-100); `; const sideNavCSS = css` padding: var(--ac-global-dimension-static-size-200) var(--ac-global-dimension-static-size-100); background-color: var(--ac-global-color-grey-100); flex: none; display: flex; flex-direction: column; box-sizing: border-box; height: 100vh; width: var(--px-nav-collapsed-width); transition: width 0.15s cubic-bezier(0, 0.57, 0.21, 0.99); &[data-expanded="true"] { width: var(--px-nav-expanded-width); } &[data-expanded="false"] { .brand-text-wrap { opacity: 0; } } `; const navLinkCSS = css` width: 100%; color: var(--ac-global-color-grey-500); background-color: transparent; border-radius: var(--ac-global-rounding-small); display: flex; flex-direction: row; align-items: center; overflow: hidden; transition: color 0.2s ease-in-out, background-color 0.2s ease-in-out; text-decoration: none; cursor: pointer; &.active { color: var(--ac-global-text-color-900); background-color: var(--ac-global-color-grey-200); } &:hover:not(.active) { color: var(--ac-global-text-color-900); background-color: var(--ac-global-color-grey-200); } & > .ac-icon-wrap { padding: var(--ac-global-dimension-size-100); display: inline-block; } .ac-text { padding-inline-start: var(--ac-global-dimension-size-50); padding-inline-end: var(--ac-global-dimension-size-100); white-space: nowrap; } `; const brandCSS = css` color: var(--ac-global-text-color-900); font-size: var(--ac-global-font-size-xl); text-decoration: none; margin: 0 0 var(--ac-global-dimension-static-size-200) 0; display: flex; flex-direction: row; align-items: center; gap: var(--ac-global-dimension-static-size-150); overflow: hidden; & > * { flex: none; } .brand-text-wrap { opacity: 1; transition: all 0.8s ease-in-out; display: flex; flex-direction: row; align-items: center; } `; function ExternalLink(props: { href: string; leadingVisual: ReactNode; trailingVisual?: ReactNode; text: string; replaceTab?: boolean; isExpanded: boolean; }) { return ( <TooltipTrigger delay={0} isDisabled={props.isExpanded}> <Pressable> <a href={props.href} target={props.replaceTab ? undefined : "_blank"} css={navLinkCSS} rel="noreferrer" role="button" > {props.leadingVisual} <Text>{props.text}</Text> {props.trailingVisual} </a> </Pressable> <Tooltip placement="right" offset={10}> {props.text} </Tooltip> </TooltipTrigger> ); } export function DocsLink({ isExpanded }: { isExpanded: boolean }) { return ( <ExternalLink href="https://arize.com/docs/phoenix" leadingVisual={<Icon svg={<Icons.BookOutline />} />} text="Documentation" isExpanded={isExpanded} /> ); } export function GitHubLink({ isExpanded }: { isExpanded: boolean }) { return ( <ExternalLink href="https://github.com/Arize-ai/phoenix" leadingVisual={<Icon svg={<Icons.GitHub />} />} trailingVisual={<GitHubStarCount />} text="Star on GitHub" isExpanded={isExpanded} /> ); } export function ThemeSelector({ isExpanded }: { isExpanded: boolean }) { const { theme, systemTheme, themeMode, setThemeMode } = useTheme(); const { themeText, themeIcon } = useMemo(() => { let themeIcon: ReactNode; let themeText: string; switch (themeMode) { case "light": themeIcon = <Icons.SunOutline />; themeText = "Light"; break; case "dark": themeIcon = <Icons.MoonOutline />; themeText = "Dark"; break; case "system": themeIcon = <Icons.HalfMoonHalfSunOutline />; themeText = `${theme === "light" ? "Light" : "Dark"} (auto)`; break; default: assertUnreachable(themeMode); } return { themeIcon, themeText, }; }, [theme, themeMode]); return ( <TooltipTrigger delay={0} isDisabled={isExpanded}> <MenuTrigger> <Button css={navLinkCSS} className="button--reset"> <Icon svg={themeIcon} /> <Text>{themeText}</Text> </Button> <Popover placement="right top"> <PopoverArrow /> <Menu aria-label="Theme selection" selectedKeys={new Set([themeMode])} selectionMode="single" onSelectionChange={(keys) => { const selectedKey = keys instanceof Set ? Array.from(keys)[0] : null; if (selectedKey && isProviderThemeMode(selectedKey)) { setThemeMode(selectedKey); } }} > <MenuItem id="system"> <Flex direction="row" gap="size-100" justifyContent="start" alignItems="center" > <Icon svg={<Icons.HalfMoonHalfSunOutline />} /> <Text>{`Auto (${systemTheme})`}</Text> </Flex> </MenuItem> <MenuItem id="dark"> <Flex direction="row" gap="size-100" justifyContent="start" alignItems="center" > <Icon svg={<Icons.MoonOutline />} /> <Text>Dark</Text> </Flex> </MenuItem> <MenuItem id="light"> <Flex direction="row" gap="size-100" justifyContent="start" alignItems="center" > <Icon svg={<Icons.SunOutline />} /> <Text>Light</Text> </Flex> </MenuItem> </Menu> </Popover> </MenuTrigger> <Tooltip placement="right" offset={10}> {themeText} </Tooltip> </TooltipTrigger> ); } export function Brand() { return ( <Link to="/" css={brandCSS} title={`version: ${window.Config.platformVersion}`} > <Logo /> <div className="brand-text-wrap"> <LogoText className="brand-text" /> </div> </Link> ); } export function TopNavbar({ children }: { children: ReactNode }) { return <nav css={topNavCSS}>{children}</nav>; } export function SideNavbar({ children, isExpanded, }: PropsWithChildren<{ isExpanded: boolean }>) { return ( <nav data-expanded={isExpanded} css={sideNavCSS}> {children} </nav> ); } export function NavLink(props: { to: string; text: string; leadingVisual: ReactNode; isExpanded: boolean; }) { return ( <TooltipTrigger delay={0} isDisabled={props.isExpanded}> <Pressable> <div role="button"> <RRNavLink to={props.to} css={navLinkCSS}> {props.leadingVisual} <Text>{props.text}</Text> </RRNavLink> </div> </Pressable> <Tooltip placement="right" offset={10}> {props.text} </Tooltip> </TooltipTrigger> ); } export function NavButton(props: { text: string; leadingVisual: ReactNode; onClick: () => void; }) { return ( <button className="button--reset" css={navLinkCSS} onClick={props.onClick}> {props.leadingVisual} <Text>{props.text}</Text> </button> ); } export const ManagementLink = ({ isExpanded }: { isExpanded: boolean }) => { const { viewer } = useViewer(); if (viewer?.isManagementUser && window.Config.managementUrl) { return ( <li key="management"> <ExternalLink href={window.Config.managementUrl} leadingVisual={<Icon svg={<Icons.Server />} />} text="Management Console" replaceTab isExpanded={isExpanded} /> </li> ); } return null; };

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Arize-ai/phoenix'

If you have feedback or need assistance with the MCP directory API, please join our Discord server