Skip to content

Commit c2746a2

Browse files
authored
Feat/demo 1 (#19)
* wip * feat: added demo board
1 parent 428cfeb commit c2746a2

14 files changed

+799
-444
lines changed

dist/kasper.js

+7-10
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/kasper.min.js

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

live/css/sdf.css

-1
This file was deleted.

live/css/style.css

+193
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,193 @@
1+
:root {
2+
--normal-padding: 10px 20px;
3+
--background: rgba(0, 0, 0, 0.5);
4+
--short-padding: 10px;
5+
--radius: 10px;
6+
--text: #f0f0f0;
7+
}
8+
html,
9+
body {
10+
height: 100%;
11+
overflow: hidden;
12+
}
13+
14+
html {
15+
margin: 0;
16+
padding: 0;
17+
font-family: "IBM Plex Sans", sans-serif;
18+
font-weight: 300;
19+
font-style: normal;
20+
color: var(--text);
21+
background-image: url("../img/bg.jpg");
22+
background-position: center center;
23+
background-size: cover;
24+
background-color: #9d3cae;
25+
line-height: 1.25;
26+
}
27+
28+
kasper-app {
29+
display: block;
30+
height: 100%;
31+
overflow: hidden;
32+
display: flex;
33+
flex-direction: column;
34+
}
35+
36+
nav {
37+
padding: var(--normal-padding);
38+
background-color: var(--background);
39+
backdrop-filter: blur(10px);
40+
font-size: 32px;
41+
}
42+
43+
main {
44+
position: relative;
45+
padding: var(--short-padding);
46+
display: grid;
47+
grid-gap: 10px;
48+
grid-template-columns: 1fr 1fr 1fr 1fr;
49+
grid-auto-columns: 1fr;
50+
height: 100%;
51+
overflow: hidden;
52+
align-items: start;
53+
}
54+
55+
button,
56+
textarea {
57+
background-color: var(--background);
58+
color: var(--text);
59+
border: none;
60+
border-radius: var(--radius);
61+
padding: var(--short-padding);
62+
cursor: pointer;
63+
font-size: 16px;
64+
}
65+
66+
textarea {
67+
height: 120px;
68+
}
69+
70+
button:hover {
71+
background-color: black;
72+
}
73+
74+
.fixed {
75+
position: absolute;
76+
inset: 0;
77+
display: flex;
78+
justify-content: center;
79+
align-items: center;
80+
}
81+
82+
.column {
83+
background-color: var(--background);
84+
border-radius: var(--radius);
85+
padding: 0;
86+
backdrop-filter: blur(10px);
87+
max-height: 100%;
88+
overflow: hidden;
89+
display: flex;
90+
flex-direction: column;
91+
}
92+
93+
.todos {
94+
overflow-y: auto;
95+
padding: var(--short-padding);
96+
display: flex;
97+
flex-direction: column;
98+
gap: 10px;
99+
-webkit-overflow-scrolling: touch;
100+
-webkit-transform: translate3d(0, 0, 0);
101+
scrollbar-color: rgba(255, 255, 255, 0.6) var(--background);
102+
scrollbar-width: thin;
103+
}
104+
105+
.card {
106+
background-color: var(--background);
107+
border-radius: var(--radius);
108+
padding: var(--short-padding);
109+
}
110+
.card[dragged="true"]:hover {
111+
background-color: black;
112+
}
113+
114+
.column > .title {
115+
background: black;
116+
padding: var(--normal-padding);
117+
border-top-left-radius: var(--radius);
118+
border-top-right-radius: var(--radius);
119+
}
120+
121+
.tags {
122+
display: flex;
123+
gap: 10px;
124+
padding-bottom: 10px;
125+
}
126+
127+
.tags > .tag {
128+
width: 30px;
129+
height: 10px;
130+
border-radius: var(--radius);
131+
}
132+
133+
.tag.red {
134+
background-color: rgba(255, 0, 0, 0.5);
135+
}
136+
137+
.tag.blue {
138+
background-color: rgba(0, 0, 255, 0.5);
139+
}
140+
141+
.tag.yellow {
142+
background-color: rgba(255, 255, 0, 0.5);
143+
}
144+
145+
.tag.green {
146+
background-color: rgba(0, 255, 0, 0.5);
147+
}
148+
149+
.tag.gray {
150+
background-color: rgba(255, 255, 255, 0.5);
151+
}
152+
153+
.loading:before {
154+
content: "";
155+
display: block;
156+
position: absolute;
157+
inset: 0;
158+
background-color: rgba(0, 0, 0, 0.3);
159+
}
160+
161+
.loading:after {
162+
content: "";
163+
display: block;
164+
font-size: 10px;
165+
width: 5px;
166+
height: 5px;
167+
margin-top: -0.5em;
168+
-webkit-animation: spinner 1500ms infinite linear;
169+
animation: spinner 1500ms infinite linear;
170+
border-radius: 0.5em;
171+
box-shadow: var(--text) 1.5em 0 0 0, var(--text) 1.1em 1.1em 0 0,
172+
var(--text) 0 1.5em 0 0, var(--text) -1.1em 1.1em 0 0,
173+
var(--text) -1.5em 0 0 0, var(--text) -1.1em -1.1em 0 0,
174+
var(--text) 0 -1.5em 0 0, var(--text) 1.1em -1.1em 0 0;
175+
}
176+
177+
@-webkit-keyframes spinner {
178+
0% {
179+
transform: rotate(0deg);
180+
}
181+
100% {
182+
transform: rotate(360deg);
183+
}
184+
}
185+
186+
@keyframes spinner {
187+
0% {
188+
transform: rotate(0deg);
189+
}
190+
100% {
191+
transform: rotate(360deg);
192+
}
193+
}

live/demo.html

+84-75
Original file line numberDiff line numberDiff line change
@@ -3,99 +3,108 @@
33
<head>
44
<meta charset="utf-8" />
55
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
6-
<title>Blog with KasperJs</title>
6+
<title>KasperJS Kanban</title>
77
<meta name="viewport" content="width=device-width, initial-scale=1" />
8-
<script src="../dist/kasper.js"></script>
9-
<script src="https://cdn.tailwindcss.com"></script>
10-
<script>
11-
tailwind.config = {
12-
theme: {
13-
fontFamily: {
14-
mono: [
15-
"Share Tech Mono",
16-
"Consolas",
17-
"Liberation Mono",
18-
"Courier New",
19-
],
20-
},
21-
},
22-
};
23-
</script>
8+
<link
9+
rel="stylesheet"
10+
href="https://cdnjs.cloudflare.com/ajax/libs/normalize/8.0.1/normalize.min.css"
11+
/>
12+
<link rel="preconnect" href="https://fonts.googleapis.com" />
13+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
14+
<link
15+
href="https://fonts.googleapis.com/css2?family=IBM+Plex+Sans:wght@100;300;400;700&display=swap"
16+
rel="stylesheet"
17+
/>
18+
<link rel="stylesheet" type="text/css" href="./css/style.css" />
19+
<script src="./js/todos.js"></script>
20+
<script src="../dist/kasper.min.js"></script>
2421
</head>
2522
<body>
26-
<kasper-app></kasper-app>
27-
<template id="kasper-app">
28-
<div class="w-dvw h-dvh flex text-gray-50">
29-
<div class="w-96 flex-none bg-gray-900 p-6 h-full overflow-y-scroll">
30-
<div class="flex flex-col gap-4">
23+
<template>
24+
<nav>KasperJS Kanban</nav>
25+
<main>
26+
<void @if="loading.value">
27+
<div class="fixed">
28+
<div class="loading"></div>
29+
</div>
30+
</void>
31+
<void @else>
32+
<div class="column" @each="category of categories.value">
33+
<div class="title">{{category.title}}</div>
3134
<div
32-
@each="const post of posts.value"
33-
class="py-2 rounded border border-gray-100"
35+
class="todos"
36+
@on:dragover="onDragover($event)"
37+
@on:drop="onDrop(category.name, $event)"
3438
>
35-
<button
36-
class="flex flex-col text-left gap-2"
37-
@on:click="onOpenPost(post)"
39+
<div
40+
class="card"
41+
draggable="true"
42+
data-todo-id="{{todo.id}}"
43+
@each="todo of todos.value[category.name]"
44+
@on:dragstart="onDragStart(todo.id, category.name, $event)"
3845
>
39-
<div class="text-lg px-2 leading-tight">{{post.title}}</div>
40-
<div class="text-xs px-2">{{post.body}}</div>
46+
<div class="tags">
47+
<div @each="tag of todo.tags" class="tag {{tag}}"></div>
48+
</div>
49+
<div>{{todo.task}}</div>
50+
</div>
51+
<button type="button" @on:click="onAddCard()">
52+
+ Add a card
4153
</button>
4254
</div>
4355
</div>
44-
</div>
45-
<div class="flex-grow bg-gray-700 p-6">
46-
<div @if="post.value && user.value">
47-
<void @let="u = user.value">
48-
<div class="text-lg">Author</div>
49-
<div class="flex flex-col pb-4">
50-
<div class="text-lg font-bold">{{u.name}}</div>
51-
<div class="text-sm text-gray-400">{{u.email}}</div>
52-
</div>
53-
</void>
54-
<void @let="p = post.value">
55-
<div class="text-2xl font-bold">{{p.title}}</div>
56-
<div class="text-sm text-gray-400">{{p.body}}</div>
57-
</void>
58-
</div>
59-
</div>
60-
</div>
56+
</void>
57+
</main>
6158
</template>
59+
<kasper-app></kasper-app>
6260
<script>
63-
async function fetchPosts() {
64-
const response = await fetch(
65-
"https://jsonplaceholder.typicode.com/posts"
66-
);
67-
return (await response.json()).slice(0, 7);
68-
}
69-
70-
async function fetchPostById(id) {
71-
const response = await fetch(
72-
`https://jsonplaceholder.typicode.com/posts/${id}`
73-
);
74-
return await response.json();
75-
}
76-
77-
async function fetchUserById(id) {
78-
const response = await fetch(
79-
`https://jsonplaceholder.typicode.com/users/${id}`
80-
);
81-
return await response.json();
61+
async function fetchTodos() {
62+
return new Promise((resolve) => {
63+
setTimeout(() => {
64+
resolve(TODOS);
65+
}, 500);
66+
});
8267
}
8368

8469
class TodoApp extends Component {
85-
posts = $state([]);
86-
user = $state(null);
87-
post = $state(null);
70+
loading = $state(true);
71+
todos = $state({});
72+
categories = $state([]);
73+
editing = $state(null);
8874

8975
$onInit = async () => {
90-
const posts = await fetchPosts();
91-
this.posts.set(posts);
92-
console.log(this.posts);
76+
const data = await fetchTodos();
77+
this.todos.set(data.todos);
78+
this.categories.set(data.categories);
79+
this.loading.set(false);
80+
};
81+
82+
onAddCard = () => {
83+
alert("TODO");
84+
};
85+
86+
onDragStart = (todoId, category, event) => {
87+
event.dataTransfer.dropEffect = "move";
88+
event.dataTransfer.setData(
89+
"text/plain",
90+
JSON.stringify({ todoId, category })
91+
);
92+
event.srcElement.setAttribute("dragged", true);
93+
};
94+
95+
onDragover = (event) => {
96+
event.preventDefault();
9397
};
9498

95-
onOpenPost = async (post) => {
96-
const user = await fetchUserById(post.userId);
97-
this.post.set(post);
98-
this.user.set(user);
99+
onDrop = (newCategory, event) => {
100+
event.preventDefault();
101+
const data = event.dataTransfer.getData("text/plain");
102+
const { todoId, category } = JSON.parse(data);
103+
const todos = this.todos.value;
104+
const todo = todos[category].find((t) => t.id === todoId);
105+
todos[category] = todos[category].filter((t) => t.id !== todo.id);
106+
todos[newCategory] = [...todos[newCategory], todo];
107+
this.todos.set(todos);
99108
};
100109
}
101110

live/img/bg.jpg

358 KB
Loading

live/img/bg1.jpg

47.1 KB
Loading

live/js/kasper.min.js

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)