diff --git a/src/app/Layout.tsx b/src/app/Layout.tsx index fa58df8c80..63235262b8 100644 --- a/src/app/Layout.tsx +++ b/src/app/Layout.tsx @@ -1,6 +1,6 @@ import { useEffect, useState } from 'react'; -import { Box, Toolbar, useMediaQuery, useTheme } from '@mui/material'; +import { Box, useMediaQuery, useTheme } from '@mui/material'; import { useShallow } from 'zustand/react/shallow'; @@ -10,6 +10,7 @@ import { useLocalStorage } from 'react-use'; import { Toast } from 'src/components/AgentSkills/Toast'; import Navigation from 'src/components/navigation/Navigation'; +import Topbar from 'src/components/navigation/TopBar'; import ErrorBoundryWrapper from 'src/components/shared/ErrorBoundryWrapper'; import PageContainer from 'src/components/shared/PageContainer'; import DocsSidePanel from 'src/components/sidePanelDocs/SidePanel'; @@ -55,16 +56,11 @@ function AppLayout() { showDocs && !belowMd && hasLength(docsURL) ); - // We want to control the flex and not size as it seems to work better - // when showing/hiding and also allows a sort of percentage view instead - // of hardcoded size values useEffect(() => { setLeftPaneFlex(displaySidePanel ? 0.7 : 1.0); setRightPaneFlex(displaySidePanel ? 0.3 : 0.0); }, [displaySidePanel]); - // So the transition does not mess with a user resizing the elements - // and during initial load of the app const resizeHandlers = { start: () => { setAnimateOpening(false); @@ -75,38 +71,47 @@ function AppLayout() { }; return ( - - - + + `grid-template-columns ${t.transitions.duration.shortest}ms`, + }} + > + + + + - + - + - - + diff --git a/src/components/admin/Billing/TenantOptions.tsx b/src/components/admin/Billing/TenantOptions.tsx index 1ce83e6a31..7587d9b85a 100644 --- a/src/components/admin/Billing/TenantOptions.tsx +++ b/src/components/admin/Billing/TenantOptions.tsx @@ -1,8 +1,7 @@ import type { SelectableTableStore } from 'src/stores/Tables/Store'; -import { useCallback } from 'react'; +import { useCallback, useEffect, useRef } from 'react'; -import TenantSelector from 'src/components/shared/TenantSelector'; import { useZustandStore } from 'src/context/Zustand/provider'; import { useBillingStore } from 'src/stores/Billing/Store'; import { SelectTableStoreNames } from 'src/stores/names'; @@ -11,10 +10,12 @@ import { useBillingTable_setHydrationErrorsExist, } from 'src/stores/Tables/Billing/hooks'; import { selectableTableStoreSelectors } from 'src/stores/Tables/Store'; +import { useTenantStore } from 'src/stores/Tenant/Store'; -function TenantOptions() { - const resetBillingState = useBillingStore((state) => state.resetState); +function useTenantChangeReset() { + const selectedTenant = useTenantStore((state) => state.selectedTenant); + const resetBillingState = useBillingStore((state) => state.resetState); const setHydrated = useBillingTable_setHydrated(); const setHydrationErrorsExist = useBillingTable_setHydrationErrorsExist(); @@ -23,9 +24,8 @@ function TenantOptions() { SelectableTableStore['resetState'] >(SelectTableStoreNames.BILLING, selectableTableStoreSelectors.state.reset); - const updateStoreState = useCallback(() => { + const resetStores = useCallback(() => { resetBillingState(); - resetBillingSelectTableState(false); setHydrated(false); setHydrationErrorsExist(false); @@ -36,7 +36,13 @@ function TenantOptions() { setHydrationErrorsExist, ]); - return ; + const previousTenant = useRef(selectedTenant); + useEffect(() => { + if (previousTenant.current !== selectedTenant) { + previousTenant.current = selectedTenant; + resetStores(); + } + }, [selectedTenant, resetStores]); } -export default TenantOptions; +export default useTenantChangeReset; diff --git a/src/components/admin/Billing/index.tsx b/src/components/admin/Billing/index.tsx index 8299fdd57c..ba9aa82753 100644 --- a/src/components/admin/Billing/index.tsx +++ b/src/components/admin/Billing/index.tsx @@ -19,7 +19,7 @@ import BillingLoadError from 'src/components/admin/Billing/LoadError'; import PaymentMethods from 'src/components/admin/Billing/PaymentMethods'; import PricingTierDetails from 'src/components/admin/Billing/PricingTierDetails'; import { INVOICE_ROW_HEIGHT } from 'src/components/admin/Billing/shared'; -import TenantOptions from 'src/components/admin/Billing/TenantOptions'; +import useTenantChangeReset from 'src/components/admin/Billing/TenantOptions'; import AdminTabs from 'src/components/admin/Tabs'; import GraphLoadingState from 'src/components/graphs/states/Loading'; import GraphStateWrapper from 'src/components/graphs/states/Wrapper'; @@ -48,6 +48,8 @@ function AdminBilling({ showAddPayment }: AdminBillingProps) { headerLink: 'https://www.estuary.dev/pricing/', }); + useTenantChangeReset(); + const intl = useIntl(); const selectedTenant = useTenantStore((state) => state.selectedTenant); @@ -142,12 +144,6 @@ function AdminBilling({ showAddPayment }: AdminBillingProps) { - - - diff --git a/src/components/admin/Settings/index.tsx b/src/components/admin/Settings/index.tsx index e731f94c79..10054fd37d 100644 --- a/src/components/admin/Settings/index.tsx +++ b/src/components/admin/Settings/index.tsx @@ -1,11 +1,10 @@ -import { Divider, Grid, Stack } from '@mui/material'; +import { Divider, Stack } from '@mui/material'; import { authenticatedRoutes } from 'src/app/routes'; import DataPlanes from 'src/components/admin/Settings/DataPlanes'; import PrefixAlerts from 'src/components/admin/Settings/PrefixAlerts'; import { StorageMappings } from 'src/components/admin/Settings/StorageMappings'; import AdminTabs from 'src/components/admin/Tabs'; -import TenantSelector from 'src/components/shared/TenantSelector'; import usePageTitle from 'src/hooks/usePageTitle'; function Settings() { @@ -17,19 +16,6 @@ function Settings() { <> - - - - - - diff --git a/src/components/graphics/CompanyLogo.tsx b/src/components/graphics/CompanyLogo.tsx index 0be8ed03a3..2645d90f94 100644 --- a/src/components/graphics/CompanyLogo.tsx +++ b/src/components/graphics/CompanyLogo.tsx @@ -12,8 +12,8 @@ function CompanyLogo() { return ( {intl.formatMessage({ ); diff --git a/src/components/graphics/CompanyMark.tsx b/src/components/graphics/CompanyMark.tsx new file mode 100644 index 0000000000..45df8e1db1 --- /dev/null +++ b/src/components/graphics/CompanyMark.tsx @@ -0,0 +1,22 @@ +import { useTheme } from '@mui/material'; + +import { useIntl } from 'react-intl'; + +import darkMark from 'src/images/pictorial-marks/pictorial-mark__multi-blue.png'; +import lightMark from 'src/images/pictorial-marks/pictorial-mark__white.png'; + +function CompanyMark() { + const intl = useIntl(); + const theme = useTheme(); + + return ( + {intl.formatMessage({ + ); +} + +export default CompanyMark; diff --git a/src/components/home/dashboard/index.tsx b/src/components/home/dashboard/index.tsx index ed59efb0a2..6112494686 100644 --- a/src/components/home/dashboard/index.tsx +++ b/src/components/home/dashboard/index.tsx @@ -1,20 +1,10 @@ -import { Box, Grid } from '@mui/material'; +import { Grid } from '@mui/material'; import EntityStatOverview from 'src/components/home/dashboard/EntityStatOverview'; -import TenantSelector from 'src/components/shared/TenantSelector'; export default function Dashboard() { return ( - - - - - - ); diff --git a/src/components/home/hero/Demo.tsx b/src/components/home/hero/Demo.tsx index 1384bdd487..8de8421dae 100644 --- a/src/components/home/hero/Demo.tsx +++ b/src/components/home/hero/Demo.tsx @@ -1,10 +1,10 @@ -import { Grid } from '@mui/material'; +import { Button, Grid } from '@mui/material'; +import { OpenNewWindow } from 'iconoir-react'; import { FormattedMessage } from 'react-intl'; import DemoButton from 'src/components/home/hero/DemoButton'; import DemoStep from 'src/components/home/hero/Steps/Demo'; -import ExternalLink from 'src/components/shared/ExternalLink'; const DEMO_URL = 'https://docs.google.com/spreadsheets/d/1Cd_afDejaVXKeGxSTCupKaTtrb3a7ZHBghTemDNKE5I/edit#gid=0'; @@ -33,17 +33,17 @@ function HeroDemo() { mt: 3, }} > - } + href={DEMO_URL} + target="_blank" + rel="noopener" + sx={{ py: 1, px: 3 }} > - + ); diff --git a/src/components/inputs/PrefixedName/index.tsx b/src/components/inputs/PrefixedName/index.tsx index b9193ba518..a4f7b1b080 100644 --- a/src/components/inputs/PrefixedName/index.tsx +++ b/src/components/inputs/PrefixedName/index.tsx @@ -169,16 +169,27 @@ function PrefixedName({ }, }} > - handlers.setPrefix(newValue)} - options={objectRoles} - value={prefix} - variantString={variantString} - /> + {singleOption ? ( + + ) : ( + handlers.setPrefix(newValue)} + options={objectRoles} + value={prefix} + variantString={variantString} + /> + )} [ - // state.selectedTenant, - // state.setSelectedTenant, - // ])); + const selectedTenant = useTenantStore((state) => state.selectedTenant); + const singleOption = objectRoles.length === 1 || hasLength(selectedTenant); // Local State for editing const [errors, setErrors] = useState(null); const [name, setName] = useState(''); const [nameError, setNameError] = useState(null); const [prefix, setPrefix] = useState( - singleOption || defaultPrefix ? objectRoles[0] : '' //selectedTenant + hasLength(selectedTenant) + ? selectedTenant + : singleOption || defaultPrefix + ? objectRoles[0] + : '' ); const [prefixError, setPrefixError] = useState(null); diff --git a/src/components/menus/HelpMenu.tsx b/src/components/menus/HelpMenu.tsx index c1855ce0a8..6a9094631c 100644 --- a/src/components/menus/HelpMenu.tsx +++ b/src/components/menus/HelpMenu.tsx @@ -1,18 +1,61 @@ -import { HelpCircle } from 'iconoir-react'; +import type { ReactNode } from 'react'; + +import { Link, Menu, MenuItem } from '@mui/material'; + +import { OpenNewWindow } from 'iconoir-react'; import { FormattedMessage, useIntl } from 'react-intl'; -import IconMenu from 'src/components/menus/IconMenu'; -import ExternalLinkMenuItem from 'src/components/shared/ExternalLinkMenuItem'; +const ExternalLinkMenuItem = ({ + children, + link, +}: { + children: ReactNode; + link: string; +}) => ( + + {children} + + + +); + +interface HelpMenuProps { + anchorEl: HTMLElement | null; + onClose: () => void; +} -function HelpMenu() { +export function HelpMenu({ anchorEl, onClose }: HelpMenuProps) { const intl = useIntl(); return ( - } - identifier="help-menu" - tooltip={intl.formatMessage({ id: 'helpMenu.tooltip' })} + - + ); } diff --git a/src/components/navigation/ListItemLink.tsx b/src/components/navigation/ListItemLink.tsx index 7dd1eef94c..f6010075b7 100644 --- a/src/components/navigation/ListItemLink.tsx +++ b/src/components/navigation/ListItemLink.tsx @@ -11,14 +11,12 @@ import { import { useIntl } from 'react-intl'; import RouterLink from 'src/components/navigation/RouterLink'; -import { NavWidths } from 'src/context/Theme'; interface Props { icon: ReactNode; title: string; link: string | any; isOpen?: boolean; - menuWidth?: number; badgeContent?: number; tooltipDelay?: number; } @@ -28,7 +26,6 @@ const ListItemLink = ({ title, link, isOpen, - menuWidth, badgeContent, tooltipDelay, }: Props) => { @@ -42,64 +39,23 @@ const ListItemLink = ({
  • - {menuWidth === NavWidths.FULL ? ( - - {icon ? ( - - theme.palette.text.primary, - }} - > - {icon} - - ) : null} + + {icon ? ( + + {icon} + + ) : null} - - - - - ) : ( - - {icon ? ( - - theme.palette.text.primary, - }} - > - - {icon} - - - ) : null} - - - - )} + +
  • ); diff --git a/src/components/navigation/ModeSwitch.tsx b/src/components/navigation/ModeSwitch.tsx index 8328dd40f0..8d8da0a92a 100644 --- a/src/components/navigation/ModeSwitch.tsx +++ b/src/components/navigation/ModeSwitch.tsx @@ -7,7 +7,7 @@ import { } from '@mui/material'; import { HalfMoon, SunLight } from 'iconoir-react'; -import { FormattedMessage, useIntl } from 'react-intl'; +import { useIntl } from 'react-intl'; import { useColorMode } from 'src/context/Theme'; @@ -42,7 +42,9 @@ function ModeSwitch() { - + {theme.palette.mode === 'dark' + ? intl.formatMessage({ id: 'modeSwitch.label.dark' }) + : intl.formatMessage({ id: 'modeSwitch.label.light' })} diff --git a/src/components/navigation/Navigation.tsx b/src/components/navigation/Navigation.tsx index 82ef0714bd..e969d4fb66 100644 --- a/src/components/navigation/Navigation.tsx +++ b/src/components/navigation/Navigation.tsx @@ -1,31 +1,57 @@ -//TODO (UI / UX) - These icons are not final +import React from 'react'; + import { Box, + Dialog, + DialogContent, + DialogTitle, + Divider, List, ListItemButton, ListItemIcon, ListItemText, + Menu, + MenuItem, + Popover, Stack, - Toolbar, Tooltip, + Typography, useTheme, } from '@mui/material'; import MuiDrawer, { drawerClasses } from '@mui/material/Drawer'; +import { useShallow } from 'zustand/react/shallow'; + import { + Building, + Check, CloudDownload, CloudUpload, DatabaseScript, FastArrowLeft, + HalfMoon, + HelpCircle, HomeSimple, + LogOut, Settings, + SunLight, } from 'iconoir-react'; -import { useIntl } from 'react-intl'; +import { FormattedMessage, useIntl } from 'react-intl'; import { authenticatedRoutes } from 'src/app/routes'; +import PrefixSelector from 'src/components/inputs/PrefixedName/PrefixSelector'; +import { HelpMenu } from 'src/components/menus/HelpMenu'; import ListItemLink from 'src/components/navigation/ListItemLink'; -import ModeSwitch from 'src/components/navigation/ModeSwitch'; -import { paperBackground } from 'src/context/Theme'; +import UserAvatar from 'src/components/shared/UserAvatar'; +import { supabaseClient } from 'src/context/GlobalProviders'; +import { useColorMode } from 'src/context/Theme'; +import { useUserStore } from 'src/context/User/useUserContextStore'; +import { useUserInfoSummaryStore } from 'src/context/UserInfoSummary/useUserInfoSummaryStore'; +import { + useEntitiesStore_capabilities_adminable, + useEntitiesStore_tenantsWithAdmin, +} from 'src/stores/Entities/hooks'; +import { useTenantStore } from 'src/stores/Tenant/Store'; interface NavigationProps { open: boolean; @@ -36,6 +62,35 @@ interface NavigationProps { const Navigation = ({ open, width, onNavigationToggle }: NavigationProps) => { const intl = useIntl(); const theme = useTheme(); + const colorMode = useColorMode(); + const userDetails = useUserStore(useShallow((state) => state.userDetails)); + const selectedTenant = useTenantStore((state) => state.selectedTenant); + const setSelectedTenant = useTenantStore( + (state) => state.setSelectedTenant + ); + const tenantNames = useEntitiesStore_tenantsWithAdmin(); + const hasSupportAccess = useUserInfoSummaryStore( + (state) => state.hasSupportAccess + ); + const allPrefixes = useEntitiesStore_capabilities_adminable(false); + + const [menuAnchor, setMenuAnchor] = React.useState( + null + ); + const menuOpen = Boolean(menuAnchor); + + const [helpAnchor, setHelpAnchor] = React.useState( + null + ); + + const [orgAnchor, setOrgAnchor] = React.useState(null); + const orgOpen = Boolean(orgAnchor); + + const [orgDialogOpen, setOrgDialogOpen] = React.useState(false); + + const tenantLabel = selectedTenant + ? selectedTenant.replace(/\/$/, '') + : null; const openNavigation = () => { onNavigationToggle(true); @@ -55,19 +110,17 @@ const Navigation = ({ open, width, onNavigationToggle }: NavigationProps) => { sx={{ [`& .${drawerClasses.paper}`]: { boxSizing: 'border-box', + position: 'static', + height: '100%', transition: (paperTheme) => `${paperTheme.transitions.duration.shortest}ms`, width, - border: 0, - background: paperBackground[theme.palette.mode], }, transition: (drawerTheme) => `${drawerTheme.transitions.duration.shortest}ms`, width, }} > - - { { - - - - + - + { /> - + } + title="helpMenu.tooltip" + link={(e: React.MouseEvent) => + setHelpAnchor(e.currentTarget) + } + isOpen={open} + /> + setHelpAnchor(null)} + /> + + {userDetails ? ( + <> + + setMenuAnchor(e.currentTarget) + } + sx={{ mx: 1, my: 0.25 }} + > + + + + + setMenuAnchor(null)} + onClick={() => setMenuAnchor(null)} + anchorOrigin={{ + horizontal: 'left', + vertical: 'top', + }} + transformOrigin={{ + horizontal: 'left', + vertical: 'bottom', + }} + > + + + + {userDetails.userName ?? + userDetails.email} + + + {userDetails.email} + + + + + + + { + e.stopPropagation(); + colorMode.toggleColorMode(); + }} + > + + {theme.palette.mode === 'dark' ? ( + + ) : ( + + )} + + + + + + { + void supabaseClient.auth.signOut(); + }} + > + + + + + + + + + hasSupportAccess + ? setOrgDialogOpen(true) + : setOrgAnchor(e.currentTarget) + } + sx={{ mx: 1, my: 0.25 }} + > + + + + + + + setOrgAnchor(null)} + anchorOrigin={{ + horizontal: 'left', + vertical: 'top', + }} + transformOrigin={{ + horizontal: 'left', + vertical: 'bottom', + }} + slotProps={{ + paper: { + sx: { + width: 240, + p: 1, + borderRadius: 2, + }, + }, + }} + > + + + + + {tenantNames.map((tenant) => { + const label = tenant.replace(/\/$/, ''); + const isSelected = + tenant === selectedTenant; + + return ( + { + setSelectedTenant(tenant); + setOrgAnchor(null); + }} + sx={{ + borderRadius: 1, + fontSize: 13, + py: 0.75, + justifyContent: + 'space-between', + }} + > + {label} + + {isSelected ? : null} + + ); + })} + + + setOrgDialogOpen(false)} + fullWidth + maxWidth="xs" + > + + + + + { + setSelectedTenant(newValue); + setOrgDialogOpen(false); + }} + options={allPrefixes} + value={selectedTenant} + variantString="outlined" + /> + + + + ) : null} diff --git a/src/components/navigation/TopBar.tsx b/src/components/navigation/TopBar.tsx index 5d35e1a122..bc89b50af8 100644 --- a/src/components/navigation/TopBar.tsx +++ b/src/components/navigation/TopBar.tsx @@ -1,54 +1,36 @@ -import { Divider, Stack, Toolbar } from '@mui/material'; +import { Stack, Toolbar } from '@mui/material'; import MuiAppBar from '@mui/material/AppBar'; -import { useTheme } from '@mui/material/styles'; import { HeaderPill } from 'src/components/AgentSkills/HeaderPill'; import CompanyLogo from 'src/components/graphics/CompanyLogo'; -import HelpMenu from 'src/components/menus/HelpMenu'; -import UserMenu from 'src/components/menus/UserMenu'; -import PageTitle from 'src/components/navigation/PageTitle'; +import CompanyMark from 'src/components/graphics/CompanyMark'; import SidePanelDocsOpenButton from 'src/components/sidePanelDocs/OpenButton'; import { UpdateAlert } from 'src/components/UpdateAlert'; -import { zIndexIncrement } from 'src/context/Theme'; -const Topbar = () => { - const theme = useTheme(); +interface TopbarProps { + navigationOpen?: boolean; +} +const Topbar = ({ navigationOpen = true }: TopbarProps) => { return ( - + + {navigationOpen ? : } + } > - - - - - - - - - - - - - + diff --git a/src/components/shared/ExternalLink.tsx b/src/components/shared/ExternalLink.tsx index 4479e2a0b3..e24d8647c4 100644 --- a/src/components/shared/ExternalLink.tsx +++ b/src/components/shared/ExternalLink.tsx @@ -1,18 +1,12 @@ -import type { ButtonTypeMap, SxProps } from '@mui/material'; -import type { ReactNode } from 'react'; +import type { SxProps, Theme } from '@mui/material'; +import type { MouseEvent, ReactNode } from 'react'; -import { Button } from '@mui/material'; +import { Link } from '@mui/material'; import { OpenNewWindow } from 'iconoir-react'; -import { linkButtonSx } from 'src/context/Theme'; - export interface ExternalLinkOptions { - color?: ButtonTypeMap['props']['color']; - hideIcon?: boolean; - padding?: number; - sx?: SxProps; - variant?: ButtonTypeMap['props']['variant']; + sx?: SxProps; } interface Props extends ExternalLinkOptions { @@ -20,35 +14,32 @@ interface Props extends ExternalLinkOptions { link: string; } -const ExternalLink = ({ - color, - children, - link, - hideIcon, - sx, - variant, -}: Props) => { - const onClick = (event: any) => { +const ExternalLink = ({ children, link, sx }: Props) => { + const onClick = (event: MouseEvent) => { event.stopPropagation(); }; - const styling = sx ?? ({} as any); - return ( - + + ); }; diff --git a/src/components/shared/ExternalLinkMenuItem.tsx b/src/components/shared/ExternalLinkMenuItem.tsx deleted file mode 100644 index 2b437bf1ae..0000000000 --- a/src/components/shared/ExternalLinkMenuItem.tsx +++ /dev/null @@ -1,39 +0,0 @@ -import type { ReactNode } from 'react'; - -import { Link, MenuItem } from '@mui/material'; - -import { OpenNewWindow } from 'iconoir-react'; - -interface Props { - children: ReactNode; - link: string; -} - -export const externalLinkStyling = { - bgcolor: 'none', - color: 'text.primary', - fontSize: 14, - fontWeight: 500, - px: 3, - py: 1.5, - textTransform: 'uppercase', -}; - -function ExternalLinkMenuItem({ children, link }: Props) { - return ( - - {children} - - - - ); -} - -export default ExternalLinkMenuItem; diff --git a/src/components/shared/PageContainer.tsx b/src/components/shared/PageContainer.tsx index a331571946..87a7dad79d 100644 --- a/src/components/shared/PageContainer.tsx +++ b/src/components/shared/PageContainer.tsx @@ -3,22 +3,34 @@ import type { Notification } from 'src/stores/NotificationStore'; import { useEffect, useMemo, useState } from 'react'; -import { Container, Paper, Snackbar, useTheme } from '@mui/material'; +import { Box, Paper, Snackbar, Typography, useTheme } from '@mui/material'; + +import { Building } from 'iconoir-react'; +import { useIntl } from 'react-intl'; -import Topbar from 'src/components/navigation/TopBar'; import AlertBox from 'src/components/shared/AlertBox'; import { paperBackground } from 'src/context/Theme'; import useNotificationStore, { notificationStoreSelectors, } from 'src/stores/NotificationStore'; +import { useTenantStore } from 'src/stores/Tenant/Store'; +import { useTopBarStore } from 'src/stores/TopBar/Store'; interface Props { children: ReactNode | ReactNode[]; hideBackground?: boolean; + navigationOpen?: boolean; } -function PageContainer({ children, hideBackground }: Props) { +function PageContainer({ + children, + hideBackground, + navigationOpen = true, +}: Props) { + const intl = useIntl(); const theme = useTheme(); + const selectedTenant = useTenantStore((state) => state.selectedTenant); + const header = useTopBarStore((state) => state.header); const notification = useNotificationStore( notificationStoreSelectors.notification @@ -77,10 +89,12 @@ function PageContainer({ children, hideBackground }: Props) { }, [notification]); return ( - {notification && alertBody ? ( @@ -112,20 +126,55 @@ function PageContainer({ children, hideBackground }: Props) { ) : null} - + {header ? ( + + + + {selectedTenant.replace(/\/$/, '')} + {' / '} + + {intl.formatMessage({ id: header })} + + + + ) : null} + `padding ${t.transitions.duration.shortest}ms`, + py: 2, + flex: 1, + minHeight: 0, + overflow: 'auto', + overscrollBehavior: 'none', width: '100%', + mb: 1, boxShadow: boxShadowMixin, - borderRadius: 3, + borderRadius: header ? '0 0 16px 16px' : 8, background: backgroundMixin, }} > {children} - +
    ); } diff --git a/src/context/Theme.tsx b/src/context/Theme.tsx index f59f66d742..249660b83e 100644 --- a/src/context/Theme.tsx +++ b/src/context/Theme.tsx @@ -92,11 +92,13 @@ declare module '@mui/material/Typography' { } // Navigation Width -export enum NavWidths { - MOBILE = 0, - RAIL = 48, - FULL = 200, -} +export const NavWidths = { + MOBILE: 0, + RAIL: 54, + FULL: 170, +} as const; + +export type NavWidths = (typeof NavWidths)[keyof typeof NavWidths]; // Colors export const sample_blue = { @@ -1010,10 +1012,24 @@ const themeSettings = createTheme({ styleOverrides: { root: { fontSize: 14, - borderRadius: 4, + borderRadius: 8, + textTransform: 'none', }, }, }, + MuiIconButton: { + styleOverrides: { + root: { + fontSize: 14, + borderRadius: 8, + }, + }, + }, + MuiLink: { + defaultProps: { + underline: 'hover' as const, + }, + }, MuiCheckbox: { defaultProps: { icon: , @@ -1051,6 +1067,13 @@ const themeSettings = createTheme({ }, }, }, + MuiTab: { + styleOverrides: { + root: { + textTransform: 'none', + }, + }, + }, MuiTabs: { ...baseBackground, defaultProps: { @@ -1152,17 +1175,54 @@ const ThemeProvider = ({ children }: BaseComponentProps) => { }, }, MuiAppBar: { + defaultProps: { + position: 'static' as const, + elevation: 0, + }, styleOverrides: { root: { - background: - palette.mode === 'dark' - ? sample_grey[800] - : 'white', + background: palette.background?.default, boxShadow: 'none', color: palette.text?.primary, }, }, }, + MuiDrawer: { + styleOverrides: { + paper: { + background: palette.background?.default, + border: 0, + }, + }, + }, + MuiListItemButton: { + styleOverrides: { + root: { + gap: 8, + whiteSpace: 'nowrap', + overflow: 'hidden', + padding: '6px 8px', + borderRadius: 8, + }, + }, + }, + MuiListItemIcon: { + styleOverrides: { + root: { + minWidth: 'auto', + color: 'inherit', + }, + }, + }, + MuiListItemText: { + styleOverrides: { + primary: { + fontSize: 13, + overflow: 'hidden', + textOverflow: 'ellipsis', + }, + }, + }, MuiDialog: { styleOverrides: { paper: { diff --git a/src/lang/en-US/CTAs.ts b/src/lang/en-US/CTAs.ts index 79f2a8b9cc..e89e5734f0 100644 --- a/src/lang/en-US/CTAs.ts +++ b/src/lang/en-US/CTAs.ts @@ -9,6 +9,7 @@ export const CTAs: Record = { 'cta.edit': `Edit`, 'cta.login': `Login`, 'cta.logout': `Logout`, + 'cta.new': `New`, 'cta.materialize': `Materialize`, 'cta.register': `Sign up`, 'cta.registerFinish': `Complete Registration`, diff --git a/src/lang/en-US/Navigation.ts b/src/lang/en-US/Navigation.ts index 304f759a81..bf2d3192d5 100644 --- a/src/lang/en-US/Navigation.ts +++ b/src/lang/en-US/Navigation.ts @@ -2,15 +2,17 @@ import { CommonMessages } from 'src/lang/en-US/CommonMessages'; import { CTAs } from 'src/lang/en-US/CTAs'; export const Navigation: Record = { + 'navigation.ariaLabel': `Main Navigation`, 'navigation.toggle.ariaLabel': `Toggle Navigation`, - 'navigation.expand': `Expand Navigation`, - 'navigation.collapse': `Collapse Navigation`, + 'navigation.tooltip.expand': `Expand Navigation`, + 'navigation.tooltip.collapse': `Collapse Navigation`, + 'navigation.collapse': `Collapse`, // Header 'mainMenu.tooltip': `Open Main Menu`, 'helpMenu.ariaLabel': `Open Help Menu`, - 'helpMenu.tooltip': `Helpful Links`, + 'helpMenu.tooltip': `Help`, 'helpMenu.docs': `Docs`, 'helpMenu.docs.link': `https://docs.estuary.dev/`, 'helpMenu.slack': `Estuary Slack`, @@ -27,7 +29,10 @@ export const Navigation: Record = { 'accountMenu.tooltip': `My Account`, 'accountMenu.emailVerified': `verified`, - 'modeSwitch.label': `Toggle Color Mode`, + 'modeSwitch.label.light': `Light mode`, + 'modeSwitch.label.dark': `Dark mode`, + + 'tenant.organization': `Organization`, 'updateAlert.cta': `Update`, 'updateAlert.title': `Dashboard Updated`,