UI/update global UI (#459)
* Update loading screen to use Lottie animation - Replace simple logo with Lottie animation from loadercalendar.lottie - Center animation on screen with full viewport coverage - Set animation width to 175px - Install @lottiefiles/dotlottie-react package * update spacing event modal * add twake workplace logo to loading screen * update spacing create calendar modal * fix evenchip description color * using variant instead of sx
This commit is contained in:
@@ -88,7 +88,8 @@ export function AccessTab({ calendar }: { calendar: Calendar }) {
|
||||
<TextField
|
||||
disabled
|
||||
fullWidth
|
||||
label={t("calendar.caldav_access")}
|
||||
label=""
|
||||
inputProps={{ "aria-label": t("calendar.caldav_access") }}
|
||||
value={calDAVLink}
|
||||
size="small"
|
||||
InputProps={{
|
||||
@@ -109,7 +110,8 @@ export function AccessTab({ calendar }: { calendar: Calendar }) {
|
||||
<TextField
|
||||
disabled
|
||||
fullWidth
|
||||
label={t("calendar.secretUrl")}
|
||||
label=""
|
||||
inputProps={{ "aria-label": t("calendar.secretUrl") }}
|
||||
value={secretLink}
|
||||
size="small"
|
||||
InputProps={{
|
||||
|
||||
@@ -359,3 +359,7 @@ tbody > tr.fc-scrollgrid-section:first-of-type .fc-scroller
|
||||
position absolute
|
||||
width 1px
|
||||
whiteSpace nowrap
|
||||
.date-time-group .MuiFormControl-root
|
||||
margin: 0
|
||||
.date-time-group.show-full-field > .MuiBox-root:first-of-type
|
||||
margin-bottom: 8px
|
||||
|
||||
@@ -53,27 +53,30 @@ export function ImportTab({
|
||||
}, [importFile, importUrl, importMode]);
|
||||
|
||||
return (
|
||||
<Box mt={2}>
|
||||
<>
|
||||
{/* Form group 1: Select file button - first group, margin top 0 */}
|
||||
{importMode === "file" && (
|
||||
<>
|
||||
<Box mb={1}>
|
||||
<Button
|
||||
variant="outlined"
|
||||
component="label"
|
||||
size="medium"
|
||||
sx={{ borderRadius: "12px" }}
|
||||
>
|
||||
{t("common.select_file")}
|
||||
<input
|
||||
type="file"
|
||||
hidden
|
||||
accept=".ics"
|
||||
onChange={(e) => setImportFile(e.target.files?.[0] ?? null)}
|
||||
/>
|
||||
</Button>
|
||||
</Box>
|
||||
<Box mt={0}>
|
||||
<Button
|
||||
variant="outlined"
|
||||
component="label"
|
||||
size="medium"
|
||||
sx={{ borderRadius: "12px" }}
|
||||
>
|
||||
{t("common.select_file")}
|
||||
<input
|
||||
type="file"
|
||||
hidden
|
||||
accept=".ics"
|
||||
onChange={(e) => setImportFile(e.target.files?.[0] ?? null)}
|
||||
/>
|
||||
</Button>
|
||||
{importFile && (
|
||||
<Typography variant="body2" color="text.secondary">
|
||||
<Typography
|
||||
variant="body2"
|
||||
color="text.secondary"
|
||||
sx={{ marginTop: "6px" }}
|
||||
>
|
||||
{importFile.name}
|
||||
</Typography>
|
||||
)}
|
||||
@@ -81,38 +84,67 @@ export function ImportTab({
|
||||
variant="caption"
|
||||
color="text.secondary"
|
||||
display="block"
|
||||
mb={2}
|
||||
sx={{ marginTop: "6px" }}
|
||||
>
|
||||
{t("calendar.import_file_description")}
|
||||
</Typography>
|
||||
</>
|
||||
</Box>
|
||||
)}
|
||||
|
||||
{/* Form group 2: URL field */}
|
||||
{importMode === "url" && (
|
||||
<TextField
|
||||
<Box mt={0}>
|
||||
<TextField
|
||||
fullWidth
|
||||
label={t("calendar.ics_feed_url")}
|
||||
value={importUrl}
|
||||
onChange={(e) => setImportUrl(e.target.value)}
|
||||
size="small"
|
||||
margin="dense"
|
||||
sx={{
|
||||
"&.MuiFormControl-root.MuiFormControl-marginDense": {
|
||||
marginTop: "6px",
|
||||
marginBottom: 0,
|
||||
},
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
)}
|
||||
|
||||
{/* Form group 3: Import to */}
|
||||
<Box mt={2}>
|
||||
<FormControl
|
||||
fullWidth
|
||||
label={t("calendar.ics_feed_url")}
|
||||
value={importUrl}
|
||||
onChange={(e) => setImportUrl(e.target.value)}
|
||||
size="small"
|
||||
margin="dense"
|
||||
/>
|
||||
)}
|
||||
|
||||
<FormControl fullWidth size="small" sx={{ mt: 2 }}>
|
||||
<InputLabel id="import-to-label">{t("calendar.import_to")}</InputLabel>
|
||||
<Select
|
||||
labelId="import-to-label"
|
||||
label={t("calendar.import_to")}
|
||||
value={importTarget}
|
||||
onChange={(e) => setImportTarget(e.target.value)}
|
||||
sx={{
|
||||
"&.MuiFormControl-root.MuiFormControl-marginDense": {
|
||||
marginTop: "6px",
|
||||
marginBottom: 0,
|
||||
},
|
||||
}}
|
||||
>
|
||||
<MenuItem value="new">{t("calendar.new_calendar")}</MenuItem>
|
||||
{CalendarItemList(personalCalendars)}
|
||||
</Select>
|
||||
</FormControl>
|
||||
<InputLabel id="import-to-label">
|
||||
{t("calendar.import_to")}
|
||||
</InputLabel>
|
||||
<Select
|
||||
labelId="import-to-label"
|
||||
label={t("calendar.import_to")}
|
||||
value={importTarget}
|
||||
onChange={(e) => setImportTarget(e.target.value)}
|
||||
>
|
||||
<MenuItem value="new">{t("calendar.new_calendar")}</MenuItem>
|
||||
{CalendarItemList(personalCalendars)}
|
||||
</Select>
|
||||
</FormControl>
|
||||
</Box>
|
||||
|
||||
{importTarget === "new" && <SettingsTab {...newCalParams} />}
|
||||
</Box>
|
||||
{/* Form group 4: SettingsTab (when importing to new calendar) */}
|
||||
{importTarget === "new" && (
|
||||
<Box mt={2}>
|
||||
<SettingsTab {...newCalParams} />
|
||||
</Box>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -49,62 +49,79 @@ export function SettingsTab({
|
||||
}, [description]);
|
||||
|
||||
return (
|
||||
<Box mt={2}>
|
||||
<TextField
|
||||
fullWidth
|
||||
label=""
|
||||
inputProps={{ "aria-label": t("common.name") }}
|
||||
placeholder={t("common.name")}
|
||||
value={name}
|
||||
onChange={(e) => setName(e.target.value)}
|
||||
size="small"
|
||||
margin="dense"
|
||||
/>
|
||||
|
||||
<AddDescButton
|
||||
showDescription={toggleDesc}
|
||||
setShowDescription={setToggleDesc}
|
||||
showMore={false}
|
||||
description={description}
|
||||
setDescription={setDescription}
|
||||
buttonVariant="contained"
|
||||
buttonColor="secondary"
|
||||
/>
|
||||
|
||||
<Box mt={2}>
|
||||
<Typography variant="body2" gutterBottom>
|
||||
{t("calendar.color")}
|
||||
</Typography>
|
||||
<ColorPicker
|
||||
onChange={(color) => setColor(color)}
|
||||
selectedColor={color}
|
||||
<>
|
||||
{/* Form group 1: Name field - first group, margin top 0 */}
|
||||
<Box mt={0}>
|
||||
<TextField
|
||||
fullWidth
|
||||
label=""
|
||||
inputProps={{ "aria-label": t("common.name") }}
|
||||
placeholder={t("common.name")}
|
||||
value={name}
|
||||
onChange={(e) => setName(e.target.value)}
|
||||
size="small"
|
||||
sx={{
|
||||
"&.MuiFormControl-root": {
|
||||
marginTop: 0,
|
||||
marginBottom: 0,
|
||||
},
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
|
||||
{/* Form group 2: Description */}
|
||||
<Box mt={2}>
|
||||
<AddDescButton
|
||||
showDescription={toggleDesc}
|
||||
setShowDescription={setToggleDesc}
|
||||
showMore={false}
|
||||
description={description}
|
||||
setDescription={setDescription}
|
||||
buttonVariant="contained"
|
||||
buttonColor="secondary"
|
||||
/>
|
||||
</Box>
|
||||
|
||||
{/* Form group 3: Color */}
|
||||
<Box mt={2}>
|
||||
<Typography variant="h6" sx={{ margin: 0 }}>
|
||||
{t("calendar.color")}
|
||||
</Typography>
|
||||
<Box sx={{ marginTop: "6px" }}>
|
||||
<ColorPicker
|
||||
onChange={(color) => setColor(color)}
|
||||
selectedColor={color}
|
||||
/>
|
||||
</Box>
|
||||
</Box>
|
||||
|
||||
{/* Form group 4: New events visibility */}
|
||||
{isOwn && (
|
||||
<Box mt={2}>
|
||||
<Typography variant="body2" gutterBottom>
|
||||
<Typography variant="h6" sx={{ margin: 0 }}>
|
||||
{t("calendar.newEventsVisibility")}
|
||||
</Typography>
|
||||
<ToggleButtonGroup
|
||||
value={visibility}
|
||||
exclusive
|
||||
onChange={(e, val) => val && setVisibility(val)}
|
||||
size="medium"
|
||||
sx={{ borderRadius: "12px" }}
|
||||
>
|
||||
<ToggleButton value="public" sx={{ width: "140px" }}>
|
||||
<PublicIcon fontSize="small" sx={{ mr: 1 }} />
|
||||
{t("common.all")}
|
||||
</ToggleButton>
|
||||
<Box sx={{ marginTop: "6px" }}>
|
||||
<ToggleButtonGroup
|
||||
value={visibility}
|
||||
exclusive
|
||||
onChange={(e, val) => val && setVisibility(val)}
|
||||
size="medium"
|
||||
sx={{ borderRadius: "12px" }}
|
||||
>
|
||||
<ToggleButton value="public" sx={{ width: "140px" }}>
|
||||
<PublicIcon fontSize="small" sx={{ mr: 1 }} />
|
||||
{t("common.all")}
|
||||
</ToggleButton>
|
||||
|
||||
<ToggleButton value="private" sx={{ width: "140px" }}>
|
||||
<LockOutlineIcon fontSize="small" sx={{ mr: 1 }} />
|
||||
{t("common.you")}
|
||||
</ToggleButton>
|
||||
</ToggleButtonGroup>
|
||||
<ToggleButton value="private" sx={{ width: "140px" }}>
|
||||
<LockOutlineIcon fontSize="small" sx={{ mr: 1 }} />
|
||||
{t("common.you")}
|
||||
</ToggleButton>
|
||||
</ToggleButtonGroup>
|
||||
</Box>
|
||||
</Box>
|
||||
)}
|
||||
</Box>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ A highly reusable dialog component that supports both normal and expanded (fulls
|
||||
- ✅ **Clean Expanded View**: No backdrop/shadow in expanded mode for seamless integration
|
||||
- ✅ **Instant Transition**: No animation when expanding for immediate feedback
|
||||
- ✅ **Back Navigation**: Expanded mode shows back arrow icon in header for easy collapse
|
||||
- ✅ **MUI Stack Spacing**: Uses MUI Stack component with configurable spacing prop (2=16px normal, 3=24px expanded)
|
||||
- ✅ **MUI Stack Spacing**: Uses MUI Stack component with configurable spacing prop (2=16px for both normal and expanded modes)
|
||||
- ✅ **Fully Customizable**: Override styles with `sx`, `contentSx`, `titleSx` props
|
||||
- ✅ **Container Support**: Content container with configurable max-width
|
||||
- ✅ **Type Safe**: Full TypeScript support
|
||||
@@ -45,7 +45,7 @@ function MyComponent() {
|
||||
>
|
||||
<TextField label="Name" fullWidth />
|
||||
<TextField label="Email" fullWidth />
|
||||
{/* Wrapped in Stack with spacing={2} (normal) or spacing={3} (expanded) */}
|
||||
{/* Wrapped in Stack with spacing={2} for both normal and expanded modes */}
|
||||
</ResponsiveDialog>
|
||||
);
|
||||
}
|
||||
@@ -66,7 +66,7 @@ function MyComponent() {
|
||||
| `expandedContentMaxWidth` | `string` | `"990px"` | Content container max-width in expanded mode |
|
||||
| `headerHeight` | `string` | `"90px"` | App header height to preserve |
|
||||
| `normalSpacing` | `number` | `2` | Stack spacing in normal mode (MUI spacing units: 1 = 8px) |
|
||||
| `expandedSpacing` | `number` | `3` | Stack spacing in expanded mode (MUI spacing units: 1 = 8px) |
|
||||
| `expandedSpacing` | `number` | `2` | Stack spacing in expanded mode (MUI spacing units: 1 = 8px) |
|
||||
| `contentSx` | `SxProps<Theme>` | - | Custom styles for DialogContent |
|
||||
| `titleSx` | `SxProps<Theme>` | - | Custom styles for DialogTitle |
|
||||
| `dialogContentProps` | `DialogContentProps` | - | Additional DialogContent props |
|
||||
@@ -175,7 +175,7 @@ For apps with different header heights:
|
||||
- Shadow: removed (no elevation in expanded mode)
|
||||
- Transition: disabled (instant expand/collapse for better UX)
|
||||
- Title: replaced by back arrow IconButton (calls `onExpandToggle`)
|
||||
- Children spacing: `expandedSpacing={3}` (24px via MUI Stack component)
|
||||
- Children spacing: `expandedSpacing={2}` (16px via MUI Stack component)
|
||||
- Actions (MuiBox): max-width = `expandedContentMaxWidth` (990px), centered container with buttons right-aligned
|
||||
- padding: 0 12px
|
||||
- width: 100%
|
||||
|
||||
@@ -66,7 +66,7 @@ interface ResponsiveDialogProps extends Omit<
|
||||
headerHeight?: string;
|
||||
/** Spacing between children in normal mode (default: 2 = 16px) */
|
||||
normalSpacing?: number;
|
||||
/** Spacing between children in expanded mode (default: 3 = 24px) */
|
||||
/** Spacing between children in expanded mode (default: 2 = 16px) */
|
||||
expandedSpacing?: number;
|
||||
/** Custom styles for DialogContent - merged with base styles */
|
||||
contentSx?: SxProps<Theme>;
|
||||
@@ -102,7 +102,7 @@ function ResponsiveDialog({
|
||||
expandedContentMaxWidth = "990px",
|
||||
headerHeight = "90px",
|
||||
normalSpacing = 2,
|
||||
expandedSpacing = 3,
|
||||
expandedSpacing = 2,
|
||||
contentSx,
|
||||
titleSx,
|
||||
dialogContentProps,
|
||||
|
||||
@@ -32,7 +32,7 @@ export function AddDescButton({
|
||||
<>
|
||||
{!showDescription && (
|
||||
<FieldWithLabel label=" " isExpanded={showMore}>
|
||||
<Box display="flex" gap={1} mb={1}>
|
||||
<Box display="flex" gap={1}>
|
||||
<Button
|
||||
startIcon={<DescriptionIcon />}
|
||||
onClick={() => setShowDescription(true)}
|
||||
|
||||
@@ -245,6 +245,7 @@ export function EventChip({
|
||||
whiteSpace: "normal",
|
||||
flex: 1,
|
||||
maxWidth: "75%",
|
||||
color: titleStyle.color,
|
||||
}}
|
||||
>
|
||||
{event._def.extendedProps.description}
|
||||
|
||||
@@ -13,6 +13,7 @@ import {
|
||||
TextField,
|
||||
ToggleButtonGroup,
|
||||
ToggleButton,
|
||||
Typography,
|
||||
} from "@linagora/twake-mui";
|
||||
import {
|
||||
Description as DescriptionIcon,
|
||||
@@ -481,7 +482,9 @@ export default function EventFormFields({
|
||||
control={
|
||||
<Checkbox checked={allday} onChange={handleAllDayToggle} />
|
||||
}
|
||||
label={t("event.form.allDay")}
|
||||
label={
|
||||
<Typography variant="h6">{t("event.form.allDay")}</Typography>
|
||||
}
|
||||
/>
|
||||
<FormControlLabel
|
||||
control={
|
||||
@@ -513,7 +516,9 @@ export default function EventFormFields({
|
||||
}}
|
||||
/>
|
||||
}
|
||||
label={t("event.form.repeat")}
|
||||
label={
|
||||
<Typography variant="h6">{t("event.form.repeat")}</Typography>
|
||||
}
|
||||
/>
|
||||
<TimezoneAutocomplete
|
||||
value={timezone}
|
||||
|
||||
@@ -80,7 +80,7 @@ export default function RepeatEvent({
|
||||
<Stack>
|
||||
{/* Interval */}
|
||||
<Box display="flex" alignItems="center" gap={2} mb={2}>
|
||||
<Typography>{t("event.repeat.repeatEvery")}</Typography>
|
||||
<Typography variant="h6">{t("event.repeat.repeatEvery")}</Typography>
|
||||
<TextField
|
||||
type="number"
|
||||
value={repetition.interval ?? 1}
|
||||
@@ -161,7 +161,7 @@ export default function RepeatEvent({
|
||||
|
||||
{/* End options */}
|
||||
<Box>
|
||||
<Typography variant="body2" gutterBottom>
|
||||
<Typography variant="h6" gutterBottom>
|
||||
{t("event.repeat.end.label")}
|
||||
</Typography>
|
||||
<RadioGroup
|
||||
@@ -193,7 +193,11 @@ export default function RepeatEvent({
|
||||
disabled={!isOwn}
|
||||
value="never"
|
||||
control={<Radio />}
|
||||
label={t("event.repeat.end.never")}
|
||||
label={
|
||||
<Typography variant="h6">
|
||||
{t("event.repeat.end.never")}
|
||||
</Typography>
|
||||
}
|
||||
/>
|
||||
|
||||
<FormControlLabel
|
||||
@@ -202,7 +206,9 @@ export default function RepeatEvent({
|
||||
control={<Radio />}
|
||||
label={
|
||||
<Box display="flex" alignItems="center" gap={1}>
|
||||
{t("event.repeat.end.after")}
|
||||
<Typography variant="h6">
|
||||
{t("event.repeat.end.after")}
|
||||
</Typography>
|
||||
<TextField
|
||||
type="number"
|
||||
size="small"
|
||||
@@ -218,7 +224,9 @@ export default function RepeatEvent({
|
||||
inputProps={{ min: 1, "data-testid": "occurrences-input" }}
|
||||
disabled={!isOwn || endOption !== "after"}
|
||||
/>
|
||||
{t("event.repeat.end.occurrences")}
|
||||
<Typography variant="h6">
|
||||
{t("event.repeat.end.occurrences")}
|
||||
</Typography>
|
||||
</Box>
|
||||
}
|
||||
/>
|
||||
@@ -229,7 +237,9 @@ export default function RepeatEvent({
|
||||
control={<Radio />}
|
||||
label={
|
||||
<Box display="flex" alignItems="center" gap={1}>
|
||||
{t("event.repeat.end.on")}
|
||||
<Typography variant="h6">
|
||||
{t("event.repeat.end.on")}
|
||||
</Typography>
|
||||
<TextField
|
||||
type="date"
|
||||
inputProps={{ "data-testid": "end-date" }}
|
||||
|
||||
@@ -342,6 +342,9 @@ export const DateTimeFields: React.FC<DateTimeFieldsProps> = ({
|
||||
<Box
|
||||
display="flex"
|
||||
flexDirection="column"
|
||||
className={`date-time-group ${
|
||||
isExpanded || shouldShowFullFieldsInNormal ? "show-full-field" : ""
|
||||
}`.trim()}
|
||||
sx={{ maxWidth: showMore ? "calc(100% - 145px)" : "100%" }}
|
||||
>
|
||||
{isExpanded || shouldShowFullFieldsInNormal ? (
|
||||
|
||||
@@ -19,19 +19,52 @@ export const FieldWithLabel = React.memo(
|
||||
}) => {
|
||||
if (!isExpanded) {
|
||||
// Normal mode: label on top
|
||||
const isEmptyLabel =
|
||||
label === null ||
|
||||
label === undefined ||
|
||||
(typeof label === "string" && label.trim() === "");
|
||||
|
||||
return (
|
||||
<Box sx={sx}>
|
||||
<Typography
|
||||
component="div"
|
||||
sx={{
|
||||
display: "block",
|
||||
marginBottom: "4px",
|
||||
fontSize: "0.875rem",
|
||||
fontWeight: 500,
|
||||
}}
|
||||
>
|
||||
{label}
|
||||
</Typography>
|
||||
<Box
|
||||
sx={[
|
||||
{
|
||||
"& > *:not(:first-of-type)": {
|
||||
marginTop: isEmptyLabel ? 0 : "6px",
|
||||
},
|
||||
// Only apply margin to direct child MuiTextField-root
|
||||
"& > .MuiFormControl-root": {
|
||||
marginTop: "6px",
|
||||
marginBottom: 0,
|
||||
},
|
||||
"& > .MuiTextField-root": {
|
||||
marginTop: "6px",
|
||||
marginBottom: 0,
|
||||
},
|
||||
// Reset margin for nested MuiTextField-root
|
||||
"& .MuiFormControl-root .MuiTextField-root": {
|
||||
marginTop: 0,
|
||||
marginBottom: 0,
|
||||
},
|
||||
"& .MuiTextField-root .MuiTextField-root": {
|
||||
marginTop: 0,
|
||||
marginBottom: 0,
|
||||
},
|
||||
// Reset margin for nested Box children (DateTimeFields structure)
|
||||
"& > .MuiBox-root > .MuiBox-root": {
|
||||
marginTop: 0,
|
||||
},
|
||||
"& > .MuiBox-root > .MuiBox-root > .MuiBox-root": {
|
||||
marginTop: 0,
|
||||
},
|
||||
},
|
||||
...(Array.isArray(sx) ? sx : sx ? [sx] : []),
|
||||
]}
|
||||
>
|
||||
{!isEmptyLabel && (
|
||||
<Typography component="div" variant="h6" sx={{ display: "block" }}>
|
||||
{label}
|
||||
</Typography>
|
||||
)}
|
||||
{children}
|
||||
</Box>
|
||||
);
|
||||
@@ -42,17 +75,35 @@ export const FieldWithLabel = React.memo(
|
||||
<Box display="flex" alignItems="center" sx={sx}>
|
||||
<Typography
|
||||
component="div"
|
||||
variant="h6"
|
||||
sx={{
|
||||
minWidth: "115px",
|
||||
marginRight: "12px",
|
||||
flexShrink: 0,
|
||||
fontSize: "0.875rem",
|
||||
fontWeight: 500,
|
||||
}}
|
||||
>
|
||||
{label}
|
||||
</Typography>
|
||||
<Box flexGrow={1}>{children}</Box>
|
||||
<Box
|
||||
flexGrow={1}
|
||||
sx={{
|
||||
// Set margin-top: 8px for second row in DateTimeFields (4 fields layout)
|
||||
"& > .MuiBox-root > .MuiBox-root:nth-of-type(2)": {
|
||||
marginTop: "8px",
|
||||
},
|
||||
// Remove margin from MuiFormControl-root MuiFormControl-marginDense in extended mode
|
||||
"& .MuiFormControl-root.MuiFormControl-marginDense": {
|
||||
marginTop: 0,
|
||||
marginBottom: 0,
|
||||
},
|
||||
"& .MuiTextField-root.MuiFormControl-marginDense": {
|
||||
marginTop: 0,
|
||||
marginBottom: 0,
|
||||
},
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</Box>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,41 @@
|
||||
import React from "react";
|
||||
import logo from "../../static/images/calendar.svg";
|
||||
import { DotLottieReact } from "@lottiefiles/dotlottie-react";
|
||||
import { Box } from "@linagora/twake-mui";
|
||||
import twakeLogo from "../../static/twake-workplace.svg";
|
||||
|
||||
export function Loading() {
|
||||
return <img src={logo} alt="loading" />;
|
||||
return (
|
||||
<Box
|
||||
data-testid="loading"
|
||||
sx={{
|
||||
display: "flex",
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
width: "100vw",
|
||||
height: "100vh",
|
||||
position: "fixed",
|
||||
top: 0,
|
||||
left: 0,
|
||||
}}
|
||||
>
|
||||
<DotLottieReact
|
||||
src="/loadercalendar.lottie"
|
||||
loop
|
||||
autoplay
|
||||
style={{ width: "175px" }}
|
||||
/>
|
||||
<Box
|
||||
component="img"
|
||||
src={twakeLogo}
|
||||
alt="twake workplace"
|
||||
sx={{
|
||||
position: "absolute",
|
||||
bottom: "50px",
|
||||
left: "50%",
|
||||
transform: "translateX(-50%)",
|
||||
width: "210px",
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user