Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added frontend/src/assets/edenmoon-earth-8463728.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion frontend/src/components/layout/AppLayout.css
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
.page-content {
flex: 1;
min-width: 0;
padding: 32px;
padding: 36px 20px;
}

@media (max-width: 768px) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ function TechniqueCard({
</section>

<Link
to={`/techniques/${mitreId}`}
to={`/techniques/details/`}
className="technique-card-footer"
>
<span>Open profile</span>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
.associated-software {
padding: 24px;

background: var(--surface);

border: 1px solid var(--border);
border-radius: 8px;
}

.associated-software-grid {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 12px;
}

.associated-software-header {
display: flex;
align-items: center;
gap: 12px;

margin-bottom: 20px;
}

.associated-software h2 {
margin-bottom: 16px;
}

.associated-software-card {
padding: 14px;

border: 1px solid var(--border);
border-radius: 8px;
}

.associated-software-card + .associated-software-card {
margin-top: 10px;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import "./AssociatedSoftware.css";
import { Cog } from "lucide-react";

type Software = {
name: string;
};

type AssociatedSoftwareProps = {
software: Software[];
};

function AssociatedSoftware({
software,
}: AssociatedSoftwareProps) {
return (
<section className="associated-software">
<div className="associated-software-header">
<Cog />
<h2>Associated Software</h2>
</div>

{software.map((item) => (
<article
key={item.name}
className="associated-software-card"
>
{item.name}
</article>
))}
</section>
);
}

export default AssociatedSoftware;
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
.related-threat-actors {
padding: 24px;
width: 100%;

background: var(--surface);

border: 1px solid var(--border);
border-radius: 8px;
}

.related-threat-actors-header {
display: flex;
align-items: center;
gap: 12px;

margin-bottom: 20px;
}

.related-threat-actors h2 {
margin-bottom: 16px;
}

.related-threat-actor-card {
padding: 16px;
white-space: nowrap;

border: 1px solid var(--border);
border-radius: 8px;
}

.related-threat-actor-card + .related-threat-actor-card {
margin-top: 10px;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import "./RelatedThreatActors.css";
import { Users } from "lucide-react";

type ThreatActor = {
mitreId: string;
name: string;
alias: string;
};

type RelatedThreatActorsProps = {
actors: ThreatActor[];
};

function RelatedThreatActors({
actors,
}: RelatedThreatActorsProps) {
return (
<section className="related-threat-actors">
<div className="related-threat-actors-header">
<Users />
<h2>Related Threat Actors</h2>
</div>

{actors.map((actor) => (
<article
key={actor.mitreId}
className="related-threat-actor-card"
>
<div className="actor-top-row">
<h3>{actor.name}</h3>
<span className="actor-id">
{actor.mitreId}
</span>
</div>
<p>
Also known as {actor.alias}
</p>
</article>
))}
</section>
);
}

export default RelatedThreatActors;
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
.technique-description {
padding: 24px;

background: var(--surface);

border: 1px solid var(--border);
border-radius: 8px;
}

.technique-description-header {
display: flex;
align-items: center;
gap: 12px;

margin-bottom: 12px;
}

.technique-description-header svg {
width: 28px;
height: 28px;
}

.technique-description p {
color: var(--text-muted);

line-height: 1.6;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { FileText } from "lucide-react";
import "./TechniqueDescription.css";

type TechniqueDescriptionProps = {
description: string;
};

function TechniqueDescription({
description,
}: TechniqueDescriptionProps) {
return (
<section className="technique-description">
<div className="technique-description-header">
<FileText />

<h2>Description</h2>
</div>

<div className="technique-description-content">
<p>{description}</p>
</div>
</section>
);
}

export default TechniqueDescription;
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
.technique-detailed-header {
display: flex;
flex-direction: column;
gap: 14px;
}

.technique-detailed-back-link {
display: flex;
align-items: center;
gap: 8px;

color: var(--accent);
text-decoration: none;

font-size: 14px;
font-weight: 600;
}

.technique-detailed-type {
color: var(--text-muted);

font-size: 12px;
font-weight: 700;

letter-spacing: 0.08em;
color: #6d3bf7;
font-size: 12px;
font-weight: 700;
letter-spacing: 0.08em;
}

.technique-detailed-title-row {
display: flex;
align-items: center;
gap: 16px;
}

.technique-detailed-title-row h1 {
font-size: 56px;
font-weight: 800;
}

.technique-detailed-title-row p {
font-size: 20px;
}

.technique-detailed-favorite-button {
background: transparent;
border: none;

color: var(--text);

cursor: pointer;
}

.technique-detailed-tags {
display: flex;
gap: 12px;
flex-wrap: wrap;
}

.technique-tactic-tag {
padding: 8px 16px;

border-radius: 999px;

background: rgba(0, 0, 0, 0.946);;
color: #6d3bf7;
}

.technique-platform-tag {
padding: 8px 16px;

border-radius: 999px;

background: rgba(0, 0, 0, 0.85);
color: #c7ddff;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import { ArrowLeft, Star } from "lucide-react";
import { Link } from "react-router-dom";

import "./TechniqueDetailedHeader.css";

type TechniqueDetailedHeaderProps = {
mitreId: string;
name: string;
tactic: string;
platforms: string[];
};

function TechniqueDetailedHeader({
mitreId,
name,
tactic,
platforms,
}: TechniqueDetailedHeaderProps) {
return (
<header className="technique-detailed-header">
<Link
to="/techniques"
className="technique-detailed-back-link"
>
<ArrowLeft />
Back to Techniques
</Link>

<span className="technique-detailed-type">
TECHNIQUE
</span>

<div className="technique-detailed-title-row">
<div>
<h1>{mitreId}</h1>
<p>{name}</p>
</div>

<button
type="button"
className="technique-detailed-favorite-button"
aria-label={`Save ${name}`}
>
<Star />
</button>
</div>

<div className="technique-detailed-tags">
<span className="technique-tactic-tag">
{tactic}
</span>

{platforms.map((platform) => (
<span
key={platform}
className="technique-platform-tag"
>
{platform}
</span>
))}
</div>
</header>
);
}

export default TechniqueDetailedHeader;
Loading