Design System

A contextual atomic design system for kinoo.dev. Shared components live in a common library, while feature-specific components stay with their context.

Work in progress.

Foundations

Design tokens and base styles that form the building blocks of the system.

Colors

Color palette and CSS variables used throughout the website.

Background Colors

--background-color #181927
--background-frosted rgba(24, 25, 39, 0.05)

Text Colors

--color #e0e0e0
--light-color #f6f5f7

Accent Colors

--accent-color #f8ba88
--secondary-accent-color #c9a88d
--accent-bright #f6b17a

Section Theme Colors

Each section uses a themed color palette. These override --accent-color and --secondary-accent-color at the section level.

Green (Realisations)

--green-lightest#9ae5b1
--green-light#80d49a
--green#66c384
--green-dark#5ab376
--green-darker#4a9c63
--green-darkest#3d8552

Pink (Experiences)

--pink-lightest#f8c8d9
--pink-light#f8a4c0
--pink#f68dab
--pink-dark#f47799
--pink-darker#f26088
--pink-darkest#d55478

Purple (Formations)

--purple-lightest#c9bce6
--purple-light#b09ee0
--purple#9c85d3
--purple-dark#8870c7
--purple-darker#745bba
--purple-darkest#6048a0

Card Colors

--card-first-background-color#2d2d3b
--card-alt-background-color#1c2638
--card-hover-background#313d50

Border Colors

--border-colorrgba(255, 255, 255, 0.1)
--border-hover-colorrgba(255, 255, 255, 0.2)

Usage

Import variables from @/styles/variables.css or use CSS custom properties directly in your styles.

Typography

Font sizes and heading styles used throughout the website.

Headings

h1 --h1-size

Heading 1

h2 --h2-size

Heading 2

h3 --h3-size

Heading 3

subtitle --subtitle-size

Subtitle text

p --font-size

Body text paragraph

button --button-font-size Button text

Size Variables

VariableDefault1368px900px600px
--h1-size 96px 92px 86px 64px
--h2-size 38px 48px 44px 36px
--h3-size 24px 24px 20px 18px
--subtitle-size 22px 24px 20px -
--font-size 18px 18px 16px -
--button-font-size 15px 15px 15px -

Font Family

The website uses Outfit as the primary font family with weights from 100 to 800.

Spacing

Consistent spacing scale used throughout the application.

Scale

4px
8px
12px
16px
24px
32px
48px
64px

Section Margin

VariableDefault1368px900px600px
--section-margin 142px 192px 148px 94px

Shared / Atoms

Reusable atomic components shared across multiple features.

Tag

Atom

Default

TypeScript
title="TypeScript"

With Icon

Terminal
title="Terminal" icon={terminalSvg}

Highlighted

Featured
title="Featured" highlight

Props

PropTypeDefaultDescription
title string required The text content of the tag
icon string - SVG icon as raw string
highlight boolean false Adds accent border
hero boolean false Hero animation variant

Button

Atom

Primary

Primary Link
<button class="primary">...</button>

Secondary

Secondary Link
<button class="secondary">...</button>

CSS Classes

ClassDescription
.primary Accent background, dark text
.secondary Card background, light text, border
.anime Adds hover lift animation to links

Interactions

Both variants have hover states that lift by 4px. Secondary also changes background and border color on hover.

IconButton

Atom

Default Color

<IconButton label="Menu"><BurgerIcon /></IconButton>

Primary Color

<IconButton label="Contact" color="primary">...</IconButton>

As Link

<IconButton label="Contact" href="#contact" color="primary">...</IconButton>

When href is provided, renders as <a> instead of <button>.

With Open State

Add .open class to trigger BurgerIcon animation.

Props

PropTypeDefaultDescription
label string required Accessible aria-label
id string - Optional ID for JavaScript targeting
href string - If provided, renders as <a> instead of <button>
variant "default" | "floating" "default" Floating adds fixed position and shadow
color "default" | "primary" "default" Color scheme
class string - Additional CSS classes

Variants

VariantDescription
default Standard button without positioning
floating Fixed position with z-index and box-shadow

Colors

ColorDescription
default Card background with border
primary Accent bright background

BurgerIcon

Atom

Animated hamburger menu icon that transforms to an X when the parent has .open class.

States

Closed
Open

Usage

<BurgerIcon />

Designed to be used inside an IconButton. The animation triggers when the parent element has the .open class.

Props

PropTypeDefaultDescription
class string - Additional CSS classes

Animation

The three lines transform using CSS transitions (0.3s ease):

  • Top line rotates 45deg and moves down
  • Middle line fades out
  • Bottom line rotates -45deg and moves up

H3Tagged

Atom

Heading with an inline tag badge, used for card titles with categorization.

Default

Project Title

React
title="Project Title" tag="React"

Props

PropTypeDefaultDescription
title string required The heading text
tag string required The tag/badge text

Usage

Typically used within CardTitle to display job titles or project names with their category/type.

Shared / Molecules

Reusable compound components shared across multiple features.

Card

Molecule

Base container component with gradient border effect. Parent of the Card compound system.

Basic Card

Card content goes here. Cards use slots for flexible content.

<Card>...content...</Card>

Card with Content

Project Title

React

This is a description of the project. Cards support complex layouts with titles, tags, and descriptions.

TypeScript
Next.js

Card Family Overview

ComponentPurposeUsage
Card Base container Wrapper with gradient border
CardContent Layout helper Structured content with slots
CardTitle Title block Job/project title with metadata
CardSplit Two-column layout Title + description + aside

Animation Attributes

Add data-animate-elem to elements for reveal animations. Used with revealCards utility for staggered fade-in effects.

CardContent

Molecule

Layout wrapper with named slots for structured card content. Used inside Card.

Slots

slot="title" Header/title area
slot="marge" Right-aligned content next to title
slot="description" Main body text
default slot Additional content (tags, links)

Usage

<Card><CardContent>...</CardContent></Card>

CardTitle

Molecule

Title block for cards with company/project metadata. Uses H3Tagged internally.

Props

PropTypeDescription
title string Main title (uses H3Tagged)
tag string Category badge
href string Company/project URL
label string Link text
location string Location (with dot separators)
date string Date range

Usage

<CardTitle slot="title" title="Developer" tag="Freelance" ... />

CardSplit

Molecule

Two-column grid layout for cards with title, description, and aside areas.

Layout Preview

Title Slot
Description Slot
Aside Slot
<CardSplit reverse> to flip layout

Props

PropTypeDefaultDescription
reverse boolean false Flips the layout (aside on left)

Slots

SlotGrid AreaDescription
title Top-left Card header with H3Tagged
description Bottom-left Main content area
aside Right column (spans 2 rows) Image or supplementary content

Spotlight

Molecule

Interactive spotlight effect that follows mouse movement on desktop. Creates a glowing halo that tracks the cursor.

Demo

Card 1

Hover over the container to see the spotlight effect

Card 2

Each card tracks the cursor independently

Card 3

Color is customizable via the color prop

Usage

<Spotlight color="var(--accent-bright)">...</Spotlight>

Wrap content with the Spotlight component. Add data-spotlight attribute to the parent container and initialize with spotlight() function.

Props

PropTypeDefaultDescription
color string required CSS color for the spotlight glow effect
class string - Additional CSS class for the wrapper

Implementation

The parent container needs data-spotlight attribute and must be initialized with spotlight(container) from @/lib/dom/spotlight. The function tracks mouse movement and updates --mouse-x and --mouse-y CSS properties.

Shared / Organisms

Complex patterns shared across multiple features.

Section Pattern

Organism

Shared layout pattern used by Experiences, Realisations, and Formations sections. Combines section header, themed grid, and card-based content.

Pattern Overview

SectionColor ThemeCard TypeGrid Layout
Experiences Pink (#f68dab) CardContent 2-column masonry
Realisations Green (#66c384) CardSplit 3-column
Formations Purple (#9c85d3) CardContent 3-column

Section Header

Mes

Expériences

All sections use <span class="subtitle"> + <h2> pattern with section-specific accent colors.

Structure

<section> Container with data-animate-section
<span.subtitle> Section label (e.g., "Mes")
<h2> Section title
<div.grid> Grid with data-spotlight
<Spotlight> Hover effect wrapper
<Card> Card container
<CardContent> or CardSplit for realisations

Section Theming

Each section overrides CSS custom properties for its color theme:

#experiences {
  --accent-color: #f68dab;
  --secondary-accent-color: #f8c8d9;
  --card-title-font-size: 16px;
}
VariablePurpose
--accent-color Primary section color (subtitle, links, tags)
--secondary-accent-color Lighter variant for hover states
--card-title-font-size Title size override

Data Attributes

AttributeElementPurpose
data-animate-section section Triggers section reveal animation
data-spotlight .grid Enables spotlight mouse tracking
data-animate-elem cards Staggered card reveal

Grid Layouts

Experiences (2-col masonry)
Adeo
Verty
OPO
Impact H.
Formations (3-col)
Epitech
Manipal
DernierCri
Eurotunnel
Realisations (3-col)
Arteflix
Ekeynox
kinoo.dev

Spotlight Integration

Each section initializes the spotlight effect via script:

import { spotlight } from "@/lib/dom/spotlight";

const container = document.getElementById("experiences-grid");
if (container) spotlight(container);

Demo

Example Card

Demo

Company Location 2024

demo

This demonstrates the card pattern used in section grids.

Tag 1
Tag 2

Hero

Components specific to the hero section.

HeroSubtitle

Atom

Animated subtitle that wraps each character in a span for letter-by-letter animation effects.

Preview

DéveloppeurFrontend

Props

PropTypeDescription
subtitle string Text to display (each character wrapped in a span)

Animation

Each character is wrapped in a <span class="letter"> element. The heroAnime.ts animation applies a staggered translateY effect to reveal letters sequentially.

Usage

<HeroSubtitle subtitle="Développeur Frontend Freelance" />

Styling

PropertyValue
font-size var(--hero-span-size)
font-weight 100
color var(--accent-color)
line-height 38px

Header

Site header and navigation components.

HeaderMenu

Molecule

Preview

The menu appears with opacity animation on page load.

Contents

LinkTypeDestination
GitHub icon External - GitHub profile
LinkedIn icon External - LinkedIn profile
CV badge External - PDF download
DS badge Internal - Design System
Me contacter button Internal - Contact section

Structure

.header-menu Flex container with gap
HeaderLink (icon) GitHub icon link
HeaderLink (icon) LinkedIn icon link
HeaderLink (badge) CV badge link
HeaderLink (badge) DS badge link
a.primary Contact CTA button

Responsive

On mobile (<600px), the "Me contacter" button is hidden and gap is reduced to 20px.

Contact

Contact section and related components.

Contact

Organism

Full contact section combining description text and an interactive form (SolidJS).

Structure

<section id="contact"> Main container with animation attribute
<h2> Section title
.contact-content Flexbox container
.contact-description Left column with intro text
<ContactForm /> SolidJS form component

ContactForm (SolidJS)

PropTypeDescription
accessToken string Web3Forms API access key

Uses client:load directive for immediate hydration. Form validation handled by Modular Forms.

Layout

BreakpointLayout
Desktop (>1200px) Side-by-side: description (max 466px) + form
Tablet/Mobile Stacked: description then form

Form Fields

FieldTypeValidation
Name text input Required
Email email input Required, email format
Message textarea Required

Usage

<Contact />

No props required. Form uses environment variable VITE_WEB3FORMS_ACCESS_KEY for API authentication.

Integration

The #contact section is detected by FloatingContact and viewDetection utilities for scroll-based navigation highlighting.

FloatingContact

Organism

Mobile-only sticky contact button that appears at the bottom of the screen. Auto-hides when the contact section is visible.

Preview

Default State
Contact
Hover State
Contact
Hidden (.current)
Contact

Behavior

ConditionStateCSS
Desktop (>600px) Hidden display: none
Mobile, #contact not visible Visible Default styles
Mobile, #contact in viewport Hidden .current class added

Positioning

PropertyValue
position sticky
bottom 36px
z-index 300
width 36px

View Detection Integration

Uses viewDetection utility from @/lib/dom/viewDetection to detect when #contact section enters the viewport. The .current class is toggled to fade out the button.

Usage

<FloatingContact />

No props required. Component is self-contained with its own scroll detection logic.

Sidebar

Design system navigation component.

Templates

Common patterns showing how components combine in real usage.

Compositions

Template

Real-world examples showing how atoms, molecules, and organisms combine to create complete UI patterns.

Experience Card

The primary card pattern used in the Experiences section. Combines Spotlight, Card, CardContent, and CardTitle.

Lead Developer

Freelance

Company Lille 2024

Logo

Description of the role and responsibilities. Includes highlighted technologies and achievements.

  • Feature or responsibility one
  • Feature or responsibility two
<Spotlight color="var(--pink)">
  <Card>
    <CardContent>
      <CardTitle slot="title" ... />
      <p slot="description">...</p>
      <ul>...</ul>
      <img slot="marge" ... />
    </CardContent>
  </Card>
</Spotlight>

Hero Title Block

The hero section title pattern combining HeroSubtitle (animated) with the main h1.

Développeur Frontend Freelance

Martin Kinoo

<div class="title">
  <HeroSubtitle subtitle="Développeur Frontend Freelance" />
  <h1><span>Martin</span> <span>Kinoo</span></h1>
</div>

Tech Stack Tags

A collection of Tag components displaying technology stack. Used in Hero section.

TypeScript
React
Svelte
Go
<ul>
  {techs.map(tech => (
    <li>
      <Tag
        title={tech.title}
        hero={true}
        icon={tech.icon}
        highlight={tech.highlight}
      />
    </li>
  ))}
</ul>

Section Header

Standard section header pattern with subtitle and main heading. Used across all main sections.

Mes

Expériences

<section id="experiences">
  <span class="subtitle">Mes</span>
  <h2>Expériences</h2>
  ...
</section>

Component Hierarchy

PatternComponents UsedLocation
Experience Card Spotlight / Card / CardContent / CardTitle Experiences section
Realisation Card Spotlight / Card / CardSplit / H3Tagged + Slider Realisations section
Formation Card Card / CardContent / CardTitle Formations section
Hero Block HeroSubtitle + h1 + Tags list Hero section
Page Layout Header + main content + FloatingContact All pages

DS Components

Documentation components used to build this design system. Self-documenting meta-components.

DSBlock

Atom

Example

Demo Title

Content inside DSBlock

Props

PropTypeDefaultDescription
title string required Section heading (h3)

Usage

<DSBlock title="Section Title">
  <DSPreview>
    <!-- Component preview -->
  </DSPreview>
  <DSCode>code example</DSCode>
</DSBlock>

DSBlock provides consistent 32px margin-top spacing between sections. Use it to wrap each documentation section.

DSPreview

Atom

Example

Props

PropTypeDefaultDescription
class string - Additional CSS classes

Usage

<DSPreview>
  <Button>Click me</Button>
</DSPreview>

<DSPreview class="custom-class">
  <!-- Custom styling via class -->
</DSPreview>

DSPreview uses 32px padding and 16px gap. Pass custom classes to override flex direction or alignment.

DSCode

Atom

Inline Example

<Button variant="primary" />

Block Example

const greeting = "Hello";
console.log(greeting);

Props

PropTypeDefaultDescription
inline boolean false Renders as inline code snippet

Usage

<!-- Inline code -->
<DSCode inline>&lt;Button /&gt;</DSCode>

<!-- Block code -->
<DSCode>
const foo = "bar";
console.log(foo);
</DSCode>

DSPropsTable

Atom

Example

NameValue
Primary Orange button
Secondary Outline style

With Code Cells

PropTypeDescription
title string Main heading
items array List of items

Props

PropTypeDefaultDescription
headers string[] required Table header labels
rows Cell[][] required Array of rows, each row is array of cells

Cell can be a string or { code: string } for code formatting.

Usage

<DSPropsTable
  headers={["Prop", "Type", "Default", "Description"]}
  rows={[
    [{ code: "title" }, "string", "required", "The title text"],
    [{ code: "disabled" }, "boolean", "false", "Disables the component"],
  ]}
/>

DSStructure

Atom

Hierarchy diagram for displaying component structure or DOM tree.

Example

<Card> Container component
<CardTitle> Title section
<CardContent> Main content
<p> Text paragraph

Props

PropTypeDefaultDescription
rows StructureRow[] required Array of structure rows

StructureRow: { code: string, description: string, indent?: number }

Usage

<DSStructure
  rows={[
    { code: "<section>", description: "Container" },
    { code: "<header>", description: "Header area", indent: 1 },
    { code: "<main>", description: "Main content", indent: 1 },
  ]}
/>

DSNote

Atom

Example

This is a note with inline code support. Use it for tips and additional context.

Props

PropTypeDescription
(slot) any Content to display as note

Usage

<DSNote>Note text with <code>code</code></DSNote>

DSNote has 12px margin-top and 70% opacity. Supports inline <code> tags.

kinoo.dev · Design System