Add disclosure to widgets
This commit is contained in:
@@ -7,7 +7,7 @@ export const Card = ({
|
||||
}: JSX.IntrinsicElements["div"]): JSX.Element => {
|
||||
return (
|
||||
<div
|
||||
className={`flex overflow-hidden rounded-2xl bg-white text-sm text-black shadow-md ${
|
||||
className={`flex overflow-hidden rounded-md bg-white text-sm text-black shadow-md ${
|
||||
className ?? ""
|
||||
}`}
|
||||
{...rest}
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
import type React from "react";
|
||||
|
||||
import { Disclosure } from "@headlessui/react";
|
||||
import { ChevronDownIcon, ChevronUpIcon } from "@heroicons/react/24/outline";
|
||||
|
||||
export interface DropdownProps {
|
||||
title: string;
|
||||
icon: JSX.Element;
|
||||
children: React.ReactNode;
|
||||
}
|
||||
|
||||
export const Dropdown = ({
|
||||
title,
|
||||
icon,
|
||||
children,
|
||||
}: DropdownProps): JSX.Element => {
|
||||
return (
|
||||
<Disclosure defaultOpen>
|
||||
{({ open }) => (
|
||||
<>
|
||||
<Disclosure.Button className="flex h-8 justify-between bg-slate-100 px-2 hover:bg-slate-200">
|
||||
<div className="my-auto flex gap-2 text-slate-700">
|
||||
<div className="my-auto">{icon}</div>
|
||||
<span className="text-lg font-medium">{title}</span>
|
||||
</div>
|
||||
<div className="my-auto text-slate-600">
|
||||
{open ? (
|
||||
<ChevronUpIcon className="h-5" />
|
||||
) : (
|
||||
<ChevronDownIcon className="h-5" />
|
||||
)}
|
||||
</div>
|
||||
</Disclosure.Button>
|
||||
<Disclosure.Panel>{children}</Disclosure.Panel>
|
||||
</>
|
||||
)}
|
||||
</Disclosure>
|
||||
);
|
||||
};
|
||||
@@ -1,8 +1,10 @@
|
||||
import type React from "react";
|
||||
|
||||
import { BoltIcon } from "@heroicons/react/24/outline";
|
||||
import { Battery100Icon, BoltIcon } from "@heroicons/react/24/outline";
|
||||
|
||||
import { Card } from "../Card.js";
|
||||
import { Dropdown } from "../Dropdown.js";
|
||||
import { Mono } from "../Mono.js";
|
||||
|
||||
export interface BatteryWidgetProps {
|
||||
batteryLevel: number;
|
||||
@@ -14,17 +16,22 @@ export const BatteryWidget = ({
|
||||
voltage,
|
||||
}: BatteryWidgetProps): JSX.Element => {
|
||||
return (
|
||||
<Card>
|
||||
<div className="flex w-20 bg-slate-700 p-3">
|
||||
<BoltIcon className="m-auto h-12 text-white" />
|
||||
</div>
|
||||
<div className="w-full">
|
||||
<div className="flex h-8 bg-slate-100">
|
||||
<span className="m-auto text-lg font-medium">Power</span>
|
||||
<Card className="flex-col">
|
||||
<Dropdown title="Position" icon={<BoltIcon className="h-4" />}>
|
||||
<div className="flex">
|
||||
<div className="flex w-20 bg-slate-700 p-3">
|
||||
<Battery100Icon className="m-auto h-12 text-white" />
|
||||
</div>
|
||||
<span className="m-auto text-lg">
|
||||
{batteryLevel}
|
||||
<Mono>%</Mono>
|
||||
</span>
|
||||
<span className="m-auto text-lg">
|
||||
{voltage}
|
||||
<Mono>v</Mono>
|
||||
</span>
|
||||
</div>
|
||||
<span>{batteryLevel}</span>
|
||||
<span>{voltage}</span>
|
||||
</div>
|
||||
</Dropdown>
|
||||
</Card>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
import React, { useEffect } from "react";
|
||||
|
||||
import { useDevice } from "@core/providers/useDevice.js";
|
||||
import { AdjustmentsHorizontalIcon } from "@heroicons/react/24/outline";
|
||||
|
||||
import { Button } from "../Button.js";
|
||||
import { Card } from "../Card.js";
|
||||
import { Dropdown } from "../Dropdown.js";
|
||||
|
||||
export const ConfiguringWidget = (): JSX.Element => {
|
||||
const {
|
||||
@@ -36,43 +38,45 @@ export const ConfiguringWidget = (): JSX.Element => {
|
||||
|
||||
return (
|
||||
<Card className="flex-col">
|
||||
<div className="flex h-8 bg-slate-100">
|
||||
<span className="m-auto text-lg font-medium">Power</span>
|
||||
</div>
|
||||
<div className="flex flex-col gap-2 p-3">
|
||||
<ol className="flex flex-col gap-3 overflow-hidden">
|
||||
<StatusIndicator
|
||||
title="Device Info"
|
||||
current={hardware.myNodeNum ? 1 : 0}
|
||||
total={0}
|
||||
/>
|
||||
<StatusIndicator title="Peers" current={nodes.length} total={0} />
|
||||
<StatusIndicator
|
||||
title="Device Config"
|
||||
current={Object.keys(config).length - 1}
|
||||
total={6}
|
||||
/>
|
||||
<StatusIndicator
|
||||
title="Module Config"
|
||||
current={Object.keys(moduleConfig).length - 1}
|
||||
total={6}
|
||||
/>
|
||||
<StatusIndicator
|
||||
title="Channels"
|
||||
current={channels.length}
|
||||
total={hardware.maxChannels ?? 0}
|
||||
/>
|
||||
</ol>
|
||||
<Button
|
||||
variant="secondary"
|
||||
size="sm"
|
||||
onClick={() => {
|
||||
void connection?.configure();
|
||||
}}
|
||||
>
|
||||
Retry
|
||||
</Button>
|
||||
</div>
|
||||
<Dropdown
|
||||
title="Config Status"
|
||||
icon={<AdjustmentsHorizontalIcon className="h-4" />}
|
||||
>
|
||||
<div className="flex flex-col gap-2 p-3">
|
||||
<ol className="flex flex-col gap-3 overflow-hidden">
|
||||
<StatusIndicator
|
||||
title="Device Info"
|
||||
current={hardware.myNodeNum ? 1 : 0}
|
||||
total={0}
|
||||
/>
|
||||
<StatusIndicator title="Peers" current={nodes.length} total={0} />
|
||||
<StatusIndicator
|
||||
title="Device Config"
|
||||
current={Object.keys(config).length - 1}
|
||||
total={6}
|
||||
/>
|
||||
<StatusIndicator
|
||||
title="Module Config"
|
||||
current={Object.keys(moduleConfig).length - 1}
|
||||
total={6}
|
||||
/>
|
||||
<StatusIndicator
|
||||
title="Channels"
|
||||
current={channels.length}
|
||||
total={hardware.maxChannels ?? 0}
|
||||
/>
|
||||
</ol>
|
||||
<Button
|
||||
variant="secondary"
|
||||
size="sm"
|
||||
onClick={() => {
|
||||
void connection?.configure();
|
||||
}}
|
||||
>
|
||||
Retry
|
||||
</Button>
|
||||
</div>
|
||||
</Dropdown>
|
||||
</Card>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
import type React from "react";
|
||||
|
||||
import { InformationCircleIcon } from "@heroicons/react/24/outline";
|
||||
import type { Protobuf } from "@meshtastic/meshtasticjs";
|
||||
|
||||
import { Card } from "../Card.js";
|
||||
import { Dropdown } from "../Dropdown.js";
|
||||
|
||||
export interface NodeInfoWidgetProps {
|
||||
hardware: Protobuf.MyNodeInfo;
|
||||
@@ -13,26 +15,28 @@ export const NodeInfoWidget = ({
|
||||
}: NodeInfoWidgetProps): JSX.Element => {
|
||||
return (
|
||||
<Card className="flex-col">
|
||||
<div className="flex h-8 bg-slate-100">
|
||||
<span className="m-auto text-lg font-medium">Information</span>
|
||||
</div>
|
||||
<div className="flex flex-col gap-2 p-3">
|
||||
<dl className="mt-2 border-b border-gray-200">
|
||||
<Dropdown
|
||||
title="Information"
|
||||
icon={<InformationCircleIcon className="h-4" />}
|
||||
>
|
||||
<div className="flex flex-col gap-2 p-3">
|
||||
<dl className="mt-2 border-b border-gray-200">
|
||||
<div className="flex justify-between py-1 text-sm font-medium">
|
||||
<dt className="text-gray-500">Firmware version</dt>
|
||||
<dd className="cursor-pointer whitespace-nowrap text-gray-900 hover:text-orange-400 hover:underline">
|
||||
{hardware.firmwareVersion}
|
||||
</dd>
|
||||
</div>
|
||||
</dl>
|
||||
<div className="flex justify-between py-1 text-sm font-medium">
|
||||
<dt className="text-gray-500">Firmware version</dt>
|
||||
<dd className="cursor-pointer whitespace-nowrap text-gray-900 hover:text-orange-400 hover:underline">
|
||||
{hardware.firmwareVersion}
|
||||
<dt className="text-gray-500">Bitrate</dt>
|
||||
<dd className="whitespace-nowrap text-gray-900">
|
||||
{hardware.bitrate.toFixed(2)}
|
||||
<span className="font-mono text-sm text-slate-500 ">bps</span>
|
||||
</dd>
|
||||
</div>
|
||||
</dl>
|
||||
<div className="flex justify-between py-1 text-sm font-medium">
|
||||
<dt className="text-gray-500">Bitrate</dt>
|
||||
<dd className="whitespace-nowrap text-gray-900">
|
||||
{hardware.bitrate.toFixed(2)}
|
||||
<span className="font-mono text-sm text-slate-500 ">bps</span>
|
||||
</dd>
|
||||
</div>
|
||||
</div>
|
||||
</Dropdown>
|
||||
</Card>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -3,10 +3,14 @@ import type React from "react";
|
||||
import { base16 } from "rfc4648";
|
||||
|
||||
import { Hashicon } from "@emeraldpay/hashicon-react";
|
||||
import { EllipsisHorizontalCircleIcon } from "@heroicons/react/24/outline";
|
||||
import {
|
||||
EllipsisHorizontalCircleIcon,
|
||||
UserGroupIcon,
|
||||
} from "@heroicons/react/24/outline";
|
||||
import type { Protobuf } from "@meshtastic/meshtasticjs";
|
||||
|
||||
import { Card } from "../Card.js";
|
||||
import { Dropdown } from "../Dropdown.js";
|
||||
import { IconButton } from "../IconButton.js";
|
||||
import { Mono } from "../Mono.js";
|
||||
|
||||
@@ -16,12 +20,9 @@ export interface PeersWidgetProps {
|
||||
|
||||
export const PeersWidget = ({ peers }: PeersWidgetProps): JSX.Element => {
|
||||
return (
|
||||
<Card>
|
||||
<div className="flex w-full flex-col gap-1">
|
||||
<div className="flex h-8 bg-slate-100">
|
||||
<span className="m-auto text-lg font-medium">Peers</span>
|
||||
</div>
|
||||
<div className="p-4">
|
||||
<Card className="flex-col">
|
||||
<Dropdown title="Peers" icon={<UserGroupIcon className="h-4" />}>
|
||||
<div className="p-3">
|
||||
{peers.map((peer) => (
|
||||
<div
|
||||
className="flex gap-2 rounded-md p-2 hover:bg-slate-100"
|
||||
@@ -49,7 +50,7 @@ export const PeersWidget = ({ peers }: PeersWidgetProps): JSX.Element => {
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</Dropdown>
|
||||
</Card>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -3,6 +3,7 @@ import type React from "react";
|
||||
import { MapPinIcon } from "@heroicons/react/24/outline";
|
||||
|
||||
import { Card } from "../Card.js";
|
||||
import { Dropdown } from "../Dropdown.js";
|
||||
|
||||
export interface PositionWidgetProps {
|
||||
grid: string;
|
||||
@@ -10,16 +11,15 @@ export interface PositionWidgetProps {
|
||||
|
||||
export const PositionWidget = ({ grid }: PositionWidgetProps): JSX.Element => {
|
||||
return (
|
||||
<Card>
|
||||
<div className="flex w-20 bg-teal-600 p-3">
|
||||
<MapPinIcon className="m-auto h-12 text-white" />
|
||||
</div>
|
||||
<div className="flex w-full flex-col">
|
||||
<div className="flex h-8 bg-slate-100">
|
||||
<span className="m-auto text-lg font-medium">Position</span>
|
||||
<Card className="flex-col">
|
||||
<Dropdown title="Position" icon={<MapPinIcon className="h-4" />}>
|
||||
<div className="flex">
|
||||
<div className="flex w-20 bg-teal-600 p-3">
|
||||
<MapPinIcon className="m-auto h-12 text-white" />
|
||||
</div>
|
||||
<span className="m-auto text-lg">{grid}</span>
|
||||
</div>
|
||||
<span className="m-auto text-lg">{grid}</span>
|
||||
</div>
|
||||
</Dropdown>
|
||||
</Card>
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user