diff --git a/packages/extension-polkagate/src/components/Convictions.tsx b/packages/extension-polkagate/src/components/Convictions.tsx
index 47c83dd35..52b43647c 100644
--- a/packages/extension-polkagate/src/components/Convictions.tsx
+++ b/packages/extension-polkagate/src/components/Convictions.tsx
@@ -18,7 +18,7 @@ interface Props {
export const DEFAULT_CONVICTION = 1;
-export default function Convictions ({ address, children, conviction, setConviction, style }: Props): React.ReactElement {
+export default function Convictions({ address, children, conviction, setConviction, style }: Props): React.ReactElement {
const { t } = useTranslation();
const theme = useTheme();
@@ -39,14 +39,13 @@ export default function Convictions ({ address, children, conviction, setConvict
const info = useMemo((): string => {
const newText = convictionOptions?.find(({ value }) => value === (conviction || DEFAULT_CONVICTION))?.text;
const match = newText?.match(/\(([^)]+)\)/);
- const result = match ? match[1] : '0 days';
- return 'Tokens will be locked for ' + result;
+ return match ? match[1] : '0 days';
}, [conviction, convictionOptions]);
const marks = useMemo(() =>
convictionOptions?.map(({ value }) => ({ label: `${value} X`, value: value as number }))
- , [convictionOptions]);
+ , [convictionOptions]);
const valuetext = useCallback((value: number) => {
return `${value} X`;
@@ -84,6 +83,7 @@ export default function Convictions ({ address, children, conviction, setConvict
size='small'
step={null}
sx={{
+ mx:'10px',
'& .MuiSlider-rail': {
color: 'action.focus' // Non-selected track color
},
@@ -97,9 +97,17 @@ export default function Convictions ({ address, children, conviction, setConvict
valueLabelDisplay='auto'
/>
{children}
-
- {t(info)}
-
+
+
+
+ {t('Tokens will be locked for')}
+
+
+
+ {info}
+
+
+
);
}
diff --git a/packages/extension-polkagate/src/fullscreen/governance/components/DraggableModalWithTitle.tsx b/packages/extension-polkagate/src/fullscreen/governance/components/DraggableModalWithTitle.tsx
new file mode 100644
index 000000000..90a1fffa1
--- /dev/null
+++ b/packages/extension-polkagate/src/fullscreen/governance/components/DraggableModalWithTitle.tsx
@@ -0,0 +1,106 @@
+// Copyright 2019-2024 @polkadot/extension-polkagate authors & contributors
+// SPDX-License-Identifier: Apache-2.0
+
+/* eslint-disable react/jsx-max-props-per-line */
+
+import type { IconDefinition } from '@fortawesome/fontawesome-svg-core';
+
+import { Box, Modal, useTheme } from '@mui/material';
+import React, { useCallback, useMemo, useState } from 'react';
+
+import ModalTitleWithDrag from '../../partials/ModalTitleWithDrag';
+
+interface Props {
+ width?: number;
+ maxHeight?: number;
+ minHeight?: number;
+ children: React.ReactElement;
+ open: boolean;
+ onClose: () => void
+ title: string;
+ icon?: string | IconDefinition;
+}
+
+export function DraggableModalWithTitle ({ children, icon, maxHeight = 740, minHeight = 615, onClose, open, title, width = 500 }: Props): React.ReactElement {
+ const theme = useTheme();
+
+ const isDarkMode = useMemo(() => theme.palette.mode === 'dark', [theme.palette.mode]);
+
+ const [isDragging, setIsDragging] = useState(false);
+ const initialX = (window.innerWidth - width) / 2;
+ const initialY = (window.innerHeight - maxHeight) / 2;
+
+ const [modalPosition, setModalPosition] = useState({ x: initialX, y: initialY });
+ const [dragStartPosition, setDragStartPosition] = useState({ x: 0, y: 0 });
+
+ const handleMouseDown = useCallback((e: { clientX: number; clientY: number; }) => {
+ setIsDragging(true);
+ setDragStartPosition({ x: e.clientX, y: e.clientY });
+ }, []);
+
+ const _onClose = useCallback((_event: unknown, reason: string) => {
+ if (reason && reason === 'backdropClick') {
+ return;
+ }
+
+ onClose();
+ }, [onClose]);
+
+ const handleMouseMove = useCallback((e: { clientX: number; clientY: number; }) => {
+ if (isDragging) {
+ const dx = e.clientX - dragStartPosition.x;
+ const dy = e.clientY - dragStartPosition.y;
+
+ setModalPosition((prevPosition) => ({
+ x: prevPosition.x + dx,
+ y: prevPosition.y + dy
+ }));
+ setDragStartPosition({ x: e.clientX, y: e.clientY });
+ }
+ }, [dragStartPosition, isDragging]);
+
+ const handleMouseUp = useCallback(() => {
+ setIsDragging(false);
+ }, []);
+
+ const style = {
+ '&:focus': {
+ outline: 'none' // Remove outline when Box is focused
+ },
+ bgcolor: 'background.default',
+ border: isDarkMode ? '0.5px solid' : 'none',
+ borderColor: 'secondary.light',
+ borderRadius: '10px',
+ boxShadow: 24,
+ cursor: isDragging ? 'grabbing' : 'grab',
+ left: modalPosition.x,
+ maxHeight: `${maxHeight}px`,
+ minHeight: `${minHeight}px`,
+ pb: 3,
+ position: 'absolute',
+ pt: 2,
+ px: 4,
+ top: modalPosition.y,
+ width: `${width}px`
+ };
+
+ return (
+
+
+
+ {children}
+
+
+ );
+}
diff --git a/packages/extension-polkagate/src/fullscreen/governance/post/castVote/index.tsx b/packages/extension-polkagate/src/fullscreen/governance/post/castVote/index.tsx
index b5abaadcc..e13196e98 100644
--- a/packages/extension-polkagate/src/fullscreen/governance/post/castVote/index.tsx
+++ b/packages/extension-polkagate/src/fullscreen/governance/post/castVote/index.tsx
@@ -18,8 +18,7 @@ import { cryptoWaitReady } from '@polkadot/util-crypto';
import { useInfo, useProxies, useTranslation } from '../../../../hooks';
import { PROXY_TYPE } from '../../../../util/constants';
import { amountToHuman, amountToMachine } from '../../../../util/utils';
-import SimpleModalTitle from '../../../partials/SimpleModalTitle';
-import { DraggableModal } from '../../components/DraggableModal';
+import { DraggableModalWithTitle } from '../../components/DraggableModalWithTitle';
import SelectProxyModal2 from '../../components/SelectProxyModal2';
import WaitScreen from '../../partials/WaitScreen';
import { getVoteType } from '../../utils/util';
@@ -187,13 +186,8 @@ export default function Index ({ address, cantModify, hasVoted, myVote, notVoted
}, [notVoted, step]);
return (
-
+
<>
-
{step === STEPS.ABOUT &&
}
>
-
+
);
}
diff --git a/packages/extension-polkagate/src/fullscreen/partials/ModalTitleWithDrag.tsx b/packages/extension-polkagate/src/fullscreen/partials/ModalTitleWithDrag.tsx
new file mode 100644
index 000000000..504f458bb
--- /dev/null
+++ b/packages/extension-polkagate/src/fullscreen/partials/ModalTitleWithDrag.tsx
@@ -0,0 +1,70 @@
+// Copyright 2019-2024 @polkadot/extension-polkagate authors & contributors
+// SPDX-License-Identifier: Apache-2.0
+
+/* eslint-disable react/jsx-max-props-per-line */
+
+import type { IconDefinition, IconProp } from '@fortawesome/fontawesome-svg-core';
+
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
+import { Close as CloseIcon, DragIndicator as DragIndicatorIcon } from '@mui/icons-material';
+import { Divider, Grid, IconButton, Typography, useTheme } from '@mui/material';
+import React from 'react';
+
+import { Infotip2, VaadinIcon } from '../../components';
+import { useTranslation } from '../../hooks';
+
+interface Props {
+ onClose: () => void;
+ title: string;
+ icon?: string | IconDefinition;
+ onMouseDown: (e: { clientX: number; clientY: number; }) => void;
+ onMouseMove?: (e: { clientX: number; clientY: number; }) => void;
+ onMouseUp?: () => void
+}
+
+export default function ModalTitleWithDrag ({ icon, onClose, onMouseDown, onMouseMove, onMouseUp, title }: Props): React.ReactElement {
+ const theme = useTheme();
+ const { t } = useTranslation();
+
+ const isIconVaadin = typeof icon === 'string' && icon?.startsWith('vaadin');
+ const isIconFontAwesome = !!icon;
+
+ return (
+
+
+ {icon &&
+ <>
+ {isIconVaadin
+ ?
+ : isIconFontAwesome
+ ?
+ : <>>
+ }
+ >}
+
+ {title}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+}