mirror of
https://github.com/ajnart/homarr.git
synced 2025-11-09 15:05:48 +01:00
🏗️ 💥 Change the whole folder structure.
Now using src as a subfolder to the source files
This commit is contained in:
18
src/components/layout/Aside.tsx
Normal file
18
src/components/layout/Aside.tsx
Normal file
@@ -0,0 +1,18 @@
|
||||
import { Aside as MantineAside } from '@mantine/core';
|
||||
import { CalendarModule } from '../modules/calendar/CalendarModule';
|
||||
import ModuleWrapper from '../modules/moduleWrapper';
|
||||
|
||||
export default function Aside() {
|
||||
return (
|
||||
<MantineAside
|
||||
height="100%"
|
||||
hiddenBreakpoint="md"
|
||||
hidden
|
||||
width={{
|
||||
base: 'auto',
|
||||
}}
|
||||
>
|
||||
<ModuleWrapper module={CalendarModule} />
|
||||
</MantineAside>
|
||||
);
|
||||
}
|
||||
81
src/components/layout/Footer.tsx
Normal file
81
src/components/layout/Footer.tsx
Normal file
@@ -0,0 +1,81 @@
|
||||
import React from 'react';
|
||||
import { createStyles, Anchor, Text, Group, ActionIcon } from '@mantine/core';
|
||||
import { BrandGithub } from 'tabler-icons-react';
|
||||
|
||||
const useStyles = createStyles((theme) => ({
|
||||
footer: {
|
||||
borderTop: `1px solid ${
|
||||
theme.colorScheme === 'dark' ? theme.colors.dark[5] : theme.colors.gray[2]
|
||||
}`,
|
||||
},
|
||||
|
||||
inner: {
|
||||
display: 'flex',
|
||||
justifyContent: 'space-between',
|
||||
alignItems: 'center',
|
||||
padding: `${theme.spacing.md}px ${theme.spacing.md}px`,
|
||||
|
||||
[theme.fn.smallerThan('sm')]: {
|
||||
flexDirection: 'column',
|
||||
},
|
||||
},
|
||||
|
||||
links: {
|
||||
[theme.fn.smallerThan('sm')]: {
|
||||
marginTop: theme.spacing.lg,
|
||||
marginBottom: theme.spacing.sm,
|
||||
},
|
||||
},
|
||||
}));
|
||||
|
||||
interface FooterCenteredProps {
|
||||
links: { link: string; label: string }[];
|
||||
}
|
||||
|
||||
export function Footer({ links }: FooterCenteredProps) {
|
||||
const { classes } = useStyles();
|
||||
const items = links.map((link) => (
|
||||
<Anchor<'a'>
|
||||
color="dimmed"
|
||||
key={link.label}
|
||||
href={link.link}
|
||||
sx={{ lineHeight: 1 }}
|
||||
onClick={(event) => event.preventDefault()}
|
||||
size="sm"
|
||||
>
|
||||
{link.label}
|
||||
</Anchor>
|
||||
));
|
||||
|
||||
return (
|
||||
<Group
|
||||
sx={{
|
||||
position: 'fixed',
|
||||
bottom: 0,
|
||||
right: 15,
|
||||
}}
|
||||
direction="row"
|
||||
align="center"
|
||||
mb={15}
|
||||
>
|
||||
<Group className={classes.links}>{items}</Group>
|
||||
<Group spacing="xs" position="right" noWrap>
|
||||
<ActionIcon<'a'> component="a" href="https://github.com/ajnart/homarr" size="lg">
|
||||
<BrandGithub size={18} />
|
||||
</ActionIcon>
|
||||
</Group>
|
||||
<Text
|
||||
style={{
|
||||
fontSize: '0.75rem',
|
||||
textAlign: 'center',
|
||||
color: '#a0aec0',
|
||||
}}
|
||||
>
|
||||
Made with ❤️ by @
|
||||
<Anchor href="https://github.com/ajnart" style={{ color: 'inherit', fontStyle: 'inherit' }}>
|
||||
ajnart
|
||||
</Anchor>
|
||||
</Text>
|
||||
</Group>
|
||||
);
|
||||
}
|
||||
155
src/components/layout/Header.tsx
Normal file
155
src/components/layout/Header.tsx
Normal file
@@ -0,0 +1,155 @@
|
||||
import React, { useState } from 'react';
|
||||
import {
|
||||
createStyles,
|
||||
Header as Head,
|
||||
Container,
|
||||
Group,
|
||||
Burger,
|
||||
Drawer,
|
||||
Center,
|
||||
} from '@mantine/core';
|
||||
import { useBooleanToggle } from '@mantine/hooks';
|
||||
import { NextLink } from '@mantine/next';
|
||||
import { Logo } from './Logo';
|
||||
import { SettingsMenuButton } from '../Settings/SettingsMenu';
|
||||
import CalendarComponent from '../modules/calendar/CalendarModule';
|
||||
|
||||
const HEADER_HEIGHT = 60;
|
||||
|
||||
const useStyles = createStyles((theme) => ({
|
||||
root: {
|
||||
position: 'relative',
|
||||
zIndex: 1,
|
||||
},
|
||||
|
||||
dropdown: {
|
||||
position: 'absolute',
|
||||
top: HEADER_HEIGHT,
|
||||
left: 0,
|
||||
right: 0,
|
||||
zIndex: 0,
|
||||
borderTopRightRadius: 0,
|
||||
borderTopLeftRadius: 0,
|
||||
borderTopWidth: 0,
|
||||
overflow: 'hidden',
|
||||
|
||||
[theme.fn.largerThan('md')]: {
|
||||
display: 'none',
|
||||
},
|
||||
},
|
||||
|
||||
header: {
|
||||
display: 'flex',
|
||||
justifyContent: 'space-between',
|
||||
alignItems: 'center',
|
||||
height: '100%',
|
||||
},
|
||||
|
||||
links: {
|
||||
[theme.fn.smallerThan('md')]: {
|
||||
display: 'none',
|
||||
},
|
||||
},
|
||||
|
||||
burger: {
|
||||
[theme.fn.largerThan('md')]: {
|
||||
display: 'none',
|
||||
},
|
||||
},
|
||||
|
||||
link: {
|
||||
display: 'block',
|
||||
lineHeight: 1,
|
||||
padding: '8px 12px',
|
||||
borderRadius: theme.radius.sm,
|
||||
textDecoration: 'none',
|
||||
color: theme.colorScheme === 'dark' ? theme.colors.dark[0] : theme.colors.gray[7],
|
||||
fontSize: theme.fontSizes.sm,
|
||||
fontWeight: 500,
|
||||
|
||||
'&:hover': {
|
||||
backgroundColor: theme.colorScheme === 'dark' ? theme.colors.dark[6] : theme.colors.gray[0],
|
||||
},
|
||||
|
||||
[theme.fn.smallerThan('sm')]: {
|
||||
borderRadius: 0,
|
||||
padding: theme.spacing.md,
|
||||
},
|
||||
},
|
||||
|
||||
linkActive: {
|
||||
'&, &:hover': {
|
||||
backgroundColor:
|
||||
theme.colorScheme === 'dark'
|
||||
? theme.fn.rgba(theme.colors[theme.primaryColor][9], 0.25)
|
||||
: theme.colors[theme.primaryColor][0],
|
||||
color: theme.colors[theme.primaryColor][theme.colorScheme === 'dark' ? 3 : 7],
|
||||
},
|
||||
},
|
||||
}));
|
||||
|
||||
interface HeaderResponsiveProps {
|
||||
links: { link: string; label: string }[];
|
||||
}
|
||||
|
||||
export function Header({ links }: HeaderResponsiveProps) {
|
||||
const [opened, toggleOpened] = useBooleanToggle(false);
|
||||
const [active, setActive] = useState('/');
|
||||
const { classes, cx } = useStyles();
|
||||
|
||||
const items = (
|
||||
<>
|
||||
{links.map((link) => (
|
||||
<NextLink
|
||||
key={link.label}
|
||||
href={link.link}
|
||||
className={cx(classes.link, { [classes.linkActive]: active === link.link })}
|
||||
onClick={(event) => {
|
||||
setActive(link.link);
|
||||
toggleOpened(false);
|
||||
}}
|
||||
>
|
||||
{link.label}
|
||||
</NextLink>
|
||||
))}
|
||||
</>
|
||||
);
|
||||
return (
|
||||
<Head height={HEADER_HEIGHT} mb={10} className={classes.root}>
|
||||
<Container className={classes.header}>
|
||||
<Group>
|
||||
<NextLink style={{ textDecoration: 'none' }} href="/">
|
||||
<Logo style={{ fontSize: 22 }} />
|
||||
</NextLink>
|
||||
</Group>
|
||||
<Group spacing={5} className={classes.links}>
|
||||
{items}
|
||||
</Group>
|
||||
<Group>
|
||||
<SettingsMenuButton />
|
||||
|
||||
<Burger
|
||||
opened={opened}
|
||||
onClick={() => toggleOpened()}
|
||||
className={classes.burger}
|
||||
size="sm"
|
||||
/>
|
||||
</Group>
|
||||
|
||||
<Drawer
|
||||
opened={opened}
|
||||
overlayOpacity={0.55}
|
||||
overlayBlur={3}
|
||||
onClose={() => toggleOpened()}
|
||||
position="right"
|
||||
>
|
||||
{opened ?? (
|
||||
<Center>
|
||||
<CalendarComponent />
|
||||
</Center>
|
||||
)}
|
||||
</Drawer>
|
||||
</Container>
|
||||
</Head>
|
||||
);
|
||||
}
|
||||
36
src/components/layout/Layout.tsx
Normal file
36
src/components/layout/Layout.tsx
Normal file
@@ -0,0 +1,36 @@
|
||||
import { AppShell, Center, createStyles } from '@mantine/core';
|
||||
import { Header } from './Header';
|
||||
import { Footer } from './Footer';
|
||||
import Aside from './Aside';
|
||||
import Navbar from './Navbar';
|
||||
|
||||
const useStyles = createStyles((theme) => ({
|
||||
main: {
|
||||
[theme.fn.largerThan('md')]: {
|
||||
width: 1200,
|
||||
},
|
||||
},
|
||||
}));
|
||||
|
||||
export default function Layout({ children, style }: any) {
|
||||
const { classes, cx } = useStyles();
|
||||
return (
|
||||
<AppShell
|
||||
navbar={<Navbar />}
|
||||
aside={<Aside />}
|
||||
header={<Header links={[]} />}
|
||||
footer={<Footer links={[]} />}
|
||||
>
|
||||
<Center>
|
||||
<main
|
||||
className={cx(classes.main)}
|
||||
style={{
|
||||
...style,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</main>
|
||||
</Center>
|
||||
</AppShell>
|
||||
);
|
||||
}
|
||||
15
src/components/layout/Logo.tsx
Normal file
15
src/components/layout/Logo.tsx
Normal file
@@ -0,0 +1,15 @@
|
||||
import { Text } from '@mantine/core';
|
||||
import * as React from 'react';
|
||||
|
||||
export function Logo({ style }: any) {
|
||||
return (
|
||||
<Text
|
||||
sx={style}
|
||||
weight="bold"
|
||||
variant="gradient"
|
||||
gradient={{ from: 'red', to: 'orange', deg: 145 }}
|
||||
>
|
||||
Homarr
|
||||
</Text>
|
||||
);
|
||||
}
|
||||
18
src/components/layout/Navbar.tsx
Normal file
18
src/components/layout/Navbar.tsx
Normal file
@@ -0,0 +1,18 @@
|
||||
import { Navbar as MantineNavbar } from '@mantine/core';
|
||||
import { DateModule } from '../modules/date/DateModule';
|
||||
import ModuleWrapper from '../modules/moduleWrapper';
|
||||
|
||||
export default function Navbar() {
|
||||
return (
|
||||
<MantineNavbar
|
||||
height="100%"
|
||||
hiddenBreakpoint="md"
|
||||
hidden
|
||||
width={{
|
||||
base: 'auto',
|
||||
}}
|
||||
>
|
||||
<ModuleWrapper module={DateModule} />
|
||||
</MantineNavbar>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user