Refactored icons.

This commit is contained in:
Mike Cao 2025-05-27 00:50:28 -07:00
parent 18eceee4c4
commit 99330a1a4d
86 changed files with 310 additions and 273 deletions

View file

@ -2,10 +2,9 @@ import { ThemeButton, Row, Button, Icon } from '@umami/react-zen';
import { LanguageButton } from '@/components/input/LanguageButton'; import { LanguageButton } from '@/components/input/LanguageButton';
import { ProfileButton } from '@/components/input/ProfileButton'; import { ProfileButton } from '@/components/input/ProfileButton';
import { TeamsButton } from '@/components/input/TeamsButton'; import { TeamsButton } from '@/components/input/TeamsButton';
import useGlobalState from '@/components/hooks/useGlobalState';
import { Lucide } from '@/components/icons';
import { WebsiteSelect } from '@/components/input/WebsiteSelect'; import { WebsiteSelect } from '@/components/input/WebsiteSelect';
import { useNavigation } from '@/components/hooks'; import { PanelLeft, Slash } from '@/components/icons';
import { useNavigation, useGlobalState } from '@/components/hooks';
export function MenuBar() { export function MenuBar() {
const [isCollapsed, setCollapsed] = useGlobalState('sidenav-collapsed'); const [isCollapsed, setCollapsed] = useGlobalState('sidenav-collapsed');
@ -26,7 +25,7 @@ export function MenuBar() {
<Row alignItems="center"> <Row alignItems="center">
<Button onPress={() => setCollapsed(!isCollapsed)} variant="quiet"> <Button onPress={() => setCollapsed(!isCollapsed)} variant="quiet">
<Icon> <Icon>
<Lucide.PanelLeft /> <PanelLeft />
</Icon> </Icon>
</Button> </Button>
<Row alignItems="center" gap="1"> <Row alignItems="center" gap="1">
@ -34,7 +33,7 @@ export function MenuBar() {
{websiteId && ( {websiteId && (
<> <>
<Icon strokeColor="7" rotate={-25}> <Icon strokeColor="7" rotate={-25}>
<Lucide.Slash /> <Slash />
</Icon> </Icon>
<WebsiteSelect variant="quiet" websiteId={websiteId} onSelect={handleSelect} /> <WebsiteSelect variant="quiet" websiteId={websiteId} onSelect={handleSelect} />
</> </>

View file

@ -1,6 +1,14 @@
import Link from 'next/link'; import Link from 'next/link';
import { Sidebar, SidebarHeader, SidebarSection, SidebarItem } from '@umami/react-zen'; import { Sidebar, SidebarHeader, SidebarSection, SidebarItem } from '@umami/react-zen';
import { Lucide, Icons } from '@/components/icons'; import {
Copy,
Globe,
LayoutDashboard,
Link as LinkIcon,
Logo,
Grid2X2,
Settings,
} from '@/components/icons';
import { useMessages, useNavigation } from '@/components/hooks'; import { useMessages, useNavigation } from '@/components/hooks';
import useGlobalState from '@/components/hooks/useGlobalState'; import useGlobalState from '@/components/hooks/useGlobalState';
@ -13,39 +21,39 @@ export function SideNav(props: any) {
{ {
label: formatMessage(labels.dashboard), label: formatMessage(labels.dashboard),
href: renderTeamUrl('/dashboard'), href: renderTeamUrl('/dashboard'),
icon: <Lucide.Copy />, icon: <Copy />,
}, },
{ {
label: formatMessage(labels.websites), label: formatMessage(labels.websites),
href: renderTeamUrl('/websites'), href: renderTeamUrl('/websites'),
icon: <Lucide.Globe />, icon: <Globe />,
}, },
{ {
label: formatMessage(labels.boards), label: formatMessage(labels.boards),
href: renderTeamUrl('/boards'), href: renderTeamUrl('/boards'),
icon: <Lucide.LayoutDashboard />, icon: <LayoutDashboard />,
}, },
{ {
label: formatMessage(labels.links), label: formatMessage(labels.links),
href: renderTeamUrl('/links'), href: renderTeamUrl('/links'),
icon: <Lucide.Link />, icon: <LinkIcon />,
}, },
{ {
label: formatMessage(labels.pixels), label: formatMessage(labels.pixels),
href: renderTeamUrl('/pixels'), href: renderTeamUrl('/pixels'),
icon: <Lucide.Grid2X2 />, icon: <Grid2X2 />,
}, },
{ {
label: formatMessage(labels.settings), label: formatMessage(labels.settings),
href: renderTeamUrl('/settings'), href: renderTeamUrl('/settings'),
icon: <Lucide.Settings />, icon: <Settings />,
}, },
].filter(n => n); ].filter(n => n);
return ( return (
<Sidebar {...props} isCollapsed={isCollapsed} variant="0" showBorder={true}> <Sidebar {...props} isCollapsed={isCollapsed} variant="0" showBorder={true}>
<SidebarSection> <SidebarSection>
<SidebarHeader label="umami" icon={<Icons.Logo />} /> <SidebarHeader label="umami" icon={<Logo />} />
</SidebarSection> </SidebarSection>
<SidebarSection> <SidebarSection>
{links.map(({ href, label, icon }) => { {links.map(({ href, label, icon }) => {

View file

@ -1,14 +1,6 @@
import { useMessages, useModified, useNavigation } from '@/components/hooks'; import { useMessages, useModified, useNavigation } from '@/components/hooks';
import { import { Button, Icon, Modal, Dialog, DialogTrigger, Text, useToast } from '@umami/react-zen';
Button, import { Plus } from '@/components/icons';
Icon,
Icons,
Modal,
Dialog,
DialogTrigger,
Text,
useToast,
} from '@umami/react-zen';
import { BoardAddForm } from './BoardAddForm'; import { BoardAddForm } from './BoardAddForm';
export function BoardAddButton() { export function BoardAddButton() {
@ -26,7 +18,7 @@ export function BoardAddButton() {
<DialogTrigger> <DialogTrigger>
<Button data-test="button-website-add" variant="primary"> <Button data-test="button-website-add" variant="primary">
<Icon> <Icon>
<Icons.Plus /> <Plus />
</Icon> </Icon>
<Text>{formatMessage(labels.addBoard)}</Text> <Text>{formatMessage(labels.addBoard)}</Text>
</Button> </Button>

View file

@ -1,5 +1,5 @@
'use client'; 'use client';
import { Icon, Icons, Loading, Text } from '@umami/react-zen'; import { Icon, Loading, Text } from '@umami/react-zen';
import { SectionHeader } from '@/components/common/SectionHeader'; import { SectionHeader } from '@/components/common/SectionHeader';
import { Pager } from '@/components/common/Pager'; import { Pager } from '@/components/common/Pager';
import { WebsiteChartList } from '../websites/[websiteId]/WebsiteChartList'; import { WebsiteChartList } from '../websites/[websiteId]/WebsiteChartList';
@ -7,6 +7,7 @@ import { DashboardSettingsButton } from '@/app/(main)/dashboard/DashboardSetting
import { DashboardEdit } from '@/app/(main)/dashboard/DashboardEdit'; import { DashboardEdit } from '@/app/(main)/dashboard/DashboardEdit';
import { EmptyPlaceholder } from '@/components/common/EmptyPlaceholder'; import { EmptyPlaceholder } from '@/components/common/EmptyPlaceholder';
import { useMessages, useNavigation, useWebsites } from '@/components/hooks'; import { useMessages, useNavigation, useWebsites } from '@/components/hooks';
import { Arrow } from '@/components/icons';
import { useDashboard } from '@/store/dashboard'; import { useDashboard } from '@/store/dashboard';
import { LinkButton } from '@/components/common/LinkButton'; import { LinkButton } from '@/components/common/LinkButton';
@ -37,7 +38,7 @@ export function DashboardPage() {
<EmptyPlaceholder message={formatMessage(messages.noWebsitesConfigured)}> <EmptyPlaceholder message={formatMessage(messages.noWebsitesConfigured)}>
<LinkButton href={renderTeamUrl('/settings')}> <LinkButton href={renderTeamUrl('/settings')}>
<Icon> <Icon>
<Icons.Arrow /> <Arrow />
</Icon> </Icon>
<Text>{formatMessage(messages.goToSettings)}</Text> <Text>{formatMessage(messages.goToSettings)}</Text>
</LinkButton> </LinkButton>

View file

@ -1,5 +1,5 @@
import { Row, TooltipTrigger, Tooltip, Icon, Text, Button } from '@umami/react-zen'; import { Row, TooltipTrigger, Tooltip, Icon, Text, Button } from '@umami/react-zen';
import { Icons } from '@/components/icons'; import { BarChart, Edit } from '@/components/icons';
import { saveDashboard } from '@/store/dashboard'; import { saveDashboard } from '@/store/dashboard';
import { useMessages } from '@/components/hooks'; import { useMessages } from '@/components/hooks';
@ -19,14 +19,14 @@ export function DashboardSettingsButton() {
<TooltipTrigger> <TooltipTrigger>
<Button onPress={handleToggleCharts}> <Button onPress={handleToggleCharts}>
<Icon> <Icon>
<Icons.BarChart /> <BarChart />
</Icon> </Icon>
</Button> </Button>
<Tooltip placement="bottom">{formatMessage(labels.toggleCharts)}</Tooltip> <Tooltip placement="bottom">{formatMessage(labels.toggleCharts)}</Tooltip>
</TooltipTrigger> </TooltipTrigger>
<Button onPress={handleEdit}> <Button onPress={handleEdit}>
<Icon> <Icon>
<Icons.Edit /> <Edit />
</Icon> </Icon>
<Text>{formatMessage(labels.edit)}</Text> <Text>{formatMessage(labels.edit)}</Text>
</Button> </Button>

View file

@ -1,5 +1,6 @@
import { Button, Icon, Icons, Modal, DialogTrigger, Dialog, Text } from '@umami/react-zen'; import { Button, Icon, Modal, DialogTrigger, Dialog, Text } from '@umami/react-zen';
import { useApi, useMessages, useModified } from '@/components/hooks'; import { useApi, useMessages, useModified } from '@/components/hooks';
import { Trash } from '@/components/icons';
import { ConfirmationForm } from '@/components/common/ConfirmationForm'; import { ConfirmationForm } from '@/components/common/ConfirmationForm';
export function ReportDeleteButton({ export function ReportDeleteButton({
@ -32,7 +33,7 @@ export function ReportDeleteButton({
<DialogTrigger> <DialogTrigger>
<Button> <Button>
<Icon> <Icon>
<Icons.Trash /> <Trash />
</Icon> </Icon>
<Text>{formatMessage(labels.delete)}</Text> <Text>{formatMessage(labels.delete)}</Text>
</Button> </Button>

View file

@ -1,6 +1,7 @@
import { SectionHeader } from '@/components/common/SectionHeader'; import { SectionHeader } from '@/components/common/SectionHeader';
import { Icon, Icons, Text } from '@umami/react-zen'; import { Icon, Text } from '@umami/react-zen';
import { useLoginQuery, useMessages, useNavigation } from '@/components/hooks'; import { useLoginQuery, useMessages, useNavigation } from '@/components/hooks';
import { Plus } from '@/components/icons';
import { LinkButton } from '@/components/common/LinkButton'; import { LinkButton } from '@/components/common/LinkButton';
import { ROLES } from '@/lib/constants'; import { ROLES } from '@/lib/constants';
@ -15,7 +16,7 @@ export function ReportsHeader() {
{canEdit && ( {canEdit && (
<LinkButton href={renderTeamUrl('/reports/create')} variant="primary"> <LinkButton href={renderTeamUrl('/reports/create')} variant="primary">
<Icon> <Icon>
<Icons.Plus /> <Plus />
</Icon> </Icon>
<Text>{formatMessage(labels.createReport)}</Text> <Text>{formatMessage(labels.createReport)}</Text>
</LinkButton> </LinkButton>

View file

@ -1,7 +1,8 @@
import { Icon, Icons, Text, DataTable, DataColumn, Row } from '@umami/react-zen'; import { Icon, Text, DataTable, DataColumn, Row } from '@umami/react-zen';
import { LinkButton } from '@/components/common/LinkButton'; import { LinkButton } from '@/components/common/LinkButton';
import { useMessages, useLoginQuery, useNavigation } from '@/components/hooks'; import { useMessages, useLoginQuery, useNavigation } from '@/components/hooks';
import { REPORT_TYPES } from '@/lib/constants'; import { REPORT_TYPES } from '@/lib/constants';
import { Arrow } from '@/components/icons';
import { ReportDeleteButton } from './ReportDeleteButton'; import { ReportDeleteButton } from './ReportDeleteButton';
export function ReportsTable({ data = [] }: { data: any[]; showDomain?: boolean }) { export function ReportsTable({ data = [] }: { data: any[]; showDomain?: boolean }) {
@ -30,7 +31,7 @@ export function ReportsTable({ data = [] }: { data: any[]; showDomain?: boolean
)} )}
<LinkButton href={renderTeamUrl(`/reports/${id}`)}> <LinkButton href={renderTeamUrl(`/reports/${id}`)}>
<Icon> <Icon>
<Icons.Arrow /> <Arrow />
</Icon> </Icon>
<Text>{formatMessage(labels.view)}</Text> <Text>{formatMessage(labels.view)}</Text>
</LinkButton> </LinkButton>

View file

@ -8,7 +8,6 @@ import {
Row, Row,
Select, Select,
Icon, Icon,
Icons,
Loading, Loading,
Menu, Menu,
MenuItem, MenuItem,
@ -18,6 +17,7 @@ import {
TextField, TextField,
Label, Label,
} from '@umami/react-zen'; } from '@umami/react-zen';
import { Close } from '@/components/icons';
import styles from './FieldFilterEditForm.module.css'; import styles from './FieldFilterEditForm.module.css';
export interface FieldFilterFormProps { export interface FieldFilterFormProps {
@ -152,7 +152,7 @@ export function FieldFilterEditForm({
<div className={styles.selected} onClick={handleReset}> <div className={styles.selected} onClick={handleReset}>
<Text>{formatValue(selected, name)}</Text> <Text>{formatValue(selected, name)}</Text>
<Icon> <Icon>
<Icons.Close /> <Close />
</Icon> </Icon>
</div> </div>
)} )}

View file

@ -1,5 +1,5 @@
import { useFields, useMessages, useReport } from '@/components/hooks'; import { useFields, useMessages, useReport } from '@/components/hooks';
import { Icons } from '@/components/icons'; import { Plus } from '@/components/icons';
import { Button, Row, Label, Icon, Popover, MenuTrigger, Column } from '@umami/react-zen'; import { Button, Row, Label, Icon, Popover, MenuTrigger, Column } from '@umami/react-zen';
import { FieldSelectForm } from '../[reportId]/FieldSelectForm'; import { FieldSelectForm } from '../[reportId]/FieldSelectForm';
import { ParameterList } from '../[reportId]/ParameterList'; import { ParameterList } from '../[reportId]/ParameterList';
@ -29,7 +29,7 @@ export function FieldParameters() {
<MenuTrigger> <MenuTrigger>
<Button variant="quiet"> <Button variant="quiet">
<Icon size="sm"> <Icon size="sm">
<Icons.Plus /> <Plus />
</Icon> </Icon>
</Button> </Button>
<Popover placement="right top"> <Popover placement="right top">

View file

@ -1,5 +1,5 @@
import { useMessages, useFormat, useFilters, useFields, useReport } from '@/components/hooks'; import { useMessages, useFormat, useFilters, useFields, useReport } from '@/components/hooks';
import { Icons } from '@/components/icons'; import { Plus } from '@/components/icons';
import { import {
Button, Button,
Row, Row,
@ -55,7 +55,7 @@ export function FilterParameters() {
<MenuTrigger> <MenuTrigger>
<Button variant="quiet"> <Button variant="quiet">
<Icon size="sm"> <Icon size="sm">
<Icons.Plus /> <Plus />
</Icon> </Icon>
</Button> </Button>
<Popover placement="right top"> <Popover placement="right top">

View file

@ -1,6 +1,6 @@
import { ReactNode } from 'react'; import { ReactNode } from 'react';
import { Icon, Row, Text, Button, Column } from '@umami/react-zen'; import { Icon, Row, Text, Button, Column } from '@umami/react-zen';
import { Icons } from '@/components/icons'; import { Close } from '@/components/icons';
import { Empty } from '@/components/common/Empty'; import { Empty } from '@/components/common/Empty';
import { useMessages } from '@/components/hooks'; import { useMessages } from '@/components/hooks';
@ -46,7 +46,7 @@ const Item = ({
<Text>{children}</Text> <Text>{children}</Text>
<Button onPress={onRemove} variant="quiet"> <Button onPress={onRemove} variant="quiet">
<Icon> <Icon>
<Icons.Close /> <Close />
</Icon> </Icon>
</Button> </Button>
</Row> </Row>

View file

@ -1,6 +1,6 @@
import { useState } from 'react'; import { useState } from 'react';
import { Button, Column, Icon, Row } from '@umami/react-zen'; import { Button, Column, Icon, Row } from '@umami/react-zen';
import { Icons } from '@/components/icons'; import { PanelLeft } from '@/components/icons';
import { useReport } from '@/components/hooks'; import { useReport } from '@/components/hooks';
export function ReportMenu({ children }) { export function ReportMenu({ children }) {
@ -16,7 +16,7 @@ export function ReportMenu({ children }) {
<Row alignItems="center" justifyContent="flex-end"> <Row alignItems="center" justifyContent="flex-end">
<Button variant="quiet" onPress={() => setCollapsed(!collapsed)}> <Button variant="quiet" onPress={() => setCollapsed(!collapsed)}>
<Icon> <Icon>
<Icons.PanelLeft /> <PanelLeft />
</Icon> </Icon>
</Button> </Button>
</Row> </Row>

View file

@ -1,5 +1,5 @@
import { useMessages } from '@/components/hooks'; import { useMessages } from '@/components/hooks';
import { Icons } from '@/components/icons'; import { Eye, Bolt, Plus } from '@/components/icons';
import { useContext, useState } from 'react'; import { useContext, useState } from 'react';
import { import {
Button, Button,
@ -82,7 +82,7 @@ export function AttributionParameters() {
<DialogTrigger> <DialogTrigger>
<Button isDisabled={steps.length > 0}> <Button isDisabled={steps.length > 0}>
<Icon> <Icon>
<Icons.Plus /> <Plus />
</Icon> </Icon>
</Button> </Button>
<Popover placement="right top"> <Popover placement="right top">
@ -122,7 +122,7 @@ export function AttributionParameters() {
return ( return (
<DialogTrigger key={index}> <DialogTrigger key={index}>
<ParameterList.Item <ParameterList.Item
icon={step.type === 'url' ? <Icons.Eye /> : <Icons.Bolt />} icon={step.type === 'url' ? <Eye /> : <Bolt />}
onRemove={() => handleRemoveStep(index)} onRemove={() => handleRemoveStep(index)}
> >
<div>{step.value}</div> <div>{step.value}</div>

View file

@ -1,4 +1,4 @@
import { Icons } from '@/components/icons'; import { Network } from '@/components/icons';
import { REPORT_TYPES } from '@/lib/constants'; import { REPORT_TYPES } from '@/lib/constants';
import { Report } from '../[reportId]/Report'; import { Report } from '../[reportId]/Report';
import { ReportBody } from '../[reportId]/ReportBody'; import { ReportBody } from '../[reportId]/ReportBody';
@ -15,7 +15,7 @@ const defaultParameters = {
export default function AttributionReport({ reportId }: { reportId?: string }) { export default function AttributionReport({ reportId }: { reportId?: string }) {
return ( return (
<Report reportId={reportId} defaultParameters={defaultParameters}> <Report reportId={reportId} defaultParameters={defaultParameters}>
<ReportHeader icon={<Icons.Network />} /> <ReportHeader icon={<Network />} />
<ReportMenu> <ReportMenu>
<AttributionParameters /> <AttributionParameters />
</ReportMenu> </ReportMenu>

View file

@ -1,6 +1,16 @@
import { Icon, Text, Row, Column, Grid } from '@umami/react-zen'; import { Icon, Text, Row, Column, Grid } from '@umami/react-zen';
import { useMessages, useNavigation } from '@/components/hooks'; import { useMessages, useNavigation } from '@/components/hooks';
import { Icons } from '@/components/icons'; import {
Lightbulb,
Funnel,
Magnet,
Tag,
Target,
Path,
Money,
Network,
Plus,
} from '@/components/icons';
import { SectionHeader } from '@/components/common/SectionHeader'; import { SectionHeader } from '@/components/common/SectionHeader';
import { LinkButton } from '@/components/common/LinkButton'; import { LinkButton } from '@/components/common/LinkButton';
@ -13,49 +23,49 @@ export function ReportTemplates({ showHeader = true }: { showHeader?: boolean })
title: formatMessage(labels.insights), title: formatMessage(labels.insights),
description: formatMessage(labels.insightsDescription), description: formatMessage(labels.insightsDescription),
url: renderTeamUrl('/reports/insights'), url: renderTeamUrl('/reports/insights'),
icon: <Icons.Lightbulb />, icon: <Lightbulb />,
}, },
{ {
title: formatMessage(labels.funnel), title: formatMessage(labels.funnel),
description: formatMessage(labels.funnelDescription), description: formatMessage(labels.funnelDescription),
url: renderTeamUrl('/reports/funnel'), url: renderTeamUrl('/reports/funnel'),
icon: <Icons.Funnel />, icon: <Funnel />,
}, },
{ {
title: formatMessage(labels.retention), title: formatMessage(labels.retention),
description: formatMessage(labels.retentionDescription), description: formatMessage(labels.retentionDescription),
url: renderTeamUrl('/reports/retention'), url: renderTeamUrl('/reports/retention'),
icon: <Icons.Magnet />, icon: <Magnet />,
}, },
{ {
title: formatMessage(labels.utm), title: formatMessage(labels.utm),
description: formatMessage(labels.utmDescription), description: formatMessage(labels.utmDescription),
url: renderTeamUrl('/reports/utm'), url: renderTeamUrl('/reports/utm'),
icon: <Icons.Tag />, icon: <Tag />,
}, },
{ {
title: formatMessage(labels.goals), title: formatMessage(labels.goals),
description: formatMessage(labels.goalsDescription), description: formatMessage(labels.goalsDescription),
url: renderTeamUrl('/reports/goals'), url: renderTeamUrl('/reports/goals'),
icon: <Icons.Target />, icon: <Target />,
}, },
{ {
title: formatMessage(labels.journey), title: formatMessage(labels.journey),
description: formatMessage(labels.journeyDescription), description: formatMessage(labels.journeyDescription),
url: renderTeamUrl('/reports/journey'), url: renderTeamUrl('/reports/journey'),
icon: <Icons.Path />, icon: <Path />,
}, },
{ {
title: formatMessage(labels.revenue), title: formatMessage(labels.revenue),
description: formatMessage(labels.revenueDescription), description: formatMessage(labels.revenueDescription),
url: renderTeamUrl('/reports/revenue'), url: renderTeamUrl('/reports/revenue'),
icon: <Icons.Money />, icon: <Money />,
}, },
{ {
title: formatMessage(labels.attribution), title: formatMessage(labels.attribution),
description: formatMessage(labels.attributionDescription), description: formatMessage(labels.attributionDescription),
url: renderTeamUrl('/reports/attribution'), url: renderTeamUrl('/reports/attribution'),
icon: <Icons.Network />, icon: <Network />,
}, },
]; ];
@ -87,8 +97,8 @@ function ReportItem({ title, description, url, icon }) {
<Text>{description}</Text> <Text>{description}</Text>
<Row justifyContent="flex-end"> <Row justifyContent="flex-end">
<LinkButton href={url} variant="primary"> <LinkButton href={url} variant="primary">
<Icon fillColor="currentColor"> <Icon>
<Icons.Plus /> <Plus />
</Icon> </Icon>
<Text>{formatMessage(labels.create)}</Text> <Text>{formatMessage(labels.create)}</Text>
</LinkButton> </LinkButton>

View file

@ -8,7 +8,7 @@ import {
Popover, Popover,
} from '@umami/react-zen'; } from '@umami/react-zen';
import { Empty } from '@/components/common/Empty'; import { Empty } from '@/components/common/Empty';
import { Icons } from '@/components/icons'; import { Plus } from '@/components/icons';
import { useApi, useMessages, useReport } from '@/components/hooks'; import { useApi, useMessages, useReport } from '@/components/hooks';
import { DATA_TYPES, REPORT_PARAMETERS } from '@/lib/constants'; import { DATA_TYPES, REPORT_PARAMETERS } from '@/lib/constants';
import { FieldAddForm } from '../[reportId]/FieldAddForm'; import { FieldAddForm } from '../[reportId]/FieldAddForm';
@ -75,7 +75,7 @@ export function EventDataParameters() {
return ( return (
<DialogTrigger> <DialogTrigger>
<Icon> <Icon>
<Icons.Plus /> <Plus />
</Icon> </Icon>
<Popover placement="bottom start"> <Popover placement="bottom start">
{({ close }: any) => { {({ close }: any) => {

View file

@ -4,7 +4,7 @@ import { ReportMenu } from '../[reportId]/ReportMenu';
import { ReportBody } from '../[reportId]/ReportBody'; import { ReportBody } from '../[reportId]/ReportBody';
import { EventDataParameters } from './EventDataParameters'; import { EventDataParameters } from './EventDataParameters';
import { EventDataTable } from './EventDataTable'; import { EventDataTable } from './EventDataTable';
import { Icons } from '@/components/icons'; import { Nodes } from '@/components/icons';
const defaultParameters = { const defaultParameters = {
type: 'event-data', type: 'event-data',
@ -14,7 +14,7 @@ const defaultParameters = {
export function EventDataReport({ reportId }: { reportId?: string }) { export function EventDataReport({ reportId }: { reportId?: string }) {
return ( return (
<Report reportId={reportId} defaultParameters={defaultParameters}> <Report reportId={reportId} defaultParameters={defaultParameters}>
<ReportHeader icon={<Icons.Nodes />} /> <ReportHeader icon={<Nodes />} />
<ReportMenu> <ReportMenu>
<EventDataParameters /> <EventDataParameters />
</ReportMenu> </ReportMenu>

View file

@ -10,7 +10,7 @@ import {
TextField, TextField,
Button, Button,
} from '@umami/react-zen'; } from '@umami/react-zen';
import { Icons } from '@/components/icons'; import { Eye, Bolt, Plus } from '@/components/icons';
import { FunnelStepAddForm } from './FunnelStepAddForm'; import { FunnelStepAddForm } from './FunnelStepAddForm';
import { BaseParameters } from '../[reportId]/BaseParameters'; import { BaseParameters } from '../[reportId]/BaseParameters';
import { ParameterList } from '../[reportId]/ParameterList'; import { ParameterList } from '../[reportId]/ParameterList';
@ -59,7 +59,7 @@ export function FunnelParameters() {
<DialogTrigger> <DialogTrigger>
<Button> <Button>
<Icon> <Icon>
<Icons.Plus /> <Plus />
</Icon> </Icon>
</Button> </Button>
<Popover placement="start"> <Popover placement="start">
@ -85,7 +85,7 @@ export function FunnelParameters() {
return ( return (
<DialogTrigger key={index}> <DialogTrigger key={index}>
<ParameterList.Item <ParameterList.Item
icon={step.type === 'url' ? <Icons.Eye /> : <Icons.Bolt />} icon={step.type === 'url' ? <Eye /> : <Bolt />}
onRemove={() => handleRemoveStep(index)} onRemove={() => handleRemoveStep(index)}
> >
<div className={styles.value}> <div className={styles.value}>

View file

@ -4,7 +4,7 @@ import { Report } from '../[reportId]/Report';
import { ReportHeader } from '../[reportId]/ReportHeader'; import { ReportHeader } from '../[reportId]/ReportHeader';
import { ReportMenu } from '../[reportId]/ReportMenu'; import { ReportMenu } from '../[reportId]/ReportMenu';
import { ReportBody } from '../[reportId]/ReportBody'; import { ReportBody } from '../[reportId]/ReportBody';
import { Icons } from '@/components/icons'; import { Funnel } from '@/components/icons';
import { REPORT_TYPES } from '@/lib/constants'; import { REPORT_TYPES } from '@/lib/constants';
const defaultParameters = { const defaultParameters = {
@ -15,7 +15,7 @@ const defaultParameters = {
export function FunnelReport({ reportId }: { reportId?: string }) { export function FunnelReport({ reportId }: { reportId?: string }) {
return ( return (
<Report reportId={reportId} defaultParameters={defaultParameters}> <Report reportId={reportId} defaultParameters={defaultParameters}>
<ReportHeader icon={<Icons.Funnel />} /> <ReportHeader icon={<Funnel />} />
<ReportMenu> <ReportMenu>
<FunnelParameters /> <FunnelParameters />
</ReportMenu> </ReportMenu>

View file

@ -1,5 +1,5 @@
import { useMessages, useReport } from '@/components/hooks'; import { useMessages, useReport } from '@/components/hooks';
import { Icons } from '@/components/icons'; import { Plus, Eye, Bolt } from '@/components/icons';
import { formatNumber } from '@/lib/format'; import { formatNumber } from '@/lib/format';
import { import {
Button, Button,
@ -60,7 +60,7 @@ export function GoalsParameters() {
<MenuTrigger> <MenuTrigger>
<Button> <Button>
<Icon> <Icon>
<Icons.Plus /> <Plus />
</Icon> </Icon>
</Button> </Button>
<Popover placement="start"> <Popover placement="start">
@ -90,7 +90,7 @@ export function GoalsParameters() {
return ( return (
<MenuTrigger key={index}> <MenuTrigger key={index}>
<ParameterList.Item <ParameterList.Item
icon={goal.type === 'url' ? <Icons.Eye /> : <Icons.Bolt />} icon={goal.type === 'url' ? <Eye /> : <Bolt />}
onRemove={() => handleRemoveGoals(index)} onRemove={() => handleRemoveGoals(index)}
> >
<Column> <Column>

View file

@ -4,7 +4,7 @@ import { Report } from '../[reportId]/Report';
import { ReportHeader } from '../[reportId]/ReportHeader'; import { ReportHeader } from '../[reportId]/ReportHeader';
import { ReportMenu } from '../[reportId]/ReportMenu'; import { ReportMenu } from '../[reportId]/ReportMenu';
import { ReportBody } from '../[reportId]/ReportBody'; import { ReportBody } from '../[reportId]/ReportBody';
import { Icons } from '@/components/icons'; import { Target } from '@/components/icons';
import { REPORT_TYPES } from '@/lib/constants'; import { REPORT_TYPES } from '@/lib/constants';
const defaultParameters = { const defaultParameters = {
@ -15,7 +15,7 @@ const defaultParameters = {
export function GoalsReport({ reportId }: { reportId?: string }) { export function GoalsReport({ reportId }: { reportId?: string }) {
return ( return (
<Report reportId={reportId} defaultParameters={defaultParameters}> <Report reportId={reportId} defaultParameters={defaultParameters}>
<ReportHeader icon={<Icons.Target />} /> <ReportHeader icon={<Target />} />
<ReportMenu> <ReportMenu>
<GoalsParameters /> <GoalsParameters />
</ReportMenu> </ReportMenu>

View file

@ -4,7 +4,7 @@ import { ReportMenu } from '../[reportId]/ReportMenu';
import { ReportBody } from '../[reportId]/ReportBody'; import { ReportBody } from '../[reportId]/ReportBody';
import { InsightsParameters } from './InsightsParameters'; import { InsightsParameters } from './InsightsParameters';
import { InsightsTable } from './InsightsTable'; import { InsightsTable } from './InsightsTable';
import { Icons } from '@/components/icons'; import { Lightbulb } from '@/components/icons';
import { REPORT_TYPES } from '@/lib/constants'; import { REPORT_TYPES } from '@/lib/constants';
const defaultParameters = { const defaultParameters = {
@ -15,7 +15,7 @@ const defaultParameters = {
export function InsightsReport({ reportId }: { reportId?: string }) { export function InsightsReport({ reportId }: { reportId?: string }) {
return ( return (
<Report reportId={reportId} defaultParameters={defaultParameters}> <Report reportId={reportId} defaultParameters={defaultParameters}>
<ReportHeader icon={<Icons.Lightbulb />} /> <ReportHeader icon={<Lightbulb />} />
<ReportMenu> <ReportMenu>
<InsightsParameters /> <InsightsParameters />
</ReportMenu> </ReportMenu>

View file

@ -5,7 +5,7 @@ import { ReportMenu } from '../[reportId]/ReportMenu';
import { ReportBody } from '../[reportId]/ReportBody'; import { ReportBody } from '../[reportId]/ReportBody';
import { JourneyParameters } from './JourneyParameters'; import { JourneyParameters } from './JourneyParameters';
import { JourneyView } from './JourneyView'; import { JourneyView } from './JourneyView';
import { Icons } from '@/components/icons'; import { Path } from '@/components/icons';
import { REPORT_TYPES } from '@/lib/constants'; import { REPORT_TYPES } from '@/lib/constants';
const defaultParameters = { const defaultParameters = {
@ -16,7 +16,7 @@ const defaultParameters = {
export function JourneyReport({ reportId }: { reportId?: string }) { export function JourneyReport({ reportId }: { reportId?: string }) {
return ( return (
<Report reportId={reportId} defaultParameters={defaultParameters}> <Report reportId={reportId} defaultParameters={defaultParameters}>
<ReportHeader icon={<Icons.Path />} /> <ReportHeader icon={<Path />} />
<ReportMenu> <ReportMenu>
<JourneyParameters /> <JourneyParameters />
</ReportMenu> </ReportMenu>

View file

@ -1,6 +1,6 @@
import { Button, Icon, Text, useToast, DialogTrigger, Dialog, Modal } from '@umami/react-zen'; import { Button, Icon, Text, useToast, DialogTrigger, Dialog, Modal } from '@umami/react-zen';
import { PasswordEditForm } from './PasswordEditForm'; import { PasswordEditForm } from './PasswordEditForm';
import { Lucide } from '@/components/icons'; import { LockKeyhole } from '@/components/icons';
import { useMessages } from '@/components/hooks'; import { useMessages } from '@/components/hooks';
export function PasswordChangeButton() { export function PasswordChangeButton() {
@ -14,8 +14,8 @@ export function PasswordChangeButton() {
return ( return (
<DialogTrigger> <DialogTrigger>
<Button> <Button>
<Icon fillColor="currentColor"> <Icon>
<Lucide.LockKeyhole /> <LockKeyhole />
</Icon> </Icon>
<Text>{formatMessage(labels.changePassword)}</Text> <Text>{formatMessage(labels.changePassword)}</Text>
</Button> </Button>

View file

@ -1,5 +1,5 @@
import { Row, Button, Icon, useTheme } from '@umami/react-zen'; import { Row, Button, Icon, useTheme } from '@umami/react-zen';
import { Lucide } from '@/components/icons'; import { Sun, Moon } from '@/components/icons';
export function ThemeSetting() { export function ThemeSetting() {
const { theme, setTheme } = useTheme(); const { theme, setTheme } = useTheme();
@ -11,12 +11,12 @@ export function ThemeSetting() {
onPress={() => setTheme('light')} onPress={() => setTheme('light')}
> >
<Icon> <Icon>
<Lucide.Sun /> <Sun />
</Icon> </Icon>
</Button> </Button>
<Button variant={theme === 'dark' ? 'primary' : 'secondary'} onPress={() => setTheme('dark')}> <Button variant={theme === 'dark' ? 'primary' : 'secondary'} onPress={() => setTheme('dark')}>
<Icon> <Icon>
<Lucide.Moon /> <Moon />
</Icon> </Icon>
</Button> </Button>
</Row> </Row>

View file

@ -1,6 +1,7 @@
import { useLoginQuery, useMessages, useModified } from '@/components/hooks'; import { useLoginQuery, useMessages, useModified } from '@/components/hooks';
import { useRouter } from 'next/navigation'; import { useRouter } from 'next/navigation';
import { Button, Icon, Icons, Modal, DialogTrigger, Dialog, Text } from '@umami/react-zen'; import { Button, Icon, Modal, DialogTrigger, Dialog, Text } from '@umami/react-zen';
import { LogOut } from '@/components/icons';
import { TeamLeaveForm } from './TeamLeaveForm'; import { TeamLeaveForm } from './TeamLeaveForm';
export function TeamLeaveButton({ teamId, teamName }: { teamId: string; teamName: string }) { export function TeamLeaveButton({ teamId, teamName }: { teamId: string; teamName: string }) {
@ -18,7 +19,7 @@ export function TeamLeaveButton({ teamId, teamName }: { teamId: string; teamName
<DialogTrigger> <DialogTrigger>
<Button variant="secondary"> <Button variant="secondary">
<Icon> <Icon>
<Icons.Logout /> <LogOut />
</Icon> </Icon>
<Text>{formatMessage(labels.leave)}</Text> <Text>{formatMessage(labels.leave)}</Text>
</Button> </Button>

View file

@ -1,5 +1,5 @@
import { Button, Icon, Modal, DialogTrigger, Dialog, Text, useToast } from '@umami/react-zen'; import { Button, Icon, Modal, DialogTrigger, Dialog, Text, useToast } from '@umami/react-zen';
import { Icons } from '@/components/icons'; import { Plus } from '@/components/icons';
import { useMessages, useModified } from '@/components/hooks'; import { useMessages, useModified } from '@/components/hooks';
import { TeamAddForm } from './TeamAddForm'; import { TeamAddForm } from './TeamAddForm';
import { messages } from '@/components/messages'; import { messages } from '@/components/messages';
@ -19,7 +19,7 @@ export function TeamsAddButton({ onSave }: { onSave?: () => void }) {
<DialogTrigger> <DialogTrigger>
<Button variant="primary"> <Button variant="primary">
<Icon> <Icon>
<Icons.Plus /> <Plus />
</Icon> </Icon>
<Text>{formatMessage(labels.createTeam)}</Text> <Text>{formatMessage(labels.createTeam)}</Text>
</Button> </Button>

View file

@ -1,5 +1,5 @@
import { Button, Icon, Modal, DialogTrigger, Dialog, Text, useToast } from '@umami/react-zen'; import { Button, Icon, Modal, DialogTrigger, Dialog, Text, useToast } from '@umami/react-zen';
import { Icons } from '@/components/icons'; import { AddUser } from '@/components/icons';
import { useMessages, useModified } from '@/components/hooks'; import { useMessages, useModified } from '@/components/hooks';
import { TeamJoinForm } from './TeamJoinForm'; import { TeamJoinForm } from './TeamJoinForm';
@ -16,8 +16,8 @@ export function TeamsJoinButton() {
return ( return (
<DialogTrigger> <DialogTrigger>
<Button variant="secondary"> <Button variant="secondary">
<Icon fillColor="currentColor"> <Icon>
<Icons.AddUser /> <AddUser />
</Icon> </Icon>
<Text>{formatMessage(labels.joinTeam)}</Text> <Text>{formatMessage(labels.joinTeam)}</Text>
</Button> </Button>

View file

@ -1,6 +1,6 @@
import { DataColumn, DataTable, Icon, MenuItem, Text, Row } from '@umami/react-zen'; import { DataColumn, DataTable, Icon, MenuItem, Text, Row } from '@umami/react-zen';
import { useMessages } from '@/components/hooks'; import { useMessages } from '@/components/hooks';
import { Icons } from '@/components/icons'; import { Arrow, Edit } from '@/components/icons';
import { ROLES } from '@/lib/constants'; import { ROLES } from '@/lib/constants';
import { MenuButton } from '@/components/input/MenuButton'; import { MenuButton } from '@/components/input/MenuButton';
@ -36,7 +36,7 @@ export function TeamsTable({
<MenuItem href={`/teams/${id}`}> <MenuItem href={`/teams/${id}`}>
<Row alignItems="center" gap> <Row alignItems="center" gap>
<Icon> <Icon>
<Icons.Arrow /> <Arrow />
</Icon> </Icon>
<Text>{formatMessage(labels.view)}</Text> <Text>{formatMessage(labels.view)}</Text>
</Row> </Row>
@ -44,7 +44,7 @@ export function TeamsTable({
<MenuItem href={`/teams/${id}/settings`}> <MenuItem href={`/teams/${id}/settings`}>
<Row alignItems="center" gap> <Row alignItems="center" gap>
<Icon> <Icon>
<Icons.Edit /> <Edit />
</Icon> </Icon>
<Text>{formatMessage(labels.edit)}</Text> <Text>{formatMessage(labels.edit)}</Text>
</Row> </Row>

View file

@ -1,4 +1,5 @@
import { Button, Icon, Icons, Text } from '@umami/react-zen'; import { Button, Icon, Text } from '@umami/react-zen';
import { Close } from '@/components/icons';
import styles from './WebsiteTags.module.css'; import styles from './WebsiteTags.module.css';
export function WebsiteTags({ export function WebsiteTags({
@ -26,7 +27,7 @@ export function WebsiteTags({
<b>{`${website.name}`}</b> <b>{`${website.name}`}</b>
</Text> </Text>
<Icon> <Icon>
<Icons.Close /> <Close />
</Icon> </Icon>
</Button> </Button>
</div> </div>

View file

@ -1,15 +1,7 @@
import { import { Button, Icon, Text, Modal, DialogTrigger, Dialog, useToast } from '@umami/react-zen';
Button,
Icon,
Text,
Modal,
Icons,
DialogTrigger,
Dialog,
useToast,
} from '@umami/react-zen';
import { UserAddForm } from './UserAddForm'; import { UserAddForm } from './UserAddForm';
import { useMessages, useModified } from '@/components/hooks'; import { useMessages, useModified } from '@/components/hooks';
import { Plus } from '@/components/icons';
export function UserAddButton({ onSave }: { onSave?: () => void }) { export function UserAddButton({ onSave }: { onSave?: () => void }) {
const { formatMessage, labels, messages } = useMessages(); const { formatMessage, labels, messages } = useMessages();
@ -26,7 +18,7 @@ export function UserAddButton({ onSave }: { onSave?: () => void }) {
<DialogTrigger> <DialogTrigger>
<Button variant="primary" data-test="button-create-user"> <Button variant="primary" data-test="button-create-user">
<Icon> <Icon>
<Icons.Plus /> <Plus />
</Icon> </Icon>
<Text>{formatMessage(labels.createUser)}</Text> <Text>{formatMessage(labels.createUser)}</Text>
</Button> </Button>

View file

@ -1,5 +1,6 @@
import { Button, Icon, Icons, Modal, DialogTrigger, Dialog, Text } from '@umami/react-zen'; import { Button, Icon, Modal, DialogTrigger, Dialog, Text } from '@umami/react-zen';
import { useMessages, useLoginQuery } from '@/components/hooks'; import { useMessages, useLoginQuery } from '@/components/hooks';
import { Trash } from '@/components/icons';
import { UserDeleteForm } from './UserDeleteForm'; import { UserDeleteForm } from './UserDeleteForm';
export function UserDeleteButton({ export function UserDeleteButton({
@ -18,7 +19,7 @@ export function UserDeleteButton({
<DialogTrigger> <DialogTrigger>
<Button isDisabled={userId === user?.id} data-test="button-delete"> <Button isDisabled={userId === user?.id} data-test="button-delete">
<Icon size="sm"> <Icon size="sm">
<Icons.Trash /> <Trash />
</Icon> </Icon>
<Text>{formatMessage(labels.delete)}</Text> <Text>{formatMessage(labels.delete)}</Text>
</Button> </Button>

View file

@ -1,8 +1,8 @@
import { useState } from 'react';
import { import {
Row, Row,
Text, Text,
Icon, Icon,
Icons,
DataTable, DataTable,
DataColumn, DataColumn,
MenuItem, MenuItem,
@ -10,12 +10,13 @@ import {
Modal, Modal,
Dialog, Dialog,
} from '@umami/react-zen'; } from '@umami/react-zen';
import Link from 'next/link';
import { formatDistance } from 'date-fns'; import { formatDistance } from 'date-fns';
import { ROLES } from '@/lib/constants'; import { ROLES } from '@/lib/constants';
import { Trash } from '@/components/icons';
import { useMessages, useLocale } from '@/components/hooks'; import { useMessages, useLocale } from '@/components/hooks';
import { Edit } from '@/components/icons';
import { MenuButton } from '@/components/input/MenuButton'; import { MenuButton } from '@/components/input/MenuButton';
import Link from 'next/link';
import { useState } from 'react';
import { UserDeleteForm } from '@/app/(main)/settings/users/UserDeleteForm'; import { UserDeleteForm } from '@/app/(main)/settings/users/UserDeleteForm';
export function UsersTable({ export function UsersTable({
@ -64,7 +65,7 @@ export function UsersTable({
<MenuItem href={`/settings/users/${id}`} data-test="link-button-edit"> <MenuItem href={`/settings/users/${id}`} data-test="link-button-edit">
<Row alignItems="center" gap> <Row alignItems="center" gap>
<Icon> <Icon>
<Icons.Edit /> <Edit />
</Icon> </Icon>
<Text>{formatMessage(labels.edit)}</Text> <Text>{formatMessage(labels.edit)}</Text>
</Row> </Row>
@ -77,7 +78,7 @@ export function UsersTable({
> >
<Row alignItems="center" gap> <Row alignItems="center" gap>
<Icon> <Icon>
<Icons.Trash /> <Trash />
</Icon> </Icon>
<Text>{formatMessage(labels.delete)}</Text> <Text>{formatMessage(labels.delete)}</Text>
</Row> </Row>

View file

@ -1,6 +1,6 @@
import { useContext } from 'react'; import { useContext } from 'react';
import { Tabs, Tab, TabList, TabPanel } from '@umami/react-zen'; import { Tabs, Tab, TabList, TabPanel } from '@umami/react-zen';
import { Icons } from '@/components/icons'; import { User } from '@/components/icons';
import { UserEditForm } from './UserEditForm'; import { UserEditForm } from './UserEditForm';
import { SectionHeader } from '@/components/common/SectionHeader'; import { SectionHeader } from '@/components/common/SectionHeader';
import { useMessages } from '@/components/hooks'; import { useMessages } from '@/components/hooks';
@ -13,7 +13,7 @@ export function UserSettings({ userId }: { userId: string }) {
return ( return (
<> <>
<SectionHeader title={user?.username} icon={<Icons.User />} /> <SectionHeader title={user?.username} icon={<User />} />
<Tabs> <Tabs>
<TabList> <TabList>
<Tab id="details">{formatMessage(labels.details)}</Tab> <Tab id="details">{formatMessage(labels.details)}</Tab>

View file

@ -1,14 +1,6 @@
import { useMessages, useModified } from '@/components/hooks'; import { useMessages, useModified } from '@/components/hooks';
import { import { Button, Icon, Modal, Dialog, DialogTrigger, Text, useToast } from '@umami/react-zen';
Button, import { Plus } from '@/components/icons';
Icon,
Icons,
Modal,
Dialog,
DialogTrigger,
Text,
useToast,
} from '@umami/react-zen';
import { WebsiteAddForm } from './WebsiteAddForm'; import { WebsiteAddForm } from './WebsiteAddForm';
export function WebsiteAddButton({ teamId, onSave }: { teamId: string; onSave?: () => void }) { export function WebsiteAddButton({ teamId, onSave }: { teamId: string; onSave?: () => void }) {
@ -26,7 +18,7 @@ export function WebsiteAddButton({ teamId, onSave }: { teamId: string; onSave?:
<DialogTrigger> <DialogTrigger>
<Button data-test="button-website-add" variant="primary"> <Button data-test="button-website-add" variant="primary">
<Icon> <Icon>
<Icons.Plus /> <Plus />
</Icon> </Icon>
<Text>{formatMessage(labels.addWebsite)}</Text> <Text>{formatMessage(labels.addWebsite)}</Text>
</Button> </Button>

View file

@ -2,7 +2,7 @@ import { ReactNode } from 'react';
import { Row, Text, Icon, DataTable, DataColumn, MenuItem } from '@umami/react-zen'; import { Row, Text, Icon, DataTable, DataColumn, MenuItem } from '@umami/react-zen';
import { useMessages, useNavigation } from '@/components/hooks'; import { useMessages, useNavigation } from '@/components/hooks';
import { MenuButton } from '@/components/input/MenuButton'; import { MenuButton } from '@/components/input/MenuButton';
import { Lucide } from '@/components/icons'; import { Eye, SquarePen } from '@/components/icons';
import Link from 'next/link'; import Link from 'next/link';
export interface WebsitesTableProps { export interface WebsitesTableProps {
@ -45,7 +45,7 @@ export function WebsitesTable({
<MenuItem href={renderTeamUrl(`/websites/${websiteId}`)}> <MenuItem href={renderTeamUrl(`/websites/${websiteId}`)}>
<Row alignItems="center" gap> <Row alignItems="center" gap>
<Icon data-test="link-button-view"> <Icon data-test="link-button-view">
<Lucide.Eye /> <Eye />
</Icon> </Icon>
<Text>{formatMessage(labels.view)}</Text> <Text>{formatMessage(labels.view)}</Text>
</Row> </Row>
@ -55,7 +55,7 @@ export function WebsitesTable({
<MenuItem href={renderTeamUrl(`/settings/websites/${websiteId}`)}> <MenuItem href={renderTeamUrl(`/settings/websites/${websiteId}`)}>
<Row alignItems="center" gap> <Row alignItems="center" gap>
<Icon data-test="link-button-edit"> <Icon data-test="link-button-edit">
<Lucide.SquarePen /> <SquarePen />
</Icon> </Icon>
<Text>{formatMessage(labels.edit)}</Text> <Text>{formatMessage(labels.edit)}</Text>
</Row> </Row>

View file

@ -2,7 +2,7 @@ import { useContext } from 'react';
import { Icon, Tabs, TabList, Tab, TabPanel, Text } from '@umami/react-zen'; import { Icon, Tabs, TabList, Tab, TabPanel, Text } from '@umami/react-zen';
import { WebsiteContext } from '@/app/(main)/websites/[websiteId]/WebsiteProvider'; import { WebsiteContext } from '@/app/(main)/websites/[websiteId]/WebsiteProvider';
import { useMessages } from '@/components/hooks'; import { useMessages } from '@/components/hooks';
import { Icons } from '@/components/icons'; import { Globe, Arrow } from '@/components/icons';
import { SectionHeader } from '@/components/common/SectionHeader'; import { SectionHeader } from '@/components/common/SectionHeader';
import { ShareUrl } from './ShareUrl'; import { ShareUrl } from './ShareUrl';
import { TrackingCode } from './TrackingCode'; import { TrackingCode } from './TrackingCode';
@ -22,14 +22,14 @@ export function WebsiteSettings({
return ( return (
<> <>
<SectionHeader title={website?.name} icon={<Icons.Globe />}> <SectionHeader title={website?.name} icon={<Globe />}>
<LinkButton <LinkButton
variant="primary" variant="primary"
href={`/websites/${websiteId}`} href={`/websites/${websiteId}`}
target={openExternal ? '_blank' : null} target={openExternal ? '_blank' : null}
> >
<Icon> <Icon>
<Icons.Arrow /> <Arrow />
</Icon> </Icon>
<Text>{formatMessage(labels.view)}</Text> <Text>{formatMessage(labels.view)}</Text>
</LinkButton> </LinkButton>

View file

@ -3,7 +3,6 @@ import {
Row, Row,
Pressable, Pressable,
Icon, Icon,
Icons,
Modal, Modal,
DialogTrigger, DialogTrigger,
Dialog, Dialog,
@ -11,6 +10,7 @@ import {
useToast, useToast,
} from '@umami/react-zen'; } from '@umami/react-zen';
import { TeamMemberEditForm } from './TeamMemberEditForm'; import { TeamMemberEditForm } from './TeamMemberEditForm';
import { Edit } from '@/components/icons';
export function TeamMemberEditButton({ export function TeamMemberEditButton({
teamId, teamId,
@ -38,7 +38,7 @@ export function TeamMemberEditButton({
<Pressable> <Pressable>
<Row alignItems="center" gap> <Row alignItems="center" gap>
<Icon> <Icon>
<Icons.Edit /> <Edit />
</Icon> </Icon>
<Text>{formatMessage(labels.edit)}</Text> <Text>{formatMessage(labels.edit)}</Text>
</Row> </Row>

View file

@ -1,7 +1,8 @@
import { ConfirmationForm } from '@/components/common/ConfirmationForm'; import { ConfirmationForm } from '@/components/common/ConfirmationForm';
import { useApi, useMessages, useModified } from '@/components/hooks'; import { useApi, useMessages, useModified } from '@/components/hooks';
import { messages } from '@/components/messages'; import { messages } from '@/components/messages';
import { Button, Icon, Icons, Modal, DialogTrigger, Dialog, Text } from '@umami/react-zen'; import { Close } from '@/components/icons';
import { Button, Icon, Modal, DialogTrigger, Dialog, Text } from '@umami/react-zen';
export function TeamMemberRemoveButton({ export function TeamMemberRemoveButton({
teamId, teamId,
@ -36,7 +37,7 @@ export function TeamMemberRemoveButton({
<DialogTrigger> <DialogTrigger>
<Button> <Button>
<Icon> <Icon>
<Icons.Close /> <Close />
</Icon> </Icon>
<Text>{formatMessage(labels.remove)}</Text> <Text>{formatMessage(labels.remove)}</Text>
</Button> </Button>

View file

@ -1,5 +1,6 @@
import { useApi, useMessages } from '@/components/hooks'; import { useApi, useMessages } from '@/components/hooks';
import { Icon, Icons, LoadingButton, Text } from '@umami/react-zen'; import { Icon, LoadingButton, Text } from '@umami/react-zen';
import { Close } from '@/components/icons';
export function TeamWebsiteRemoveButton({ teamId, websiteId, onSave }) { export function TeamWebsiteRemoveButton({ teamId, websiteId, onSave }) {
const { formatMessage, labels } = useMessages(); const { formatMessage, labels } = useMessages();
@ -19,7 +20,7 @@ export function TeamWebsiteRemoveButton({ teamId, websiteId, onSave }) {
return ( return (
<LoadingButton variant="quiet" onClick={() => handleRemoveTeamMember()} isLoading={isPending}> <LoadingButton variant="quiet" onClick={() => handleRemoveTeamMember()} isLoading={isPending}>
<Icon> <Icon>
<Icons.Close /> <Close />
</Icon> </Icon>
<Text>{formatMessage(labels.remove)}</Text> <Text>{formatMessage(labels.remove)}</Text>
</LoadingButton> </LoadingButton>

View file

@ -1,6 +1,6 @@
import { DataColumn, DataTable, Icon, MenuItem, Text, Row } from '@umami/react-zen'; import { DataColumn, DataTable, Icon, MenuItem, Text, Row } from '@umami/react-zen';
import { useLoginQuery, useMessages } from '@/components/hooks'; import { useLoginQuery, useMessages } from '@/components/hooks';
import { Icons } from '@/components/icons'; import { Arrow, Edit } from '@/components/icons';
import { MenuButton } from '@/components/input/MenuButton'; import { MenuButton } from '@/components/input/MenuButton';
export function TeamWebsitesTable({ export function TeamWebsitesTable({
@ -31,7 +31,7 @@ export function TeamWebsitesTable({
<MenuItem href={`/teams/${teamId}/websites/${websiteId}`}> <MenuItem href={`/teams/${teamId}/websites/${websiteId}`}>
<Row alignItems="center" gap> <Row alignItems="center" gap>
<Icon> <Icon>
<Icons.Arrow /> <Arrow />
</Icon> </Icon>
<Text>{formatMessage(labels.view)}</Text> <Text>{formatMessage(labels.view)}</Text>
</Row> </Row>
@ -40,7 +40,7 @@ export function TeamWebsitesTable({
<MenuItem href={`/teams/${teamId}/settings/websites/${websiteId}`}> <MenuItem href={`/teams/${teamId}/settings/websites/${websiteId}`}>
<Row alignItems="center" gap> <Row alignItems="center" gap>
<Icon> <Icon>
<Icons.Edit /> <Edit />
</Icon> </Icon>
<Text>{formatMessage(labels.edit)}</Text> <Text>{formatMessage(labels.edit)}</Text>
</Row> </Row>

View file

@ -1,4 +1,4 @@
import { Text, Icon, Icons } from '@umami/react-zen'; import { Text, Icon } from '@umami/react-zen';
import { useMemo } from 'react'; import { useMemo } from 'react';
import { firstBy } from 'thenby'; import { firstBy } from 'thenby';
import { WebsiteChart } from './WebsiteChart'; import { WebsiteChart } from './WebsiteChart';
@ -7,6 +7,7 @@ import { WebsiteControls } from './WebsiteControls';
import { WebsiteMetricsBar } from './WebsiteMetricsBar'; import { WebsiteMetricsBar } from './WebsiteMetricsBar';
import { useMessages, useNavigation } from '@/components/hooks'; import { useMessages, useNavigation } from '@/components/hooks';
import { LinkButton } from '@/components/common/LinkButton'; import { LinkButton } from '@/components/common/LinkButton';
import { Arrow } from '@/components/icons';
export function WebsiteChartList({ export function WebsiteChartList({
websites, websites,
@ -30,7 +31,7 @@ export function WebsiteChartList({
return ( return (
<div> <div>
{ordered.map(({ id }, index) => { {ordered.map(({ id }: { id: string }, index) => {
return index < limit ? ( return index < limit ? (
<div key={id}> <div key={id}>
<WebsiteControls websiteId={id} showLinks={false}> <WebsiteControls websiteId={id} showLinks={false}>
@ -38,7 +39,7 @@ export function WebsiteChartList({
<Text>{formatMessage(labels.viewDetails)}</Text> <Text>{formatMessage(labels.viewDetails)}</Text>
<Icon> <Icon>
<Icon> <Icon>
<Icons.Arrow /> <Arrow />
</Icon> </Icon>
</Icon> </Icon>
</LinkButton> </LinkButton>

View file

@ -1,4 +1,4 @@
import { Icon, Icons, Text, Grid, Column } from '@umami/react-zen'; import { Icon, Text, Grid, Column } from '@umami/react-zen';
import { LinkButton } from '@/components/common/LinkButton'; import { LinkButton } from '@/components/common/LinkButton';
import { useMessages, useNavigation } from '@/components/hooks'; import { useMessages, useNavigation } from '@/components/hooks';
import { SideMenu } from '@/components/common/SideMenu'; import { SideMenu } from '@/components/common/SideMenu';
@ -18,6 +18,7 @@ import { ScreenTable } from '@/components/metrics/ScreenTable';
import { TagsTable } from '@/components/metrics/TagsTable'; import { TagsTable } from '@/components/metrics/TagsTable';
import { ChannelsTable } from '@/components/metrics/ChannelsTable'; import { ChannelsTable } from '@/components/metrics/ChannelsTable';
import { Panel } from '@/components/common/Panel'; import { Panel } from '@/components/common/Panel';
import { Arrow } from '@/components/icons';
const views = { const views = {
url: PagesTable, url: PagesTable,
@ -140,7 +141,7 @@ export function WebsiteExpandedView({
<Column gap="6" width="200px" border="right" paddingRight="3"> <Column gap="6" width="200px" border="right" paddingRight="3">
<LinkButton href={renderUrl({ view: undefined })} variant="quiet" scroll={false}> <LinkButton href={renderUrl({ view: undefined })} variant="quiet" scroll={false}>
<Icon rotate={180}> <Icon rotate={180}>
<Icons.Arrow /> <Arrow />
</Icon> </Icon>
<Text>{formatMessage(labels.back)}</Text> <Text>{formatMessage(labels.back)}</Text>
</LinkButton> </LinkButton>

View file

@ -1,5 +1,5 @@
import { Button, Icon, DialogTrigger, Dialog, Modal, Text } from '@umami/react-zen'; import { Button, Icon, DialogTrigger, Dialog, Modal, Text } from '@umami/react-zen';
import { Lucide } from '@/components/icons'; import { ListFilter } from '@/components/icons';
import { FilterEditForm } from '@/components/common/FilterEditForm'; import { FilterEditForm } from '@/components/common/FilterEditForm';
import { useMessages, useNavigation, useFilters } from '@/components/hooks'; import { useMessages, useNavigation, useFilters } from '@/components/hooks';
@ -34,7 +34,7 @@ export function WebsiteFilterButton({
<DialogTrigger> <DialogTrigger>
<Button variant="quiet"> <Button variant="quiet">
<Icon> <Icon>
<Lucide.ListFilter /> <ListFilter />
</Icon> </Icon>
{showText && <Text weight="bold">{formatMessage(labels.filter)}</Text>} {showText && <Text weight="bold">{formatMessage(labels.filter)}</Text>}
</Button> </Button>

View file

@ -1,7 +1,7 @@
import { Button, Icon, Text, Row } from '@umami/react-zen'; import { Button, Icon, Text, Row } from '@umami/react-zen';
import { PageHeader } from '@/components/common/PageHeader'; import { PageHeader } from '@/components/common/PageHeader';
import { useWebsite } from '@/components/hooks/useWebsite'; import { useWebsite } from '@/components/hooks/useWebsite';
import { Lucide } from '@/components/icons'; import { Share, Edit } from '@/components/icons';
import { Favicon } from '@/components/common/Favicon'; import { Favicon } from '@/components/common/Favicon';
import { ActiveUsers } from '@/components/metrics/ActiveUsers'; import { ActiveUsers } from '@/components/metrics/ActiveUsers';
@ -14,13 +14,13 @@ export function WebsiteHeader() {
<ActiveUsers websiteId={website.id} /> <ActiveUsers websiteId={website.id} />
<Button> <Button>
<Icon> <Icon>
<Lucide.Share /> <Share />
</Icon> </Icon>
<Text>Share</Text> <Text>Share</Text>
</Button> </Button>
<Button> <Button>
<Icon> <Icon>
<Lucide.Edit /> <Edit />
</Icon> </Icon>
<Text>Edit</Text> <Text>Edit</Text>
</Button> </Button>

View file

@ -1,7 +1,6 @@
import { import {
Button, Button,
Icon, Icon,
Icons,
Menu, Menu,
MenuItem, MenuItem,
MenuSeparator, MenuSeparator,
@ -10,7 +9,7 @@ import {
Text, Text,
} from '@umami/react-zen'; } from '@umami/react-zen';
import { Fragment } from 'react'; import { Fragment } from 'react';
import { Lucide } from '@/components/icons'; import { More, Share, Edit } from '@/components/icons';
import { useMessages, useNavigation } from '@/components/hooks'; import { useMessages, useNavigation } from '@/components/hooks';
import { InputItem } from '@/lib/types'; import { InputItem } from '@/lib/types';
@ -19,8 +18,8 @@ export function WebsiteMenu({ websiteId }: { websiteId: string }) {
const { router, renderUrl, renderTeamUrl } = useNavigation(); const { router, renderUrl, renderTeamUrl } = useNavigation();
const menuItems: InputItem[] = [ const menuItems: InputItem[] = [
{ id: 'share', label: formatMessage(labels.share), icon: <Lucide.Share /> }, { id: 'share', label: formatMessage(labels.share), icon: <Share /> },
{ id: 'edit', label: formatMessage(labels.edit), icon: <Lucide.Edit />, seperator: true }, { id: 'edit', label: formatMessage(labels.edit), icon: <Edit />, seperator: true },
]; ];
const handleAction = (id: any) => { const handleAction = (id: any) => {
@ -35,7 +34,7 @@ export function WebsiteMenu({ websiteId }: { websiteId: string }) {
<MenuTrigger> <MenuTrigger>
<Button variant="quiet"> <Button variant="quiet">
<Icon> <Icon>
<Icons.More /> <More />
</Icon> </Icon>
</Button> </Button>
<Popover placement="bottom"> <Popover placement="bottom">

View file

@ -1,5 +1,18 @@
import { Icon, Text, Row, NavMenu, NavMenuItem } from '@umami/react-zen'; import { Icon, Text, Row, NavMenu, NavMenuItem } from '@umami/react-zen';
import { Icons } from '@/components/icons'; import {
Overview,
Lightning,
User,
Clock,
Lightbulb,
Target,
Funnel,
Path,
Magnet,
Tag,
Money,
Network,
} from '@/components/icons';
import { useMessages, useNavigation } from '@/components/hooks'; import { useMessages, useNavigation } from '@/components/hooks';
import Link from 'next/link'; import Link from 'next/link';
@ -11,73 +24,73 @@ export function WebsiteNav({ websiteId }: { websiteId: string }) {
{ {
id: 'overview', id: 'overview',
label: formatMessage(labels.overview), label: formatMessage(labels.overview),
icon: <Icons.Overview />, icon: <Overview />,
path: '', path: '',
}, },
{ {
id: 'events', id: 'events',
label: formatMessage(labels.events), label: formatMessage(labels.events),
icon: <Icons.Lightning />, icon: <Lightning />,
path: '/events', path: '/events',
}, },
{ {
id: 'sessions', id: 'sessions',
label: formatMessage(labels.sessions), label: formatMessage(labels.sessions),
icon: <Icons.User />, icon: <User />,
path: '/sessions', path: '/sessions',
}, },
{ {
id: 'realtime', id: 'realtime',
label: formatMessage(labels.realtime), label: formatMessage(labels.realtime),
icon: <Icons.Clock />, icon: <Clock />,
path: '/realtime', path: '/realtime',
}, },
{ {
id: 'insights', id: 'insights',
label: formatMessage(labels.insights), label: formatMessage(labels.insights),
icon: <Icons.Lightbulb />, icon: <Lightbulb />,
path: '/insights', path: '/insights',
}, },
{ {
id: 'goals', id: 'goals',
label: formatMessage(labels.goals), label: formatMessage(labels.goals),
icon: <Icons.Target />, icon: <Target />,
path: '/goals', path: '/goals',
}, },
{ {
id: 'funnel', id: 'funnel',
label: formatMessage(labels.funnel), label: formatMessage(labels.funnel),
icon: <Icons.Funnel />, icon: <Funnel />,
path: '/funnels', path: '/funnels',
}, },
{ {
id: 'journeys', id: 'journeys',
label: formatMessage(labels.journey), label: formatMessage(labels.journey),
icon: <Icons.Path />, icon: <Path />,
path: '/goals', path: '/goals',
}, },
{ {
id: 'retention', id: 'retention',
label: formatMessage(labels.retention), label: formatMessage(labels.retention),
icon: <Icons.Magnet />, icon: <Magnet />,
path: '/retention', path: '/retention',
}, },
{ {
id: 'utm', id: 'utm',
label: formatMessage(labels.utm), label: formatMessage(labels.utm),
icon: <Icons.Tag />, icon: <Tag />,
path: '/utm', path: '/utm',
}, },
{ {
id: 'revenue', id: 'revenue',
label: formatMessage(labels.revenue), label: formatMessage(labels.revenue),
icon: <Icons.Money />, icon: <Money />,
path: '/revenue', path: '/revenue',
}, },
{ {
id: 'attribution', id: 'attribution',
label: formatMessage(labels.attribution), label: formatMessage(labels.attribution),
icon: <Icons.Network />, icon: <Network />,
path: '/attribution', path: '/attribution',
}, },
]; ];

View file

@ -3,7 +3,7 @@ import { useMessages, useNavigation, useTimezone } from '@/components/hooks';
import { Empty } from '@/components/common/Empty'; import { Empty } from '@/components/common/Empty';
import { Avatar } from '@/components/common/Avatar'; import { Avatar } from '@/components/common/Avatar';
import Link from 'next/link'; import Link from 'next/link';
import { Icons } from '@/components/icons'; import { Bolt, Eye } from '@/components/icons';
export function EventsTable({ data = [] }) { export function EventsTable({ data = [] }) {
const { formatTimezoneDate } = useTimezone(); const { formatTimezoneDate } = useTimezone();
@ -27,7 +27,7 @@ export function EventsTable({ data = [] }) {
{(row: any) => { {(row: any) => {
return ( return (
<Row alignItems="center" gap="2"> <Row alignItems="center" gap="2">
<Icon>{row.eventName ? <Icons.Bolt /> : <Icons.Eye />}</Icon> <Icon>{row.eventName ? <Bolt /> : <Eye />}</Icon>
{formatMessage(row.eventName ? labels.triggeredEvent : labels.viewedPage)} {formatMessage(row.eventName ? labels.triggeredEvent : labels.viewedPage)}
<strong>{row.eventName || row.urlPath}</strong> <strong>{row.eventName || row.urlPath}</strong>
</Row> </Row>

View file

@ -1,7 +1,7 @@
import { Button, MenuTrigger, Dialog, Icon, Text, Modal } from '@umami/react-zen'; import { Button, MenuTrigger, Dialog, Icon, Text, Modal } from '@umami/react-zen';
import { useMessages } from '@/components/hooks'; import { useMessages } from '@/components/hooks';
import { GoalAddForm } from './GoalAddForm'; import { GoalAddForm } from './GoalAddForm';
import { Icons } from '@/components/icons'; import { Plus } from '@/components/icons';
export function GoalAddButton({ websiteId }: { websiteId: string }) { export function GoalAddButton({ websiteId }: { websiteId: string }) {
const { formatMessage, labels } = useMessages(); const { formatMessage, labels } = useMessages();
@ -10,7 +10,7 @@ export function GoalAddButton({ websiteId }: { websiteId: string }) {
<MenuTrigger> <MenuTrigger>
<Button variant="primary"> <Button variant="primary">
<Icon> <Icon>
<Icons.Plus /> <Plus />
</Icon> </Icon>
<Text>{formatMessage(labels.addGoal)}</Text> <Text>{formatMessage(labels.addGoal)}</Text>
</Button> </Button>

View file

@ -9,7 +9,15 @@ import {
} from '@umami/react-zen'; } from '@umami/react-zen';
import { useApi, useMessages } from '@/components/hooks'; import { useApi, useMessages } from '@/components/hooks';
export function GoalAddForm({ onSave, onClose }: { onSave?: () => void; onClose?: () => void }) { export function GoalAddForm({
websiteId,
onSave,
onClose,
}: {
websiteId: string;
onSave?: () => void;
onClose?: () => void;
}) {
const { formatMessage, labels } = useMessages(); const { formatMessage, labels } = useMessages();
const { post, useMutation } = useApi(); const { post, useMutation } = useApi();
const { mutate, error, isPending } = useMutation({ const { mutate, error, isPending } = useMutation({
@ -32,6 +40,7 @@ export function GoalAddForm({ onSave, onClose }: { onSave?: () => void; onClose?
return ( return (
<Form onSubmit={handleSubmit} error={error?.message}> <Form onSubmit={handleSubmit} error={error?.message}>
{websiteId}
<FormField <FormField
name="name" name="name"
label={formatMessage(labels.name)} label={formatMessage(labels.name)}

View file

@ -2,7 +2,7 @@ import { useFormat } from '@/components//hooks/useFormat';
import { Empty } from '@/components/common/Empty'; import { Empty } from '@/components/common/Empty';
import { FilterButtons } from '@/components/common/FilterButtons'; import { FilterButtons } from '@/components/common/FilterButtons';
import { useCountryNames, useLocale, useMessages, useTimezone } from '@/components/hooks'; import { useCountryNames, useLocale, useMessages, useTimezone } from '@/components/hooks';
import { Icons } from '@/components/icons'; import { Eye, Visitor, Bolt } from '@/components/icons';
import { BROWSERS, OS_NAMES } from '@/lib/constants'; import { BROWSERS, OS_NAMES } from '@/lib/constants';
import { stringToColor } from '@/lib/format'; import { stringToColor } from '@/lib/format';
import { RealtimeData } from '@/lib/types'; import { RealtimeData } from '@/lib/types';
@ -18,9 +18,9 @@ const TYPE_SESSION = 'session';
const TYPE_EVENT = 'event'; const TYPE_EVENT = 'event';
const icons = { const icons = {
[TYPE_PAGEVIEW]: <Icons.Eye />, [TYPE_PAGEVIEW]: <Eye />,
[TYPE_SESSION]: <Icons.Visitor />, [TYPE_SESSION]: <Visitor />,
[TYPE_EVENT]: <Icons.Bolt />, [TYPE_EVENT]: <Bolt />,
}; };
export function RealtimeLog({ data }: { data: RealtimeData }) { export function RealtimeLog({ data }: { data: RealtimeData }) {

View file

@ -1,7 +1,7 @@
import { ReactNode } from 'react'; import { ReactNode } from 'react';
import { Grid, Row, Column, Text, Loading, Icon } from '@umami/react-zen'; import { Grid, Row, Column, Text, Loading, Icon } from '@umami/react-zen';
import { EmptyPlaceholder } from '@/components/common/EmptyPlaceholder'; import { EmptyPlaceholder } from '@/components/common/EmptyPlaceholder';
import { Lucide } from '@/components/icons'; import { Users } from '@/components/icons';
import { useMessages, useLocale, useRetentionQuery } from '@/components/hooks'; import { useMessages, useLocale, useRetentionQuery } from '@/components/hooks';
import { formatDate } from '@/lib/date'; import { formatDate } from '@/lib/date';
import { formatLongNumber } from '@/lib/format'; import { formatLongNumber } from '@/lib/format';
@ -68,7 +68,7 @@ export function RetentionTable({ websiteId, days = DAYS }: { websiteId: string;
<Text weight="bold">{formatDate(date, 'PP', locale)}</Text> <Text weight="bold">{formatDate(date, 'PP', locale)}</Text>
<Row alignItems="center" gap> <Row alignItems="center" gap>
<Icon> <Icon>
<Lucide.Users /> <Users />
</Icon> </Icon>
<Text>{formatLongNumber(visitors)}</Text> <Text>{formatLongNumber(visitors)}</Text>
</Row> </Row>

View file

@ -1,6 +1,6 @@
import { isSameDay } from 'date-fns'; import { isSameDay } from 'date-fns';
import { Loading, Icon, StatusLight } from '@umami/react-zen'; import { Loading, Icon, StatusLight } from '@umami/react-zen';
import { Icons } from '@/components/icons'; import { Bolt, Eye } from '@/components/icons';
import { useSessionActivityQuery, useTimezone } from '@/components/hooks'; import { useSessionActivityQuery, useTimezone } from '@/components/hooks';
import styles from './SessionActivity.module.css'; import styles from './SessionActivity.module.css';
import { Fragment } from 'react'; import { Fragment } from 'react';
@ -42,7 +42,7 @@ export function SessionActivity({
{formatTimezoneDate(createdAt, 'pp')} {formatTimezoneDate(createdAt, 'pp')}
</StatusLight> </StatusLight>
</div> </div>
<Icon>{eventName ? <Icons.Bolt /> : <Icons.Eye />}</Icon> <Icon>{eventName ? <Bolt /> : <Eye />}</Icon>
<div>{eventName || urlPath}</div> <div>{eventName || urlPath}</div>
</div> </div>
</Fragment> </Fragment>

View file

@ -1,7 +1,7 @@
import { Icon, TextField, Column, Row, Label, Box, Text } from '@umami/react-zen'; import { Icon, TextField, Column, Row, Label, Box, Text } from '@umami/react-zen';
import { useFormat, useLocale, useMessages, useRegionNames, useTimezone } from '@/components/hooks'; import { useFormat, useLocale, useMessages, useRegionNames, useTimezone } from '@/components/hooks';
import { TypeIcon } from '@/components/common/TypeIcon'; import { TypeIcon } from '@/components/common/TypeIcon';
import { Icons } from '@/components/icons'; import { Location } from '@/components/icons';
export function SessionInfo({ data }) { export function SessionInfo({ data }) {
const { locale } = useLocale(); const { locale } = useLocale();
@ -44,7 +44,7 @@ export function SessionInfo({ data }) {
<Label>{formatMessage(labels.region)}</Label> <Label>{formatMessage(labels.region)}</Label>
<Row gap="3"> <Row gap="3">
<Icon> <Icon>
<Icons.Location /> <Location />
</Icon> </Icon>
{getRegionName(data?.region)} {getRegionName(data?.region)}
</Row> </Row>
@ -54,7 +54,7 @@ export function SessionInfo({ data }) {
<Label>{formatMessage(labels.city)}</Label> <Label>{formatMessage(labels.city)}</Label>
<Row gap="3"> <Row gap="3">
<Icon> <Icon>
<Icons.Location /> <Location />
</Icon> </Icon>
<Text>{data?.city}</Text> <Text>{data?.city}</Text>
</Row> </Row>

View file

@ -13,7 +13,7 @@ import { useRouter } from 'next/navigation';
import { useApi, useMessages } from '@/components/hooks'; import { useApi, useMessages } from '@/components/hooks';
import { setUser } from '@/store/app'; import { setUser } from '@/store/app';
import { setClientAuthToken } from '@/lib/client'; import { setClientAuthToken } from '@/lib/client';
import { Icons } from '@/components/icons'; import { Logo } from '@/components/icons';
export function LoginForm() { export function LoginForm() {
const { formatMessage, labels, getMessage } = useMessages(); const { formatMessage, labels, getMessage } = useMessages();
@ -37,7 +37,7 @@ export function LoginForm() {
return ( return (
<Column justifyContent="center" alignItems="center" padding="8" gap="6"> <Column justifyContent="center" alignItems="center" padding="8" gap="6">
<Icon size="lg"> <Icon size="lg">
<Icons.Logo /> <Logo />
</Icon> </Icon>
<Heading>umami</Heading> <Heading>umami</Heading>
<Form onSubmit={handleSubmit} error={getMessage(error)}> <Form onSubmit={handleSubmit} error={getMessage(error)}>

View file

@ -2,7 +2,7 @@ import { Row, Icon, Text, ThemeButton } from '@umami/react-zen';
import Link from 'next/link'; import Link from 'next/link';
import { LanguageButton } from '@/components/input/LanguageButton'; import { LanguageButton } from '@/components/input/LanguageButton';
import { SettingsButton } from '@/components/input/SettingsButton'; import { SettingsButton } from '@/components/input/SettingsButton';
import { Icons } from '@/components/icons'; import { Logo } from '@/components/icons';
export function Header() { export function Header() {
return ( return (
@ -10,7 +10,7 @@ export function Header() {
<Row gap> <Row gap>
<Link href="https://umami.is" target="_blank"> <Link href="https://umami.is" target="_blank">
<Icon size="lg"> <Icon size="lg">
<Icons.Logo /> <Logo />
</Icon> </Icon>
<Text>umami</Text> <Text>umami</Text>
</Link> </Link>

View file

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path d="M400 64h-48V12c0-6.6-5.4-12-12-12h-8c-6.6 0-12 5.4-12 12v52H128V12c0-6.6-5.4-12-12-12h-8c-6.6 0-12 5.4-12 12v52H48C21.5 64 0 85.5 0 112v352c0 26.5 21.5 48 48 48h352c26.5 0 48-21.5 48-48V112c0-26.5-21.5-48-48-48zM48 96h352c8.8 0 16 7.2 16 16v48H32v-48c0-8.8 7.2-16 16-16zm352 384H48c-8.8 0-16-7.2-16-16V192h384v272c0 8.8-7.2 16-16 16zM148 320h-40c-6.6 0-12-5.4-12-12v-40c0-6.6 5.4-12 12-12h40c6.6 0 12 5.4 12 12v40c0 6.6-5.4 12-12 12zm96 0h-40c-6.6 0-12-5.4-12-12v-40c0-6.6 5.4-12 12-12h40c6.6 0 12 5.4 12 12v40c0 6.6-5.4 12-12 12zm96 0h-40c-6.6 0-12-5.4-12-12v-40c0-6.6 5.4-12 12-12h40c6.6 0 12 5.4 12 12v40c0 6.6-5.4 12-12 12zm-96 96h-40c-6.6 0-12-5.4-12-12v-40c0-6.6 5.4-12 12-12h40c6.6 0 12 5.4 12 12v40c0 6.6-5.4 12-12 12zm-96 0h-40c-6.6 0-12-5.4-12-12v-40c0-6.6 5.4-12 12-12h40c6.6 0 12 5.4 12 12v40c0 6.6-5.4 12-12 12zm192 0h-40c-6.6 0-12-5.4-12-12v-40c0-6.6 5.4-12 12-12h40c6.6 0 12 5.4 12 12v40c0 6.6-5.4 12-12 12z"/></svg>

Before

Width:  |  Height:  |  Size: 1,002 B

View file

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512"><path d="M288 144a110.94 110.94 0 0 0-31.24 5 55.4 55.4 0 0 1 7.24 27 56 56 0 0 1-56 56 55.4 55.4 0 0 1-27-7.24A111.71 111.71 0 1 0 288 144zm284.52 97.4C518.29 135.59 410.93 64 288 64S57.68 135.64 3.48 241.41a32.35 32.35 0 0 0 0 29.19C57.71 376.41 165.07 448 288 448s230.32-71.64 284.52-177.41a32.35 32.35 0 0 0 0-29.19zM288 400c-98.65 0-189.09-55-237.93-144C98.91 167 189.34 112 288 112s189.09 55 237.93 144C477.1 345 386.66 400 288 400z"/></svg>

Before

Width:  |  Height:  |  Size: 509 B

View file

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 496 512"><path d="M248 8C111 8 0 119 0 256s111 248 248 248 248-111 248-248S385 8 248 8zm179.3 160h-67.2c-6.7-36.5-17.5-68.8-31.2-94.7 42.9 19 77.7 52.7 98.4 94.7zM248 56c18.6 0 48.6 41.2 63.2 112H184.8C199.4 97.2 229.4 56 248 56zM48 256c0-13.7 1.4-27.1 4-40h77.7c-1 13.1-1.7 26.3-1.7 40s.7 26.9 1.7 40H52c-2.6-12.9-4-26.3-4-40zm20.7 88h67.2c6.7 36.5 17.5 68.8 31.2 94.7-42.9-19-77.7-52.7-98.4-94.7zm67.2-176H68.7c20.7-42 55.5-75.7 98.4-94.7-13.7 25.9-24.5 58.2-31.2 94.7zM248 456c-18.6 0-48.6-41.2-63.2-112h126.5c-14.7 70.8-44.7 112-63.3 112zm70.1-160H177.9c-1.1-12.8-1.9-26-1.9-40s.8-27.2 1.9-40h140.3c1.1 12.8 1.9 26 1.9 40s-.9 27.2-2 40zm10.8 142.7c13.7-25.9 24.4-58.2 31.2-94.7h67.2c-20.7 42-55.5 75.7-98.4 94.7zM366.3 296c1-13.1 1.7-26.3 1.7-40s-.7-26.9-1.7-40H444c2.6 12.9 4 26.3 4 40s-1.4 27.1-4 40h-77.7z"/></svg>

Before

Width:  |  Height:  |  Size: 874 B

View file

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path d="M314.222 197.78c51.091 51.091 54.377 132.287 9.75 187.16-6.242 7.73-2.784 3.865-84.94 86.02-54.696 54.696-143.266 54.745-197.99 0-54.711-54.69-54.734-143.255 0-197.99 32.773-32.773 51.835-51.899 63.409-63.457 7.463-7.452 20.331-2.354 20.486 8.192a173.31 173.31 0 0 0 4.746 37.828c.966 4.029-.272 8.269-3.202 11.198L80.632 312.57c-32.755 32.775-32.887 85.892 0 118.8 32.775 32.755 85.892 32.887 118.8 0l75.19-75.2c32.718-32.725 32.777-86.013 0-118.79a83.722 83.722 0 0 0-22.814-16.229c-4.623-2.233-7.182-7.25-6.561-12.346 1.356-11.122 6.296-21.885 14.815-30.405l4.375-4.375c3.625-3.626 9.177-4.594 13.76-2.294 12.999 6.524 25.187 15.211 36.025 26.049zM470.958 41.04c-54.724-54.745-143.294-54.696-197.99 0-82.156 82.156-78.698 78.29-84.94 86.02-44.627 54.873-41.341 136.069 9.75 187.16 10.838 10.838 23.026 19.525 36.025 26.049 4.582 2.3 10.134 1.331 13.76-2.294l4.375-4.375c8.52-8.519 13.459-19.283 14.815-30.405.621-5.096-1.938-10.113-6.561-12.346a83.706 83.706 0 0 1-22.814-16.229c-32.777-32.777-32.718-86.065 0-118.79l75.19-75.2c32.908-32.887 86.025-32.755 118.8 0 32.887 32.908 32.755 86.025 0 118.8l-45.848 45.84c-2.93 2.929-4.168 7.169-3.202 11.198a173.31 173.31 0 0 1 4.746 37.828c.155 10.546 13.023 15.644 20.486 8.192 11.574-11.558 30.636-30.684 63.409-63.457 54.733-54.735 54.71-143.3-.001-197.991z"/></svg>

Before

Width:  |  Height:  |  Size: 1.4 KiB

View file

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1399.98 1400"><path d="M562.44 837.55C335.89 611 288.08 273.54 418.71 0a734.31 734.31 0 0 0-203.17 143.73c-287.39 287.39-287.39 753.33 0 1040.72s753.33 287.4 1040.74 0A733.8 733.8 0 0 0 1400 981.29c-273.55 130.63-611 82.8-837.56-143.74Z"/></svg>

Before

Width:  |  Height:  |  Size: 298 B

View file

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1400 1400"><path d="M367.43 422.13a54.44 54.44 0 0 1-38.66-16L205 282.35A54.69 54.69 0 0 1 282.37 205l123.74 123.79a54.68 54.68 0 0 1-38.68 93.34ZM1156.3 1211a54.51 54.51 0 0 1-38.67-16l-123.74-123.79a54.68 54.68 0 1 1 77.34-77.33L1195 1117.65a54.7 54.7 0 0 1-38.7 93.35Zm-912.6 0a54.7 54.7 0 0 1-38.7-93.35l123.74-123.76a54.69 54.69 0 0 1 77.36 77.32L282.37 1195a54.51 54.51 0 0 1-38.67 16Zm788.87-788.87a54.68 54.68 0 0 1-38.68-93.34L1117.61 205a54.69 54.69 0 0 1 77.39 77.35l-123.77 123.76a54.44 54.44 0 0 1-38.66 16.02ZM229.69 754.69h-175a54.69 54.69 0 0 1 0-109.38h175a54.69 54.69 0 0 1 0 109.38Zm1115.62 0h-175a54.69 54.69 0 0 1 0-109.38h175a54.69 54.69 0 0 1 0 109.38ZM700 1400a54.68 54.68 0 0 1-54.69-54.69v-175a54.69 54.69 0 0 1 109.38 0v175A54.68 54.68 0 0 1 700 1400Zm0-1115.62a54.7 54.7 0 0 1-54.69-54.69v-175a54.69 54.69 0 0 1 109.38 0v175A54.7 54.7 0 0 1 700 284.38Z"/><circle cx="700" cy="700" r="306.25"/></svg>

Before

Width:  |  Height:  |  Size: 980 B

View file

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" style="enable-background:new 0 0 477.869 477.869" viewBox="0 0 477.869 477.869"><path d="M387.415 233.496c48.976-44.029 52.987-119.424 8.958-168.4C355.991 20.177 288.4 12.546 239.02 47.332c-53.83-37.99-128.264-25.149-166.254 28.68-34.859 49.393-27.259 117.054 17.689 157.483C34.606 262.935-.251 320.976.002 384.108v51.2c0 9.426 7.641 17.067 17.067 17.067h443.733c9.426 0 17.067-7.641 17.067-17.067v-51.2c.252-63.132-34.605-121.173-90.454-150.612zM307.201 59.842c47.062-.052 85.256 38.057 85.309 85.119.037 33.564-19.631 64.023-50.237 77.799-1.314.597-2.628 1.143-3.959 1.707a83.66 83.66 0 0 1-12.988 4.045c-.853.188-1.707.29-2.577.461a85.366 85.366 0 0 1-15.019 1.519c-2.27 0-4.557-.171-6.827-.375-.853 0-1.707 0-2.56-.171a86.219 86.219 0 0 1-27.904-8.226c-.324-.154-.7-.137-1.024-.273-1.707-.819-3.413-1.536-4.932-2.458.137-.171.222-.358.358-.529a119.721 119.721 0 0 0 18.278-33.297l.529-1.434a120.381 120.381 0 0 0 4.523-17.562c.154-.87.273-1.707.41-2.645.987-6.067 1.506-12.2 1.553-18.347a120.041 120.041 0 0 0-1.553-18.313c-.137-.887-.256-1.707-.41-2.645a120.414 120.414 0 0 0-4.523-17.562l-.529-1.434a119.747 119.747 0 0 0-18.278-33.297c-.137-.171-.222-.358-.358-.529a84.787 84.787 0 0 1 42.718-11.553zM85.335 145.176c-.121-47.006 37.886-85.21 84.892-85.331a85.112 85.112 0 0 1 59.134 23.686c.99.956 1.963 1.911 2.918 2.901a87.748 87.748 0 0 1 8.09 9.813c.751 1.058 1.434 2.185 2.133 3.277a83.951 83.951 0 0 1 6.263 11.52c.427.973.751 1.963 1.126 2.935a83.422 83.422 0 0 1 4.233 13.653c.12.512.154 1.024.256 1.553a80.338 80.338 0 0 1 0 32.119c-.102.529-.137 1.041-.256 1.553a83.228 83.228 0 0 1-4.233 13.653c-.375.973-.7 1.963-1.126 2.935a84.251 84.251 0 0 1-6.263 11.503c-.7 1.092-1.382 2.219-2.133 3.277a87.549 87.549 0 0 1-8.09 9.813c-.956.99-1.929 1.946-2.918 2.901a85.187 85.187 0 0 1-23.569 15.906 49.35 49.35 0 0 1-4.198 1.707 85.839 85.839 0 0 1-12.663 3.925c-1.075.239-2.185.375-3.277.563a84.67 84.67 0 0 1-14.046 1.417h-1.877a84.563 84.563 0 0 1-14.046-1.417c-1.092-.188-2.202-.324-3.277-.563a85.802 85.802 0 0 1-12.663-3.925c-1.417-.563-2.816-1.143-4.198-1.707-30.534-13.786-50.173-44.166-50.212-77.667zm221.866 273.066H34.135v-34.133c-.25-57.833 36.188-109.468 90.76-128.614a119.092 119.092 0 0 0 91.546 0 137.138 137.138 0 0 1 16.623 7.356c3.55 1.826 6.827 3.908 10.24 6.007 2.219 1.382 4.471 2.731 6.605 4.25 3.294 2.338 6.4 4.881 9.455 7.492 1.963 1.707 3.908 3.413 5.751 5.12 2.816 2.662 5.461 5.478 8.004 8.363a134.465 134.465 0 0 1 5.291 6.383 132.594 132.594 0 0 1 6.349 8.823c1.707 2.56 3.226 5.222 4.727 7.885 1.707 2.935 3.277 5.871 4.71 8.926 1.434 3.055 2.697 6.4 3.925 9.66 1.075 2.833 2.219 5.649 3.106 8.533 1.195 3.959 2.031 8.055 2.867 12.151.512 2.423 1.178 4.796 1.553 7.253a141.153 141.153 0 0 1 1.553 20.412v34.133zm136.534 0h-102.4v-34.133c0-5.342-.307-10.633-.785-15.872-.137-1.536-.375-3.055-.546-4.591-.461-3.772-.99-7.509-1.707-11.213a246.936 246.936 0 0 0-.973-4.762c-.819-3.8-1.769-7.566-2.85-11.298-.358-1.229-.683-2.475-1.058-3.686a169.105 169.105 0 0 0-20.565-43.127l-.666-.973a168.958 168.958 0 0 0-9.404-12.646l-.119-.154a154.895 154.895 0 0 0-11.008-12.237h.7a120.8 120.8 0 0 0 14.524 1.024h.939c4.496-.039 8.985-.33 13.449-.87 1.399-.171 2.782-.427 4.181-.649a117.43 117.43 0 0 0 10.752-2.167c1.007-.256 2.031-.495 3.055-.785a116.211 116.211 0 0 0 13.653-4.642c54.612 19.127 91.083 70.785 90.829 128.649v34.132z"/></svg>

Before

Width:  |  Height:  |  Size: 3.4 KiB

View file

@ -1,7 +1,8 @@
import Link from 'next/link';
import { Flexbox, Icon, Icons, Text } from '@umami/react-zen';
import styles from './Breadcrumb.module.css';
import { Fragment } from 'react'; import { Fragment } from 'react';
import Link from 'next/link';
import { Row, Icon, Text } from '@umami/react-zen';
import { Chevron } from '@/components/icons';
import styles from './Breadcrumb.module.css';
export interface BreadcrumbProps { export interface BreadcrumbProps {
data: { data: {
@ -12,7 +13,7 @@ export interface BreadcrumbProps {
export function Breadcrumb({ data }: BreadcrumbProps) { export function Breadcrumb({ data }: BreadcrumbProps) {
return ( return (
<Flexbox alignItems="center" gap={3} className={styles.bar}> <Row alignItems="center" gap className={styles.bar}>
{data.map((a, i) => { {data.map((a, i) => {
return ( return (
<Fragment key={i}> <Fragment key={i}>
@ -25,12 +26,12 @@ export function Breadcrumb({ data }: BreadcrumbProps) {
)} )}
{i !== data.length - 1 ? ( {i !== data.length - 1 ? (
<Icon rotate={270}> <Icon rotate={270}>
<Icons.Chevron /> <Chevron />
</Icon> </Icon>
) : null} ) : null}
</Fragment> </Fragment>
); );
})} })}
</Flexbox> </Row>
); );
} }

View file

@ -1,7 +1,7 @@
import { Icon, Row, Text } from '@umami/react-zen'; import { Icon, Row, Text } from '@umami/react-zen';
import { differenceInDays, isSameDay } from 'date-fns'; import { differenceInDays, isSameDay } from 'date-fns';
import { useLocale } from '@/components/hooks'; import { useLocale } from '@/components/hooks';
import { Lucide } from '@/components/icons'; import { Calendar } from '@/components/icons';
import { formatDate } from '@/lib/date'; import { formatDate } from '@/lib/date';
export function DateDisplay({ startDate, endDate }) { export function DateDisplay({ startDate, endDate }) {
@ -11,7 +11,7 @@ export function DateDisplay({ startDate, endDate }) {
return ( return (
<Row gap="3" alignItems="center" wrap="nowrap"> <Row gap="3" alignItems="center" wrap="nowrap">
<Icon> <Icon>
<Lucide.Calendar /> <Calendar />
</Icon> </Icon>
<Text wrap="nowrap"> <Text wrap="nowrap">
{isSingleDate ? ( {isSingleDate ? (

View file

@ -1,6 +1,6 @@
import { ReactNode } from 'react'; import { ReactNode } from 'react';
import { Icon, Text, Column } from '@umami/react-zen'; import { Icon, Text, Column } from '@umami/react-zen';
import { Icons } from '@/components/icons'; import { Logo } from '@/components/icons';
export interface EmptyPlaceholderProps { export interface EmptyPlaceholderProps {
message?: string; message?: string;
@ -11,7 +11,7 @@ export function EmptyPlaceholder({ message, children }: EmptyPlaceholderProps) {
return ( return (
<Column alignItems="center" justifyContent="center" gap="5" height="100%" width="100%"> <Column alignItems="center" justifyContent="center" gap="5" height="100%" width="100%">
<Icon size="xl" fillColor="3" strokeColor="3"> <Icon size="xl" fillColor="3" strokeColor="3">
<Icons.Logo /> <Logo />
</Icon> </Icon>
<Text>{message}</Text> <Text>{message}</Text>
<div>{children}</div> <div>{children}</div>

View file

@ -1,6 +1,7 @@
import { Icon, Icons, Text } from '@umami/react-zen'; import { Icon, Text } from '@umami/react-zen';
import styles from './ErrorMessage.module.css'; import styles from './ErrorMessage.module.css';
import { useMessages } from '@/components/hooks'; import { useMessages } from '@/components/hooks';
import { Alert } from '@/components/icons';
export function ErrorMessage() { export function ErrorMessage() {
const { formatMessage, messages } = useMessages(); const { formatMessage, messages } = useMessages();
@ -8,7 +9,7 @@ export function ErrorMessage() {
return ( return (
<div className={styles.error}> <div className={styles.error}>
<Icon className={styles.icon} size="lg"> <Icon className={styles.icon} size="lg">
<Icons.Alert /> <Alert />
</Icon> </Icon>
<Text>{formatMessage(messages.error)}</Text> <Text>{formatMessage(messages.error)}</Text>
</div> </div>

View file

@ -1,8 +1,9 @@
import { ReactNode } from 'react'; import { ReactNode } from 'react';
import classNames from 'classnames'; import classNames from 'classnames';
import Link from 'next/link'; import Link from 'next/link';
import { Icon, Icons } from '@umami/react-zen'; import { Icon } from '@umami/react-zen';
import { useMessages, useNavigation } from '@/components/hooks'; import { useMessages, useNavigation } from '@/components/hooks';
import { ExternalLink } from '@/components/icons';
import styles from './FilterLink.module.css'; import styles from './FilterLink.module.css';
export interface FilterLinkProps { export interface FilterLinkProps {
@ -44,7 +45,7 @@ export function FilterLink({
{externalUrl && ( {externalUrl && (
<a className={styles.link} href={externalUrl} target="_blank" rel="noreferrer noopener"> <a className={styles.link} href={externalUrl} target="_blank" rel="noreferrer noopener">
<Icon className={styles.icon}> <Icon className={styles.icon}>
<Icons.ExternalLink /> <ExternalLink />
</Icon> </Icon>
</a> </a>
)} )}

View file

@ -7,10 +7,10 @@ import {
ListItem, ListItem,
Select, Select,
Icon, Icon,
Icons,
Button, Button,
} from '@umami/react-zen'; } from '@umami/react-zen';
import { useFilters } from '@/components/hooks'; import { useFilters } from '@/components/hooks';
import { Close } from '@/components/icons';
export interface FilterRecordProps { export interface FilterRecordProps {
name: string; name: string;
@ -55,7 +55,7 @@ export function FilterRecord({
<Column justifyContent="flex-end"> <Column justifyContent="flex-end">
<Button variant="quiet" onPress={() => onRemove?.(name)}> <Button variant="quiet" onPress={() => onRemove?.(name)}>
<Icon> <Icon>
<Icons.Close /> <Close />
</Icon> </Icon>
</Button> </Button>
</Column> </Column>

View file

@ -1,5 +1,6 @@
import { Button, Icon, Icons } from '@umami/react-zen'; import { Button, Icon } from '@umami/react-zen';
import { useState } from 'react'; import { useState } from 'react';
import { Close, Menu } from '@/components/icons';
import { MobileMenu } from './MobileMenu'; import { MobileMenu } from './MobileMenu';
export function HamburgerButton({ menuItems }: { menuItems: any[] }) { export function HamburgerButton({ menuItems }: { menuItems: any[] }) {
@ -11,7 +12,7 @@ export function HamburgerButton({ menuItems }: { menuItems: any[] }) {
return ( return (
<> <>
<Button variant="quiet" onClick={handleClick}> <Button variant="quiet" onClick={handleClick}>
<Icon>{active ? <Icons.Close /> : <Icons.Menu />}</Icon> <Icon>{active ? <Close /> : <Menu />}</Icon>
</Button> </Button>
{active && <MobileMenu items={menuItems} onClose={handleClose} />} {active && <MobileMenu items={menuItems} onClose={handleClose} />}
</> </>

View file

@ -1,5 +1,6 @@
import { Button, Icon, Icons, Row, Text } from '@umami/react-zen'; import { Button, Icon, Row, Text } from '@umami/react-zen';
import { useMessages } from '@/components/hooks'; import { useMessages } from '@/components/hooks';
import { Chevron } from '@/components/icons';
export interface PagerProps { export interface PagerProps {
page: string | number; page: string | number;
@ -38,12 +39,12 @@ export function Pager({ page, pageSize, count, onPageChange }: PagerProps) {
<Text>{formatMessage(labels.pageOf, { current: page, total: maxPage })}</Text> <Text>{formatMessage(labels.pageOf, { current: page, total: maxPage })}</Text>
<Button onPress={() => handlePageChange(-1)} isDisabled={firstPage}> <Button onPress={() => handlePageChange(-1)} isDisabled={firstPage}>
<Icon size="sm" rotate={180}> <Icon size="sm" rotate={180}>
<Icons.Chevron /> <Chevron />
</Icon> </Icon>
</Button> </Button>
<Button onPress={() => handlePageChange(1)} isDisabled={lastPage}> <Button onPress={() => handlePageChange(1)} isDisabled={lastPage}>
<Icon size="sm"> <Icon size="sm">
<Icons.Chevron /> <Chevron />
</Icon> </Icon>
</Button> </Button>
</Row> </Row>

View file

@ -40,6 +40,7 @@ export * from './useFields';
export * from './useFilters'; export * from './useFilters';
export * from './useForceUpdate'; export * from './useForceUpdate';
export * from './useFormat'; export * from './useFormat';
export * from './useGlobalState';
export * from './useLanguageNames'; export * from './useLanguageNames';
export * from './useLocale'; export * from './useLocale';
export * from './useMessages'; export * from './useMessages';

View file

@ -10,4 +10,4 @@ const useGlobalState = (key: string, value?: any) => {
return [store(state => state[key]), (value: any) => store.setState({ [key]: value })]; return [store(state => state[key]), (value: any) => store.setState({ [key]: value })];
}; };
export default useGlobalState; export { useGlobalState };

View file

@ -1,12 +1,33 @@
import { Icons as ZenIcons } from '@umami/react-zen'; export {
import * as lucide from 'lucide-react'; AlertTriangle as Alert,
import * as LocalIcons from '@/components/svg'; ArrowRight as Arrow,
Calendar,
const icons = { ChevronRight as Chevron,
...ZenIcons, X as Close,
...LocalIcons, Copy,
}; Edit,
Ellipsis,
export const Lucide = lucide; Eye,
ExternalLink,
export const Icons = icons; Globe,
Grid2X2,
LayoutDashboard,
Link,
ListFilter,
LockKeyhole,
LogOut,
Menu,
Moon,
MoreHorizontal as More,
PanelLeft,
Plus,
RefreshCw as Refresh,
Settings,
Share,
Slash,
SquarePen,
Sun,
Trash,
Users,
} from 'lucide-react';
export * from '@/components/svg';

View file

@ -1,6 +1,7 @@
import { MouseEvent } from 'react'; import { MouseEvent } from 'react';
import { Button, Icon, Icons, Text, Row, TooltipTrigger, Tooltip } from '@umami/react-zen'; import { Button, Icon, Text, Row, TooltipTrigger, Tooltip } from '@umami/react-zen';
import { useNavigation, useMessages, useFormat, useFilters } from '@/components/hooks'; import { useNavigation, useMessages, useFormat, useFilters } from '@/components/hooks';
import { Close } from '@/components/icons';
import { isSearchOperator } from '@/lib/params'; import { isSearchOperator } from '@/lib/params';
export function FilterBar() { export function FilterBar() {
@ -51,8 +52,8 @@ export function FilterBar() {
{paramValue} {paramValue}
</Text> </Text>
</Row> </Row>
<Icon onClick={e => handleCloseFilter(name, e)} size="xs" color> <Icon onClick={e => handleCloseFilter(name, e)} size="xs">
<Icons.Close /> <Close />
</Icon> </Icon>
</Row> </Row>
</Row> </Row>
@ -62,7 +63,7 @@ export function FilterBar() {
<TooltipTrigger delay={0}> <TooltipTrigger delay={0}>
<Button variant="quiet" onPress={handleResetFilter}> <Button variant="quiet" onPress={handleResetFilter}>
<Icon> <Icon>
<Icons.Close /> <Close />
</Icon> </Icon>
</Button> </Button>
<Tooltip> <Tooltip>

View file

@ -1,6 +1,6 @@
import { ReactNode, Key } from 'react'; import { ReactNode, Key } from 'react';
import { DialogTrigger, Button, Menu, Popover, Icon } from '@umami/react-zen'; import { DialogTrigger, Button, Menu, Popover, Icon } from '@umami/react-zen';
import { Lucide } from '@/components/icons'; import { Ellipsis } from '@/components/icons';
export function MenuButton({ export function MenuButton({
children, children,
@ -17,7 +17,7 @@ export function MenuButton({
<DialogTrigger> <DialogTrigger>
<Button variant="outline"> <Button variant="outline">
<Icon> <Icon>
<Lucide.Ellipsis /> <Ellipsis />
</Icon> </Icon>
</Button> </Button>
<Popover placement="bottom start"> <Popover placement="bottom start">

View file

@ -1,6 +1,6 @@
import { Row, Text, Icon, Button, MenuTrigger, Popover, Menu, MenuItem } from '@umami/react-zen'; import { Row, Text, Icon, Button, MenuTrigger, Popover, Menu, MenuItem } from '@umami/react-zen';
import { startOfMonth, endOfMonth, startOfYear, addMonths, subYears } from 'date-fns'; import { startOfMonth, endOfMonth, startOfYear, addMonths, subYears } from 'date-fns';
import { Icons } from '@/components/icons'; import { Chevron } from '@/components/icons';
import { useLocale } from '@/components/hooks'; import { useLocale } from '@/components/hooks';
import { formatDate } from '@/lib/date'; import { formatDate } from '@/lib/date';
@ -9,7 +9,7 @@ export function MonthSelect({ date = new Date(), onChange }) {
const month = formatDate(date, 'MMMM', locale); const month = formatDate(date, 'MMMM', locale);
const year = date.getFullYear(); const year = date.getFullYear();
// eslint-disable-next-line @typescript-eslint/no-unused-vars // eslint-disable-next-line
const handleChange = (close: () => void, date: Date) => { const handleChange = (close: () => void, date: Date) => {
onChange(`range:${startOfMonth(date).getTime()}:${endOfMonth(date).getTime()}`); onChange(`range:${startOfMonth(date).getTime()}:${endOfMonth(date).getTime()}`);
close(); close();
@ -31,7 +31,7 @@ export function MonthSelect({ date = new Date(), onChange }) {
<Button variant="quiet"> <Button variant="quiet">
<Text>{month}</Text> <Text>{month}</Text>
<Icon size="sm"> <Icon size="sm">
<Icons.Chevron /> <Chevron />
</Icon> </Icon>
</Button> </Button>
<Popover> <Popover>
@ -50,13 +50,17 @@ export function MonthSelect({ date = new Date(), onChange }) {
<Button variant="quiet"> <Button variant="quiet">
<Text>{year}</Text> <Text>{year}</Text>
<Icon size="sm"> <Icon size="sm">
<Icons.Chevron /> <Chevron />
</Icon> </Icon>
</Button> </Button>
<Popover> <Popover>
<Menu> <Menu>
{years.map(year => { {years.map(year => {
return <MenuItem id={year}>{year}</MenuItem>; return (
<MenuItem key={year} id={year}>
{year}
</MenuItem>
);
})} })}
</Menu> </Menu>
</Popover> </Popover>

View file

@ -1,7 +1,7 @@
import { LoadingButton, Icon, Tooltip, TooltipTrigger } from '@umami/react-zen'; import { LoadingButton, Icon, Tooltip, TooltipTrigger } from '@umami/react-zen';
import { setWebsiteDateRange } from '@/store/websites'; import { setWebsiteDateRange } from '@/store/websites';
import { useDateRange } from '@/components/hooks'; import { useDateRange } from '@/components/hooks';
import { Icons } from '@/components/icons'; import { Refresh } from '@/components/icons';
import { useMessages } from '@/components/hooks'; import { useMessages } from '@/components/hooks';
export function RefreshButton({ export function RefreshButton({
@ -24,7 +24,7 @@ export function RefreshButton({
<TooltipTrigger> <TooltipTrigger>
<LoadingButton isLoading={isLoading} onPress={handleClick}> <LoadingButton isLoading={isLoading} onPress={handleClick}>
<Icon> <Icon>
<Icons.Refresh /> <Refresh />
</Icon> </Icon>
</LoadingButton> </LoadingButton>
<Tooltip>{formatMessage(labels.refresh)}</Tooltip> <Tooltip>{formatMessage(labels.refresh)}</Tooltip>

View file

@ -1,7 +1,7 @@
import { Button, Icon, DialogTrigger, Popover, Column, Label } from '@umami/react-zen'; import { Button, Icon, DialogTrigger, Popover, Column, Label } from '@umami/react-zen';
import { TimezoneSetting } from '@/app/(main)/settings/profile/TimezoneSetting'; import { TimezoneSetting } from '@/app/(main)/settings/profile/TimezoneSetting';
import { DateRangeSetting } from '@/app/(main)/settings/profile/DateRangeSetting'; import { DateRangeSetting } from '@/app/(main)/settings/profile/DateRangeSetting';
import { Icons } from '@/components/icons'; import { Gear } from '@/components/icons';
import { useMessages } from '@/components/hooks'; import { useMessages } from '@/components/hooks';
export function SettingsButton() { export function SettingsButton() {
@ -11,7 +11,7 @@ export function SettingsButton() {
<DialogTrigger> <DialogTrigger>
<Button variant="quiet"> <Button variant="quiet">
<Icon> <Icon>
<Icons.Gear /> <Gear />
</Icon> </Icon>
</Button> </Button>
<Popover placement="bottom end"> <Popover placement="bottom end">

View file

@ -12,10 +12,10 @@ import {
Popover, Popover,
Row, Row,
Box, Box,
Icons,
} from '@umami/react-zen'; } from '@umami/react-zen';
import { User, Users } from 'lucide-react'; import { User, Users } from 'lucide-react';
import { useLoginQuery, useMessages, useTeamsQuery, useNavigation } from '@/components/hooks'; import { useLoginQuery, useMessages, useTeamsQuery, useNavigation } from '@/components/hooks';
import { Chevron } from '@/components/icons';
export function TeamsButton({ export function TeamsButton({
className, className,
@ -46,8 +46,8 @@ export function TeamsButton({
<Row alignItems="center" gap="3"> <Row alignItems="center" gap="3">
<Icon>{teamId ? <Users /> : <User />}</Icon> <Icon>{teamId ? <Users /> : <User />}</Icon>
{showText && <Text>{teamId ? team?.name : user.username}</Text>} {showText && <Text>{teamId ? team?.name : user.username}</Text>}
<Icon rotate={90} size="xs"> <Icon rotate={90} size="sm">
<Icons.Chevron /> <Chevron />
</Icon> </Icon>
</Row> </Row>
</Button> </Button>

View file

@ -9,7 +9,7 @@ import {
Tooltip, Tooltip,
} from '@umami/react-zen'; } from '@umami/react-zen';
import { isAfter } from 'date-fns'; import { isAfter } from 'date-fns';
import { Icons } from '@/components/icons'; import { Chevron, Close, Compare } from '@/components/icons';
import { useDateRange, useMessages, useNavigation } from '@/components/hooks'; import { useDateRange, useMessages, useNavigation } from '@/components/hooks';
import { getOffsetDateRange } from '@/lib/date'; import { getOffsetDateRange } from '@/lib/date';
import { DateRange } from '@/lib/types'; import { DateRange } from '@/lib/types';
@ -65,12 +65,12 @@ export function WebsiteDateFilter({
<Row gap="1"> <Row gap="1">
<Button onPress={() => handleIncrement(-1)} variant="quiet"> <Button onPress={() => handleIncrement(-1)} variant="quiet">
<Icon size="xs" rotate={180}> <Icon size="xs" rotate={180}>
<Icons.Chevron /> <Chevron />
</Icon> </Icon>
</Button> </Button>
<Button onPress={() => handleIncrement(1)} variant="quiet" isDisabled={disableForward}> <Button onPress={() => handleIncrement(1)} variant="quiet" isDisabled={disableForward}>
<Icon size="xs"> <Icon size="xs">
<Icons.Chevron /> <Chevron />
</Icon> </Icon>
</Button> </Button>
</Row> </Row>
@ -95,7 +95,7 @@ export function WebsiteDateFilter({
{!isAllTime && allowCompare && ( {!isAllTime && allowCompare && (
<TooltipTrigger delay={0}> <TooltipTrigger delay={0}>
<Button variant="quiet" onPress={handleCompare}> <Button variant="quiet" onPress={handleCompare}>
<Icon fillColor>{compare ? <Icons.Close /> : <Icons.Compare />}</Icon> <Icon fillColor>{compare ? <Close /> : <Compare />}</Icon>
</Button> </Button>
<Tooltip>{formatMessage(compare ? labels.cancel : labels.compareDates)}</Tooltip> <Tooltip>{formatMessage(compare ? labels.cancel : labels.compareDates)}</Tooltip>
</TooltipTrigger> </TooltipTrigger>

View file

@ -1,6 +1,7 @@
import classNames from 'classnames'; import classNames from 'classnames';
import { Icon, Icons, Text } from '@umami/react-zen'; import { Icon, Text } from '@umami/react-zen';
import { ReactNode } from 'react'; import { ReactNode } from 'react';
import { Arrow } from '@/components/icons';
import styles from './ChangeLabel.module.css'; import styles from './ChangeLabel.module.css';
export function ChangeLabel({ export function ChangeLabel({
@ -35,7 +36,7 @@ export function ChangeLabel({
> >
{!neutral && ( {!neutral && (
<Icon rotate={positive ? -90 : 90} size={size}> <Icon rotate={positive ? -90 : 90} size={size}>
<Icons.Arrow /> <Arrow />
</Icon> </Icon>
)} )}
<Text>{children || value}</Text> <Text>{children || value}</Text>

View file

@ -5,7 +5,7 @@ import { LinkButton } from '@/components/common/LinkButton';
import { DEFAULT_ANIMATION_DURATION } from '@/lib/constants'; import { DEFAULT_ANIMATION_DURATION } from '@/lib/constants';
import { percentFilter } from '@/lib/filters'; import { percentFilter } from '@/lib/filters';
import { useNavigation, useWebsiteMetricsQuery, useMessages, useFormat } from '@/components/hooks'; import { useNavigation, useWebsiteMetricsQuery, useMessages, useFormat } from '@/components/hooks';
import { Icons } from '@/components/icons'; import { Arrow } from '@/components/icons';
import { ListTable, ListTableProps } from './ListTable'; import { ListTable, ListTableProps } from './ListTable';
export interface MetricsTableProps extends ListTableProps { export interface MetricsTableProps extends ListTableProps {
@ -98,7 +98,7 @@ export function MetricsTable({
<LinkButton href={renderUrl({ view: type })} variant="quiet"> <LinkButton href={renderUrl({ view: type })} variant="quiet">
<Text>{formatMessage(labels.more)}</Text> <Text>{formatMessage(labels.more)}</Text>
<Icon size="sm"> <Icon size="sm">
<Icons.Arrow /> <Arrow />
</Icon> </Icon>
</LinkButton> </LinkButton>
)} )}

View file

@ -1,8 +0,0 @@
import * as React from 'react';
import type { SVGProps } from 'react';
const SvgEye = (props: SVGProps<SVGSVGElement>) => (
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512" {...props}>
<path d="M288 144a111 111 0 0 0-31.24 5 55.4 55.4 0 0 1 7.24 27 56 56 0 0 1-56 56 55.4 55.4 0 0 1-27-7.24A111.71 111.71 0 1 0 288 144m284.52 97.4C518.29 135.59 410.93 64 288 64S57.68 135.64 3.48 241.41a32.35 32.35 0 0 0 0 29.19C57.71 376.41 165.07 448 288 448s230.32-71.64 284.52-177.41a32.35 32.35 0 0 0 0-29.19M288 400c-98.65 0-189.09-55-237.93-144C98.91 167 189.34 112 288 112s189.09 55 237.93 144C477.1 345 386.66 400 288 400" />
</svg>
);
export default SvgEye;

View file

@ -3,27 +3,22 @@ export { default as BarChart } from './BarChart';
export { default as Bars } from './Bars'; export { default as Bars } from './Bars';
export { default as Bolt } from './Bolt'; export { default as Bolt } from './Bolt';
export { default as Bookmark } from './Bookmark'; export { default as Bookmark } from './Bookmark';
export { default as Calendar } from './Calendar';
export { default as Change } from './Change'; export { default as Change } from './Change';
export { default as Clock } from './Clock'; export { default as Clock } from './Clock';
export { default as Compare } from './Compare'; export { default as Compare } from './Compare';
export { default as Dashboard } from './Dashboard'; export { default as Dashboard } from './Dashboard';
export { default as Expand } from './Expand'; export { default as Expand } from './Expand';
export { default as Eye } from './Eye';
export { default as Flag } from './Flag'; export { default as Flag } from './Flag';
export { default as Funnel } from './Funnel'; export { default as Funnel } from './Funnel';
export { default as Gear } from './Gear'; export { default as Gear } from './Gear';
export { default as Globe } from './Globe';
export { default as Lightbulb } from './Lightbulb'; export { default as Lightbulb } from './Lightbulb';
export { default as Lightning } from './Lightning'; export { default as Lightning } from './Lightning';
export { default as Link } from './Link';
export { default as Location } from './Location'; export { default as Location } from './Location';
export { default as Lock } from './Lock'; export { default as Lock } from './Lock';
export { default as LogoWhite } from './LogoWhite'; export { default as LogoWhite } from './LogoWhite';
export { default as Logo } from './Logo'; export { default as Logo } from './Logo';
export { default as Magnet } from './Magnet'; export { default as Magnet } from './Magnet';
export { default as Money } from './Money'; export { default as Money } from './Money';
export { default as Moon } from './Moon';
export { default as Network } from './Network'; export { default as Network } from './Network';
export { default as Nodes } from './Nodes'; export { default as Nodes } from './Nodes';
export { default as Overview } from './Overview'; export { default as Overview } from './Overview';
@ -34,10 +29,8 @@ export { default as Redo } from './Redo';
export { default as Reports } from './Reports'; export { default as Reports } from './Reports';
export { default as Security } from './Security'; export { default as Security } from './Security';
export { default as Speaker } from './Speaker'; export { default as Speaker } from './Speaker';
export { default as Sun } from './Sun';
export { default as Tag } from './Tag'; export { default as Tag } from './Tag';
export { default as Target } from './Target'; export { default as Target } from './Target';
export { default as User } from './User'; export { default as User } from './User';
export { default as Users } from './Users';
export { default as Visitor } from './Visitor'; export { default as Visitor } from './Visitor';
export { default as Website } from './Website'; export { default as Website } from './Website';