Skip to content

Commit 8c37be4

Browse files
authored
Merge pull request #274 from rcarteraz/add-footer
2 parents 2b34d78 + 076dae8 commit 8c37be4

File tree

9 files changed

+368
-313
lines changed

9 files changed

+368
-313
lines changed

src/App.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { DeviceSelector } from "@components/DeviceSelector.js";
55
import { DialogManager } from "@components/Dialog/DialogManager.js";
66
import { NewDeviceDialog } from "@components/Dialog/NewDeviceDialog.js";
77
import { Toaster } from "@components/Toaster.js";
8+
import Footer from "@components/UI/Footer.js";
89
import { ThemeController } from "@components/generic/ThemeController.js";
910
import { useAppStore } from "@core/stores/appStore.js";
1011
import { useDeviceStore } from "@core/stores/deviceStore.js";
@@ -40,7 +41,10 @@ export const App = (): JSX.Element => {
4041
<PageRouter />
4142
</div>
4243
) : (
43-
<Dashboard />
44+
<>
45+
<Dashboard />
46+
<Footer />
47+
</>
4448
)}
4549
</div>
4650
</div>

src/components/PageComponents/Messages/ChannelChat.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ export const ChannelChat = ({
6868
)}
6969
</div>
7070
</div>
71-
<div className="p-3">
71+
<div className="pl-3 pr-3 pt-3 pb-1">
7272
<MessageInput to={to} channel={channel} />
7373
</div>
7474
</div>

src/components/PageLayout.tsx

Lines changed: 35 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { cn } from "@app/core/utils/cn.js";
22
import { AlignLeftIcon, type LucideIcon } from "lucide-react";
3+
import Footer from "./UI/Footer";
34

45
export interface PageLayoutProps {
56
label: string;
@@ -18,40 +19,43 @@ export const PageLayout = ({
1819
children,
1920
}: PageLayoutProps): JSX.Element => {
2021
return (
21-
<div className="relative flex h-full w-full flex-col">
22-
<div className="flex h-14 shrink-0 border-b-[0.5px] border-slate-300 dark:border-slate-700 md:h-16 md:px-4">
23-
<button
24-
type="button"
25-
className="pl-4 transition-all hover:text-accent md:hidden"
26-
>
27-
<AlignLeftIcon />
28-
</button>
29-
<div className="flex flex-1 items-center justify-between px-4 md:px-0">
30-
<div className="flex w-full items-center">
31-
<span className="w-full text-lg font-medium">{label}</span>
32-
<div className="flex justify-end space-x-4">
33-
{actions?.map((action, index) => (
34-
<button
35-
key={action.icon.name}
36-
type="button"
37-
className="transition-all hover:text-accent"
38-
onClick={action.onClick}
39-
>
40-
<action.icon />
41-
</button>
42-
))}
22+
<>
23+
<div className="relative flex h-full w-full flex-col">
24+
<div className="flex h-14 shrink-0 border-b-[0.5px] border-slate-300 dark:border-slate-700 md:h-16 md:px-4">
25+
<button
26+
type="button"
27+
className="pl-4 transition-all hover:text-accent md:hidden"
28+
>
29+
<AlignLeftIcon />
30+
</button>
31+
<div className="flex flex-1 items-center justify-between px-4 md:px-0">
32+
<div className="flex w-full items-center">
33+
<span className="w-full text-lg font-medium">{label}</span>
34+
<div className="flex justify-end space-x-4">
35+
{actions?.map((action, index) => (
36+
<button
37+
key={action.icon.name}
38+
type="button"
39+
className="transition-all hover:text-accent"
40+
onClick={action.onClick}
41+
>
42+
<action.icon />
43+
</button>
44+
))}
45+
</div>
4346
</div>
4447
</div>
4548
</div>
49+
<div
50+
className={cn(
51+
"flex h-full w-full flex-col overflow-y-auto",
52+
!noPadding && "pl-3 pr-3 ",
53+
)}
54+
>
55+
{children}
56+
<Footer />
57+
</div>
4658
</div>
47-
<div
48-
className={cn(
49-
"flex h-full w-full flex-col overflow-y-auto",
50-
!noPadding && "p-3",
51-
)}
52-
>
53-
{children}
54-
</div>
55-
</div>
59+
</>
5660
);
5761
};

src/components/UI/Footer.tsx

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import React from "react";
2+
3+
export interface FooterProps extends React.HTMLAttributes<HTMLElement> {}
4+
5+
const Footer = React.forwardRef<HTMLElement, FooterProps>(
6+
({ className, ...props }, ref) => {
7+
return (
8+
<footer
9+
className={`flex flex- justify-center p-2 ${className}`}
10+
style={{
11+
backgroundColor: "var(--backgroundPrimary)",
12+
color: "var(--textPrimary)",
13+
}}
14+
>
15+
<p>
16+
<a
17+
href="https://vercel.com/?utm_source=meshtastic&utm_campaign=oss"
18+
className="hover:underline"
19+
style={{ color: "var(--link)" }}
20+
>
21+
Powered by ▲ Vercel
22+
</a>{" "}
23+
| Meshtastic® is a registered trademark of Meshtastic LLC. |{" "}
24+
<a
25+
href="https://meshtastic.org/docs/legal"
26+
className="hover:underline"
27+
style={{ color: "var(--link)" }}
28+
>
29+
Legal Information
30+
</a>
31+
</p>
32+
</footer>
33+
);
34+
},
35+
);
36+
37+
export default Footer;

src/components/UI/Tabs.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ const TabsList = React.forwardRef<
1212
<TabsPrimitive.List
1313
ref={ref}
1414
className={cn(
15-
"inline-flex flex-wrap items-center rounded-md bg-slate-100 p-1 dark:bg-slate-800",
15+
"inline-flex flex-wrap items-center rounded-md bg-slate-100 p-1 mt-2 dark:bg-slate-800",
1616
className,
1717
)}
1818
{...props}

src/pages/Dashboard/index.tsx

Lines changed: 69 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -21,79 +21,81 @@ export const Dashboard = () => {
2121
const devices = useMemo(() => getDevices(), [getDevices]);
2222

2323
return (
24-
<div className="flex flex-col gap-3 p-3">
25-
<div className="flex items-center justify-between">
26-
<div className="space-y-1">
27-
<H3>Connected Devices</H3>
28-
<Subtle>Manage, connect and disconnect devices</Subtle>
24+
<>
25+
<div className="flex flex-col gap-3 p-3">
26+
<div className="flex items-center justify-between">
27+
<div className="space-y-1">
28+
<H3>Connected Devices</H3>
29+
<Subtle>Manage, connect and disconnect devices</Subtle>
30+
</div>
2931
</div>
30-
</div>
3132

32-
<Separator />
33+
<Separator />
3334

34-
<div className="flex h-[450px] rounded-md border border-dashed border-slate-200 p-3 dark:border-slate-700">
35-
{devices.length ? (
36-
<ul className="grow divide-y divide-gray-200">
37-
{devices.map((device) => {
38-
return (
39-
<li key={device.id}>
40-
<div className="px-4 py-4 sm:px-6">
41-
<div className="flex items-center justify-between">
42-
<p className="truncate text-sm font-medium text-accent">
43-
{device.nodes.get(device.hardware.myNodeNum)?.user
44-
?.longName ?? "UNK"}
45-
</p>
46-
<div className="inline-flex w-24 justify-center gap-2 rounded-full bg-slate-100 py-1 text-xs font-semibold text-slate-900 transition-colors hover:bg-slate-700 hover:text-slate-50">
47-
{device.connection?.connType === "ble" && (
48-
<>
49-
<BluetoothIcon size={16} />
50-
BLE
51-
</>
52-
)}
53-
{device.connection?.connType === "serial" && (
54-
<>
55-
<UsbIcon size={16} />
56-
Serial
57-
</>
58-
)}
59-
{device.connection?.connType === "http" && (
60-
<>
61-
<NetworkIcon size={16} />
62-
Network
63-
</>
64-
)}
35+
<div className="flex h-[450px] rounded-md border border-dashed border-slate-200 p-3 dark:border-slate-700">
36+
{devices.length ? (
37+
<ul className="grow divide-y divide-gray-200">
38+
{devices.map((device) => {
39+
return (
40+
<li key={device.id}>
41+
<div className="px-4 py-4 sm:px-6">
42+
<div className="flex items-center justify-between">
43+
<p className="truncate text-sm font-medium text-accent">
44+
{device.nodes.get(device.hardware.myNodeNum)?.user
45+
?.longName ?? "UNK"}
46+
</p>
47+
<div className="inline-flex w-24 justify-center gap-2 rounded-full bg-slate-100 py-1 text-xs font-semibold text-slate-900 transition-colors hover:bg-slate-700 hover:text-slate-50">
48+
{device.connection?.connType === "ble" && (
49+
<>
50+
<BluetoothIcon size={16} />
51+
BLE
52+
</>
53+
)}
54+
{device.connection?.connType === "serial" && (
55+
<>
56+
<UsbIcon size={16} />
57+
Serial
58+
</>
59+
)}
60+
{device.connection?.connType === "http" && (
61+
<>
62+
<NetworkIcon size={16} />
63+
Network
64+
</>
65+
)}
66+
</div>
6567
</div>
66-
</div>
67-
<div className="mt-2 sm:flex sm:justify-between">
68-
<div className="flex gap-2 text-sm text-gray-500">
69-
<UsersIcon
70-
size={20}
71-
className="text-gray-400"
72-
aria-hidden="true"
73-
/>
74-
{device.nodes.size === 0 ? 0 : device.nodes.size - 1}
68+
<div className="mt-2 sm:flex sm:justify-between">
69+
<div className="flex gap-2 text-sm text-gray-500">
70+
<UsersIcon
71+
size={20}
72+
className="text-gray-400"
73+
aria-hidden="true"
74+
/>
75+
{device.nodes.size === 0 ? 0 : device.nodes.size - 1}
76+
</div>
7577
</div>
7678
</div>
77-
</div>
78-
</li>
79-
);
80-
})}
81-
</ul>
82-
) : (
83-
<div className="m-auto flex flex-col gap-3 text-center">
84-
<ListPlusIcon size={48} className="mx-auto text-textSecondary" />
85-
<H3>No Devices</H3>
86-
<Subtle>Connect atleast one device to get started</Subtle>
87-
<Button
88-
className="gap-2"
89-
onClick={() => setConnectDialogOpen(true)}
90-
>
91-
<PlusIcon size={16} />
92-
New Connection
93-
</Button>
94-
</div>
95-
)}
79+
</li>
80+
);
81+
})}
82+
</ul>
83+
) : (
84+
<div className="m-auto flex flex-col gap-3 text-center">
85+
<ListPlusIcon size={48} className="mx-auto text-textSecondary" />
86+
<H3>No Devices</H3>
87+
<Subtle>Connect atleast one device to get started</Subtle>
88+
<Button
89+
className="gap-2"
90+
onClick={() => setConnectDialogOpen(true)}
91+
>
92+
<PlusIcon size={16} />
93+
New Connection
94+
</Button>
95+
</div>
96+
)}
97+
</div>
9698
</div>
97-
</div>
99+
</>
98100
);
99101
};

0 commit comments

Comments
 (0)