Skip to content

Commit 772cb78

Browse files
committed
ui: use inline slideout impl
1 parent 0890c75 commit 772cb78

3 files changed

Lines changed: 82 additions & 30 deletions

File tree

packages/ui-default/components/navigation/navigation.page.js

Lines changed: 68 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import $ from 'jquery';
2-
import Slideout from 'slideout';
32
import Notification from 'vj/components/notification';
43
import selectUser from 'vj/components/selectUser';
54
import { AutoloadPage } from 'vj/misc/Page';
@@ -88,23 +87,76 @@ const navigationPage = new AutoloadPage('navigationPage', () => {
8887
$(document).on('click', '[name="nav_logout"]', handleNavLogoutClick);
8988
$(document).on('click', '[name="nav_switch_account"]', handlerSwitchAccount);
9089

91-
const slideout = new Slideout({
92-
panel: document.getElementById('panel'),
93-
menu: document.getElementById('menu'),
94-
padding: 200,
95-
tolerance: 70,
96-
side: 'right',
97-
});
98-
[['beforeopen', 'add'], ['beforeclose', 'remove']].forEach(([event, action]) => {
99-
slideout.on(event, () => $('.header__hamburger .hamburger')[`${action}Class`]('is-active'));
100-
});
101-
90+
let isOpen = false;
91+
const panel = document.getElementById('panel');
10292
const $slideoutOverlay = $('.slideout-overlay');
103-
$slideoutOverlay.on('click', () => slideout.close());
104-
slideout.on('beforeopen', () => $slideoutOverlay.show());
105-
slideout.on('beforeclose', () => $slideoutOverlay.hide());
93+
const $hamburger = $('.header__hamburger .hamburger');
94+
const PADDING = 200;
95+
const TOLERANCE = 70;
96+
97+
function setTranslateX(x) {
98+
panel.style.transform = x ? `translateX(${x}px)` : '';
99+
}
100+
101+
function open() {
102+
isOpen = true;
103+
$('html').addClass('slideout-open');
104+
setTranslateX(-PADDING);
105+
$hamburger.addClass('is-active');
106+
$slideoutOverlay.show();
107+
}
108+
109+
function close() {
110+
isOpen = false;
111+
setTranslateX(0);
112+
$hamburger.removeClass('is-active');
113+
$slideoutOverlay.hide();
114+
$('html').removeClass('slideout-open');
115+
}
116+
117+
// Touch swipe support
118+
let touchStartX = 0;
119+
let touchCurrentX = 0;
120+
let isSwiping = false;
121+
122+
panel.addEventListener('touchstart', (e) => {
123+
if (e.target.closest('[data-slideout-ignore]')) return;
124+
touchStartX = e.touches[0].clientX;
125+
touchCurrentX = touchStartX;
126+
isSwiping = false;
127+
}, { passive: true });
128+
129+
panel.addEventListener('touchmove', (e) => {
130+
touchCurrentX = e.touches[0].clientX;
131+
const dx = touchStartX - touchCurrentX;
132+
if (!isSwiping) {
133+
if (Math.abs(dx) < 10) return;
134+
isSwiping = true;
135+
if (!isOpen) $slideoutOverlay.show();
136+
$('html').addClass('slideout-open');
137+
panel.style.transition = 'none';
138+
}
139+
setTranslateX(isOpen
140+
? Math.max(-PADDING, Math.min(0, -PADDING - dx))
141+
: Math.max(-PADDING, Math.min(0, -dx)));
142+
}, { passive: true });
143+
144+
panel.addEventListener('touchend', () => {
145+
if (!isSwiping) return;
146+
panel.style.transition = '';
147+
const dx = touchStartX - touchCurrentX;
148+
if (isOpen) {
149+
if (-dx > TOLERANCE) close();
150+
else open();
151+
} else {
152+
if (dx > TOLERANCE) open();
153+
else close();
154+
}
155+
isSwiping = false;
156+
});
106157

107-
$('.header__hamburger').on('click', () => slideout.toggle());
158+
$slideoutOverlay.on('click', close);
159+
$('.header__hamburger').on('click', () => (isOpen ? close() : open()));
108160
$(window).on('resize', handleNavbar);
109161
setInterval(handleNavbar, 3000);
110162
}, () => {

packages/ui-default/misc/slideout.styl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ body, #panel
1111
.slideout-panel
1212
position: relative
1313
z-index: 1
14+
transition: transform .3s ease
1415

1516
.slideout-overlay
1617
display: none

packages/ui-default/package.json

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,11 @@
2020
"@fontsource/source-code-pro": "^5.2.7",
2121
"@fontsource/ubuntu-mono": "^5.2.8",
2222
"@hydrooj/utils": "workspace:^",
23-
"@mantine/core": "^9.0.0",
24-
"@mantine/hooks": "^9.0.0",
25-
"@mantine/notifications": "^9.0.0",
26-
"@sentry/browser": "^10.47.0",
27-
"@sentry/webpack-plugin": "^5.1.1",
23+
"@mantine/core": "^9.0.2",
24+
"@mantine/hooks": "^9.0.2",
25+
"@mantine/notifications": "^9.0.2",
26+
"@sentry/browser": "^10.49.0",
27+
"@sentry/webpack-plugin": "^5.2.0",
2828
"@simplewebauthn/browser": "13.2.2",
2929
"@svgr/webpack": "^8.1.0",
3030
"@types/html-to-text": "^9.0.4",
@@ -45,14 +45,14 @@
4545
"@vscode/codicons": "^0.0.45",
4646
"ajv": "^8.18.0",
4747
"allotment": "^1.20.5",
48-
"autoprefixer": "^10.4.27",
48+
"autoprefixer": "^10.5.0",
4949
"browser-update": "^3.3.63",
5050
"chalk": "^5.6.2",
5151
"classnames": "^2.5.1",
5252
"clean-webpack-plugin": "^4.0.0",
5353
"clipboard": "^2.0.11",
5454
"copy-webpack-plugin": "^14.0.0",
55-
"cordis": "4.0.0-rc.0",
55+
"cordis": "4.0.0-rc.2",
5656
"core-js": "^3.49.0",
5757
"core-js-compat": "^3.49.0",
5858
"css-loader": "^7.1.4",
@@ -69,18 +69,18 @@
6969
"jquery.transit": "^0.9.12",
7070
"mantine-contextmenu": "^8.3.13",
7171
"matchmedia-polyfill": "^0.3.2",
72-
"md-editor-rt": "^6.4.1",
72+
"md-editor-rt": "^6.4.2",
7373
"mini-css-extract-plugin": "^2.10.2",
7474
"moment": "^2.30.1",
7575
"monaco-editor": "0.52.2",
7676
"monaco-editor-nls": "^3.1.0",
7777
"monaco-editor-webpack-plugin": "^7.1.1",
7878
"monaco-themes": "0.4.7",
7979
"monaco-yaml": "5.4.1",
80-
"nanoid": "^5.1.7",
80+
"nanoid": "^5.1.9",
8181
"normalize.css": "^8.0.1",
8282
"nprogress": "^0.2.0",
83-
"p-queue": "^9.1.1",
83+
"p-queue": "^9.1.2",
8484
"pickadate": "patch:pickadate@npm%3A3.6.4#~/.yarn/patches/pickadate-npm-3.6.4-5795acb19d.patch",
8585
"postcss-loader": "7.3.4",
8686
"postcss-preset-mantine": "^1.18.0",
@@ -89,11 +89,11 @@
8989
"prop-types": "^15.8.1",
9090
"qface": "^1.4.1",
9191
"qrcode": "^1.5.4",
92-
"react": "^19.2.4",
92+
"react": "^19.2.5",
9393
"react-colorful": "^5.6.1",
9494
"react-dnd": "^16.0.1",
9595
"react-dnd-html5-backend": "^16.0.1",
96-
"react-dom": "^19.2.4",
96+
"react-dom": "^19.2.5",
9797
"react-redux": "^9.2.0",
9898
"reconnecting-websocket": "^4.4.0",
9999
"redux": "^5.0.1",
@@ -105,7 +105,6 @@
105105
"sass-loader": "^16.0.7",
106106
"schemastery": "^3.18.0",
107107
"shorty.js": "^1.0.1",
108-
"slideout": "^1.0.1",
109108
"sticky-kit": "^1.1.3",
110109
"style-loader": "^4.0.0",
111110
"stylus": "^0.64.0",
@@ -117,7 +116,7 @@
117116
"timeago.js": "^4.0.2",
118117
"ts-loader": "^9.5.7",
119118
"web-streams-polyfill": "^4.2.0",
120-
"webpack": "^5.105.4",
119+
"webpack": "^5.106.2",
121120
"webpack-bundle-analyzer": "^5.3.0",
122121
"webpack-dev-server": "^5.2.3",
123122
"webpack-manifest-plugin": "^6.0.1",

0 commit comments

Comments
 (0)