Skip to content

Commit fd7b2de

Browse files
Initialize informatics and networks semester lab
1 parent 1095e87 commit fd7b2de

10 files changed

Lines changed: 504 additions & 1 deletion

File tree

.github/workflows/smoke.yml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
name: Static Smoke Test
2+
3+
on:
4+
push:
5+
branches: [main]
6+
pull_request:
7+
workflow_dispatch:
8+
9+
jobs:
10+
smoke:
11+
runs-on: ubuntu-latest
12+
steps:
13+
- uses: actions/checkout@v4
14+
- uses: actions/setup-python@v5
15+
with:
16+
python-version: '3.11'
17+
- run: python scripts/smoke_static.py

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
.DS_Store
2+
Thumbs.db
3+
.vscode/
4+
dist/

.portfolio-init

Lines changed: 0 additions & 1 deletion
This file was deleted.

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2026 Alberto Mateus P. da Gama
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

Makefile

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
smoke:
2+
python scripts/smoke_static.py
3+
4+
serve:
5+
python -m http.server 8000

README.md

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
# Mini Design System CSS Lab
2+
3+
Mini design system with CSS custom properties, color tokens, typography scale, buttons, cards, and badges.
4+
5+
> Educational project inspired by EETEPA Vilhena Alves. It is not an official institutional system and does not use real student data.
6+
7+
## Overview
8+
9+
**Curricular code:** I-06
10+
**Course:** Technical Computing
11+
**Discipline:** Website Design
12+
**Difficulty:** Intermediate
13+
14+
This repository is a small runnable MVP for portfolio and classroom practice. It uses only static files and local sample content, so it can run on GitHub Pages without a backend.
15+
16+
## Concepts Practiced
17+
18+
- CSS variables
19+
- component reuse
20+
- design tokens
21+
- documentation
22+
- visual consistency
23+
24+
## Run Locally
25+
26+
Open `index.html` directly or serve the folder:
27+
28+
```bash
29+
python -m http.server 8000
30+
```
31+
32+
Then open `http://localhost:8000`.
33+
34+
## Public Demo
35+
36+
GitHub Pages target: `https://albertomateus9.github.io/mini-design-system-css-lab/`
37+
38+
## Data And Privacy
39+
40+
- Uses only synthetic educational content.
41+
- Does not submit forms to a server.
42+
- Does not include real student records or internal school documents.
43+
44+
---
45+
46+
# Mini Design System CSS Lab
47+
48+
Mini design system with CSS custom properties, color tokens, typography scale, buttons, cards, and badges.
49+
50+
> Projeto educacional inspirado na EETEPA Vilhena Alves. Nao e sistema oficial institucional e nao usa dados reais de estudantes.
51+
52+
## Visao Geral
53+
54+
**Codigo curricular:** I-06
55+
**Curso:** Tecnico em Informatica
56+
**Disciplina:** Designer de Websites
57+
**Dificuldade:** Intermediario
58+
59+
Este repositorio e um MVP pequeno e executavel para portfolio e pratica em sala. Ele usa apenas arquivos estaticos e conteudo local de amostra, entao pode rodar no GitHub Pages sem backend.
60+
61+
## Conceitos Praticados
62+
63+
- CSS variables
64+
- component reuse
65+
- design tokens
66+
- documentation
67+
- visual consistency
68+
69+
## Como Rodar
70+
71+
Abra `index.html` diretamente ou sirva a pasta:
72+
73+
```bash
74+
python -m http.server 8000
75+
```
76+
77+
Depois abra `http://localhost:8000`.
78+
79+
## Demo Publica
80+
81+
Destino GitHub Pages: `https://albertomateus9.github.io/mini-design-system-css-lab/`
82+
83+
## Dados E Privacidade
84+
85+
- Usa apenas conteudo educacional sintetico.
86+
- Nao envia formularios para servidor.
87+
- Nao inclui registros reais de estudantes nem documentos internos da escola.
88+
89+
## License
90+
91+
MIT. See [LICENSE](LICENSE).

index.html

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
<!doctype html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="utf-8">
5+
<meta name="viewport" content="width=device-width, initial-scale=1">
6+
<title>Mini Design System CSS Lab</title>
7+
<meta name="description" content="Mini design system with CSS custom properties, color tokens, typography scale, buttons, cards, and badges.">
8+
<link rel="stylesheet" href="styles.css">
9+
</head>
10+
<body data-mode="design-system">
11+
<header>
12+
<div class="topbar">
13+
<div class="brand"><span class="mark">I</span><span>Mini Design System CSS Lab</span></div>
14+
<nav aria-label="Primary navigation">
15+
<a href="#practice">Practice</a>
16+
<a href="#output">Output</a>
17+
<a href="#privacy">Data policy</a>
18+
</nav>
19+
<button class="ghost" id="themeToggle" type="button">Theme</button>
20+
</div>
21+
<section class="hero">
22+
<div class="hero-copy">
23+
<h1>Document a reusable visual language with CSS variables.</h1>
24+
<p>A compact system for tokens, buttons, status labels, cards, and type scale.</p>
25+
<div class="toolbar">
26+
<a class="button" href="#practice">Start lab</a>
27+
<button class="secondary" id="exportButton" type="button">Export report</button>
28+
</div>
29+
</div>
30+
<aside class="panel">
31+
<h2>I-06 Snapshot</h2>
32+
<p>Website Design | Intermediate</p>
33+
<div class="grid">
34+
<div class="metric"><strong>8</strong><span>tokens</span></div>
35+
<div class="metric"><strong>4</strong><span>components</span></div>
36+
<div class="metric"><strong>1</strong><span>CSS file</span></div>
37+
</div>
38+
</aside>
39+
</section>
40+
</header>
41+
42+
<main>
43+
<section id="practice">
44+
<h2>Practice Surface</h2>
45+
<div class="grid" id="cards"></div>
46+
</section>
47+
48+
<section class="grid two" id="output">
49+
<div class="panel">
50+
<h2>Interactive Output</h2>
51+
<div id="dynamicSurface"></div>
52+
</div>
53+
<div class="panel">
54+
<h2>Progress</h2>
55+
<div id="progressList"></div>
56+
</div>
57+
</section>
58+
59+
<section class="panel" id="privacy">
60+
<h2>Data Policy</h2>
61+
<p>Educational project inspired by EETEPA Vilhena Alves. It is not an official institutional system and does not use real student data.</p>
62+
<p>All demo content is synthetic and local. No form or metric is submitted to a backend.</p>
63+
</section>
64+
</main>
65+
66+
<footer>
67+
Technical Computing | Website Design | MIT License
68+
</footer>
69+
70+
<script id="projectData" type="application/json">{"title":"Mini Design System CSS Lab","code":"I-06","discipline":"Website Design","notice":"Educational project inspired by EETEPA Vilhena Alves. It is not an official institutional system and does not use real student data.","features":[{"name":"CSS variables","score":72},{"name":"component reuse","score":76},{"name":"design tokens","score":80},{"name":"documentation","score":84},{"name":"visual consistency","score":88}],"headline":"Document a reusable visual language with CSS variables.","summary":"A compact system for tokens, buttons, status labels, cards, and type scale.","cards":["Color tokens","Type scale","Buttons","Status labels"],"metrics":["8 tokens","4 components","1 CSS file"]}</script>
71+
<script src="script.js"></script>
72+
</body>
73+
</html>

script.js

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
const project = JSON.parse(document.querySelector('#projectData').textContent);
2+
const mode = document.body.dataset.mode;
3+
const cards = document.querySelector('#cards');
4+
const dynamicSurface = document.querySelector('#dynamicSurface');
5+
const progressList = document.querySelector('#progressList');
6+
7+
function renderCards() {
8+
cards.innerHTML = project.cards.map((card, index) => `
9+
<article class="card">
10+
<span class="status">${project.code}.${index + 1}</span>
11+
<h3>${card}</h3>
12+
<p>Practice item for ${project.discipline.toLowerCase()} with local-only content.</p>
13+
</article>
14+
`).join('');
15+
}
16+
17+
function renderProgress() {
18+
progressList.innerHTML = project.features.map((item) => `
19+
<p><strong>${item.name}</strong></p>
20+
<div class="bar" aria-label="${item.name} progress"><span style="--value: ${item.score}%"></span></div>
21+
`).join('');
22+
}
23+
24+
function formSurface() {
25+
return `
26+
<form id="demoForm" novalidate>
27+
<div class="form-grid">
28+
<label>Full name <input name="fullName" autocomplete="name" required><span class="error"></span></label>
29+
<label>Student code <input name="studentCode" placeholder="LAB-2026" required><span class="error"></span></label>
30+
<label>Email <input name="email" type="email" required><span class="error"></span></label>
31+
<label>Course <select name="course"><option>Computing</option><option>Networks</option></select><span class="error"></span></label>
32+
<label>Password <input name="password" type="password" required><span class="error"></span></label>
33+
</div>
34+
<button type="submit">Validate locally</button>
35+
<p id="formResult"></p>
36+
</form>
37+
`;
38+
}
39+
40+
function defaultSurface() {
41+
return `
42+
<ul class="timeline">
43+
${project.cards.map((card, index) => `<li><strong>Step ${index + 1}:</strong> ${card}</li>`).join('')}
44+
</ul>
45+
`;
46+
}
47+
48+
function careerSurface() {
49+
const jobs = [
50+
{ role: 'Frontend Intern', skills: ['HTML', 'CSS', 'JavaScript'] },
51+
{ role: 'Support Assistant', skills: ['Troubleshooting', 'Documentation', 'Empathy'] },
52+
{ role: 'Network Trainee', skills: ['Wi-Fi', 'Monitoring', 'Security'] },
53+
{ role: 'Data Assistant', skills: ['CSV', 'Python', 'Charts'] },
54+
];
55+
const counts = new Map();
56+
jobs.forEach((job) => job.skills.forEach((skill) => counts.set(skill, (counts.get(skill) || 0) + 1)));
57+
return `
58+
${jobs.map((job) => `<article class="card"><h3>${job.role}</h3><p>${job.skills.join(', ')}</p></article>`).join('')}
59+
<p><strong>Top skills:</strong> ${[...counts.entries()].map(([skill, total]) => `${skill} (${total})`).join(', ')}</p>
60+
`;
61+
}
62+
63+
function nocSurface() {
64+
const services = [
65+
['Internet link', 'ok', 18],
66+
['Learning platform', 'ok', 34],
67+
['Lab switch', 'warn', 62],
68+
['Wi-Fi classroom', 'ok', 41],
69+
['File service', 'bad', 0],
70+
];
71+
return services.map(([name, state, latency]) => `
72+
<article class="card">
73+
<span class="status ${state}">${state.toUpperCase()}</span>
74+
<h3>${name}</h3>
75+
<p>Latency sample: ${latency} ms</p>
76+
</article>
77+
`).join('');
78+
}
79+
80+
function renderDynamicSurface() {
81+
if (mode === 'form') dynamicSurface.innerHTML = formSurface();
82+
else if (mode === 'career') dynamicSurface.innerHTML = careerSurface();
83+
else if (mode === 'noc') dynamicSurface.innerHTML = nocSurface();
84+
else dynamicSurface.innerHTML = defaultSurface();
85+
}
86+
87+
function wireForm() {
88+
const form = document.querySelector('#demoForm');
89+
if (!form) return;
90+
form.addEventListener('submit', (event) => {
91+
event.preventDefault();
92+
const rules = {
93+
fullName: (value) => value.trim().split(/\s+/).length >= 2 || 'Use at least two words.',
94+
studentCode: (value) => /^LAB-[0-9]{4}$/.test(value) || 'Use the format LAB-2026.',
95+
email: (value) => /^[^@\s]+@[^@\s]+\.[^@\s]+$/.test(value) || 'Use a valid email format.',
96+
password: (value) => value.length >= 8 || 'Use at least 8 characters.',
97+
};
98+
let valid = true;
99+
for (const [name, rule] of Object.entries(rules)) {
100+
const input = form.elements[name];
101+
const result = rule(input.value);
102+
const error = input.parentElement.querySelector('.error');
103+
error.textContent = result === true ? '' : result;
104+
valid = valid && result === true;
105+
}
106+
document.querySelector('#formResult').textContent = valid ? 'Local validation passed. Nothing was sent.' : 'Review the highlighted fields.';
107+
});
108+
}
109+
110+
document.querySelector('#themeToggle').addEventListener('click', () => {
111+
document.body.classList.toggle('dark');
112+
localStorage.setItem('theme', document.body.classList.contains('dark') ? 'dark' : 'light');
113+
});
114+
115+
document.querySelector('#exportButton').addEventListener('click', () => {
116+
const report = `# ${project.title}\n\nCode: ${project.code}\nDiscipline: ${project.discipline}\nMode: ${mode}\n`;
117+
const blob = new Blob([report], { type: 'text/markdown' });
118+
const link = document.createElement('a');
119+
link.href = URL.createObjectURL(blob);
120+
link.download = `${project.code.toLowerCase()}-report.md`;
121+
link.click();
122+
URL.revokeObjectURL(link.href);
123+
});
124+
125+
if (localStorage.getItem('theme') === 'dark') document.body.classList.add('dark');
126+
renderCards();
127+
renderProgress();
128+
renderDynamicSurface();
129+
wireForm();

scripts/smoke_static.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
from pathlib import Path
2+
3+
ROOT = Path(__file__).resolve().parents[1]
4+
required = ["index.html", "styles.css", "script.js", "README.md", "LICENSE"]
5+
for name in required:
6+
path = ROOT / name
7+
assert path.exists(), f"Missing {name}"
8+
html = (ROOT / "index.html").read_text(encoding="utf-8")
9+
script = (ROOT / "script.js").read_text(encoding="utf-8")
10+
for token in ["<main>", "data-mode=", "projectData", "Data Policy"]:
11+
assert token in html, f"Missing token: {token}"
12+
external_calls = ["http" + "://", "https" + "://", "send" + "Beacon", "XML" + "HttpRequest", "Web" + "Socket"]
13+
for token in external_calls:
14+
assert token not in script, f"Unexpected external/browser backend call marker: {token}"
15+
print("static smoke ok")

0 commit comments

Comments
 (0)