fix(page-templates): clean up page-embed node chrome (#39)

Two design problems on the whole-page embed (pageEmbed) node:

- Double selection frame: the generic square cyan .ProseMirror-selectednode
  outline stacked on top of the rounded .includeWrap border. Add node-pageEmbed
  to the existing outline:none rule (already covering the transclusion nodes) so
  only the single rounded border remains.
- Redundant 'open source' controls: the floating toolbar's external-link button
  duplicated the header badge title link. Remove the toolbar button; the badge
  title is now the single way to open the source (kept Refresh + ... menu).
  Also swap the badge fallback icon IconArrowsMaximize (read as 'expand') for a
  neutral IconFileText.

Follow-ups from review: render the badge whenever the source resolves (so the
only open-source link can't vanish when title+icon are empty), and label the
link (title/aria-label) + add the 'Open source page' i18n key (en-US, ru-RU).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
claude code agent 227
2026-06-20 21:21:32 +03:00
parent 859223db1a
commit c9eb495688
4 changed files with 12 additions and 19 deletions

View File

@@ -474,6 +474,7 @@
"Make sub-pages public too": "Make sub-pages public too",
"Allow search engines to index page": "Allow search engines to index page",
"Open page": "Open page",
"Open source page": "Open source page",
"Page": "Page",
"Delete public share link": "Delete public share link",
"Delete share": "Delete share",

View File

@@ -472,6 +472,7 @@
"Make sub-pages public too": "Сделать подстраницы тоже общедоступными",
"Allow search engines to index page": "Разрешить поисковым системам индексировать страницу",
"Open page": "Открыть страницу",
"Open source page": "Открыть исходную страницу",
"Page": "Страница",
"Delete public share link": "Удалить публичную ссылку",
"Delete share": "Удалить общий доступ",

View File

@@ -2,10 +2,9 @@ import { NodeViewProps, NodeViewWrapper } from "@tiptap/react";
import { ActionIcon, Menu, Tooltip } from "@mantine/core";
import {
IconAlertTriangle,
IconArrowsMaximize,
IconDots,
IconExternalLink,
IconEyeOff,
IconFileText,
IconInfoCircle,
IconRefresh,
IconRepeat,
@@ -136,20 +135,6 @@ function PageEmbedBody({
<IconRefresh size={14} />
</ActionIcon>
</Tooltip>
{sourceHref && (
<Tooltip label={t("Open source page")}>
<ActionIcon
component={Link}
to={sourceHref}
variant="subtle"
color="gray"
size="sm"
style={{ textDecoration: "none", borderBottom: "none" }}
>
<IconExternalLink size={14} />
</ActionIcon>
</Tooltip>
)}
<Menu position="bottom-end" withinPortal onChange={trackOpen}>
<Menu.Target>
<ActionIcon variant="subtle" color="gray" size="sm">
@@ -170,13 +155,18 @@ function PageEmbedBody({
) : null;
const header =
sourceTitle || sourceIcon ? (
// Render the badge whenever the source resolves (sourceHref), not only when
// it has a title/icon — the title link is now the single way to open the
// source, so it must not disappear when title and icon are both empty.
sourceTitle || sourceIcon || sourceHref ? (
<div className={classes.transclusionBadge}>
{sourceIcon ? `${sourceIcon} ` : <IconArrowsMaximize size={12} />}
{sourceIcon ? `${sourceIcon} ` : <IconFileText size={12} />}
{sourceHref ? (
<Link
to={sourceHref}
style={{ borderBottom: "none", textDecoration: "none" }}
title={t("Open source page")}
aria-label={t("Open source page")}
>
{sourceTitle || t("Untitled")}
</Link>

View File

@@ -183,7 +183,8 @@
}
:global(.react-renderer.node-transclusionSource.ProseMirror-selectednode),
:global(.react-renderer.node-transclusionReference.ProseMirror-selectednode) {
:global(.react-renderer.node-transclusionReference.ProseMirror-selectednode),
:global(.react-renderer.node-pageEmbed.ProseMirror-selectednode) {
outline: none;
}