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
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,17 @@ Interactive frontend for learning Clean Architecture β€” part of the CAVE (CA Vi
- Plain CSS with CSS Modules
- Google Fonts: Bricolage Grotesque, Plus Jakarta Sans, JetBrains Mono

## Setting up the repo

**If you are cloning this for the first time:**

```bash
git clone https://github.com/CA-Visualizer-for-Education/cave-learn.git
cd cave-learn
npm install
npm run dev
```

## Getting started

```bash
Expand Down
13 changes: 3 additions & 10 deletions app/diagram/page.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
// app/diagram/page.tsx β€” Diagram page (route: /diagram)
// ─────────────────────────────────────────────────────────────
// Two-column layout: diagram canvas (left) + component sidebar (right).
// Owns the selectedId state and passes it down to both children.
// Needs 'use client' because of useState.
// ─────────────────────────────────────────────────────────────
// app/diagram/page.tsx β€” Diagram page (route: /diagram)
// Two-column layout: CADiagram + DiagramLegend on the left, ComponentSidebar on the right.
// Owns selectedId state and passes it down to both children.

'use client'

Expand All @@ -13,11 +10,7 @@ import DiagramLegend from '@/components/diagram/DiagramLegend'
import ComponentSidebar from '@/components/diagram/ComponentSidebar'

export default function DiagramPage() {
// null = nothing selected; string = the id of the clicked CA component
const [selectedId, setSelectedId] = useState<string | null>(null)

// TODO: lay out the two-column page (diagram + sidebar)
// TODO: pass selectedId and setSelectedId into CADiagram
// TODO: pass selectedId into ComponentSidebar
return <main className="page-shell">This is the Diagram page</main>
}
3 changes: 1 addition & 2 deletions app/exercise/page.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
// app/exercise/page.tsx β€” Exercise page (route: /exercise)
// app/exercise/page.tsx β€” Exercise page (route: /exercise)
// Drag-and-drop lesson: place every CA component into its correct layer.
// See the mockup in the project Figma / design images for the full spec.

export default function ExercisePage() {
return <main className="page-shell">This is the Exercise page</main>
Expand Down
30 changes: 2 additions & 28 deletions app/page.tsx
Original file line number Diff line number Diff line change
@@ -1,32 +1,6 @@
// app/page.tsx β€” Home page (route: /)
// ─────────────────────────────────────────────────────────────
// This file composes the home page layout.
// It imports two components and arranges them on the page.
// You should not need to write styling here β€” style each
// component in its own CSS module file.
//
// PAGE LAYOUT (top to bottom):
// <main>
// <HeroSection /> ← headline, subtitle, stats chips
// <section> ← side-by-side cards grid
// <StepCard step 1 /> ← "Explore the diagram" card
// <StepCard step 2 /> ← "Test yourself" card
// </section>
// </main>
//
// The two StepCards sit in a two-column grid on desktop,
// stacked single-column on mobile.
//
// WHAT TO DO:
// 1. Import HeroSection from '@/components/home/HeroSection'
// 2. Import StepCard from '@/components/home/StepCard'
// 3. Render them inside <main className="page-shell">
// (page-shell is defined in globals.css β€” it adds the
// top padding needed to clear the fixed navbar)
// 4. Create a CSS module (page.module.css) for the grid layout.
// ─────────────────────────────────────────────────────────────
// app/page.tsx β€” Home page (route: /)
// Composes HeroSection and two StepCards.

export default function HomePage() {
// TODO: build this page
return <main className="page-shell">This is the Home page</main>
}
22 changes: 3 additions & 19 deletions components/diagram/CADiagram.tsx
Original file line number Diff line number Diff line change
@@ -1,22 +1,7 @@
// components/diagram/CADiagram.tsx
// ─────────────────────────────────────────────────────────────
// The interactive Clean Architecture diagram.
// Renders four layer rectangles with component boxes inside them.
// Clicking a box calls onSelect with that component's id.
// Clicking the background calls onSelect(null) to deselect.
//
// Props:
// selectedId β€” id of the currently selected component (from page state)
// onSelect β€” callback: (id: string | null) => void
//
// Data: import CA_LAYERS and CA_COMPONENTS from '@/lib/ca-data'
// Never hardcode component names or colors here.
//
// Approach:
// Position component boxes using absolute CSS inside a relative container.
// Draw dependency/implements arrows with SVG overlaid on top.
// Highlight the selected box (border, shadow, or opacity change).
// ─────────────────────────────────────────────────────────────
// Interactive Clean Architecture diagram.
// Renders CA_LAYERS as rectangles and CA_COMPONENTS as clickable boxes.
// Props: selectedId (string | null), onSelect ((id: string | null) => void)

import { CA_COMPONENTS, CA_LAYERS } from '@/lib/ca-data'

Expand All @@ -26,6 +11,5 @@ interface CADiagramProps {
}

export default function CADiagram({ selectedId, onSelect }: CADiagramProps) {
// TODO: build the diagram
return <div onClick={() => onSelect(null)}></div>
}
19 changes: 3 additions & 16 deletions components/diagram/ComponentSidebar.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,7 @@
// components/diagram/ComponentSidebar.tsx
// ─────────────────────────────────────────────────────────────
// Right-hand panel on the /diagram page.
// Shows info about the clicked component, or a prompt when nothing is selected.
//
// Props:
// selectedId β€” string | null (from DiagramPage state)
//
// Logic:
// const component = CA_COMPONENTS.find(c => c.id === selectedId) ?? null
// if (!component) β†’ show "Click a component to learn about it"
// if (component) β†’ show name, layer badge, description, dependsOn[], implements[]
//
// Data: import CA_COMPONENTS and CA_LAYERS from '@/lib/ca-data'
// Use CA_LAYERS[component.layer].colorHex for the layer badge color.
// ─────────────────────────────────────────────────────────────
// Right-hand panel on the diagram page.
// Shows component details when selectedId is set, otherwise shows an empty state.
// Look up the selected component with CA_COMPONENTS.find(c => c.id === selectedId).

import { CA_COMPONENTS, CA_LAYERS } from '@/lib/ca-data'

Expand All @@ -24,6 +12,5 @@ interface ComponentSidebarProps {
export default function ComponentSidebar({ selectedId }: ComponentSidebarProps) {
const component = CA_COMPONENTS.find((c) => c.id === selectedId) ?? null

// TODO: build the sidebar β€” empty state and detail state
return <aside></aside>
}
10 changes: 2 additions & 8 deletions components/diagram/DiagramLegend.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,7 @@
// components/diagram/DiagramLegend.tsx
// ─────────────────────────────────────────────────────────────
// Shows the three diagram symbol explanations below the canvas:
// β€”β€”β†’ Dependency (solid arrow)
// - β†’ Implements (dashed arrow)
// [β– ] Component (filled coloured box, use brand-green as example)
// No props or state needed β€” purely presentational.
// ─────────────────────────────────────────────────────────────
// Legend row below the diagram canvas.
// Three items: solid arrow (Dependency), dashed arrow (Implements), filled box (Component).

export default function DiagramLegend() {
// TODO: build the legend row
return <div></div>
}
75 changes: 21 additions & 54 deletions components/home/HeroSection.module.css
Original file line number Diff line number Diff line change
@@ -1,54 +1,21 @@
/* HeroSection.module.css
─────────────────────────────────────────────────────────────
ELEMENTS TO STYLE:
.section the outer wrapper β€” controls max-width and padding
.eyebrow the uppercase micro label at the top
.logoRow flex row containing the logo mark + headline
.logoMark the CAVE circular logo image/placeholder
.headline the <h1> element
.headlineAccent the "Clean Architecture" span inside h1 β€” pink color
.subtitle the paragraph below the headline
.statsRow horizontal flex row of stat chips
.statChip a single chip (dot + label)
.statDot the small colored circle in each chip
───────────────────────────────────────────────────────────── */

.section {
/* TODO */
}

.eyebrow {
/* TODO - hint: use var(--font-mono) and var(--tracking-eyebrow) */
}

.logoRow {
/* TODO - hint: display flex, align-items flex-start, gap */
}

.logoMark {
/* TODO - 56px circle, placeholder background until SVG is ready */
}

.headline {
/* TODO - hint: use var(--font-display) and var(--text-display) */
}

.headlineAccent {
/* TODO - hint: color: var(--color-brand-pink) */
}

.subtitle {
/* TODO */
}

.statsRow {
/* TODO - hint: display flex, flex-wrap wrap, gap */
}

.statChip {
/* TODO - hint: display flex, align-items center, gap, small font */
}

.statDot {
/* TODO - hint: 8px circle, background-color set inline in JSX */
}
/* HeroSection.module.css */

.section {}

.eyebrow {}

.logoRow {}

.logoMark {}

.headline {}

.headlineAccent {}

.subtitle {}

.statsRow {}

.statChip {}

.statDot {}
48 changes: 3 additions & 45 deletions components/home/HeroSection.tsx
Original file line number Diff line number Diff line change
@@ -1,50 +1,8 @@
// components/home/HeroSection.tsx
// ─────────────────────────────────────────────────────────────
// The hero block at the top of the home page.
// Placed directly inside <main> in app/page.tsx.
//
// VISUAL STRUCTURE (top to bottom):
//
// [ eyebrow text ]
// "INTERACTIVE Β· SELF-PACED Β· OPEN SOURCE"
// β€” small uppercase label, muted color, letter-spaced
// β€” use the .text-eyebrow utility class from globals.css
//
// [ logo + headline row ] β€” side by side
// Left: CAVE logo mark image (public/logo.svg, ~56px)
// placeholder <div> is fine until the SVG is ready
// Right: <h1> β€” two lines:
// "Learn Clean Architecture" ← "Clean Architecture" in brand-pink
// "by playing with it."
// Use the .text-display class from globals.css for the font.
// Wrap just "Clean Architecture" in a <span> with pink color.
//
// [ subtitle paragraph ]
// "Two interactive lessons that teach you the components, the layers,
// and the dependency rule. No setup, no install β€” just click around
// until it clicks."
// β€” use .text-body from globals.css
//
// [ stats chips row ] β€” four small items in a horizontal flex row
// Each chip = a colored dot + a label. Data is listed below.
// Dot colors match the CA layer brand colors.
//
// STATS CHIP DATA (use this array in your component):
// { dot: '#207FD4', label: '4 layers' }
// { dot: '#3FAE5C', label: '13 components' }
// { dot: '#E2477C', label: '1 dependency rule' }
// { dot: '#F5C242', label: '~10 min' }
//
// STYLING:
// Create HeroSection.module.css next to this file.
// The whole section has generous top padding and a max-width.
// The logo + headline row uses display: flex, align-items: flex-start.
//
// IMPORTS YOU WILL NEED:
// import styles from './HeroSection.module.css'
// ─────────────────────────────────────────────────────────────
// Hero block at the top of the home page.
// Contains: eyebrow label, logo mark, headline, subtitle, stats chips.
// Stats data lives in ca-data.ts β€” import CA_LAYERS for the dot colors.

export default function HeroSection() {
// TODO: build the hero section
return <section></section>
}
46 changes: 8 additions & 38 deletions components/home/StepCard.module.css
Original file line number Diff line number Diff line change
@@ -1,45 +1,15 @@
/* StepCard.module.css
─────────────────────────────────────────────────────────────
ELEMENTS TO STYLE:
.card the outer <article> β€” white surface, border, radius, shadow
.illustration top image/placeholder area β€” light background, fixed height
.body padding wrapper for the text content below the illustration
.stepBadge the "STEP N" eyebrow label
.title the card headline
.description the body paragraph
.cta the "Start exploring β€Ί" link at the bottom
───────────────────────────────────────────────────────────── */
/* StepCard.module.css */

.card {
/* TODO
hint: background-color: var(--color-surface);
border-radius: var(--radius-card);
border: 1px solid var(--color-border);
box-shadow: var(--shadow-card);
display: flex; flex-direction: column;
*/
}
.card {}

.illustration {
/* TODO - placeholder area, e.g. height: 144px, background: var(--color-surface2) */
}
.illustration {}

.body {
/* TODO - padding around the text content */
}
.body {}

.stepBadge {
/* TODO - hint: font-family: var(--font-mono), color: var(--color-brand-blue) */
}
.stepBadge {}

.title {
/* TODO */
}
.title {}

.description {
/* TODO */
}
.description {}

.cta {
/* TODO - hint: color: var(--color-brand-pink), no text-decoration, hover opacity */
}
.cta {}
Loading
Loading