Skip to content

Commit 7ed6fdd

Browse files
artem-harbourArtem Nistuley
authored andcommitted
fix: improve toolbar responsiveness
1 parent 5d52db3 commit 7ed6fdd

File tree

5 files changed

+79
-46
lines changed

5 files changed

+79
-46
lines changed

packages/super-editor/src/editors/v1/components/toolbar/ButtonGroup.vue

Lines changed: 22 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -39,30 +39,37 @@ const props = defineProps({
3939
type: Boolean,
4040
default: false,
4141
},
42+
compactSideGroups: {
43+
type: Boolean,
44+
default: false,
45+
},
4246
});
4347
4448
const currentItem = ref(null);
4549
const { isHighContrastMode } = useHighContrastMode();
4650
// Matches media query from SuperDoc.vue
4751
const isMobile = window.matchMedia('(max-width: 768px)').matches;
48-
const styleMap = {
49-
left: {
50-
minWidth: '120px',
51-
justifyContent: 'flex-start',
52-
},
53-
right: {
54-
minWidth: '120px',
55-
justifyContent: 'flex-end',
56-
},
57-
default: {
52+
53+
const getPositionStyle = computed(() => {
54+
if (props.position === 'left') {
55+
return {
56+
minWidth: props.compactSideGroups ? 'auto' : '120px',
57+
justifyContent: 'flex-start',
58+
};
59+
}
60+
61+
if (props.position === 'right') {
62+
return {
63+
minWidth: props.compactSideGroups ? 'auto' : '120px',
64+
justifyContent: 'flex-end',
65+
};
66+
}
67+
68+
return {
5869
// Only grow if not on a mobile device
5970
flexGrow: isMobile ? 0 : 1,
6071
justifyContent: 'center',
61-
},
62-
};
63-
64-
const getPositionStyle = computed(() => {
65-
return styleMap[props.position] || styleMap.default;
72+
};
6673
});
6774
6875
const isButton = (item) => item.type === 'button';

packages/super-editor/src/editors/v1/components/toolbar/Toolbar.vue

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ const { proxy } = getCurrentInstance();
1414
const emit = defineEmits(['command', 'toggle', 'select']);
1515
1616
let toolbarKey = ref(1);
17+
const compactSideGroups = ref(false);
1718
1819
/**
1920
* Computed property that determines the font-family to use for toolbar UI surfaces.
@@ -40,9 +41,14 @@ const getFilteredItems = (position) => {
4041
return proxy.$toolbar.getToolbarItemByGroup(position).filter((item) => !excludeButtonsList.includes(item.name.value));
4142
};
4243
44+
const updateCompactSideGroups = () => {
45+
compactSideGroups.value = (proxy.$toolbar.toolbarContainer?.offsetWidth ?? 0) <= 1280;
46+
};
47+
4348
onMounted(() => {
4449
window.addEventListener('resize', onResizeThrottled);
4550
window.addEventListener('keydown', onKeyDown);
51+
updateCompactSideGroups();
4652
});
4753
4854
onDeactivated(() => {
@@ -66,6 +72,7 @@ const onKeyDown = async (e) => {
6672
6773
const onWindowResized = async () => {
6874
await proxy.$toolbar.onToolbarResize();
75+
updateCompactSideGroups();
6976
toolbarKey.value += 1;
7077
};
7178
const onResizeThrottled = throttle(onWindowResized, 300);
@@ -107,6 +114,7 @@ const handleToolbarMousedown = (e) => {
107114
tabindex="0"
108115
v-if="showLeftSide"
109116
:toolbar-items="getFilteredItems('left')"
117+
:compact-side-groups="compactSideGroups"
110118
:ui-font-family="uiFontFamily"
111119
position="left"
112120
@command="handleCommand"
@@ -117,6 +125,7 @@ const handleToolbarMousedown = (e) => {
117125
tabindex="0"
118126
:toolbar-items="getFilteredItems('center')"
119127
:overflow-items="proxy.$toolbar.overflowItems"
128+
:compact-side-groups="compactSideGroups"
120129
:ui-font-family="uiFontFamily"
121130
position="center"
122131
@command="handleCommand"
@@ -126,6 +135,7 @@ const handleToolbarMousedown = (e) => {
126135
tabindex="0"
127136
v-if="showRightSide"
128137
:toolbar-items="getFilteredItems('right')"
138+
:compact-side-groups="compactSideGroups"
129139
:ui-font-family="uiFontFamily"
130140
position="right"
131141
@command="handleCommand"
@@ -148,12 +158,6 @@ const handleToolbarMousedown = (e) => {
148158
z-index: var(--sd-ui-toolbar-z-index, 10);
149159
}
150160
151-
@media (max-width: 1280px) {
152-
.superdoc-toolbar-group-side {
153-
min-width: auto !important;
154-
}
155-
}
156-
157161
@media (max-width: 768px) {
158162
.superdoc-toolbar {
159163
padding: 4px 10px;

packages/super-editor/src/editors/v1/components/toolbar/ToolbarButton.vue

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -291,21 +291,19 @@ const caretIcon = computed(() => {
291291
height: 10px;
292292
}
293293
294-
@media (max-width: 1280px) {
295-
.toolbar-item--doc-mode .button-label {
296-
display: none;
297-
}
294+
.toolbar-item--doc-mode-compact .button-label {
295+
display: none;
296+
}
298297
299-
.toolbar-item--doc-mode .toolbar-icon {
300-
margin-right: 5px;
301-
}
298+
.toolbar-item--doc-mode-compact .toolbar-icon {
299+
margin-right: 5px;
300+
}
302301
303-
.toolbar-item--linked-styles {
304-
width: auto !important;
305-
}
302+
.toolbar-item--linked-styles-compact {
303+
width: auto !important;
304+
}
306305
307-
.toolbar-item--linked-styles .button-label {
308-
display: none;
309-
}
306+
.toolbar-item--linked-styles-compact .button-label {
307+
display: none;
310308
}
311309
</style>

packages/super-editor/src/editors/v1/components/toolbar/defaultItems.js

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -995,18 +995,38 @@ export const makeDefaultItems = ({
995995
}),
996996
});
997997

998-
// Responsive toolbar calculations
999-
const breakpoints = {
998+
// Responsive toolbar calculations.
999+
// `availableWidth` comes from SuperToolbar and represents either:
1000+
// - container width when `responsiveToContainer: true`
1001+
// - viewport/document width when `responsiveToContainer: false`
1002+
const RESPONSIVE_BREAKPOINTS = {
10001003
sm: 768,
10011004
md: 1024,
10021005
lg: 1280,
10031006
xl: 1410,
10041007
};
1008+
const XL_OVERFLOW_SAFETY_BUFFER = 20;
10051009
const stickyItemsWidth = 120;
10061010
const toolbarPadding = 32;
10071011

10081012
const itemsToHideXL = ['linkedStyles', 'clearFormatting', 'copyFormat', 'ruler'];
10091013
const itemsToHideSM = ['zoom', 'fontFamily', 'fontSize', 'redo'];
1014+
const shouldCompactDocumentMode = availableWidth <= RESPONSIVE_BREAKPOINTS.lg;
1015+
const shouldCompactLinkedStyles = availableWidth <= RESPONSIVE_BREAKPOINTS.lg;
1016+
1017+
if (shouldCompactDocumentMode) {
1018+
documentMode.attributes.value = {
1019+
...documentMode.attributes.value,
1020+
className: `${documentMode.attributes.value.className} toolbar-item--doc-mode-compact`,
1021+
};
1022+
}
1023+
1024+
if (shouldCompactLinkedStyles) {
1025+
linkedStyles.attributes.value = {
1026+
...linkedStyles.attributes.value,
1027+
className: `${linkedStyles.attributes.value.className} toolbar-item--linked-styles-compact`,
1028+
};
1029+
}
10101030

10111031
let toolbarItems = [
10121032
undo,
@@ -1053,7 +1073,7 @@ export const makeDefaultItems = ({
10531073
}
10541074

10551075
// Hide separators on small screens
1056-
if (availableWidth <= breakpoints.md && hideButtons) {
1076+
if (availableWidth <= RESPONSIVE_BREAKPOINTS.md && hideButtons) {
10571077
toolbarItems = toolbarItems.filter((item) => item.type !== 'separator');
10581078
}
10591079

@@ -1088,7 +1108,11 @@ export const makeDefaultItems = ({
10881108
toolbarItems.forEach((item) => {
10891109
const itemWidth = controlSizes.get(item.name.value) || controlSizes.get('default');
10901110

1091-
if (availableWidth < breakpoints.xl && itemsToHideXL.includes(item.name.value) && hideButtons) {
1111+
if (
1112+
availableWidth <= RESPONSIVE_BREAKPOINTS.xl + XL_OVERFLOW_SAFETY_BUFFER &&
1113+
itemsToHideXL.includes(item.name.value) &&
1114+
hideButtons
1115+
) {
10921116
overflowItems.push(item);
10931117
if (item.name.value === 'linkedStyles') {
10941118
const linkedStylesIdx = toolbarItems.findIndex((item) => item.name.value === 'linkedStyles');
@@ -1097,7 +1121,7 @@ export const makeDefaultItems = ({
10971121
return;
10981122
}
10991123

1100-
if (availableWidth < breakpoints.sm && itemsToHideSM.includes(item.name.value) && hideButtons) {
1124+
if (availableWidth < RESPONSIVE_BREAKPOINTS.sm && itemsToHideSM.includes(item.name.value) && hideButtons) {
11011125
overflowItems.push(item);
11021126
return;
11031127
}

packages/superdoc/src/dev/components/SuperdocDev.vue

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -730,7 +730,7 @@ const init = async () => {
730730
// },
731731
// fonts: null,
732732
// hideButtons: false,
733-
// responsiveToContainer: true,
733+
responsiveToContainer: true,
734734
excludeItems: [], // ['italic', 'bold'],
735735
// texts: {},
736736
},
@@ -853,12 +853,12 @@ const init = async () => {
853853
},
854854
}
855855
: {}),
856-
ai: {
857-
// Provide your Harbour API key here for direct endpoint access
858-
// apiKey: 'test',
859-
// Optional: Provide a custom endpoint for AI services
860-
// endpoint: 'https://sd-dev-express-gateway-i6xtm.ondigitalocean.app/insights',
861-
},
856+
// ai: {
857+
// Provide your Harbour API key here for direct endpoint access
858+
// apiKey: 'test',
859+
// Optional: Provide a custom endpoint for AI services
860+
// endpoint: 'https://sd-dev-express-gateway-i6xtm.ondigitalocean.app/insights',
861+
// },
862862
pdf: {
863863
pdfLib: pdfjsLib,
864864
setWorker: false,

0 commit comments

Comments
 (0)