mirror of
https://github.com/umami-software/umami.git
synced 2026-02-10 15:47:13 +01:00
Rename SideMenu to NavMenu, fix tooltips, and update react-zen.
- Rename SideMenu to NavMenu with visible group title labels and selected item highlighting - Update react-zen to 0.242.0 and fix responsive breakpoints (xs -> base) - Style floating tooltips with inverted background across WorldMap, charts, and WeeklyTraffic - Add CSS variables for primary color and use IconLabel consistently - Remove stray console.log from LoadingPanel Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
7cafc3e61d
commit
c6dd3fb6ff
36 changed files with 107 additions and 171 deletions
|
|
@ -65,7 +65,7 @@ export function FilterRecord({
|
|||
<Column>
|
||||
<Label>{fields.find(f => f.name === name)?.label}</Label>
|
||||
<Grid columns="1fr auto" gap>
|
||||
<Grid columns={{ xs: '1fr', md: '200px 1fr' }} gap>
|
||||
<Grid columns={{ base: '1fr', md: '200px 1fr' }} gap>
|
||||
<Select
|
||||
items={operators.filter(({ type }) => type === 'string')}
|
||||
value={operator}
|
||||
|
|
|
|||
|
|
@ -4,18 +4,18 @@ const LAYOUTS = {
|
|||
one: { columns: '1fr' },
|
||||
two: {
|
||||
columns: {
|
||||
xs: '1fr',
|
||||
base: '1fr',
|
||||
md: 'repeat(auto-fill, minmax(560px, 1fr))',
|
||||
},
|
||||
},
|
||||
three: {
|
||||
columns: {
|
||||
xs: '1fr',
|
||||
base: '1fr',
|
||||
md: 'repeat(auto-fill, minmax(360px, 1fr))',
|
||||
},
|
||||
},
|
||||
'one-two': { columns: { xs: '1fr', md: 'repeat(3, 1fr)' } },
|
||||
'two-one': { columns: { xs: '1fr', md: 'repeat(3, 1fr)' } },
|
||||
'one-two': { columns: { base: '1fr', md: 'repeat(3, 1fr)' } },
|
||||
'two-one': { columns: { base: '1fr', md: 'repeat(3, 1fr)' } },
|
||||
};
|
||||
|
||||
export function GridRow(props: {
|
||||
|
|
|
|||
|
|
@ -29,8 +29,6 @@ export function LoadingPanel({
|
|||
}: LoadingPanelProps): ReactNode {
|
||||
const empty = isEmpty ?? checkEmpty(data);
|
||||
|
||||
console.log({ empty, isEmpty, data });
|
||||
|
||||
// Show loading spinner only if no data exists
|
||||
if (isLoading || isFetching) {
|
||||
return (
|
||||
|
|
|
|||
|
|
@ -2,39 +2,46 @@ import { Column, Heading, Row, Text } from '@umami/react-zen';
|
|||
import Link from 'next/link';
|
||||
import { IconLabel } from '@/components/common/IconLabel';
|
||||
|
||||
interface SideMenuData {
|
||||
interface NavMenuData {
|
||||
id: string;
|
||||
label: string;
|
||||
icon?: any;
|
||||
path: string;
|
||||
}
|
||||
|
||||
interface SideMenuItems {
|
||||
interface NavMenuItems {
|
||||
label?: string;
|
||||
items: SideMenuData[];
|
||||
items: NavMenuData[];
|
||||
}
|
||||
|
||||
export interface SideMenuProps {
|
||||
items: SideMenuItems[];
|
||||
export interface NavMenuProps {
|
||||
items: NavMenuItems[];
|
||||
title?: string;
|
||||
selectedKey?: string;
|
||||
allowMinimize?: boolean;
|
||||
onItemClick?: () => void;
|
||||
}
|
||||
|
||||
export function SideMenu({
|
||||
export function NavMenu({
|
||||
items = [],
|
||||
title,
|
||||
selectedKey,
|
||||
allowMinimize,
|
||||
onItemClick,
|
||||
...props
|
||||
}: SideMenuProps) {
|
||||
const renderItems = (items: SideMenuData[]) => {
|
||||
}: NavMenuProps) {
|
||||
const renderItems = (items: NavMenuData[]) => {
|
||||
return items?.map(({ id, label, icon, path }) => {
|
||||
const isSelected = selectedKey === id;
|
||||
|
||||
return (
|
||||
<Link key={id} href={path}>
|
||||
<Row padding borderRadius hover={{ backgroundColor: 'surface-raised' }}>
|
||||
<Link key={id} href={path} onClick={onItemClick}>
|
||||
<Row
|
||||
padding
|
||||
borderRadius
|
||||
hover={{ backgroundColor: 'surface-sunken' }}
|
||||
backgroundColor={isSelected ? 'surface-sunken' : undefined}
|
||||
>
|
||||
<IconLabel icon={icon}>
|
||||
<Text weight={isSelected ? 'bold' : 'normal'}>{label}</Text>
|
||||
</IconLabel>
|
||||
|
|
@ -45,13 +52,7 @@ export function SideMenu({
|
|||
};
|
||||
|
||||
return (
|
||||
<Column
|
||||
gap
|
||||
overflowY="auto"
|
||||
justifyContent="space-between"
|
||||
position="sticky"
|
||||
backgroundColor="surface-base"
|
||||
>
|
||||
<Column gap overflowY="auto" justifyContent="space-between" position="sticky">
|
||||
{title && (
|
||||
<Row padding>
|
||||
<Heading size="sm">{title}</Heading>
|
||||
|
|
@ -61,13 +62,10 @@ export function SideMenu({
|
|||
{items?.map(({ label, items }, index) => {
|
||||
if (label) {
|
||||
return (
|
||||
<Column
|
||||
title={label}
|
||||
key={`${label}${index}`}
|
||||
gap="1"
|
||||
marginBottom="3"
|
||||
minHeight="40px"
|
||||
>
|
||||
<Column key={`${label}${index}`} gap="1" marginBottom="3" minHeight="40px">
|
||||
<Row padding>
|
||||
<Text weight="bold">{label}</Text>
|
||||
</Row>
|
||||
{renderItems(items)}
|
||||
</Column>
|
||||
);
|
||||
|
|
@ -34,7 +34,7 @@ export function PageBody({
|
|||
minHeight="100vh"
|
||||
paddingBottom="6"
|
||||
maxWidth={maxWidth}
|
||||
paddingX={{ xs: '3', md: '6' }}
|
||||
paddingX={{ base: '3', md: '6' }}
|
||||
style={{ margin: '0 auto' }}
|
||||
>
|
||||
{children}
|
||||
|
|
|
|||
|
|
@ -2,8 +2,8 @@ import { useBreakpoint } from '@umami/react-zen';
|
|||
|
||||
export function useMobile() {
|
||||
const breakpoint = useBreakpoint();
|
||||
const isMobile = ['xs', 'sm', 'md'].includes(breakpoint);
|
||||
const isPhone = ['xs', 'sm'].includes(breakpoint);
|
||||
const isMobile = ['base', 'sm', 'md'].includes(breakpoint);
|
||||
const isPhone = ['base', 'sm'].includes(breakpoint);
|
||||
|
||||
return { breakpoint, isMobile, isPhone };
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { Button, Icon, Tooltip, TooltipTrigger } from '@umami/react-zen';
|
||||
import { Button, Icon, Text, Tooltip, TooltipTrigger } from '@umami/react-zen';
|
||||
import Papa from 'papaparse';
|
||||
import { useMessages } from '@/components/hooks';
|
||||
import { Download } from '@/components/icons';
|
||||
|
|
@ -24,7 +24,9 @@ export function DownloadButton({
|
|||
<Download />
|
||||
</Icon>
|
||||
</Button>
|
||||
<Tooltip>{formatMessage(labels.download)}</Tooltip>
|
||||
<Tooltip>
|
||||
<Text size="sm">{formatMessage(labels.download)}</Text>
|
||||
</Tooltip>
|
||||
</TooltipTrigger>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -69,8 +69,8 @@ export function FieldFilters({ websiteId, value, exclude = [], onChange }: Field
|
|||
};
|
||||
|
||||
return (
|
||||
<Grid columns={{ xs: '1fr', md: '180px 1fr' }} overflow="hidden" gapY="6">
|
||||
<Row display={{ xs: 'flex', md: 'none' }}>
|
||||
<Grid columns={{ base: '1fr', md: '180px 1fr' }} overflow="hidden" gapY="6">
|
||||
<Row display={{ base: 'flex', md: 'none' }}>
|
||||
<MenuTrigger>
|
||||
<Button>
|
||||
<Icon>
|
||||
|
|
@ -101,7 +101,12 @@ export function FieldFilters({ websiteId, value, exclude = [], onChange }: Field
|
|||
</Popover>
|
||||
</MenuTrigger>
|
||||
</Row>
|
||||
<Column display={{ xs: 'none', md: 'flex' }} border="right" paddingRight="3" marginRight="6">
|
||||
<Column
|
||||
display={{ base: 'none', md: 'flex' }}
|
||||
border="right"
|
||||
paddingRight="3"
|
||||
marginRight="6"
|
||||
>
|
||||
<List onAction={handleAdd}>
|
||||
{groupLabels.map(({ key: groupKey, label }) => {
|
||||
const groupFields = groupedFields[groupKey];
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import { Grid, Icon, Row, Text } from '@umami/react-zen';
|
||||
import { Grid, Row } from '@umami/react-zen';
|
||||
import { useEffect, useMemo } from 'react';
|
||||
import { IconLabel } from '@/components/common/IconLabel';
|
||||
import { LinkButton } from '@/components/common/LinkButton';
|
||||
import { LoadingPanel } from '@/components/common/LoadingPanel';
|
||||
import { useMessages, useNavigation, useWebsiteMetricsQuery } from '@/components/hooks';
|
||||
|
|
@ -82,10 +83,7 @@ export function MetricsTable({
|
|||
{showMore && limit && (
|
||||
<Row justifyContent="center" alignItems="flex-end">
|
||||
<LinkButton href={updateParams({ view: type })} variant="quiet">
|
||||
<Icon size="sm">
|
||||
<Maximize />
|
||||
</Icon>
|
||||
<Text>{formatMessage(labels.more)}</Text>
|
||||
<IconLabel icon={<Maximize />}>{formatMessage(labels.more)}</IconLabel>
|
||||
</LinkButton>
|
||||
</Row>
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -95,9 +95,9 @@ export function WeeklyTraffic({ websiteId }: { websiteId: string }) {
|
|||
/>
|
||||
</Row>
|
||||
</Focusable>
|
||||
<Tooltip placement="right">{`${formatMessage(
|
||||
labels.visitors,
|
||||
)}: ${count}`}</Tooltip>
|
||||
<Tooltip placement="right">
|
||||
<Text size="sm">{`${formatMessage(labels.visitors)}: ${count}`}</Text>
|
||||
</Tooltip>
|
||||
</TooltipTrigger>
|
||||
);
|
||||
})}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { Column, type ColumnProps, FloatingTooltip, useTheme } from '@umami/react-zen';
|
||||
import { Box, Column, type ColumnProps, FloatingTooltip, Text, useTheme } from '@umami/react-zen';
|
||||
import { colord } from 'colord';
|
||||
import { useMemo, useState } from 'react';
|
||||
import { ComposableMap, Geographies, Geography, ZoomableGroup } from 'react-simple-maps';
|
||||
|
|
@ -99,7 +99,13 @@ export function WorldMap({ websiteId, data, ...props }: WorldMapProps) {
|
|||
</Geographies>
|
||||
</ZoomableGroup>
|
||||
</ComposableMap>
|
||||
{tooltip && <FloatingTooltip>{tooltip}</FloatingTooltip>}
|
||||
{tooltip && (
|
||||
<FloatingTooltip>
|
||||
<Box backgroundColor="surface-inverted" color="inverted" padding borderRadius="md">
|
||||
<Text size="sm">{tooltip}</Text>
|
||||
</Box>
|
||||
</FloatingTooltip>
|
||||
)}
|
||||
</Column>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue