Sherwin commited on
Commit
93cf0be
·
verified ·
1 Parent(s): cd294c0

Create a Portfolio for a Creative technologist that look like a Web OS

Browse files
Files changed (7) hide show
  1. README.md +8 -5
  2. components/desktop-shell.js +37 -0
  3. components/taskbar.js +152 -0
  4. components/window.js +73 -0
  5. index.html +39 -19
  6. script.js +142 -0
  7. style.css +54 -19
README.md CHANGED
@@ -1,10 +1,13 @@
1
  ---
2
- title: Pixelos Portfolio Playground
3
- emoji: 🌍
4
- colorFrom: purple
5
- colorTo: purple
6
  sdk: static
7
  pinned: false
 
 
8
  ---
9
 
10
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
1
  ---
2
+ title: PixelOS Portfolio Playground 🖥️
3
+ colorFrom: red
4
+ colorTo: blue
5
+ emoji: 🐳
6
  sdk: static
7
  pinned: false
8
+ tags:
9
+ - deepsite-v3
10
  ---
11
 
12
+ # Welcome to your new DeepSite project!
13
+ This project was created with [DeepSite](https://huggingface.co/deepsite).
components/desktop-shell.js ADDED
@@ -0,0 +1,37 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ class DesktopShell extends HTMLElement {
2
+ constructor() {
3
+ super();
4
+ this.attachShadow({ mode: 'open' });
5
+ this.shadowRoot.innerHTML = `
6
+ <style>
7
+ :host {
8
+ display: block;
9
+ position: fixed;
10
+ top: 0;
11
+ left: 0;
12
+ right: 0;
13
+ bottom: 0;
14
+ overflow: hidden;
15
+ background-image: url('http://static.photos/technology/1200x630/42');
16
+ background-size: cover;
17
+ background-position: center;
18
+ z-index: 1;
19
+ }
20
+ </style>
21
+ <div id="desktop" class="w-full h-full relative">
22
+ <!-- Windows will be added here -->
23
+ </div>
24
+ <custom-taskbar></custom-taskbar>
25
+ `;
26
+ }
27
+
28
+ createWindow(options) {
29
+ windowManager.createWindow(options);
30
+ }
31
+
32
+ connectedCallback() {
33
+ this.desktop = this.shadowRoot.getElementById('desktop');
34
+ }
35
+ }
36
+
37
+ customElements.define('desktop-shell', DesktopShell);
components/taskbar.js ADDED
@@ -0,0 +1,152 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ class CustomTaskbar extends HTMLElement {
2
+ constructor() {
3
+ super();
4
+ this.attachShadow({ mode: 'open' });
5
+ this.shadowRoot.innerHTML = `
6
+ <style>
7
+ :host {
8
+ display: block;
9
+ position: fixed;
10
+ bottom: 0;
11
+ left: 0;
12
+ right: 0;
13
+ height: 48px;
14
+ background-color: rgba(31, 41, 55, 0.9);
15
+ backdrop-filter: blur(10px);
16
+ border-top: 1px solid rgba(255, 255, 255, 0.1);
17
+ z-index: 1000;
18
+ display: flex;
19
+ align-items: center;
20
+ padding: 0 16px;
21
+ }
22
+
23
+ .start-button {
24
+ display: flex;
25
+ align-items: center;
26
+ padding: 0 12px;
27
+ height: 36px;
28
+ background-color: rgba(99, 102, 241, 0.7);
29
+ color: white;
30
+ border-radius: 4px;
31
+ cursor: pointer;
32
+ transition: all 0.2s;
33
+ }
34
+
35
+ .start-button:hover {
36
+ background-color: rgba(99, 102, 241, 0.9);
37
+ }
38
+
39
+ .taskbar-icons {
40
+ display: flex;
41
+ margin-left: 16px;
42
+ gap: 8px;
43
+ }
44
+
45
+ .taskbar-icon {
46
+ width: 36px;
47
+ height: 36px;
48
+ display: flex;
49
+ align-items: center;
50
+ justify-content: center;
51
+ border-radius: 4px;
52
+ cursor: pointer;
53
+ transition: all 0.2s;
54
+ }
55
+
56
+ .taskbar-icon:hover {
57
+ background-color: rgba(255, 255, 255, 0.1);
58
+ }
59
+
60
+ .system-tray {
61
+ margin-left: auto;
62
+ display: flex;
63
+ align-items: center;
64
+ gap: 8px;
65
+ }
66
+
67
+ .tray-icon {
68
+ width: 24px;
69
+ height: 24px;
70
+ display: flex;
71
+ align-items: center;
72
+ justify-content: center;
73
+ cursor: pointer;
74
+ opacity: 0.8;
75
+ }
76
+
77
+ .tray-icon:hover {
78
+ opacity: 1;
79
+ }
80
+
81
+ .time {
82
+ font-size: 12px;
83
+ padding: 0 8px;
84
+ }
85
+ </style>
86
+ <div class="start-button" id="start-button">
87
+ <i data-feather="grid"></i>
88
+ <span class="ml-2">Start</span>
89
+ </div>
90
+ <div class="taskbar-icons" id="taskbar-icons">
91
+ <!-- App icons will be added here -->
92
+ </div>
93
+ <div class="system-tray">
94
+ <div class="tray-icon" id="theme-toggle">
95
+ <i data-feather="moon"></i>
96
+ </div>
97
+ <div class="tray-icon">
98
+ <i data-feather="wifi"></i>
99
+ </div>
100
+ <div class="tray-icon">
101
+ <i data-feather="volume-2"></i>
102
+ </div>
103
+ <div class="time" id="clock">00:00</div>
104
+ </div>
105
+ `;
106
+ }
107
+
108
+ connectedCallback() {
109
+ this.updateClock();
110
+ setInterval(() => this.updateClock(), 60000);
111
+
112
+ this.shadowRoot.getElementById('start-button').addEventListener('click', () => {
113
+ windowManager.createWindow({
114
+ id: 'start-menu',
115
+ title: 'Start Menu',
116
+ content: `
117
+ <div class="p-4 grid grid-cols-3 gap-4">
118
+ <div class="p-4 flex flex-col items-center cursor-pointer hover:bg-gray-100 dark:hover:bg-gray-800 rounded">
119
+ <i data-feather="user" class="w-8 h-8 mb-2"></i>
120
+ <span>About</span>
121
+ </div>
122
+ <div class="p-4 flex flex-col items-center cursor-pointer hover:bg-gray-100 dark:hover:bg-gray-800 rounded">
123
+ <i data-feather="folder" class="w-8 h-8 mb-2"></i>
124
+ <span>Projects</span>
125
+ </div>
126
+ <div class="p-4 flex flex-col items-center cursor-pointer hover:bg-gray-100 dark:hover:bg-gray-800 rounded">
127
+ <i data-feather="mail" class="w-8 h-8 mb-2"></i>
128
+ <span>Contact</span>
129
+ </div>
130
+ <div class="p-4 flex flex-col items-center cursor-pointer hover:bg-gray-100 dark:hover:bg-gray-800 rounded">
131
+ <i data-feather="settings" class="w-8 h-8 mb-2"></i>
132
+ <span>Settings</span>
133
+ </div>
134
+ </div>
135
+ `,
136
+ icon: 'grid',
137
+ initialPosition: { x: 50, y: window.innerHeight - 200 }
138
+ });
139
+ });
140
+
141
+ feather.replace();
142
+ }
143
+
144
+ updateClock() {
145
+ const now = new Date();
146
+ const hours = now.getHours().toString().padStart(2, '0');
147
+ const minutes = now.getMinutes().toString().padStart(2, '0');
148
+ this.shadowRoot.getElementById('clock').textContent = `${hours}:${minutes}`;
149
+ }
150
+ }
151
+
152
+ customElements.define('custom-taskbar', CustomTaskbar);
components/window.js ADDED
@@ -0,0 +1,73 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ class CustomWindow extends HTMLElement {
2
+ constructor() {
3
+ super();
4
+ this.isDragging = false;
5
+ this.offsetX = 0;
6
+ this.offsetY = 0;
7
+ this.attachShadow({ mode: 'open' });
8
+ }
9
+
10
+ static get observedAttributes() {
11
+ return ['title', 'icon', 'initial-x', 'initial-y'];
12
+ }
13
+
14
+ attributeChangedCallback(name, oldValue, newValue) {
15
+ if (name === 'title' || name === 'icon') {
16
+ this.render();
17
+ } else if ((name === 'initial-x' || name === 'initial-y') && newValue !== oldValue) {
18
+ this.style.left = `${this.getAttribute('initial-x')}px`;
19
+ this.style.top = `${this.getAttribute('initial-y')}px`;
20
+ }
21
+ }
22
+
23
+ connectedCallback() {
24
+ this.render();
25
+ this.setupEventListeners();
26
+ this.style.left = `${this.getAttribute('initial-x')}px`;
27
+ this.style.top = `${this.getAttribute('initial-y')}px`;
28
+ }
29
+
30
+ render() {
31
+ this.shadowRoot.innerHTML = `
32
+ <style>
33
+ :host {
34
+ position: absolute;
35
+ width: 500px;
36
+ max-width: 90vw;
37
+ min-height: 300px;
38
+ background-color: rgba(255, 255, 255, 0.9);
39
+ border-radius: 8px;
40
+ overflow: hidden;
41
+ display: flex;
42
+ flex-direction: column;
43
+ box-shadow: 0 10px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
44
+ backdrop-filter: blur(10px);
45
+ border: 1px solid rgba(0, 0, 0, 0.1);
46
+ transition: transform 0.2s, opacity 0.2s;
47
+ }
48
+
49
+ .dark :host {
50
+ background-color: rgba(31, 41, 55, 0.9);
51
+ border: 1px solid rgba(255, 255, 255, 0.1);
52
+ }
53
+
54
+ .window-header {
55
+ height: 36px;
56
+ background-color: rgba(99, 102, 241, 0.7);
57
+ color: white;
58
+ display: flex;
59
+ align-items: center;
60
+ padding: 0 12px;
61
+ cursor: move;
62
+ user-select: none;
63
+ }
64
+
65
+ .dark .window-header {
66
+ background-color: rgba(79, 70, 229, 0.8);
67
+ }
68
+
69
+ .window-title {
70
+ display: flex;
71
+ align-items: center;
72
+ flex-grow: 1;
73
+ font-weight:
index.html CHANGED
@@ -1,19 +1,39 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
19
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en" class="dark">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>PixelOS | Creative Technologist</title>
7
+ <link rel="stylesheet" href="style.css">
8
+ <script src="https://cdn.tailwindcss.com"></script>
9
+ <script src="https://cdn.jsdelivr.net/npm/feather-icons/dist/feather.min.js"></script>
10
+ <script src="https://unpkg.com/feather-icons"></script>
11
+ <script>
12
+ tailwind.config = {
13
+ darkMode: 'class',
14
+ theme: {
15
+ extend: {
16
+ colors: {
17
+ primary: {
18
+ 500: '#6366f1',
19
+ },
20
+ secondary: {
21
+ 500: '#f43f5e',
22
+ }
23
+ }
24
+ }
25
+ }
26
+ }
27
+ </script>
28
+ </head>
29
+ <body class="bg-gray-100 dark:bg-gray-900 text-gray-800 dark:text-gray-200 min-h-screen">
30
+ <desktop-shell></desktop-shell>
31
+
32
+ <script src="components/desktop-shell.js"></script>
33
+ <script src="components/taskbar.js"></script>
34
+ <script src="components/window.js"></script>
35
+ <script src="script.js"></script>
36
+ <script>feather.replace();</script>
37
+ <script src="https://huggingface.co/deepsite/deepsite-badge.js"></script>
38
+ </body>
39
+ </html>
script.js ADDED
@@ -0,0 +1,142 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ document.addEventListener('DOMContentLoaded', () => {
2
+ // Initialize desktop apps
3
+ const desktop = document.querySelector('desktop-shell');
4
+
5
+ // Create default windows
6
+ desktop.createWindow({
7
+ id: 'about',
8
+ title: 'About Me.txt',
9
+ content: `
10
+ <div class="p-4">
11
+ <h2 class="text-xl font-bold mb-4 text-primary-500">Creative Technologist</h2>
12
+ <p class="mb-4">Hello! I'm a creative technologist blending art, design, and technology to create immersive experiences.</p>
13
+ <div class="grid grid-cols-2 gap-4">
14
+ <div>
15
+ <h3 class="font-bold mb-2">Skills</h3>
16
+ <ul class="list-disc pl-5">
17
+ <li>Interactive Installations</li>
18
+ <li>Creative Coding</li>
19
+ <li>WebGL & Three.js</li>
20
+ <li>Physical Computing</li>
21
+ </ul>
22
+ </div>
23
+ <div>
24
+ <h3 class="font-bold mb-2">Tools</h3>
25
+ <ul class="list-disc pl-5">
26
+ <li>TouchDesigner</li>
27
+ <li>Processing</li>
28
+ <li>Arduino</li>
29
+ <li>p5.js</li>
30
+ </ul>
31
+ </div>
32
+ </div>
33
+ </div>
34
+ `,
35
+ icon: 'user',
36
+ initialPosition: { x: 100, y: 100 }
37
+ });
38
+
39
+ desktop.createWindow({
40
+ id: 'projects',
41
+ title: 'Projects Explorer',
42
+ content: `
43
+ <div class="p-4">
44
+ <h2 class="text-xl font-bold mb-4 text-primary-500">Featured Projects</h2>
45
+ <div class="grid grid-cols-1 md:grid-cols-2 gap-4">
46
+ <div class="border border-gray-200 dark:border-gray-700 rounded-lg p-4 hover:bg-gray-50 dark:hover:bg-gray-800 transition cursor-pointer">
47
+ <h3 class="font-bold">Interactive Light Sculpture</h3>
48
+ <p class="text-sm text-gray-500 dark:text-gray-400">Kinetic installation responding to sound</p>
49
+ </div>
50
+ <div class="border border-gray-200 dark:border-gray-700 rounded-lg p-4 hover:bg-gray-50 dark:hover:bg-gray-800 transition cursor-pointer">
51
+ <h3 class="font-bold">Generative Art Platform</h3>
52
+ <p class="text-sm text-gray-500 dark:text-gray-400">Web-based tool for creating algorithmic art</p>
53
+ </div>
54
+ <div class="border border-gray-200 dark:border-gray-700 rounded-lg p-4 hover:bg-gray-50 dark:hover:bg-gray-800 transition cursor-pointer">
55
+ <h3 class="font-bold">AR Museum Experience</h3>
56
+ <p class="text-sm text-gray-500 dark:text-gray-400">Augmented reality for cultural heritage</p>
57
+ </div>
58
+ <div class="border border-gray-200 dark:border-gray-700 rounded-lg p-4 hover:bg-gray-50 dark:hover:bg-gray-800 transition cursor-pointer">
59
+ <h3 class="font-bold">Data Visualization Suite</h3>
60
+ <p class="text-sm text-gray-500 dark:text-gray-400">Interactive tools for complex datasets</p>
61
+ </div>
62
+ </div>
63
+ </div>
64
+ `,
65
+ icon: 'folder',
66
+ initialPosition: { x: 300, y: 150 }
67
+ });
68
+
69
+ // Theme toggle
70
+ const themeToggle = document.getElementById('theme-toggle');
71
+ if (themeToggle) {
72
+ themeToggle.addEventListener('click', () => {
73
+ document.documentElement.classList.toggle('dark');
74
+ localStorage.setItem('theme', document.documentElement.classList.contains('dark') ? 'dark' : 'light');
75
+ });
76
+ }
77
+ });
78
+
79
+ class WindowManager {
80
+ constructor() {
81
+ this.windows = [];
82
+ this.zIndexCounter = 10;
83
+ }
84
+
85
+ createWindow(options) {
86
+ const windowElement = document.createElement('custom-window');
87
+ windowElement.setAttribute('id', options.id);
88
+ windowElement.setAttribute('title', options.title);
89
+ windowElement.setAttribute('icon', options.icon);
90
+ windowElement.setAttribute('initial-x', options.initialPosition.x);
91
+ windowElement.setAttribute('initial-y', options.initialPosition.y);
92
+ windowElement.innerHTML = options.content;
93
+
94
+ document.querySelector('desktop-shell').appendChild(windowElement);
95
+ this.windows.push({
96
+ id: options.id,
97
+ element: windowElement,
98
+ minimized: false
99
+ });
100
+
101
+ this.bringToFront(windowElement);
102
+ }
103
+
104
+ bringToFront(windowElement) {
105
+ this.zIndexCounter += 1;
106
+ windowElement.style.zIndex = this.zIndexCounter;
107
+ }
108
+
109
+ minimizeWindow(windowId) {
110
+ const window = this.windows.find(w => w.id === windowId);
111
+ if (window) {
112
+ window.minimized = true;
113
+ window.element.classList.add('window-minimize');
114
+ setTimeout(() => {
115
+ window.element.style.display = 'none';
116
+ }, 300);
117
+ }
118
+ }
119
+
120
+ restoreWindow(windowId) {
121
+ const window = this.windows.find(w => w.id === windowId);
122
+ if (window) {
123
+ window.minimized = false;
124
+ window.element.style.display = 'block';
125
+ window.element.classList.add('window-restore');
126
+ setTimeout(() => {
127
+ window.element.classList.remove('window-restore');
128
+ }, 300);
129
+ this.bringToFront(window.element);
130
+ }
131
+ }
132
+
133
+ closeWindow(windowId) {
134
+ const windowIndex = this.windows.findIndex(w => w.id === windowId);
135
+ if (windowIndex !== -1) {
136
+ this.windows[windowIndex].element.remove();
137
+ this.windows.splice(windowIndex, 1);
138
+ }
139
+ }
140
+ }
141
+
142
+ window.windowManager = new WindowManager();
style.css CHANGED
@@ -1,28 +1,63 @@
1
- body {
2
- padding: 2rem;
3
- font-family: -apple-system, BlinkMacSystemFont, "Arial", sans-serif;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4
  }
5
 
6
- h1 {
7
- font-size: 16px;
8
- margin-top: 0;
9
  }
10
 
11
- p {
12
- color: rgb(107, 114, 128);
13
- font-size: 15px;
14
- margin-bottom: 10px;
15
- margin-top: 5px;
16
  }
17
 
18
- .card {
19
- max-width: 620px;
20
- margin: 0 auto;
21
- padding: 16px;
22
- border: 1px solid lightgray;
23
- border-radius: 16px;
24
  }
25
 
26
- .card p:last-child {
27
- margin-bottom: 0;
 
28
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ @import url('https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;700&display=swap');
2
+
3
+ * {
4
+ font-family: 'JetBrains Mono', monospace;
5
+ box-sizing: border-box;
6
+ }
7
+
8
+ .draggable {
9
+ -webkit-app-region: drag;
10
+ }
11
+
12
+ .window-shadow {
13
+ box-shadow: 0 10px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
14
+ }
15
+
16
+ .window-content {
17
+ scrollbar-width: thin;
18
+ scrollbar-color: rgba(156, 163, 175, 0.5) transparent;
19
  }
20
 
21
+ .window-content::-webkit-scrollbar {
22
+ width: 6px;
 
23
  }
24
 
25
+ .window-content::-webkit-scrollbar-track {
26
+ background: transparent;
 
 
 
27
  }
28
 
29
+ .window-content::-webkit-scrollbar-thumb {
30
+ background-color: rgba(156, 163, 175, 0.5);
31
+ border-radius: 3px;
 
 
 
32
  }
33
 
34
+ .icon-hover:hover {
35
+ transform: scale(1.1);
36
+ transition: transform 0.2s ease;
37
  }
38
+
39
+ .window-minimize {
40
+ animation: minimize 0.3s forwards;
41
+ }
42
+
43
+ @keyframes minimize {
44
+ to {
45
+ transform: translateY(100vh);
46
+ opacity: 0;
47
+ }
48
+ }
49
+
50
+ .window-restore {
51
+ animation: restore 0.3s forwards;
52
+ }
53
+
54
+ @keyframes restore {
55
+ from {
56
+ transform: translateY(100vh);
57
+ opacity: 0;
58
+ }
59
+ to {
60
+ transform: translateY(0);
61
+ opacity: 1;
62
+ }
63
+ }