Skip to content

Commit a5e82dd

Browse files
feat: Table row/column extension UI (#1172)
* Added buttons to extend table rows/columns * Added proper extend button implementations * Fixed table handle menu buttons not preserving column widths * Implemented PR feedback * Implemented PR feedback * Cleaned up code * Updated test snapshots & fixes * Added unit tests for column widths * remaining todos * prosemirror-tables upgrade * show buttons when to right / bottom of table * fix lint * fix names * fix small bugs * fix drag handle * fix safari support (will require prosemirror-tables upgrade * add comment * fix safari --------- Co-authored-by: yousefed <[email protected]>
1 parent 8867e64 commit a5e82dd

File tree

53 files changed

+2186
-271
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

53 files changed

+2186
-271
lines changed

package-lock.json

Lines changed: 4 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/ariakit/src/index.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ import { SuggestionMenuItem } from "./suggestionMenu/SuggestionMenuItem.js";
3939
import { SuggestionMenuLabel } from "./suggestionMenu/SuggestionMenuLabel.js";
4040
import { SuggestionMenuLoader } from "./suggestionMenu/SuggestionMenuLoader.js";
4141
import { TableHandle } from "./tableHandle/TableHandle.js";
42+
import { ExtendButton } from "./tableHandle/ExtendButton.js";
4243
import { Toolbar } from "./toolbar/Toolbar.js";
4344
import { ToolbarButton } from "./toolbar/ToolbarButton.js";
4445
import { ToolbarSelect } from "./toolbar/ToolbarSelect.js";
@@ -81,6 +82,7 @@ export const components: Components = {
8182
},
8283
TableHandle: {
8384
Root: TableHandle,
85+
ExtendButton: ExtendButton,
8486
},
8587
Generic: {
8688
Form: {

packages/ariakit/src/style.css

Lines changed: 106 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -6,181 +6,206 @@
66
@import "./ariakitStyles.css";
77

88
.bn-ak-input-wrapper {
9-
align-items: center;
10-
display: flex;
11-
gap: 0.5rem;
9+
align-items: center;
10+
display: flex;
11+
gap: 0.5rem;
1212
}
1313

1414
.bn-toolbar .bn-ak-button {
15-
width: unset;
15+
width: unset;
1616
}
1717

1818
.bn-toolbar .bn-ak-button[data-selected] {
19-
padding-top: 0.125rem;
20-
box-shadow: inset 0 0 0 1px var(--border), inset 0 2px 0 var(--border);
19+
padding-top: 0.125rem;
20+
box-shadow: inset 0 0 0 1px var(--border), inset 0 2px 0 var(--border);
2121
}
2222

2323
.bn-toolbar .bn-ak-button[data-selected]:where(.dark, .dark *) {
24-
box-shadow: inset 0 0 0 1px var(--border), inset 0 1px 1px 1px var(--shadow);
24+
box-shadow: inset 0 0 0 1px var(--border), inset 0 1px 1px 1px var(--shadow);
2525
}
2626

2727
.bn-toolbar .bn-ak-popover {
28-
gap: 0.5rem;
28+
gap: 0.5rem;
2929
}
3030

3131
.bn-ariakit .bn-tab-panel {
32-
align-items: center;
33-
display: flex;
34-
flex-direction: column;
35-
gap: 0.5rem;
32+
align-items: center;
33+
display: flex;
34+
flex-direction: column;
35+
gap: 0.5rem;
3636
}
3737

3838
.bn-ariakit .bn-file-input {
39-
max-width: 100%;
39+
max-width: 100%;
4040
}
4141

4242
.bn-ak-button {
43-
outline-style: none;
43+
outline-style: none;
4444
}
4545

4646
.bn-ak-menu-item[aria-selected="true"],
4747
.bn-ak-menu-item:hover {
48-
background-color: hsl(204 100% 40%);
49-
color: hsl(204 20% 100%);
48+
background-color: hsl(204 100% 40%);
49+
color: hsl(204 20% 100%);
5050
}
5151

5252
.bn-ak-menu-item {
53-
display: flex;
53+
display: flex;
5454
}
5555

5656
.bn-ariakit .bn-dropdown {
57-
overflow: visible;
57+
overflow: visible;
5858
}
5959

6060
.bn-ariakit .bn-suggestion-menu {
61-
height: fit-content;
62-
max-height: 100%;
61+
height: fit-content;
62+
max-height: 100%;
6363
}
6464

6565
.bn-ariakit .bn-color-picker-dropdown {
66-
overflow: scroll;
66+
overflow: scroll;
6767
}
6868

6969
.bn-ak-suggestion-menu-item-body {
70-
flex: 1;
70+
flex: 1;
7171
}
7272

7373
.bn-ak-suggestion-menu-item-subtitle {
74-
font-size: 0.7rem;
74+
font-size: 0.7rem;
7575
}
7676

7777
.bn-ak-suggestion-menu-item-section[data-position="left"] {
78-
padding: 8px;
78+
padding: 8px;
7979
}
8080

8181
.bn-ak-suggestion-menu-item-section[data-position="right"] {
82-
--border: rgb(0 0 0/13%);
83-
--highlight: rgb(255 255 255/20%);
84-
--shadow: rgb(0 0 0/10%);
85-
box-shadow: inset 0 0 0 1px var(--border), inset 0 2px 0 var(--highlight),
82+
--border: rgb(0 0 0/13%);
83+
--highlight: rgb(255 255 255/20%);
84+
--shadow: rgb(0 0 0/10%);
85+
box-shadow: inset 0 0 0 1px var(--border), inset 0 2px 0 var(--highlight),
8686
inset 0 -1px 0 var(--shadow), 0 1px 1px var(--shadow);
87-
font-size: 0.7rem;
88-
border-radius: 4px;
89-
padding-inline: 4px;
87+
font-size: 0.7rem;
88+
border-radius: 4px;
89+
padding-inline: 4px;
9090
}
9191

9292
.bn-ariakit .bn-grid-suggestion-menu {
93-
background: var(--bn-colors-menu-background);
94-
border-radius: var(--bn-border-radius-large);
95-
box-shadow: var(--bn-shadow-medium);
96-
display: grid;
97-
gap: 7px;
98-
height: fit-content;
99-
justify-items: center;
100-
max-height: min(500px, 100%);
101-
overflow-y: auto;
102-
padding: 20px;
93+
background: var(--bn-colors-menu-background);
94+
border-radius: var(--bn-border-radius-large);
95+
box-shadow: var(--bn-shadow-medium);
96+
display: grid;
97+
gap: 7px;
98+
height: fit-content;
99+
justify-items: center;
100+
max-height: min(500px, 100%);
101+
overflow-y: auto;
102+
padding: 20px;
103103
}
104104

105105
.bn-ariakit .bn-grid-suggestion-menu-item {
106-
align-items: center;
107-
border-radius: var(--bn-border-radius-large);
108-
cursor: pointer;
109-
display: flex;
110-
font-size: 24px;
111-
height: 32px;
112-
justify-content: center;
113-
margin: 2px;
114-
padding: 4px;
115-
width: 32px;
106+
align-items: center;
107+
border-radius: var(--bn-border-radius-large);
108+
cursor: pointer;
109+
display: flex;
110+
font-size: 24px;
111+
height: 32px;
112+
justify-content: center;
113+
margin: 2px;
114+
padding: 4px;
115+
width: 32px;
116116
}
117117

118118
.bn-ariakit .bn-grid-suggestion-menu-item[aria-selected="true"],
119119
.bn-ariakit .bn-grid-suggestion-menu-item:hover {
120-
background-color: var(--bn-colors-hovered-background);
120+
background-color: var(--bn-colors-hovered-background);
121121
}
122122

123123
.bn-ariakit .bn-grid-suggestion-menu-empty-item,
124124
.bn-ariakit .bn-grid-suggestion-menu-loader {
125-
align-items: center;
126-
color: var(--bn-colors-menu-text);
127-
display: flex;
128-
font-size: 14px;
129-
font-weight: 500;
130-
height: 32px;
131-
justify-content: center;
125+
align-items: center;
126+
color: var(--bn-colors-menu-text);
127+
display: flex;
128+
font-size: 14px;
129+
font-weight: 500;
130+
height: 32px;
131+
justify-content: center;
132132
}
133133

134134
.bn-ariakit .bn-grid-suggestion-menu-loader span {
135-
background-color: var(--bn-colors-side-menu);
135+
background-color: var(--bn-colors-side-menu);
136136
}
137137

138138
.bn-ariakit .bn-side-menu {
139-
align-items: center;
140-
display: flex;
141-
justify-content: center;
139+
align-items: center;
140+
display: flex;
141+
justify-content: center;
142142
}
143143

144144
.bn-side-menu .bn-ak-button {
145-
height: fit-content;
146-
padding: 0;
147-
width: fit-content;
145+
height: fit-content;
146+
padding: 0;
147+
width: fit-content;
148148
}
149149

150150
.bn-ariakit .bn-panel-popover {
151-
background-color: transparent;
152-
border: none;
153-
box-shadow: none;
151+
background-color: transparent;
152+
border: none;
153+
box-shadow: none;
154154
}
155155

156156
.bn-ariakit .bn-table-handle {
157-
height: fit-content;
158-
padding: 0;
159-
width: fit-content;
157+
height: fit-content;
158+
padding: 0;
159+
width: fit-content;
160160
}
161161

162162
.bn-ariakit .bn-side-menu,
163-
.bn-ariakit .bn-table-handle {
164-
color: gray;
163+
.bn-ariakit .bn-table-handle,
164+
.bn-ariakit .bn-extend-button {
165+
color: gray;
166+
}
167+
168+
.bn-ariakit .bn-extend-button-editing {
169+
background-color: hsl(204 4% 0% / 0.05);
170+
}
171+
172+
.bn-ariakit .bn-extend-button-editing:where(.dark, .dark *) {
173+
background-color: hsl(204 20% 100% / 0.05);
174+
}
175+
176+
.bn-ariakit .bn-extend-button-add-remove-columns {
177+
height: 100%;
178+
width: 18px;
179+
padding: 0;
180+
margin-left: 4px;
181+
cursor: col-resize;
182+
}
183+
184+
.bn-ariakit .bn-extend-button-add-remove-rows {
185+
height: 18px;
186+
width: 100%;
187+
padding: 0;
188+
margin-top: 4px;
189+
cursor: row-resize;
165190
}
166191

167192
.bn-ak-button:where(.dark, .dark *) {
168-
color: hsl(204 20% 100%);
193+
color: hsl(204 20% 100%);
169194
}
170195

171196
.bn-ak-tab,
172197
.bn-ariakit .bn-file-input {
173-
background-color: transparent;
174-
color: black;
198+
background-color: transparent;
199+
color: black;
175200
}
176201

177202
.bn-ak-tab:where(.dark, .dark *),
178203
.bn-ariakit .bn-file-input:where(.dark, .dark *) {
179-
color: white;
204+
color: white;
180205
}
181206

182207
.bn-ak-tooltip {
183-
align-items: center;
184-
display: flex;
185-
flex-direction: column;
208+
align-items: center;
209+
display: flex;
210+
flex-direction: column;
186211
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import { Button as AriakitButton } from "@ariakit/react";
2+
3+
import { assertEmpty, mergeCSSClasses } from "@blocknote/core";
4+
import { ComponentProps } from "@blocknote/react";
5+
import { forwardRef } from "react";
6+
7+
export const ExtendButton = forwardRef<
8+
HTMLButtonElement,
9+
ComponentProps["TableHandle"]["ExtendButton"]
10+
>((props, ref) => {
11+
const { children, className, onMouseDown, onClick, ...rest } = props;
12+
13+
// false, because rest props can be added by mantine when button is used as a trigger
14+
// assertEmpty in this case is only used at typescript level, not runtime level
15+
assertEmpty(rest, false);
16+
17+
return (
18+
<AriakitButton
19+
className={mergeCSSClasses(
20+
"bn-ak-button bn-ak-secondary",
21+
className || ""
22+
)}
23+
ref={ref}
24+
onMouseDown={onMouseDown}
25+
onClick={onClick}
26+
{...rest}>
27+
{children}
28+
</AriakitButton>
29+
);
30+
});

packages/core/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@
8282
"hast-util-from-dom": "^4.2.0",
8383
"prosemirror-model": "^1.21.0",
8484
"prosemirror-state": "^1.4.3",
85-
"prosemirror-tables": "^1.3.7",
85+
"prosemirror-tables": "^1.6.1",
8686
"prosemirror-transform": "^1.9.0",
8787
"prosemirror-view": "^1.33.7",
8888
"rehype-format": "^5.0.0",

0 commit comments

Comments
 (0)