feat: [WIP] add radar component
This commit is contained in:
committed by
Mathias Schopmans
parent
563d8debc0
commit
1b7634a2ef
@@ -34,25 +34,33 @@
|
||||
"id": "adopt",
|
||||
"title": "Adopt",
|
||||
"description": "We can clearly recommend this technology. We have used it for longer period of time in many teams and it has proven to be stable and useful.",
|
||||
"color": "#5cb449"
|
||||
"color": "#5cb449",
|
||||
"radius": 0.5,
|
||||
"strokeWidth": 6
|
||||
},
|
||||
{
|
||||
"id": "trial",
|
||||
"title": "Trial",
|
||||
"description": "We have used it with success and recommend to have a closer look at the technology in this ring. The goal of items here is to look at them more closely, with the goal to bring them to the adopt level.",
|
||||
"color": "#faa03d"
|
||||
"color": "#faa03d",
|
||||
"radius": 0.7,
|
||||
"strokeWidth": 4
|
||||
},
|
||||
{
|
||||
"id": "assess",
|
||||
"title": "Assess",
|
||||
"description": "We have tried it out and we find it promising. We recommend having a look at these items when you face a specific need for the technology in your project.",
|
||||
"color": "#029df7"
|
||||
"color": "#029df7",
|
||||
"radius": 0.88,
|
||||
"strokeWidth": 2
|
||||
},
|
||||
{
|
||||
"id": "hold",
|
||||
"title": "Hold",
|
||||
"description": "This category is a bit special. Unlike the others, we recommend to stop doing or using something. That does not mean that they are bad and it often might be ok to use them in existing projects. But we move things here if we think we shouldn't do them anymore - because we see better options or alternatives now.",
|
||||
"color": "#688190"
|
||||
"color": "#688190",
|
||||
"radius": 1,
|
||||
"strokeWidth": 1
|
||||
}
|
||||
],
|
||||
"flags": {
|
||||
|
||||
11
src/components/Radar/Radar.module.css
Normal file
11
src/components/Radar/Radar.module.css
Normal file
@@ -0,0 +1,11 @@
|
||||
.radar {
|
||||
padding: 50px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.svg {
|
||||
display: block;
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
margin: 0 auto;
|
||||
}
|
||||
102
src/components/Radar/Radar.tsx
Normal file
102
src/components/Radar/Radar.tsx
Normal file
@@ -0,0 +1,102 @@
|
||||
import React, { FC } from "react";
|
||||
|
||||
import styles from "./Radar.module.css";
|
||||
|
||||
import { Quadrant, Ring } from "@/lib/types";
|
||||
|
||||
export interface RadarProps {
|
||||
size?: number;
|
||||
quadrants: Quadrant[];
|
||||
rings: Ring[];
|
||||
}
|
||||
|
||||
export const Radar: FC<RadarProps> = ({ size = 800, quadrants, rings }) => {
|
||||
const viewBoxSize = size;
|
||||
const center = size / 2;
|
||||
const startAngles = [270, 0, 180, 90]; // Corresponding to positions 1, 2, 3, and 4 respectively
|
||||
|
||||
// Helper function to convert polar coordinates to cartesian
|
||||
const polarToCartesian = (
|
||||
radius: number,
|
||||
angleInDegrees: number,
|
||||
): { x: number; y: number } => {
|
||||
const angleInRadians = ((angleInDegrees - 90) * Math.PI) / 180.0;
|
||||
return {
|
||||
x: center + radius * Math.cos(angleInRadians),
|
||||
y: center + radius * Math.sin(angleInRadians),
|
||||
};
|
||||
};
|
||||
|
||||
// Function to generate the path for a ring segment
|
||||
const describeArc = (radiusPercentage: number, position: number): string => {
|
||||
// Define the start and end angles based on the quadrant position
|
||||
const startAngle = startAngles[position - 1];
|
||||
const endAngle = startAngle + 90;
|
||||
|
||||
const radius = radiusPercentage * center; // Convert percentage to actual radius
|
||||
const start = polarToCartesian(radius, endAngle);
|
||||
const end = polarToCartesian(radius, startAngle);
|
||||
|
||||
// prettier-ignore
|
||||
return [
|
||||
"M", start.x, start.y,
|
||||
"A", radius, radius, 0, 0, 0, end.x, end.y,
|
||||
].join(" ");
|
||||
};
|
||||
|
||||
const renderGlow = (position: number, color: string) => {
|
||||
const gradientId = `glow-${position}`;
|
||||
|
||||
const cx = position === 1 || position === 3 ? 1 : 0;
|
||||
const cy = position === 1 || position === 2 ? 1 : 0;
|
||||
|
||||
const x = position === 1 || position === 3 ? 0 : center;
|
||||
const y = position === 1 || position === 2 ? 0 : center;
|
||||
return (
|
||||
<>
|
||||
<defs>
|
||||
<radialGradient id={gradientId} x={0} y={0} r={1} cx={cx} cy={cy}>
|
||||
<stop offset="0%" stopColor={color} stopOpacity={0.5}></stop>
|
||||
<stop offset="100%" stopColor={color} stopOpacity={0}></stop>
|
||||
</radialGradient>
|
||||
</defs>
|
||||
<rect
|
||||
width={center}
|
||||
height={center}
|
||||
x={x}
|
||||
y={y}
|
||||
fill={`url(#${gradientId})`}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={styles.radar}>
|
||||
<svg
|
||||
className={styles.svg}
|
||||
width={viewBoxSize}
|
||||
height={viewBoxSize}
|
||||
viewBox={`0 0 ${viewBoxSize} ${viewBoxSize}`}
|
||||
>
|
||||
{quadrants.map((quadrant) => (
|
||||
<g className={`quadrant quadrant-${quadrant.id}`} key={quadrant.id}>
|
||||
{renderGlow(quadrant.position, quadrant.color)}
|
||||
{rings.map((ring) => (
|
||||
<path
|
||||
key={`${ring.id}-${quadrant.id}`}
|
||||
data-key={`${ring.id}-${quadrant.id}`}
|
||||
d={describeArc(ring.radius || 0.5, quadrant.position)}
|
||||
fill="none"
|
||||
stroke={quadrant.color}
|
||||
strokeWidth={ring.strokeWidth || 2}
|
||||
/>
|
||||
))}
|
||||
</g>
|
||||
))}
|
||||
</svg>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Radar;
|
||||
@@ -30,6 +30,8 @@ export interface Ring {
|
||||
title: string;
|
||||
description: string;
|
||||
color: string;
|
||||
radius?: number;
|
||||
strokeWidth?: number;
|
||||
}
|
||||
|
||||
export interface Quadrant {
|
||||
|
||||
@@ -1,10 +1,19 @@
|
||||
import { QuadrantList } from "@/components/QuadrantList/QuadrantList";
|
||||
import { getAppName, getItems, getReleases } from "@/lib/data";
|
||||
import { Radar } from "@/components/Radar/Radar";
|
||||
import {
|
||||
getAppName,
|
||||
getItems,
|
||||
getQuadrants,
|
||||
getReleases,
|
||||
getRings,
|
||||
} from "@/lib/data";
|
||||
import { CustomPage } from "@/pages/_app";
|
||||
|
||||
const Home: CustomPage = () => {
|
||||
const appName = getAppName();
|
||||
const version = getReleases().length;
|
||||
const rings = getRings();
|
||||
const quadrants = getQuadrants();
|
||||
const items = getItems(undefined, true);
|
||||
return (
|
||||
<>
|
||||
@@ -12,6 +21,7 @@ const Home: CustomPage = () => {
|
||||
{appName}{" "}
|
||||
<span style={{ color: "var(--highlight)" }}>Version #{version}</span>
|
||||
</h1>
|
||||
<Radar quadrants={quadrants} rings={rings} />
|
||||
<QuadrantList items={items} />
|
||||
</>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user