From 1b7634a2efa559509911f0399b51de160952f8cd Mon Sep 17 00:00:00 2001 From: Mathias Schopmans Date: Tue, 20 Feb 2024 15:39:43 +0100 Subject: [PATCH] feat: [WIP] add radar component --- data/config.json | 16 +++- src/components/Radar/Radar.module.css | 11 +++ src/components/Radar/Radar.tsx | 102 ++++++++++++++++++++++++++ src/lib/types.ts | 2 + src/pages/index.tsx | 12 ++- 5 files changed, 138 insertions(+), 5 deletions(-) create mode 100644 src/components/Radar/Radar.module.css create mode 100644 src/components/Radar/Radar.tsx diff --git a/data/config.json b/data/config.json index fee8722..0a09df9 100644 --- a/data/config.json +++ b/data/config.json @@ -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": { diff --git a/src/components/Radar/Radar.module.css b/src/components/Radar/Radar.module.css new file mode 100644 index 0000000..40e3695 --- /dev/null +++ b/src/components/Radar/Radar.module.css @@ -0,0 +1,11 @@ +.radar { + padding: 50px; + position: relative; +} + +.svg { + display: block; + max-width: 100%; + height: auto; + margin: 0 auto; +} diff --git a/src/components/Radar/Radar.tsx b/src/components/Radar/Radar.tsx new file mode 100644 index 0000000..1056907 --- /dev/null +++ b/src/components/Radar/Radar.tsx @@ -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 = ({ 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 ( + <> + + + + + + + + + ); + }; + + return ( +
+ + {quadrants.map((quadrant) => ( + + {renderGlow(quadrant.position, quadrant.color)} + {rings.map((ring) => ( + + ))} + + ))} + +
+ ); +}; + +export default Radar; diff --git a/src/lib/types.ts b/src/lib/types.ts index 5195aad..fd4b5c8 100644 --- a/src/lib/types.ts +++ b/src/lib/types.ts @@ -30,6 +30,8 @@ export interface Ring { title: string; description: string; color: string; + radius?: number; + strokeWidth?: number; } export interface Quadrant { diff --git a/src/pages/index.tsx b/src/pages/index.tsx index 806dccd..07f959b 100644 --- a/src/pages/index.tsx +++ b/src/pages/index.tsx @@ -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}{" "} Version #{version} + );