Hardware page component breakout

This commit is contained in:
Sacha Weatherstone 2022-04-04 22:02:31 +10:00
parent 5ba2b9e14d
commit b101307f2f
13 changed files with 5079 additions and 85 deletions

View file

@ -0,0 +1,18 @@
import React from 'react';
export interface BadgeProps {
name: string;
color: string;
icon: React.ReactNode;
}
export const Badge = ({ name, color, icon }: BadgeProps): JSX.Element => {
return (
<div
className={`flex h-min cursor-pointer gap-1 rounded-md px-1 text-white shadow-md hover:opacity-80 ${color}`}
>
<div className="m-auto">{icon}</div>
<span>{name}</span>
</div>
);
};

View file

@ -0,0 +1,21 @@
import React from 'react';
import { Tab } from '@headlessui/react';
export interface CardTabProps {
title: string;
}
export const CardTab = ({ title }: CardTabProps): JSX.Element => {
return (
<Tab
className={({ selected }) =>
`w-1/3 truncate rounded-md px-3 py-2 text-sm font-medium hover:bg-tertiary ${
selected ? 'bg-secondary shadow-md' : ''
}`
}
>
{title}
</Tab>
);
};

View file

@ -4,11 +4,11 @@ import { IDevice, Stability } from '@site/src/data/device';
import { HardwareModal } from './HardwareModal';
export interface HardwareCard {
export interface HardwareCardProps {
device: IDevice;
}
export const HardwareCard = ({ device }: HardwareCard): JSX.Element => {
export const HardwareCard = ({ device }: HardwareCardProps): JSX.Element => {
const [open, setOpen] = useState(false);
return (
@ -21,12 +21,12 @@ export const HardwareCard = ({ device }: HardwareCard): JSX.Element => {
>
<div className="overflow-hidden rounded-lg">
<div
className={`flex aspect-[4/3] overflow-hidden bg-gradient-to-r ${device.misc.Gradient}`}
className={`flex aspect-[4/3] overflow-hidden ${device.misc.Gradient}`}
>
<img
src={device.misc.ImagePath}
alt=""
className="pointer-events-none m-auto object-cover p-2 group-hover:opacity-75"
className="pointer-events-none m-auto max-h-full max-w-full object-cover p-2 group-hover:opacity-75"
/>
</div>
<button type="button" className="absolute inset-0 focus:outline-none">

View file

@ -1,17 +1,16 @@
import React, { useState } from 'react';
import { FiBluetooth, FiChevronRight, FiWifi, FiX } from 'react-icons/fi';
import {
VictoryChart,
VictoryLine,
VictoryPolarAxis,
VictoryTheme,
} from 'victory';
import { Tab, Transition } from '@headlessui/react';
import type { IDevice } from '@site/src/data/device';
import { Modal } from '../Modal';
import { Badge } from './Badge';
import { CardTab } from './CardTab';
import { InfoTab } from './Tabs/InfoTab';
import { PinoutTab } from './Tabs/PinoutTab';
import { PowerTab } from './Tabs/PowerTab';
import { VariantSelectButton } from './VariantSelectButton';
export interface HardwareModal {
@ -33,7 +32,7 @@ export const HardwareModal = ({
<div className="inline-block w-full max-w-md transform overflow-hidden rounded-2xl bg-base text-left align-middle transition-all md:max-w-2xl md:bg-primary lg:max-w-4xl xl:max-w-6xl">
<div className="flex aspect-[3/2] flex-col md:aspect-[2/1] md:flex-row">
<div
className={`relative flex h-full rounded-t-2xl bg-gradient-to-r md:rounded-l-2xl md:rounded-tr-none ${
className={`relative flex h-full rounded-t-2xl md:rounded-l-2xl md:rounded-tr-none ${
device.misc.Gradient
} ${hideDetails ? 'w-full' : ''}`}
>
@ -61,16 +60,14 @@ export const HardwareModal = ({
{!hideDetails && (
<div className="absolute -bottom-3 right-0 m-auto mr-2 ml-auto flex gap-2 md:bottom-2 md:mr-14 md:mt-2">
{device.features.BLE && (
<div className="flex h-min gap-1 rounded-md bg-blue-500 px-1 text-white shadow-md">
<FiBluetooth className="m-auto" />
<span>Bluetooth</span>
</div>
<Badge
name="Bluetooth"
color="bg-blue-500"
icon={<FiBluetooth />}
/>
)}
{device.features.WiFi && (
<div className="m-auto flex h-min gap-1 rounded-md bg-orange-500 px-1 text-white shadow-md">
<FiWifi className="m-auto" />
<span>WiFi</span>
</div>
<Badge name="WiFi" color="bg-orange-500" icon={<FiWifi />} />
)}
</div>
)}
@ -83,7 +80,7 @@ export const HardwareModal = ({
<FiX className="m-auto" />
</div>
<div
className={`transition-[width] duration-100 ease-linear ${
className={`transition-[all] duration-100 ease-linear ${
hideDetails ? 'h-7 bg-base md:h-auto md:w-7' : 'w-full'
}`}
>
@ -109,70 +106,14 @@ export const HardwareModal = ({
className="flex-grow rounded-2xl bg-primary p-2"
>
<Tab.List className="flex gap-2">
<Tab
className={({ selected }) =>
`w-1/3 truncate rounded-md px-3 py-2 text-sm font-medium hover:bg-tertiary ${
selected ? 'bg-secondary shadow-md' : ''
}`
}
>
Info
</Tab>
<Tab
className={({ selected }) =>
`w-1/3 truncate rounded-md px-3 py-2 text-sm font-medium hover:bg-tertiary ${
selected ? 'bg-secondary shadow-md' : ''
}`
}
>
Power
</Tab>
<Tab
className={({ selected }) =>
`w-1/3 truncate rounded-md px-3 py-2 text-sm font-medium hover:bg-tertiary ${
selected ? 'bg-secondary shadow-md' : ''
}`
}
>
Pinout
</Tab>
<CardTab title="Info" />
<CardTab title="Power" />
<CardTab title="Pinout" />
</Tab.List>
<Tab.Panels as="div" className="">
<Tab.Panel className="h-32">Content 1</Tab.Panel>
<Tab.Panel className="h-96">
<VictoryChart
polar
theme={VictoryTheme.material}
domain={{ y: [0, 10] }}
>
<VictoryPolarAxis
dependentAxis
style={{ axis: { stroke: 'none' } }}
tickFormat={() => ''}
/>
<VictoryPolarAxis
tickValues={[
0,
Math.PI / 2,
Math.PI,
(3 * Math.PI) / 2,
]}
tickFormat={['2π', 'π/2', 'π', '3π/2']}
labelPlacement="vertical"
/>
{[5, 4, 3, 2, 1].map((val, i) => {
return (
<VictoryLine
key={i}
samples={100}
style={{ data: { stroke: colors[i] } }}
y={(d) => val * (1 - Math.cos(d.x))}
/>
);
})}
</VictoryChart>
</Tab.Panel>
<Tab.Panel>Content 3</Tab.Panel>
<InfoTab device={device} />
<PowerTab device={device} />
<PinoutTab device={device} />
</Tab.Panels>
</Tab.Group>
</div>

View file

@ -0,0 +1,13 @@
import React from 'react';
import { Tab } from '@headlessui/react';
import type { IDevice } from '../../../data/device';
export interface InfoTabProps {
device: IDevice;
}
export const InfoTab = ({ device }: InfoTabProps): JSX.Element => {
return <Tab.Panel className="h-32">Content 1</Tab.Panel>;
};

View file

@ -0,0 +1,13 @@
import React from 'react';
import { Tab } from '@headlessui/react';
import type { IDevice } from '../../../data/device';
export interface PinoutTabProps {
device: IDevice;
}
export const PinoutTab = ({ device }: PinoutTabProps): JSX.Element => {
return <Tab.Panel className="h-32">Content 1</Tab.Panel>;
};

View file

@ -0,0 +1,13 @@
import React from 'react';
import { Tab } from '@headlessui/react';
import type { IDevice } from '../../../data/device';
export interface PowerTabProps {
device: IDevice;
}
export const PowerTab = ({ device }: PowerTabProps): JSX.Element => {
return <Tab.Panel className="h-32">Content 1</Tab.Panel>;
};

View file

@ -46,7 +46,7 @@ export const VariantSelectButton = ({
active ? 'bg-indigo-600' : ''
}`
}
value={variant.name}
value={variant}
>
{({ selected, active }) => (
<>

63
src/data/devices/hydra.ts Normal file
View file

@ -0,0 +1,63 @@
import { IDevice, Stability, UseCase } from '../device';
export const hydra: IDevice = {
name: 'Hydra',
misc: {
Stability: Stability.Stable,
SuggestedUse: [UseCase.Portable],
ImagePath: '/img/hardware/Hydra-PCB.2.1.svg',
Gradient: 'bg-gradient-to-r from-indigo-200 via-red-200 to-yellow-100',
},
features: {
BLE: true,
WiFi: true,
Modules: [
'cannedMessage',
'externalNotification',
'rangeTest',
'rotaryEncoder',
'storeAndForward',
'telemetry',
],
},
specifications: {
BLEVersion: '4.2',
BLEAntenna: 'Integrated',
WiFiVersion: '2.4GHz 802.11 b/g/n WPA/WPA2/WPA2-Enterprise/SPS',
WiFiAntenna: 'Integrated',
Chipset: 'ESP32',
Driver: 'CH9102',
GNSS: 'NEO-6M',
FlashSize: 4,
Frequencies: [433, 868, 915, 923],
LoRa: 'SX1262',
PSRAM: 8,
RAM: undefined,
},
variants: [
{
name: 'TBeam 0.7',
misc: {
Stability: Stability.Unstable,
},
specifications: {
Driver: 'CP210X',
GNSS: 'NEO-6M',
Frequencies: [868, 915],
},
},
{
name: 'TBeam 1.0',
specifications: {
Frequencies: [868, 915],
},
},
{
name: 'TBeam 1.1',
specifications: {
Driver: 'CP210X',
GNSS: 'NEO-6M',
},
},
],
};

View file

@ -6,7 +6,7 @@ export const rak19003: IDevice = {
Stability: Stability.Stable,
SuggestedUse: [UseCase.Portable],
ImagePath: '/img/hardware/rak/RAK19003.png',
Gradient: 'from-green-300 via-blue-500 to-purple-600',
Gradient: 'bg-gradient-to-b from-orange-500 to-yellow-300',
},
features: {
BLE: true,

View file

@ -6,7 +6,7 @@ export const tbeam: IDevice = {
Stability: Stability.Stable,
SuggestedUse: [UseCase.Portable],
ImagePath: '/img/hardware/tbeam-v1.1.svg',
Gradient: 'from-pink-500 via-red-500 to-yellow-500',
Gradient: 'bg-gradient-to-r from-pink-500 via-red-500 to-yellow-500',
},
features: {
BLE: true,

View file

@ -5,6 +5,7 @@ import { FiPlus } from 'react-icons/fi';
import { HardwareCard } from '../../components/hardware/HardwareCard';
import { PageLayout } from '../../components/PageLayout';
import { heltec } from '../../data/devices/heltec';
import { hydra } from '../../data/devices/hydra';
import { rak19003 } from '../../data/devices/rak19003';
import { tbeam } from '../../data/devices/tbeam';
import { techo } from '../../data/devices/techo';
@ -12,6 +13,7 @@ import { techo } from '../../data/devices/techo';
const Hardware = (): JSX.Element => {
const hardware = [
tbeam,
hydra,
rak19003,
heltec,
techo,

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 798 KiB