Test favicon, fix remove/add overlap bug, fix badge overlapping component bug

This commit is contained in:
Francis Cao
2026-03-12 11:28:19 -07:00
parent 534af98809
commit 013c929cd1
4 changed files with 68 additions and 39 deletions
+28 -2
View File
@@ -1,12 +1,38 @@
import { Icon, Row, Text } from '@umami/react-zen';
import { useState } from 'react';
import { Favicon } from '@/components/common/Favicon';
import { Globe, Grid2x2, Link } from '@/components/icons';
import type { BoardEntityType } from '@/lib/boards';
export function BoardEntityBadge({ type, name }: { type: BoardEntityType; name: string }) {
function WebsiteIcon({ domain }: { domain?: string }) {
const [failed, setFailed] = useState(false);
if (domain && !failed) {
return <Favicon domain={domain} onError={() => setFailed(true)} />;
}
return <Globe />;
}
export function BoardEntityBadge({
type,
name,
domain,
}: {
type: BoardEntityType;
name: string;
domain?: string;
}) {
return (
<Row padding borderRadius="full" backgroundColor="surface-base" border gap="2">
<Icon>
{type === 'pixel' ? <Grid2x2 /> : type === 'link' ? <Link /> : <Globe />}
{type === 'pixel' ? (
<Grid2x2 />
) : type === 'link' ? (
<Link />
) : (
<WebsiteIcon domain={domain} />
)}
</Icon>
<Text size="sm">{name}</Text>
</Row>
@@ -1,3 +1,8 @@
import { Panel } from '@/components/common/Panel';
import { useBoard, useMessages, useNavigation } from '@/components/hooks';
import { Pencil, Plus, X } from '@/components/icons';
import { getBoardEntity, getBoardType, getResolvedComponentEntity } from '@/lib/boards';
import type { BoardComponentConfig } from '@/lib/types';
import {
Box,
Button,
@@ -10,11 +15,6 @@ import {
TooltipTrigger,
} from '@umami/react-zen';
import { useMemo, useState } from 'react';
import { Panel } from '@/components/common/Panel';
import { useBoard, useMessages, useNavigation } from '@/components/hooks';
import { Pencil, Plus, X } from '@/components/icons';
import { getBoardEntity, getBoardType, getResolvedComponentEntity } from '@/lib/boards';
import type { BoardComponentConfig } from '@/lib/types';
import { getComponentDefinition } from '../boardComponentRegistry';
import { BoardComponentRenderer } from './BoardComponentRenderer';
import { BoardComponentSelect } from './BoardComponentSelect';
@@ -79,7 +79,7 @@ export function BoardEditColumn({
onMouseEnter={() => setShowActions(true)}
onMouseLeave={() => setShowActions(false)}
>
{canEdit && canRemoveAction && showActions && (
{canEdit && (showActions || !hasComponent) && (
<Box
position="absolute"
top="50%"
@@ -87,44 +87,39 @@ export function BoardEditColumn({
zIndex={100}
style={{ transform: 'translate(-50%, -50%)' }}
>
<Row gap="1" padding="2" borderRadius backgroundColor="surface-sunken">
{hasComponent && (
<TooltipTrigger delay={0}>
<Button variant="outline" onPress={() => setShowSelect(true)}>
<Icon size="sm">
<Pencil />
</Icon>
</Button>
<Tooltip>{t(labels.edit)}</Tooltip>
</TooltipTrigger>
)}
<Row
gap="1"
padding={hasComponent ? '2' : undefined}
borderRadius={hasComponent || undefined}
backgroundColor={hasComponent ? 'surface-sunken' : undefined}
>
<TooltipTrigger delay={0}>
<Button variant="outline" onPress={handleRemove} isDisabled={!canRemoveAction}>
<Button variant="outline" onPress={() => setShowSelect(true)}>
<Icon size="sm">
<X />
{hasComponent ? <Pencil /> : <Plus />}
</Icon>
</Button>
<Tooltip>{t(labels.remove)}</Tooltip>
<Tooltip>{t(hasComponent ? labels.edit : labels.selectComponent)}</Tooltip>
</TooltipTrigger>
{canRemoveAction && (
<TooltipTrigger delay={0}>
<Button variant="outline" onPress={handleRemove}>
<Icon size="sm">
<X />
</Icon>
</Button>
<Tooltip>{t(labels.remove)}</Tooltip>
</TooltipTrigger>
)}
</Row>
</Box>
)}
{renderedComponent ? (
{renderedComponent && (
<Column width="100%" height="100%" style={{ minHeight: 0 }}>
<Box width="100%" flexGrow={1} overflow="auto" style={{ minHeight: 0 }}>
{renderedComponent}
</Box>
</Column>
) : (
canEdit && (
<Column width="100%" height="100%" alignItems="center" justifyContent="center">
<Button variant="outline" onPress={() => setShowSelect(true)}>
<Icon>
<Plus />
</Icon>
</Button>
</Column>
)
)}
<Modal isOpen={showSelect} onOpenChange={setShowSelect}>
<Dialog
@@ -1,4 +1,4 @@
import { Box, Column } from '@umami/react-zen';
import { Box, Column, Row } from '@umami/react-zen';
import { Panel } from '@/components/common/Panel';
import { useBoard } from '@/components/hooks';
import { getBoardType, getResolvedComponentEntity, isOpenBoardType } from '@/lib/boards';
@@ -28,12 +28,20 @@ export function BoardViewColumn({
const title = component.title;
const description = component.description;
const showBadge = showEntityBadge && isOpenBoardType(boardType) && !!entityBadge;
return (
<Panel title={title} description={description} height="100%" position="relative">
{showEntityBadge && isOpenBoardType(boardType) && entityBadge && (
<Box position="absolute" top="12px" right="12px" zIndex={100}>
<BoardEntityBadge {...entityBadge} />
</Box>
{showBadge && (
title ? (
<Box position="absolute" top="12px" right="12px" zIndex={100}>
<BoardEntityBadge {...entityBadge} />
</Box>
) : (
<Row justifyContent="flex-end">
<BoardEntityBadge {...entityBadge} />
</Row>
)
)}
<Column width="100%" height="100%" style={{ minHeight: 0 }}>
<Box width="100%" flexGrow={1} style={{ minHeight: 0 }}>
@@ -13,7 +13,7 @@ export function useBoardEntityBadgeProps(
const { data: link } = useLinkQuery(enabled && entityType === 'link' ? entityId : undefined);
if (entityType === 'website' && website?.name) {
return { type: entityType, name: website.name };
return { type: entityType, name: website.name, domain: website.domain ?? undefined };
}
if (entityType === 'pixel' && pixel?.name) {