🚧 Work in progress for Mantine v5

This commit is contained in:
ajnart
2022-07-26 00:51:55 +02:00
parent 7fcdb17d84
commit d4d9e5cfcb
25 changed files with 423 additions and 389 deletions

View File

@@ -8,8 +8,8 @@ import {
LoadingOverlay,
Modal,
MultiSelect,
ScrollArea,
Select,
Stack,
Switch,
Tabs,
TextInput,
@@ -18,7 +18,7 @@ import {
} from '@mantine/core';
import { useForm } from '@mantine/form';
import { useDebouncedValue } from '@mantine/hooks';
import { IconApps as Apps } from '@tabler/icons';
import { IconApps } from '@tabler/icons';
import { useEffect, useState } from 'react';
import { v4 as uuidv4 } from 'uuid';
import { useConfig } from '../../tools/state';
@@ -38,6 +38,7 @@ export function AddItemShelfButton(props: any) {
>
<AddAppShelfItemForm setOpened={setOpened} />
</Modal>
<Tooltip label="Add a service">
<ActionIcon
variant="default"
radius="md"
@@ -46,10 +47,9 @@ export function AddItemShelfButton(props: any) {
style={props.style}
onClick={() => setOpened(true)}
>
<Tooltip label="Add a service">
<Apps />
</Tooltip>
<IconApps />
</ActionIcon>
</Tooltip>
</>
);
}
@@ -192,10 +192,13 @@ export function AddAppShelfItemForm(props: { setOpened: (b: boolean) => void } &
form.reset();
})}
>
<Tabs grow>
<Tabs.Tab label="Options">
<ScrollArea style={{ height: 500 }} scrollbarSize={4}>
<Group direction="column" grow>
<Tabs defaultValue="Options">
<Tabs.List grow>
<Tabs.Tab value="Options">Options</Tabs.Tab>
<Tabs.Tab value="Advanced Options">Advanced options</Tabs.Tab>
</Tabs.List>
<Tabs.Panel value="Options">
<Stack>
<TextInput
required
label="Service name"
@@ -332,11 +335,10 @@ export function AddAppShelfItemForm(props: { setOpened: (b: boolean) => void } &
/>
</>
)}
</Group>
</ScrollArea>
</Tabs.Tab>
<Tabs.Tab label="Advanced Options">
<Group direction="column" grow>
</Stack>
</Tabs.Panel>
<Tabs.Panel value="Advanced Options">
<Stack>
<MultiSelect
required
label="HTTP Status Codes"
@@ -354,8 +356,8 @@ export function AddAppShelfItemForm(props: { setOpened: (b: boolean) => void } &
defaultChecked={form.values.newTab}
{...form.getInputProps('newTab')}
/>
</Group>
</Tabs.Tab>
</Stack>
</Tabs.Panel>
</Tabs>
<Group grow position="center" mt="xl">
<Button type="submit">{props.message ?? 'Add service'}</Button>

View File

@@ -1,5 +1,5 @@
import React, { useState } from 'react';
import { Accordion, createStyles, Grid, Group, Paper, useMantineColorScheme } from '@mantine/core';
import { Accordion, createStyles, Grid, Group, Paper, Stack, useMantineColorScheme } from '@mantine/core';
import {
closestCenter,
DndContext,
@@ -156,7 +156,7 @@ const AppShelf = (props: any) => {
// Create an item with 0: true, 1: true, 2: true... For each category
return (
// Return one item for each category
<Group grow direction="column">
<Stack>
<Accordion
disableIconRotation
classNames={classes}
@@ -195,14 +195,14 @@ const AppShelf = (props: any) => {
</Accordion.Item>
) : null}
</Accordion>
</Group>
</Stack>
);
}
return (
<Group grow direction="column">
<Stack>
{item()}
<ModuleWrapper mt="xl" module={DownloadsModule} />
</Group>
</Stack>
);
};

View File

@@ -1,7 +1,7 @@
import { Menu, Modal, Text, useMantineTheme } from '@mantine/core';
import { ActionIcon, Menu, Modal, Text, useMantineTheme } from '@mantine/core';
import { showNotification } from '@mantine/notifications';
import { useState } from 'react';
import { IconCheck as Check, IconEdit as Edit, IconTrash as Trash } from '@tabler/icons';
import { IconCheck as Check, IconEdit as Edit, IconMenu, IconTrash as Trash } from '@tabler/icons';
import { useConfig } from '../../tools/state';
import { serviceItem } from '../../tools/types';
import { AddAppShelfItemForm } from './AddAppShelfItem';
@@ -23,16 +23,26 @@ export default function AppShelfMenu(props: any) {
<AddAppShelfItemForm setOpened={setOpened} {...service} message="Save service" />
</Modal>
<Menu
position="right"
radius="md"
withinPortal
width={150}
shadow="xl"
withArrow
closeOnItemClick={false}
radius="md"
position="right"
styles={{
body: {
dropdown: {
// Add shadow and elevation to the body
boxShadow: '0 0 14px 14px rgba(0, 0, 0, 0.05)',
},
}}
>
<Menu.Target>
<ActionIcon style={{}}>
<IconMenu />
</ActionIcon>
</Menu.Target>
<Menu.Dropdown>
<Menu.Label>Settings</Menu.Label>
<Menu.Item
color="primary"
@@ -66,6 +76,7 @@ export default function AppShelfMenu(props: any) {
>
Delete
</Menu.Item>
</Menu.Dropdown>
</Menu>
</>
);

View File

@@ -5,25 +5,27 @@ import { useConfig } from '../../tools/state';
export default function ConfigChanger() {
const { config, loadConfig, setConfig, getConfigs } = useConfig();
const [configList, setConfigList] = useState([] as string[]);
const [configList, setConfigList] = useState<string[]>([]);
const [value, setValue] = useState(config.name);
useEffect(() => {
getConfigs().then((configs) => setConfigList(configs));
// setConfig(initialConfig);
}, [config]);
// If configlist is empty, return a loading indicator
if (configList.length === 0) {
return (
<Center>
<Tooltip label={"Loading your configs. This doesn't load in vercel."}>
<Center>
<Loader />
</Tooltip>
</Center>
</Tooltip>
);
}
// return <Select data={[{ value: '1', label: '1' },]} onChange={(e) => console.log(e)} value="1" />;
return (
<Select
defaultValue={config.name}
label="Config loader"
value={value}
defaultValue={config.name}
onChange={(e) => {
loadConfig(e ?? 'default');
setCookie('config-name', e ?? 'default', {

View File

@@ -6,11 +6,11 @@ import {
IconCheck as Check,
TablerIcon,
} from '@tabler/icons';
import { DropzoneStatus, FullScreenDropzone } from '@mantine/dropzone';
import { showNotification } from '@mantine/notifications';
import { useRef } from 'react';
import { useRouter } from 'next/router';
import { setCookie } from 'cookies-next';
import { Dropzone } from '@mantine/dropzone';
import { useConfig } from '../../tools/state';
import { Config } from '../../tools/types';
import { migrateToIdConfig } from '../../tools/migrate';
@@ -62,7 +62,7 @@ export default function LoadConfigComponent(props: any) {
const openRef = useRef<() => void>();
return (
<FullScreenDropzone
<Dropzone.FullScreen
onDrop={(files) => {
files[0].text().then((e) => {
try {
@@ -100,7 +100,7 @@ export default function LoadConfigComponent(props: any) {
}}
accept={['application/json']}
>
{(status) => dropzoneChildren(status, theme)}
</FullScreenDropzone>
{(status: any) => dropzoneChildren(status, theme)}
</Dropzone.FullScreen>
);
}

View File

@@ -1,4 +1,4 @@
import { TextInput, Group, Button } from '@mantine/core';
import { TextInput, Group, Button, Stack } from '@mantine/core';
import { useForm } from '@mantine/form';
import { useConfig } from '../../tools/state';
import { ColorSelector } from './ColorSelector';
@@ -37,9 +37,9 @@ export default function TitleChanger() {
};
return (
<Group direction="column" grow mb="lg">
<Stack mb="lg">
<form onSubmit={form.onSubmit((values) => saveChanges(values))}>
<Group grow direction="column">
<Stack>
<TextInput label="Page title" placeholder="Homarr 🦞" {...form.getInputProps('title')} />
<TextInput label="Logo" placeholder="/img/logo.png" {...form.getInputProps('logo')} />
<TextInput
@@ -53,13 +53,13 @@ export default function TitleChanger() {
{...form.getInputProps('background')}
/>
<Button type="submit">Save</Button>
</Group>
</Stack>
</form>
<ColorSelector type="primary" />
<ColorSelector type="secondary" />
<ShadeSelector />
<OpacitySelector />
<AppCardWidthSelector />
</Group>
</Stack>
);
}

View File

@@ -1,5 +1,5 @@
import React from 'react';
import { Group, Text, Slider } from '@mantine/core';
import { Group, Text, Slider, Stack } from '@mantine/core';
import { useConfig } from '../../tools/state';
export function AppCardWidthSelector() {
@@ -16,7 +16,7 @@ export function AppCardWidthSelector() {
};
return (
<Group direction="column" spacing="xs" grow>
<Stack spacing="xs">
<Text>App Width</Text>
<Slider
label={null}
@@ -27,6 +27,6 @@ export function AppCardWidthSelector() {
styles={{ markLabel: { fontSize: 'xx-small' } }}
onChange={(value) => setappCardWidth(value)}
/>
</Group>
</Stack>
);
}

View File

@@ -1,5 +1,5 @@
import React, { useState } from 'react';
import { ColorSwatch, Group, Popover, Text, useMantineTheme } from '@mantine/core';
import { ColorSwatch, Grid, Group, Popover, Text, useMantineTheme } from '@mantine/core';
import { useConfig } from '../../tools/state';
import { useColorTheme } from '../../tools/color';
@@ -44,6 +44,7 @@ export function ColorSelector({ type }: ColorControlProps) {
};
const swatches = colors.map(({ color, swatch }) => (
<Grid.Col span={2}>
<ColorSwatch
component="button"
type="button"
@@ -51,44 +52,36 @@ export function ColorSelector({ type }: ColorControlProps) {
key={color}
color={swatch}
size={22}
style={{ color: theme.white, cursor: 'pointer' }}
style={{ cursor: 'pointer' }}
/>
</Grid.Col>
));
return (
<Group direction="row" spacing={3}>
<Group>
<Popover
width={250}
withinPortal
opened={opened}
onClose={() => setOpened(false)}
transitionDuration={0}
target={
position="left"
withArrow
>
<Popover.Target>
<ColorSwatch
component="button"
type="button"
color={theme.colors[configColor][6]}
onClick={() => setOpened((o) => !o)}
size={22}
style={{ display: 'block', cursor: 'pointer' }}
style={{ cursor: 'pointer' }}
/>
}
styles={{
root: {
marginRight: theme.spacing.xs,
},
body: {
width: 152,
backgroundColor: theme.colorScheme === 'dark' ? theme.colors.dark[8] : theme.white,
},
arrow: {
backgroundColor: theme.colorScheme === 'dark' ? theme.colors.dark[8] : theme.white,
},
}}
position="bottom"
placement="end"
withArrow
arrowSize={3}
>
<Group spacing="xs">{swatches}</Group>
</Popover.Target>
<Popover.Dropdown>
<Grid gutter="lg" columns={14}>
{swatches}
</Grid>
</Popover.Dropdown>
</Popover>
<Text>{type[0].toUpperCase() + type.slice(1)} color</Text>
</Group>

View File

@@ -1,4 +1,4 @@
import { Group, Text, SegmentedControl, TextInput } from '@mantine/core';
import { Group, Text, SegmentedControl, TextInput, Stack } from '@mantine/core';
import { useState } from 'react';
import { useConfig } from '../../tools/state';
import { ColorSchemeSwitch } from '../ColorSchemeToggle/ColorSchemeSwitch';
@@ -24,8 +24,8 @@ export default function CommonSettings(args: any) {
);
return (
<Group direction="column" grow mb="lg">
<Group grow direction="column" spacing={0}>
<Stack mb="lg">
<Stack spacing={0}>
<Text>Search engine</Text>
<Tip>
Use the prefixes <b>!yt</b> and <b>!t</b> in front of your query to search on YouTube or
@@ -74,13 +74,13 @@ export default function CommonSettings(args: any) {
/>
</>
)}
</Group>
</Stack>
<ColorSchemeSwitch />
<WidgetsPositionSwitch />
<ModuleEnabler />
<ConfigChanger />
<SaveConfigComponent />
<Tip>Upload your config file by dragging and dropping it onto the page!</Tip>
</Group>
</Stack>
);
}

View File

@@ -1,5 +1,5 @@
import React from 'react';
import { Group, Text, Slider } from '@mantine/core';
import { Group, Text, Slider, Stack } from '@mantine/core';
import { useConfig } from '../../tools/state';
export function OpacitySelector() {
@@ -29,7 +29,7 @@ export function OpacitySelector() {
};
return (
<Group direction="column" spacing="xs" grow>
<Stack spacing="xs">
<Text>App Opacity</Text>
<Slider
defaultValue={config.settings.appOpacity || 100}
@@ -39,6 +39,6 @@ export function OpacitySelector() {
styles={{ markLabel: { fontSize: 'xx-small' } }}
onChange={(value) => setConfigOpacity(value)}
/>
</Group>
</Stack>
);
}

View File

@@ -8,17 +8,21 @@ import Credits from './Credits';
function SettingsMenu(props: any) {
return (
<Tabs grow>
<Tabs.Tab data-autofocus label="Common">
<Tabs defaultValue="Common">
<Tabs.List grow>
<Tabs.Tab value="Common">Common</Tabs.Tab>
<Tabs.Tab value="Customizations">Customizations</Tabs.Tab>
</Tabs.List>
<Tabs.Panel data-autofocus value="Common">
<ScrollArea style={{ height: '78vh' }} offsetScrollbars>
<CommonSettings />
</ScrollArea>
</Tabs.Tab>
<Tabs.Tab label="Customizations">
</Tabs.Panel>
<Tabs.Panel value="Customizations">
<ScrollArea style={{ height: '78vh' }} offsetScrollbars>
<AdvancedSettings />
</ScrollArea>
</Tabs.Tab>
</Tabs.Panel>
</Tabs>
);
}

View File

@@ -1,5 +1,14 @@
import React, { useState } from 'react';
import { ColorSwatch, Group, Popover, Text, useMantineTheme, MantineTheme } from '@mantine/core';
import {
ColorSwatch,
Group,
Popover,
Text,
useMantineTheme,
MantineTheme,
Stack,
Grid,
} from '@mantine/core';
import { useConfig } from '../../tools/state';
import { useColorTheme } from '../../tools/color';
@@ -31,6 +40,7 @@ export function ShadeSelector() {
};
const primarySwatches = primaryShades.map(({ swatch, shade }) => (
<Grid.Col span={1}>
<ColorSwatch
component="button"
type="button"
@@ -38,11 +48,13 @@ export function ShadeSelector() {
key={Number(shade)}
color={swatch}
size={22}
style={{ color: theme.white, cursor: 'pointer' }}
style={{ cursor: 'pointer' }}
/>
</Grid.Col>
));
const secondarySwatches = secondaryShades.map(({ swatch, shade }) => (
<Grid.Col span={1}>
<ColorSwatch
component="button"
type="button"
@@ -50,17 +62,22 @@ export function ShadeSelector() {
key={Number(shade)}
color={swatch}
size={22}
style={{ color: theme.white, cursor: 'pointer' }}
style={{ cursor: 'pointer' }}
/>
</Grid.Col>
));
return (
<Group direction="row" spacing={3}>
<Group>
<Popover
width={350}
withinPortal
opened={opened}
onClose={() => setOpened(false)}
transitionDuration={0}
target={
position="left"
withArrow
>
<Popover.Target>
<ColorSwatch
component="button"
type="button"
@@ -69,27 +86,15 @@ export function ShadeSelector() {
size={22}
style={{ display: 'block', cursor: 'pointer' }}
/>
}
styles={{
root: {
marginRight: theme.spacing.xs,
},
body: {
backgroundColor: theme.colorScheme === 'dark' ? theme.colors.dark[8] : theme.white,
},
arrow: {
backgroundColor: theme.colorScheme === 'dark' ? theme.colors.dark[8] : theme.white,
},
}}
position="bottom"
placement="end"
withArrow
arrowSize={3}
>
<Group direction="column" spacing="xs">
<Group spacing="xs">{primarySwatches}</Group>
<Group spacing="xs">{secondarySwatches}</Group>
</Group>
</Popover.Target>
<Popover.Dropdown>
<Stack spacing="xs">
<Grid gutter="lg" columns={10}>
{primarySwatches}
{secondarySwatches}
</Grid>
</Stack>
</Popover.Dropdown>
</Popover>
<Text>Shade</Text>
</Group>

View File

@@ -1,5 +1,4 @@
import { Box, createStyles, Group, Header as Head } from '@mantine/core';
import { useBooleanToggle } from '@mantine/hooks';
import { AddItemShelfButton } from '../AppShelf/AddAppShelfItem';
import DockerMenuButton from '../../modules/docker/DockerModule';
@@ -23,9 +22,7 @@ const useStyles = createStyles((theme) => ({
}));
export function Header(props: any) {
const [opened, toggleOpened] = useBooleanToggle(false);
const { classes, cx } = useStyles();
const [hidden, toggleHidden] = useBooleanToggle(true);
return (
<Head height="auto">

View File

@@ -18,6 +18,7 @@ export default function Layout({ children, style }: any) {
return (
<AppShell
fixed={false}
header={<Header />}
navbar={widgetPosition ? <Navbar /> : undefined}
aside={widgetPosition ? undefined : <Aside />}

View File

@@ -1,16 +1,16 @@
import { Group } from '@mantine/core';
import { Group, Stack } from '@mantine/core';
import { CalendarModule, DateModule, TotalDownloadsModule, WeatherModule } from '../../modules';
import { DashdotModule } from '../../modules/dashdot';
import { ModuleWrapper } from '../../modules/moduleWrapper';
export default function Widgets(props: any) {
return (
<Group my="sm" grow direction="column" style={{ width: 300 }}>
<Stack my="sm" style={{ width: 300 }}>
<ModuleWrapper module={CalendarModule} />
<ModuleWrapper module={TotalDownloadsModule} />
<ModuleWrapper module={WeatherModule} />
<ModuleWrapper module={DateModule} />
<ModuleWrapper module={DashdotModule} />
</Group>
</Stack>
);
}

View File

@@ -1,4 +1,4 @@
import { Group, Text, Title } from '@mantine/core';
import { Group, Stack, Text, Title } from '@mantine/core';
import dayjs from 'dayjs';
import { useEffect, useState } from 'react';
import { IconClock as Clock } from '@tabler/icons';
@@ -34,7 +34,7 @@ export default function DateComponent(props: any) {
}, []);
return (
<Group p="sm" spacing="xs" direction="column">
<Group p="sm" spacing="xs">
<Title>{dayjs(date).format(formatString)}</Title>
<Text size="xl">{dayjs(date).format('dddd, MMMM D')}</Text>
</Group>

View File

@@ -1,5 +1,4 @@
import { Button, Group, Modal, Title } from '@mantine/core';
import { useBooleanToggle } from '@mantine/hooks';
import { showNotification, updateNotification } from '@mantine/notifications';
import {
IconCheck,
@@ -14,6 +13,7 @@ import axios from 'axios';
import Dockerode from 'dockerode';
import { tryMatchService } from '../../tools/addToHomarr';
import { AddAppShelfItemForm } from '../../components/AppShelf/AddAppShelfItem';
import { useState } from 'react';
function sendDockerCommand(
action: string,
@@ -60,7 +60,7 @@ export interface ContainerActionBarProps {
}
export default function ContainerActionBar({ selected, reload }: ContainerActionBarProps) {
const [opened, setOpened] = useBooleanToggle(false);
const [opened, setOpened] = useState<boolean>(false);
return (
<Group>
<Modal

View File

@@ -20,7 +20,6 @@ export default function DockerMenuButton(props: any) {
const [opened, setOpened] = useState(false);
const [containers, setContainers] = useState<Docker.ContainerInfo[]>([]);
const [selection, setSelection] = useState<Docker.ContainerInfo[]>([]);
const [visible, setVisible] = useState(false);
const { config } = useConfig();
const moduleEnabled = config.modules?.[DockerModule.title]?.enabled ?? false;
@@ -32,14 +31,12 @@ export default function DockerMenuButton(props: any) {
if (!moduleEnabled) {
return;
}
setVisible(true);
setTimeout(() => {
axios
.get('/api/docker/containers')
.then((res) => {
setContainers(res.data);
setSelection([]);
setVisible(false);
})
.catch(() =>
// Send an Error notification
@@ -61,12 +58,14 @@ export default function DockerMenuButton(props: any) {
if (containers.length < 1) return null;
return (
<>
<Drawer opened={opened} onClose={() => setOpened(false)} padding="xl" size="full">
<ContainerActionBar selected={selection} reload={reload} />
<div style={{ position: 'relative' }}>
<LoadingOverlay transitionDuration={500} visible={visible} />
<Drawer
opened={opened}
onClose={() => setOpened(false)}
padding="xl"
size="full"
title={<ContainerActionBar selected={selection} reload={reload} />}
>
<DockerTable containers={containers} selection={selection} setSelection={setSelection} />
</div>
</Drawer>
<Group position="center">
<ActionIcon

View File

@@ -101,7 +101,6 @@ export default function DockerTable({
onChange={handleSearchChange}
/>
<Table captionSide="bottom" highlightOnHover sx={{ minWidth: 800 }} verticalSpacing="sm">
<caption>your docker containers</caption>
<thead>
<tr>
<th style={{ width: 40 }}>

View File

@@ -9,6 +9,7 @@ import {
ScrollArea,
Center,
Image,
Stack,
} from '@mantine/core';
import { IconDownload as Download } from '@tabler/icons';
import { useEffect, useState } from 'react';
@@ -187,13 +188,8 @@ export default function DownloadComponent() {
);
});
const easteregg = (
<Center style={{ display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
<Image fit="cover" height={300} src="https://danjohnvelasco.github.io/images/empty.png" />
</Center>
);
return (
<Group noWrap grow direction="column" mt="xl">
<Stack mt="xl">
<ScrollArea sx={{ height: 300 }}>
{rows.length > 0 ? (
<Table highlightOnHover>
@@ -201,9 +197,15 @@ export default function DownloadComponent() {
<tbody>{rows}</tbody>
</Table>
) : (
easteregg
<Center style={{ display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
<Image
fit="cover"
height={300}
src="https://danjohnvelasco.github.io/images/empty.png"
/>
</Center>
)}
</ScrollArea>
</Group>
</Stack>
);
}

View File

@@ -1,4 +1,4 @@
import { Text, Title, Group, useMantineTheme, Box, Card, ColorSwatch } from '@mantine/core';
import { Text, Title, Group, useMantineTheme, Box, Card, ColorSwatch, Stack } from '@mantine/core';
import { IconDownload as Download } from '@tabler/icons';
import { useEffect, useState } from 'react';
import axios from 'axios';
@@ -78,13 +78,13 @@ export default function TotalDownloadsComponent() {
if (downloadServices.length === 0) {
return (
<Group direction="column">
<Stack>
<Title order={4}>No supported download clients found!</Title>
<Group noWrap>
<Text>Add a download service to view your current downloads...</Text>
<AddItemShelfButton />
</Group>
</Group>
</Stack>
);
}
@@ -101,9 +101,9 @@ export default function TotalDownloadsComponent() {
})) as Datum[];
return (
<Group noWrap direction="column" grow>
<Stack>
<Title order={4}>Current download speed</Title>
<Group direction="column">
<Stack>
<Group>
<ColorSwatch size={12} color={theme.colors.green[5]} />
<Text>Download: {humanFileSize(totalDownloadSpeed)}/s</Text>
@@ -112,7 +112,7 @@ export default function TotalDownloadsComponent() {
<ColorSwatch size={12} color={theme.colors.blue[5]} />
<Text>Upload: {humanFileSize(totalUploadSpeed)}/s</Text>
</Group>
</Group>
</Stack>
<Box
style={{
height: 200,
@@ -133,7 +133,7 @@ export default function TotalDownloadsComponent() {
<Card p="sm" radius="md" withBorder>
<Text size="md">{roundedSeconds} seconds ago</Text>
<Card.Section p="sm">
<Group direction="column">
<Stack>
<Group>
<ColorSwatch size={10} color={theme.colors.green[5]} />
<Text size="md">Download: {humanFileSize(Download)}</Text>
@@ -142,7 +142,7 @@ export default function TotalDownloadsComponent() {
<ColorSwatch size={10} color={theme.colors.blue[5]} />
<Text size="md">Upload: {humanFileSize(Upload)}</Text>
</Group>
</Group>
</Stack>
</Card.Section>
</Card>
);
@@ -181,6 +181,6 @@ export default function TotalDownloadsComponent() {
]}
/>
</Box>
</Group>
</Stack>
);
}

View File

@@ -1,4 +1,6 @@
import {
ActionIcon,
Box,
Button,
Card,
Group,
@@ -8,6 +10,9 @@ import {
TextInput,
useMantineColorScheme,
} from '@mantine/core';
import { useHover } from '@mantine/hooks';
import { IconAdjustments } from '@tabler/icons';
import { motion } from 'framer-motion';
import { useConfig } from '../tools/state';
import { IModule } from './ModuleTypes';
@@ -142,6 +147,8 @@ export function ModuleWrapper(props: any) {
const enabledModules = config.modules ?? {};
// Remove 'Module' from enabled modules titles
const isShown = enabledModules[module.title]?.enabled ?? false;
//TODO: fix the hover problem
const { hovered, ref } = useHover();
if (!isShown) {
return null;
@@ -150,6 +157,8 @@ export function ModuleWrapper(props: any) {
return (
<Card
{...props}
key={module.title}
ref={ref}
hidden={!isShown}
withBorder
radius="lg"
@@ -161,47 +170,61 @@ export function ModuleWrapper(props: any) {
${(config.settings.appOpacity || 100) / 100}`,
}}
>
<ModuleMenu
module={module}
styles={{
root: {
position: 'absolute',
top: 12,
right: 12,
},
}}
/>
<Group position="apart">
<ModuleMenu module={module} hovered={hovered} />
<module.component />
</Group>
</Card>
);
}
export function ModuleMenu(props: any) {
const { module, styles } = props;
const { module, styles, hovered } = props;
const items: JSX.Element[] = getItems(module);
return (
<>
{module.options && (
<Menu
size="lg"
withinPortal
width="lg"
shadow="xl"
withArrow
closeOnItemClick={false}
radius="md"
position="left"
styles={{
root: {
...props?.styles?.root,
},
body: {
dropdown: {
// Add shadow and elevation to the body
boxShadow: '0 0 14px 14px rgba(0, 0, 0, 0.05)',
},
}}
>
<Menu.Target>
<Box
style={{
position: 'absolute',
top: 12,
right: 12,
}}
>
<motion.div
animate={{
//TODO: fix the hover problem
opacity: hovered ? 1 : 1,
}}
>
<ActionIcon>
<IconAdjustments />
</ActionIcon>
</motion.div>
</Box>
</Menu.Target>
<Menu.Dropdown>
<Menu.Label>Settings</Menu.Label>
{items.map((item) => (
<Menu.Item key={item.key}>{item}</Menu.Item>
))}
</Menu.Dropdown>
</Menu>
)}
</>

View File

@@ -1,5 +1,6 @@
import { Kbd, createStyles, Autocomplete } from '@mantine/core';
import { useDebouncedValue, useForm, useHotkeys } from '@mantine/hooks';
import { useDebouncedValue, useHotkeys } from '@mantine/hooks';
import { useForm } from '@mantine/form';
import { useEffect, useRef, useState } from 'react';
import {
IconSearch as Search,

View File

@@ -8,7 +8,6 @@ import { NotificationsProvider } from '@mantine/notifications';
import { useHotkeys } from '@mantine/hooks';
import { ConfigProvider } from '../tools/state';
import { theme } from '../tools/theme';
import { styles } from '../tools/styles';
import { ColorTheme } from '../tools/color';
export default function App(this: any, props: AppProps & { colorScheme: ColorScheme }) {
@@ -49,9 +48,6 @@ export default function App(this: any, props: AppProps & { colorScheme: ColorSch
primaryShade,
colorScheme,
}}
styles={{
...styles,
}}
withGlobalStyles
withNormalizeCSS
>

View File

@@ -1,21 +1,20 @@
import Document, { DocumentContext } from 'next/document';
import { ServerStyles, createStylesServer } from '@mantine/next';
import { createGetInitialProps } from '@mantine/next';
import Document, { Head, Html, Main, NextScript } from 'next/document';
const stylesServer = createStylesServer();
const getInitialProps = createGetInitialProps();
export default class _Document extends Document {
static async getInitialProps(ctx: DocumentContext) {
const initialProps = await Document.getInitialProps(ctx);
// Add your app specific logic here
static getInitialProps = getInitialProps;
return {
...initialProps,
styles: (
<>
{initialProps.styles}
<ServerStyles html={initialProps.html} server={stylesServer} />
</>
),
};
render() {
return (
<Html>
<Head />
<body>
<Main />
<NextScript />
</body>
</Html>
);
}
}