Skip to content

Commit bd876ce

Browse files
authored
ui(editor): tweak styling of popover components (#4640)
Fixes FER- ## Short description of the changes made - quick win pr: improves styling of our popover components by including the component name ![Screenshot 2025-10-31 at 12.51.49 PM.png](https://app.graphite.dev/user-attachments/assets/d3cefcd4-403e-42f6-be99-013319894570.png) ## What was the motivation & context behind this PR? - quick win (adds optional component name param to editable popover component) ## How has this PR been tested?
1 parent 41a4c51 commit bd876ce

File tree

19 files changed

+199
-131
lines changed

19 files changed

+199
-131
lines changed

packages/fern-dashboard/src/app/globals.css

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -751,3 +751,7 @@ code:not(.code-block) {
751751
[data-resize-handle-state] {
752752
cursor: ew-resize !important;
753753
}
754+
755+
.editor-component-title {
756+
@apply text-xs font-medium uppercase tracking-wide text-gray-900;
757+
}

packages/fern-dashboard/src/components/editor/TableActionsMenu.tsx

Lines changed: 33 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -27,31 +27,39 @@ export default function TableActionsMenu({
2727
<PopoverTrigger asChild>
2828
<EllipsisButton />
2929
</PopoverTrigger>
30-
<PopoverContent className="flex min-w-[200px] flex-col p-1">
31-
<p className="p-1 px-2 text-xs font-medium uppercase tracking-wide text-gray-900">Table</p>
32-
<Button
33-
variant="ghost"
34-
onClick={() => handleAdd("row")}
35-
disabled={disabled}
36-
className="justify-start"
37-
>
38-
<ArrowDown className="size-4" />
39-
Add Row
40-
</Button>
41-
<Button
42-
variant="ghost"
43-
onClick={() => handleAdd("col")}
44-
disabled={disabled}
45-
className="justify-start"
46-
>
47-
<ArrowRight className="size-4" />
48-
Add Column
49-
</Button>
50-
<hr className="border-border-default my-1" />
51-
<Button variant="ghost" onClick={() => deleteNode()} className="justify-start hover:text-red-600">
52-
<Trash2 className="h-4 w-4" />
53-
Delete Table
54-
</Button>
30+
<PopoverContent className="flex min-w-[200px] flex-col p-0">
31+
<p className="p-3 pb-1.5 editor-component-title">Table</p>
32+
<div className="border-border-default border-t" />
33+
<div className="flex flex-col gap-px p-1">
34+
<Button
35+
variant="ghost"
36+
onClick={() => handleAdd("row")}
37+
disabled={disabled}
38+
className="justify-start"
39+
>
40+
<ArrowDown className="size-4" />
41+
Add Row
42+
</Button>
43+
<Button
44+
variant="ghost"
45+
onClick={() => handleAdd("col")}
46+
disabled={disabled}
47+
className="justify-start"
48+
>
49+
<ArrowRight className="size-4" />
50+
Add Column
51+
</Button>
52+
53+
<hr className="border-border-default -mx-1 my-1" />
54+
<Button
55+
variant="ghost"
56+
onClick={() => deleteNode()}
57+
className="justify-start hover:text-red-600"
58+
>
59+
<Trash2 className="h-4 w-4" />
60+
Delete Table
61+
</Button>
62+
</div>
5563
</PopoverContent>
5664
</Popover>
5765
</div>

packages/fern-dashboard/src/components/editor/editor-component/EditorComponentPopover.tsx

Lines changed: 30 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -375,8 +375,10 @@ function ControlRenderer({
375375
// Button component
376376
export function EditorComponentPopoverButton<T extends AttributeConfig>({
377377
className,
378-
disableDelete
378+
disableDelete,
379+
componentName
379380
}: {
381+
componentName?: string;
380382
className?: string;
381383
disableDelete?: boolean;
382384
}) {
@@ -420,6 +422,9 @@ export function EditorComponentPopoverButton<T extends AttributeConfig>({
420422
setIsOpen(false);
421423
};
422424

425+
const hasAttributes = Object.keys(attributes).length > 0;
426+
const showDividerUnderComponentName = componentName && hasAttributes;
427+
423428
return (
424429
<Popover.Root
425430
open={isOpen}
@@ -448,19 +453,30 @@ export function EditorComponentPopoverButton<T extends AttributeConfig>({
448453
)}
449454
sideOffset={5}
450455
>
451-
<div className="flex-1 space-y-3 overflow-y-auto p-4">
452-
{(Object.entries(attributes) as [keyof T, T[keyof T]][]).map(([name, control]) => (
453-
<ControlRenderer
454-
key={name as string}
455-
name={name as string}
456-
control={control}
457-
value={tempValues[name]}
458-
onChange={(value) => setTempValues((prev) => ({ ...prev, [name]: value }))}
459-
/>
460-
))}
461-
</div>
456+
{componentName && <div className="editor-component-title p-3 pb-1.5">{componentName}</div>}
457+
{showDividerUnderComponentName && <div className="border-border-default border-t" />}
458+
{hasAttributes && (
459+
<div className="flex-1 space-y-3 overflow-y-auto p-3 pt-2">
460+
{(Object.entries(attributes) as [keyof T, T[keyof T]][]).map(([name, control]) => (
461+
<ControlRenderer
462+
key={name as string}
463+
name={name as string}
464+
control={control}
465+
value={tempValues[name]}
466+
onChange={(value) => setTempValues((prev) => ({ ...prev, [name]: value }))}
467+
/>
468+
))}
469+
</div>
470+
)}
462471

463-
<div className="bg-popover border-border-default flex shrink-0 justify-between rounded-b-lg border-t p-2">
472+
<div
473+
className={cn(
474+
"bg-popover border-border-default flex shrink-0 justify-between rounded-b-lg border-t p-2",
475+
{
476+
"justify-end": disableDelete
477+
}
478+
)}
479+
>
464480
{!disableDelete && (
465481
<Button
466482
variant="ghost"
@@ -472,7 +488,7 @@ export function EditorComponentPopoverButton<T extends AttributeConfig>({
472488
</Button>
473489
)}
474490

475-
<div className="flex gap-2">
491+
<div className="flex gap-2 self-end">
476492
<Button variant="ghost" size="sm" onClick={handleCancelPressed}>
477493
Cancel
478494
</Button>

packages/fern-dashboard/src/components/editor/table/TableHeaderActionsMenu.tsx

Lines changed: 48 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -16,51 +16,54 @@ export default function TableHeaderActionsMenu(props: NodeViewProps) {
1616
<PopoverTrigger asChild>
1717
<EllipsisButton orientation="horizontal" className="w-fit bg-gray-400 px-1 py-0 hover:bg-gray-400" />
1818
</PopoverTrigger>
19-
<PopoverContent className="table-popover flex min-w-[200px] flex-col p-1">
20-
<p className="p-1 px-2 text-xs font-medium uppercase tracking-wide text-gray-900">Column</p>
21-
<Button
22-
variant="ghost"
23-
onClick={() => {
24-
const pos = getPos();
25-
if (pos !== undefined) {
26-
editor.chain().focus().setTextSelection(pos).addColumnBefore().run();
27-
}
28-
}}
29-
disabled={disabled}
30-
className="justify-start"
31-
>
32-
<ArrowLeft className="size-4" />
33-
Insert Column Before
34-
</Button>
35-
<Button
36-
variant="ghost"
37-
onClick={() => {
38-
const pos = getPos();
39-
if (pos !== undefined) {
40-
editor.chain().focus().setTextSelection(pos).addColumnAfter().run();
41-
}
42-
}}
43-
disabled={disabled}
44-
className="justify-start"
45-
>
46-
<ArrowRight className="size-4" />
47-
Insert Column After
48-
</Button>
49-
<hr className="border-border-default my-1" />
50-
<Button
51-
variant="ghost"
52-
onClick={() => {
53-
const pos = getPos();
54-
if (pos !== undefined) {
55-
editor.chain().focus().setTextSelection(pos).deleteColumn().run();
56-
}
57-
}}
58-
disabled={disabled}
59-
className="justify-start hover:text-red-600"
60-
>
61-
<Trash2 className="size-4" />
62-
Delete Column
63-
</Button>
19+
<PopoverContent className="table-popover flex min-w-[200px] flex-col p-0">
20+
<p className="p-3 pb-1.5 editor-component-title">Column</p>
21+
<div className="border-border-default border-t" />
22+
<div className="flex flex-col gap-px p-1">
23+
<Button
24+
variant="ghost"
25+
onClick={() => {
26+
const pos = getPos();
27+
if (pos !== undefined) {
28+
editor.chain().focus().setTextSelection(pos).addColumnBefore().run();
29+
}
30+
}}
31+
disabled={disabled}
32+
className="justify-start"
33+
>
34+
<ArrowLeft className="size-4" />
35+
Insert Column Before
36+
</Button>
37+
<Button
38+
variant="ghost"
39+
onClick={() => {
40+
const pos = getPos();
41+
if (pos !== undefined) {
42+
editor.chain().focus().setTextSelection(pos).addColumnAfter().run();
43+
}
44+
}}
45+
disabled={disabled}
46+
className="justify-start"
47+
>
48+
<ArrowRight className="size-4" />
49+
Insert Column After
50+
</Button>
51+
<hr className="border-border-default -mx-1 my-1" />
52+
<Button
53+
variant="ghost"
54+
onClick={() => {
55+
const pos = getPos();
56+
if (pos !== undefined) {
57+
editor.chain().focus().setTextSelection(pos).deleteColumn().run();
58+
}
59+
}}
60+
disabled={disabled}
61+
className="justify-start hover:text-red-600"
62+
>
63+
<Trash2 className="size-4" />
64+
Delete Column
65+
</Button>
66+
</div>
6467
</PopoverContent>
6568
</Popover>
6669
);

packages/fern-dashboard/src/components/editor/table/TableRowActionsMenu.tsx

Lines changed: 38 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -26,53 +26,56 @@ export default function TableRowActionsMenu(props: NodeViewProps) {
2626
<PopoverTrigger asChild>
2727
<EllipsisButton className="bg-gray-400 px-0 py-1 hover:bg-gray-400" disabled={disabled} />
2828
</PopoverTrigger>
29-
<PopoverContent className="flex min-w-[200px] flex-col p-1">
30-
<p className="p-1 px-2 text-xs font-medium uppercase tracking-wide text-gray-900">Row</p>
31-
{!isHeaderRow && (
29+
<PopoverContent className="flex min-w-[200px] flex-col p-0">
30+
<p className="p-3 pb-1.5 editor-component-title">Row</p>
31+
<div className="border-border-default border-t" />
32+
<div className="flex flex-col gap-px p-1">
33+
{!isHeaderRow && (
34+
<Button
35+
variant="ghost"
36+
onClick={() => {
37+
const pos = getPos();
38+
if (pos !== undefined) {
39+
const cellPos = pos + 2; // Add 2 so that we are inside the first cell
40+
editor.chain().focus().setTextSelection(cellPos).addRowBefore().run();
41+
}
42+
}}
43+
className="justify-start"
44+
>
45+
<ArrowUp className="size-4" />
46+
Insert Row Above
47+
</Button>
48+
)}
3249
<Button
3350
variant="ghost"
3451
onClick={() => {
3552
const pos = getPos();
3653
if (pos !== undefined) {
3754
const cellPos = pos + 2; // Add 2 so that we are inside the first cell
38-
editor.chain().focus().setTextSelection(cellPos).addRowBefore().run();
55+
editor.chain().focus().setTextSelection(cellPos).addRowAfter().run();
3956
}
4057
}}
4158
className="justify-start"
4259
>
43-
<ArrowUp className="size-4" />
44-
Insert Row Above
60+
<ArrowDown className="size-4" />
61+
Insert Row Below
4562
</Button>
46-
)}
47-
<Button
48-
variant="ghost"
49-
onClick={() => {
50-
const pos = getPos();
51-
if (pos !== undefined) {
52-
const cellPos = pos + 2; // Add 2 so that we are inside the first cell
53-
editor.chain().focus().setTextSelection(cellPos).addRowAfter().run();
54-
}
55-
}}
56-
className="justify-start"
57-
>
58-
<ArrowDown className="size-4" />
59-
Insert Row Below
60-
</Button>
6163

62-
{!isHeaderRow && (
63-
<>
64-
<hr className="border-border-default my-1" />
65-
<Button
66-
variant="ghost"
67-
onClick={() => deleteRow()}
68-
disabled={disabled}
69-
className="justify-start hover:text-red-600"
70-
>
71-
<Trash2 className="size-4" />
72-
Delete Row
73-
</Button>
74-
</>
75-
)}
64+
{!isHeaderRow && (
65+
<>
66+
<hr className="border-border-default -mx-1 my-1" />
67+
<Button
68+
variant="ghost"
69+
onClick={() => deleteRow()}
70+
disabled={disabled}
71+
className="justify-start hover:text-red-600"
72+
>
73+
<Trash2 className="size-4" />
74+
Delete Row
75+
</Button>
76+
</>
77+
)}
78+
</div>
7679
</PopoverContent>
7780
</Popover>
7881
);

packages/fern-dashboard/src/docs/mdx/components/accordion/AccordionGroup.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,10 @@ export function AccordionGroup({ children }: AccordionGroupProps) {
157157
<AccordionContext.Provider value={contextValue}>
158158
<div ref={popoverRef} className="relative">
159159
{isWithinEditor && (
160-
<EditorComponentPopoverButton className="absolute -right-8 top-2 z-10 h-auto w-auto px-2" />
160+
<EditorComponentPopoverButton
161+
className="absolute -right-8 top-2 z-10 h-auto w-auto px-2"
162+
componentName="Accordion Group"
163+
/>
161164
)}
162165
<AccordionComponent.Accordion
163166
type="multiple"
@@ -266,6 +269,7 @@ function AccordionItem({
266269
{isWithinEditor && (
267270
<EditorComponentPopoverButton
268271
className="absolute right-2 top-2 h-auto w-auto px-2"
272+
componentName="Accordion"
269273
disableDelete={isInGroup && accordions.length === 1}
270274
/>
271275
)}

packages/fern-dashboard/src/docs/mdx/components/button/Button.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,9 @@ export function Button({
6464

6565
const buttonContent = (
6666
<div ref={buttonRef} className="relative inline-block">
67-
{isWithinEditor && <EditorComponentPopoverButton className="absolute -right-[38px] top-0" />}
67+
{isWithinEditor && (
68+
<EditorComponentPopoverButton className="absolute -right-[38px] top-0" componentName="Button" />
69+
)}
6870
{href != null ? (
6971
<DisableFernAnchor>
7072
<FernLinkButton

packages/fern-dashboard/src/docs/mdx/components/callout/Callout.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,9 @@ export const Callout: FC<PropsWithChildren<Callout.Props>> = ({ intent: intentRa
4242

4343
const calloutContent = (
4444
<div ref={calloutRef} data-intent={intent} className="fern-callout relative">
45-
{isWithinEditor && <EditorComponentPopoverButton className="absolute right-2 top-2" />}
45+
{isWithinEditor && (
46+
<EditorComponentPopoverButton className="absolute right-2 top-2" componentName="Callout" />
47+
)}
4648
<div className="flex items-start space-x-4">
4749
<div className="[&_svg]:size-icon-md mt-0.5 w-4">
4850
{typeof icon === "string" ? (

packages/fern-dashboard/src/docs/mdx/components/card/Card.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ export const Card: React.FC<Card.Props> = ({
6969
const content = (
7070
<div ref={popoverRef} className="relative">
7171
<div className="absolute -right-4 -top-4 flex items-center gap-1">
72-
{isWithinEditor && <EditorComponentPopoverButton className="h-full" />}
72+
{isWithinEditor && <EditorComponentPopoverButton className="h-full" componentName="Card" />}
7373
{badge != null && <Badge intent="primary">{badge}</Badge>}
7474
</div>
7575
<div

0 commit comments

Comments
 (0)