mirror of
https://github.com/umami-software/umami.git
synced 2026-02-13 09:05:36 +01:00
This commit is contained in:
parent
30c45f888f
commit
3b4776b0e0
6 changed files with 2055 additions and 16 deletions
|
|
@ -72,7 +72,7 @@
|
||||||
"@react-spring/web": "^10.0.3",
|
"@react-spring/web": "^10.0.3",
|
||||||
"@svgr/cli": "^8.1.0",
|
"@svgr/cli": "^8.1.0",
|
||||||
"@tanstack/react-query": "^5.90.17",
|
"@tanstack/react-query": "^5.90.17",
|
||||||
"@umami/react-zen": "^0.229.0",
|
"@umami/react-zen": "^0.231.0",
|
||||||
"@umami/redis-client": "^0.30.0",
|
"@umami/redis-client": "^0.30.0",
|
||||||
"bcryptjs": "^3.0.2",
|
"bcryptjs": "^3.0.2",
|
||||||
"chalk": "^5.6.2",
|
"chalk": "^5.6.2",
|
||||||
|
|
|
||||||
1927
pnpm-lock.yaml
generated
1927
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load diff
|
|
@ -1,4 +1,4 @@
|
||||||
import { Icon, Row, Text } from '@umami/react-zen';
|
import { IconLabel, Row } from '@umami/react-zen';
|
||||||
import { WebsiteShareForm } from '@/app/(main)/websites/[websiteId]/settings/WebsiteShareForm';
|
import { WebsiteShareForm } from '@/app/(main)/websites/[websiteId]/settings/WebsiteShareForm';
|
||||||
import { Favicon } from '@/components/common/Favicon';
|
import { Favicon } from '@/components/common/Favicon';
|
||||||
import { LinkButton } from '@/components/common/LinkButton';
|
import { LinkButton } from '@/components/common/LinkButton';
|
||||||
|
|
@ -30,12 +30,9 @@ export function WebsiteHeader({ showActions }: { showActions?: boolean }) {
|
||||||
|
|
||||||
{showActions && (
|
{showActions && (
|
||||||
<Row alignItems="center" gap>
|
<Row alignItems="center" gap>
|
||||||
<ShareButton websiteId={website.id} shareId={website.shareId} />
|
<ShareButton websiteId={website?.id} shareId={website?.shareId} />
|
||||||
<LinkButton href={renderUrl(`/websites/${website.id}/settings`, false)}>
|
<LinkButton href={renderUrl(`/websites/${website.id}/settings`, false)}>
|
||||||
<Icon>
|
<IconLabel icon={<Edit />}>{formatMessage(labels.edit)}</IconLabel>
|
||||||
<Edit />
|
|
||||||
</Icon>
|
|
||||||
<Text>{formatMessage(labels.edit)}</Text>
|
|
||||||
</LinkButton>
|
</LinkButton>
|
||||||
</Row>
|
</Row>
|
||||||
)}
|
)}
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,8 @@
|
||||||
|
:root {
|
||||||
|
--font-family: var(--font-inter), sans-serif;
|
||||||
|
--text-primary: oklch(68.5% 0.169 237.323);
|
||||||
|
}
|
||||||
|
|
||||||
html,
|
html,
|
||||||
body {
|
body {
|
||||||
font-family: var(--font-family), sans-serif;
|
font-family: var(--font-family), sans-serif;
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ export function PageHeader({
|
||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
<Grid
|
<Grid
|
||||||
columns={{ xs: '1fr', md: '1fr 1fr' }}
|
columns={{ base: '1fr', md: '1fr 1fr' }}
|
||||||
paddingY="6"
|
paddingY="6"
|
||||||
marginBottom="6"
|
marginBottom="6"
|
||||||
border={showBorder ? 'bottom' : undefined}
|
border={showBorder ? 'bottom' : undefined}
|
||||||
|
|
@ -38,10 +38,10 @@ export function PageHeader({
|
||||||
)}
|
)}
|
||||||
{title && titleHref ? (
|
{title && titleHref ? (
|
||||||
<LinkButton href={titleHref} variant="quiet">
|
<LinkButton href={titleHref} variant="quiet">
|
||||||
<Heading size={{ xs: '2', md: '3', lg: '4' }}>{title}</Heading>
|
<Heading size={{ base: 'lg', md: '2xl', lg: '3xl' }}>{title}</Heading>
|
||||||
</LinkButton>
|
</LinkButton>
|
||||||
) : (
|
) : (
|
||||||
title && <Heading size={{ xs: '2', md: '3', lg: '4' }}>{title}</Heading>
|
title && <Heading size={{ base: 'lg', md: '2xl', lg: '3xl' }}>{title}</Heading>
|
||||||
)}
|
)}
|
||||||
</Row>
|
</Row>
|
||||||
{description && (
|
{description && (
|
||||||
|
|
|
||||||
122
src/components/common/Sidebar.tsx
Normal file
122
src/components/common/Sidebar.tsx
Normal file
|
|
@ -0,0 +1,122 @@
|
||||||
|
import {
|
||||||
|
Box,
|
||||||
|
Column,
|
||||||
|
type ColumnProps,
|
||||||
|
Focusable,
|
||||||
|
Icon,
|
||||||
|
Row,
|
||||||
|
type RowProps,
|
||||||
|
Text,
|
||||||
|
Tooltip,
|
||||||
|
TooltipTrigger,
|
||||||
|
} from '@umami/react-zen';
|
||||||
|
import classNames from 'classnames';
|
||||||
|
import { createContext, type ReactNode, useContext } from 'react';
|
||||||
|
|
||||||
|
export interface SidebarProps extends ColumnProps {
|
||||||
|
isCollapsed?: boolean;
|
||||||
|
muteItems?: boolean;
|
||||||
|
children?: ReactNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
const SidebarContext = createContext(null as any);
|
||||||
|
|
||||||
|
export function Sidebar({ isCollapsed, muteItems, className, children, ...props }: SidebarProps) {
|
||||||
|
return (
|
||||||
|
<SidebarContext.Provider value={{ isCollapsed }}>
|
||||||
|
<Column
|
||||||
|
{...props}
|
||||||
|
border="right"
|
||||||
|
width={isCollapsed ? '64px' : '240px'}
|
||||||
|
backgroundColor="surface-base"
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</Column>
|
||||||
|
</SidebarContext.Provider>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function SidebarSection({
|
||||||
|
title,
|
||||||
|
className,
|
||||||
|
children,
|
||||||
|
...props
|
||||||
|
}: { title?: string; children: ReactNode } & ColumnProps) {
|
||||||
|
return (
|
||||||
|
<Column {...props} paddingY="2" className={className}>
|
||||||
|
{title && (
|
||||||
|
<Box paddingX="4" paddingY="2">
|
||||||
|
<Text size="xs" weight="semibold" transform="uppercase" color="muted">
|
||||||
|
{title}
|
||||||
|
</Text>
|
||||||
|
</Box>
|
||||||
|
)}
|
||||||
|
<Column>{children}</Column>
|
||||||
|
</Column>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function SidebarHeader({
|
||||||
|
label,
|
||||||
|
icon,
|
||||||
|
className,
|
||||||
|
children,
|
||||||
|
...props
|
||||||
|
}: {
|
||||||
|
label: string;
|
||||||
|
icon?: ReactNode;
|
||||||
|
children?: ReactNode;
|
||||||
|
} & RowProps) {
|
||||||
|
return (
|
||||||
|
<Row {...props} paddingX="4" paddingY="3" gap="3" alignItems="center" className={className}>
|
||||||
|
{icon && <Icon size="sm">{icon}</Icon>}
|
||||||
|
{label && <Text weight="semibold">{label}</Text>}
|
||||||
|
{children}
|
||||||
|
</Row>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SidebarItemProps extends RowProps {
|
||||||
|
isSelected?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function SidebarItem({
|
||||||
|
label,
|
||||||
|
icon,
|
||||||
|
isSelected,
|
||||||
|
className,
|
||||||
|
children,
|
||||||
|
...props
|
||||||
|
}: {
|
||||||
|
label?: string;
|
||||||
|
icon?: ReactNode;
|
||||||
|
} & SidebarItemProps) {
|
||||||
|
const { isCollapsed } = useContext(SidebarContext);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<TooltipTrigger delay={0} closeDelay={0} isDisabled={!isCollapsed}>
|
||||||
|
<Focusable>
|
||||||
|
<Row
|
||||||
|
{...props}
|
||||||
|
paddingX={isCollapsed ? '0' : '4'}
|
||||||
|
paddingY="2"
|
||||||
|
gap="3"
|
||||||
|
alignItems="center"
|
||||||
|
justifyContent={isCollapsed ? 'center' : undefined}
|
||||||
|
borderRadius="md"
|
||||||
|
className={classNames(
|
||||||
|
'cursor-pointer',
|
||||||
|
'hover:bg-interactive',
|
||||||
|
isSelected && 'bg-interactive font-medium',
|
||||||
|
className,
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{icon && <Icon size="sm">{icon}</Icon>}
|
||||||
|
{label && !isCollapsed && <Text>{label}</Text>}
|
||||||
|
{children}
|
||||||
|
</Row>
|
||||||
|
</Focusable>
|
||||||
|
<Tooltip placement="right">{label}</Tooltip>
|
||||||
|
</TooltipTrigger>
|
||||||
|
);
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue