stylize Notifier update
This commit is contained in:
@ -1,12 +1,77 @@
|
|||||||
import { Alert, Box, Snackbar, Button } from '@mui/material';
|
import {
|
||||||
|
Alert,
|
||||||
|
Box,
|
||||||
|
Snackbar,
|
||||||
|
Button,
|
||||||
|
Stack,
|
||||||
|
Typography,
|
||||||
|
Paper,
|
||||||
|
} from '@mui/material';
|
||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
|
import { styled, alpha, keyframes } from '@mui/material/styles';
|
||||||
|
|
||||||
|
export const GRADIENT =
|
||||||
|
'linear-gradient(71deg, #F27121 0%, #E940CD 70%, #8A2387 100%)';
|
||||||
|
|
||||||
|
const glowPulse = keyframes`
|
||||||
|
0% { opacity: .6 }
|
||||||
|
50% { opacity: 1 }
|
||||||
|
100% { opacity: .6 }
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const GlassCard = styled(Paper)(() => ({
|
||||||
|
position: 'relative',
|
||||||
|
overflow: 'hidden',
|
||||||
|
borderRadius: 18,
|
||||||
|
background: 'rgba(0,0,0,0.45)',
|
||||||
|
border: '1px solid rgba(255,255,255,0.12)',
|
||||||
|
backdropFilter: 'blur(14px)',
|
||||||
|
boxShadow: '0 16px 40px rgba(0,0,0,0.45)',
|
||||||
|
}));
|
||||||
|
|
||||||
|
export const Glow = styled('div')(() => ({
|
||||||
|
position: 'absolute',
|
||||||
|
inset: -2,
|
||||||
|
background:
|
||||||
|
'radial-gradient(400px 120px at 10% 0%, rgba(242,113,33,0.25), transparent 60%),' +
|
||||||
|
'radial-gradient(400px 120px at 90% 0%, rgba(233,64,205,0.25), transparent 60%)',
|
||||||
|
pointerEvents: 'none',
|
||||||
|
animation: `${glowPulse} 5s ease-in-out infinite`,
|
||||||
|
}));
|
||||||
|
|
||||||
|
export const GradientButton = styled(Button)(() => ({
|
||||||
|
background: GRADIENT,
|
||||||
|
borderRadius: 999,
|
||||||
|
textTransform: 'none',
|
||||||
|
fontWeight: 700,
|
||||||
|
'&:hover': {
|
||||||
|
background: GRADIENT,
|
||||||
|
filter: 'brightness(1.08)',
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
|
||||||
|
export const SoftButton = styled(Button)(() => ({
|
||||||
|
borderRadius: 999,
|
||||||
|
textTransform: 'none',
|
||||||
|
color: '#fff',
|
||||||
|
border: '1px solid rgba(255,255,255,0.14)',
|
||||||
|
background: 'rgba(255,255,255,0.06)',
|
||||||
|
'&:hover': { background: 'rgba(255,255,255,0.1)' },
|
||||||
|
}));
|
||||||
|
|
||||||
|
type Severity = 'error' | 'warning' | 'info' | 'success';
|
||||||
|
|
||||||
|
const severityColor: Record<Severity, string> = {
|
||||||
|
info: '#4fc3f7',
|
||||||
|
success: '#4caf50',
|
||||||
|
warning: '#ff9800',
|
||||||
|
error: '#f44336',
|
||||||
|
};
|
||||||
|
|
||||||
export const Notifier = () => {
|
export const Notifier = () => {
|
||||||
const [open, setOpen] = useState(false);
|
const [open, setOpen] = useState(false);
|
||||||
const [message, setMessage] = useState('');
|
const [message, setMessage] = useState('');
|
||||||
const [severity, setSeverity] = useState<
|
const [severity, setSeverity] = useState<Severity>('info');
|
||||||
'error' | 'warning' | 'info' | 'success'
|
|
||||||
>('info');
|
|
||||||
const [hasUpdateAvailable, setHasUpdateAvailable] = useState(false);
|
const [hasUpdateAvailable, setHasUpdateAvailable] = useState(false);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -24,6 +89,15 @@ export const Notifier = () => {
|
|||||||
};
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (process.env.NODE_ENV === 'development') {
|
||||||
|
setMessage('Доступно новое обновление (dev preview)');
|
||||||
|
setSeverity('info');
|
||||||
|
setHasUpdateAvailable(true);
|
||||||
|
setOpen(true);
|
||||||
|
}
|
||||||
|
}, []);
|
||||||
|
|
||||||
const handleClose = () => {
|
const handleClose = () => {
|
||||||
setOpen(false);
|
setOpen(false);
|
||||||
};
|
};
|
||||||
@ -34,30 +108,48 @@ export const Notifier = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box>
|
<Snackbar
|
||||||
<Snackbar
|
open={open}
|
||||||
open={open}
|
onClose={handleClose}
|
||||||
autoHideDuration={hasUpdateAvailable ? null : 6000}
|
autoHideDuration={hasUpdateAvailable ? null : 5000}
|
||||||
onClose={handleClose}
|
anchorOrigin={{ vertical: 'bottom', horizontal: 'center' }}
|
||||||
>
|
>
|
||||||
<Alert
|
<GlassCard sx={{ minWidth: 340 }}>
|
||||||
severity={severity}
|
<Glow />
|
||||||
action={
|
|
||||||
hasUpdateAvailable && (
|
<Box
|
||||||
<>
|
sx={{
|
||||||
<Button color="primary" size="small" onClick={handleUpdate}>
|
p: 2,
|
||||||
Обновить сейчас
|
position: 'relative',
|
||||||
</Button>
|
gap: 1,
|
||||||
<Button color="secondary" size="small" onClick={handleClose}>
|
display: 'flex',
|
||||||
Позже
|
flexDirection: 'column',
|
||||||
</Button>
|
}}
|
||||||
</>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
>
|
>
|
||||||
{message}
|
<Typography
|
||||||
</Alert>
|
sx={{
|
||||||
</Snackbar>
|
color: 'rgba(255,255,255,0.82)',
|
||||||
</Box>
|
fontSize: 13.5,
|
||||||
|
lineHeight: 1.35,
|
||||||
|
pr: hasUpdateAvailable ? 1 : 0,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{message}
|
||||||
|
</Typography>
|
||||||
|
|
||||||
|
{hasUpdateAvailable && (
|
||||||
|
<Stack direction="row" spacing={1} justifyContent="center" gap={1}>
|
||||||
|
<SoftButton size="small" onClick={handleUpdate}>
|
||||||
|
Обновить
|
||||||
|
</SoftButton>
|
||||||
|
|
||||||
|
<SoftButton size="small" onClick={handleClose}>
|
||||||
|
Позже
|
||||||
|
</SoftButton>
|
||||||
|
</Stack>
|
||||||
|
)}
|
||||||
|
</Box>
|
||||||
|
</GlassCard>
|
||||||
|
</Snackbar>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user