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

@ -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 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 {
data: {
@ -12,7 +13,7 @@ export interface BreadcrumbProps {
export function Breadcrumb({ data }: BreadcrumbProps) {
return (
<Flexbox alignItems="center" gap={3} className={styles.bar}>
<Row alignItems="center" gap className={styles.bar}>
{data.map((a, i) => {
return (
<Fragment key={i}>
@ -25,12 +26,12 @@ export function Breadcrumb({ data }: BreadcrumbProps) {
)}
{i !== data.length - 1 ? (
<Icon rotate={270}>
<Icons.Chevron />
<Chevron />
</Icon>
) : null}
</Fragment>
);
})}
</Flexbox>
</Row>
);
}

View file

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

View file

@ -1,6 +1,6 @@
import { ReactNode } from 'react';
import { Icon, Text, Column } from '@umami/react-zen';
import { Icons } from '@/components/icons';
import { Logo } from '@/components/icons';
export interface EmptyPlaceholderProps {
message?: string;
@ -11,7 +11,7 @@ export function EmptyPlaceholder({ message, children }: EmptyPlaceholderProps) {
return (
<Column alignItems="center" justifyContent="center" gap="5" height="100%" width="100%">
<Icon size="xl" fillColor="3" strokeColor="3">
<Icons.Logo />
<Logo />
</Icon>
<Text>{message}</Text>
<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 { useMessages } from '@/components/hooks';
import { Alert } from '@/components/icons';
export function ErrorMessage() {
const { formatMessage, messages } = useMessages();
@ -8,7 +9,7 @@ export function ErrorMessage() {
return (
<div className={styles.error}>
<Icon className={styles.icon} size="lg">
<Icons.Alert />
<Alert />
</Icon>
<Text>{formatMessage(messages.error)}</Text>
</div>

View file

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

View file

@ -7,10 +7,10 @@ import {
ListItem,
Select,
Icon,
Icons,
Button,
} from '@umami/react-zen';
import { useFilters } from '@/components/hooks';
import { Close } from '@/components/icons';
export interface FilterRecordProps {
name: string;
@ -55,7 +55,7 @@ export function FilterRecord({
<Column justifyContent="flex-end">
<Button variant="quiet" onPress={() => onRemove?.(name)}>
<Icon>
<Icons.Close />
<Close />
</Icon>
</Button>
</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 { Close, Menu } from '@/components/icons';
import { MobileMenu } from './MobileMenu';
export function HamburgerButton({ menuItems }: { menuItems: any[] }) {
@ -11,7 +12,7 @@ export function HamburgerButton({ menuItems }: { menuItems: any[] }) {
return (
<>
<Button variant="quiet" onClick={handleClick}>
<Icon>{active ? <Icons.Close /> : <Icons.Menu />}</Icon>
<Icon>{active ? <Close /> : <Menu />}</Icon>
</Button>
{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 { Chevron } from '@/components/icons';
export interface PagerProps {
page: string | number;
@ -38,12 +39,12 @@ export function Pager({ page, pageSize, count, onPageChange }: PagerProps) {
<Text>{formatMessage(labels.pageOf, { current: page, total: maxPage })}</Text>
<Button onPress={() => handlePageChange(-1)} isDisabled={firstPage}>
<Icon size="sm" rotate={180}>
<Icons.Chevron />
<Chevron />
</Icon>
</Button>
<Button onPress={() => handlePageChange(1)} isDisabled={lastPage}>
<Icon size="sm">
<Icons.Chevron />
<Chevron />
</Icon>
</Button>
</Row>

View file

@ -40,6 +40,7 @@ export * from './useFields';
export * from './useFilters';
export * from './useForceUpdate';
export * from './useFormat';
export * from './useGlobalState';
export * from './useLanguageNames';
export * from './useLocale';
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 })];
};
export default useGlobalState;
export { useGlobalState };

View file

@ -1,12 +1,33 @@
import { Icons as ZenIcons } from '@umami/react-zen';
import * as lucide from 'lucide-react';
import * as LocalIcons from '@/components/svg';
const icons = {
...ZenIcons,
...LocalIcons,
};
export const Lucide = lucide;
export const Icons = icons;
export {
AlertTriangle as Alert,
ArrowRight as Arrow,
Calendar,
ChevronRight as Chevron,
X as Close,
Copy,
Edit,
Ellipsis,
Eye,
ExternalLink,
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 { 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 { Close } from '@/components/icons';
import { isSearchOperator } from '@/lib/params';
export function FilterBar() {
@ -51,8 +52,8 @@ export function FilterBar() {
{paramValue}
</Text>
</Row>
<Icon onClick={e => handleCloseFilter(name, e)} size="xs" color>
<Icons.Close />
<Icon onClick={e => handleCloseFilter(name, e)} size="xs">
<Close />
</Icon>
</Row>
</Row>
@ -62,7 +63,7 @@ export function FilterBar() {
<TooltipTrigger delay={0}>
<Button variant="quiet" onPress={handleResetFilter}>
<Icon>
<Icons.Close />
<Close />
</Icon>
</Button>
<Tooltip>

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -5,7 +5,7 @@ import { LinkButton } from '@/components/common/LinkButton';
import { DEFAULT_ANIMATION_DURATION } from '@/lib/constants';
import { percentFilter } from '@/lib/filters';
import { useNavigation, useWebsiteMetricsQuery, useMessages, useFormat } from '@/components/hooks';
import { Icons } from '@/components/icons';
import { Arrow } from '@/components/icons';
import { ListTable, ListTableProps } from './ListTable';
export interface MetricsTableProps extends ListTableProps {
@ -98,7 +98,7 @@ export function MetricsTable({
<LinkButton href={renderUrl({ view: type })} variant="quiet">
<Text>{formatMessage(labels.more)}</Text>
<Icon size="sm">
<Icons.Arrow />
<Arrow />
</Icon>
</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 Bolt } from './Bolt';
export { default as Bookmark } from './Bookmark';
export { default as Calendar } from './Calendar';
export { default as Change } from './Change';
export { default as Clock } from './Clock';
export { default as Compare } from './Compare';
export { default as Dashboard } from './Dashboard';
export { default as Expand } from './Expand';
export { default as Eye } from './Eye';
export { default as Flag } from './Flag';
export { default as Funnel } from './Funnel';
export { default as Gear } from './Gear';
export { default as Globe } from './Globe';
export { default as Lightbulb } from './Lightbulb';
export { default as Lightning } from './Lightning';
export { default as Link } from './Link';
export { default as Location } from './Location';
export { default as Lock } from './Lock';
export { default as LogoWhite } from './LogoWhite';
export { default as Logo } from './Logo';
export { default as Magnet } from './Magnet';
export { default as Money } from './Money';
export { default as Moon } from './Moon';
export { default as Network } from './Network';
export { default as Nodes } from './Nodes';
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 Security } from './Security';
export { default as Speaker } from './Speaker';
export { default as Sun } from './Sun';
export { default as Tag } from './Tag';
export { default as Target } from './Target';
export { default as User } from './User';
export { default as Users } from './Users';
export { default as Visitor } from './Visitor';
export { default as Website } from './Website';