refactor: projet stand-alone sans dépendance aoe_technology_radar
- Intégration du code source du framework dans radar-app/ (vendoring) - Suppression de la dépendance npm aoe_technology_radar - Création de scripts build-radar.js et serve-radar.js pour remplacer le CLI techradar - Adaptation de tous les scripts et Docker pour utiliser radar-app/ au lieu de .techradar - Refactorisation complète de Dockerfile.business - Mise à jour de la documentation (architecture, déploiement, développement) - Mise à jour de .gitignore pour ignorer les artefacts de build de radar-app/ - Ajout de postcss dans les dépendances Docker pour le build Next.js Le projet est maintenant complètement indépendant du package externe. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
50
radar-app/src/components/Badge/Badge.module.css
Normal file
50
radar-app/src/components/Badge/Badge.module.css
Normal file
@@ -0,0 +1,50 @@
|
||||
.badge {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
padding: 6px 15px;
|
||||
text-transform: uppercase;
|
||||
border: 1px solid transparent;
|
||||
border-radius: 13px;
|
||||
font-size: 12px;
|
||||
line-height: 1;
|
||||
overflow: hidden;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.size-small {
|
||||
padding: 4px 8px;
|
||||
font-size: 9px;
|
||||
}
|
||||
|
||||
.size-large {
|
||||
padding: 7px 20px;
|
||||
font-size: 14px;
|
||||
border-radius: 15px;
|
||||
}
|
||||
|
||||
.colored {
|
||||
color: var(--foreground);
|
||||
background-color: var(--badge);
|
||||
}
|
||||
|
||||
.selectable {
|
||||
cursor: pointer;
|
||||
|
||||
&:not(.selected) {
|
||||
color: var(--foreground);
|
||||
border: 1px solid var(--foreground);
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
&:not(.colored) {
|
||||
color: var(--foreground);
|
||||
border: 1px solid var(--foreground);
|
||||
background: transparent;
|
||||
|
||||
&.selected {
|
||||
color: var(--background);
|
||||
background: var(--foreground);
|
||||
}
|
||||
}
|
||||
}
|
||||
105
radar-app/src/components/Badge/Badge.tsx
Normal file
105
radar-app/src/components/Badge/Badge.tsx
Normal file
@@ -0,0 +1,105 @@
|
||||
import {
|
||||
CSSProperties,
|
||||
ComponentPropsWithoutRef,
|
||||
ReactNode,
|
||||
useMemo,
|
||||
} from "react";
|
||||
|
||||
import styles from "./Badge.module.css";
|
||||
|
||||
import { getFlag, getRing } from "@/lib/data";
|
||||
import { formatRelease } from "@/lib/format";
|
||||
import { Flag } from "@/lib/types";
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
interface BadgeProps extends ComponentPropsWithoutRef<"span"> {
|
||||
children?: ReactNode;
|
||||
color?: string;
|
||||
selectable?: boolean;
|
||||
selected?: boolean;
|
||||
size?: "small" | "medium" | "large";
|
||||
}
|
||||
|
||||
export function Badge({
|
||||
children,
|
||||
color,
|
||||
size = "medium",
|
||||
selectable,
|
||||
selected,
|
||||
...props
|
||||
}: BadgeProps) {
|
||||
const style = useMemo(
|
||||
() => (color ? ({ "--badge": color } as CSSProperties) : undefined),
|
||||
[color],
|
||||
);
|
||||
|
||||
const Component = props.onClick ? "button" : "span";
|
||||
|
||||
return (
|
||||
<Component
|
||||
{...props}
|
||||
style={style}
|
||||
className={cn(
|
||||
props.className,
|
||||
styles.badge,
|
||||
styles[`size-${size}`],
|
||||
color && styles.colored,
|
||||
selectable && styles.selectable,
|
||||
selected && styles.selected,
|
||||
)}
|
||||
>
|
||||
{children}
|
||||
</Component>
|
||||
);
|
||||
}
|
||||
|
||||
interface RingBadgeProps extends Omit<BadgeProps, "color" | "children"> {
|
||||
ring: string;
|
||||
release?: string;
|
||||
}
|
||||
|
||||
export function RingBadge({
|
||||
ring: ringName,
|
||||
release,
|
||||
...props
|
||||
}: RingBadgeProps) {
|
||||
const ring = getRing(ringName);
|
||||
if (!ring) return null;
|
||||
|
||||
const label = release
|
||||
? `${ring.title} | ${formatRelease(release)}`
|
||||
: ring.title;
|
||||
|
||||
return (
|
||||
<Badge color={ring.color} {...props}>
|
||||
{label}
|
||||
</Badge>
|
||||
);
|
||||
}
|
||||
|
||||
// Type guard to check if flag has the required attributes
|
||||
function hasRequiredFlagAttributes(flag: any): flag is {
|
||||
color: string;
|
||||
title: string;
|
||||
titleShort: string;
|
||||
} {
|
||||
return "color" in flag && "title" in flag && "titleShort" in flag;
|
||||
}
|
||||
|
||||
interface FlagBadgeProps
|
||||
extends Omit<BadgeProps, "color" | "children" | "size"> {
|
||||
flag: Flag;
|
||||
short?: boolean;
|
||||
}
|
||||
|
||||
export function FlagBadge({ flag: flagName, short, ...props }: FlagBadgeProps) {
|
||||
if (flagName === Flag.Default) return null;
|
||||
const flag = getFlag(flagName);
|
||||
if (!flag || !hasRequiredFlagAttributes(flag)) return null;
|
||||
|
||||
return (
|
||||
<Badge color={flag.color} size="small" {...props}>
|
||||
{short ? flag.titleShort : flag.title}
|
||||
</Badge>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user