+4
-1
package.json
+4
-1
package.json
···
11
11
"@tailwindcss/vite": "^4.1.13",
12
12
"astro": "^5.13.7",
13
13
"nanoid": "^5.1.5",
14
+
"quill": "^2.0.3",
14
15
"tailwindcss": "^4.1.13"
15
16
},
16
17
"scripts": {
···
25
26
"daisyui": "^5.1.10"
26
27
},
27
28
"trustedDependencies": [
28
-
"@tailwindcss/oxide"
29
+
"@tailwindcss/oxide",
30
+
"esbuild",
31
+
"sharp"
29
32
]
30
33
}
+130
src/assets/styles/global.css
+130
src/assets/styles/global.css
···
36
36
@utility title {
37
37
font-family: var(--font-display);
38
38
font-size: var(--text-xl);
39
+
}
40
+
41
+
body {
42
+
height: 100vh;
43
+
font-family: var(--body);
44
+
font-size: var(--step-0);
45
+
line-height: 1.5;
46
+
}
47
+
48
+
h1 {
49
+
font-size: 1.5em;
50
+
font-weight: bold;
51
+
}
52
+
53
+
label {
54
+
display: block;
55
+
font-size: .8em;
56
+
font-weight: bold;
57
+
}
58
+
59
+
input[type="text"],
60
+
input[type="number"],
61
+
input[type="email"],
62
+
textarea {
63
+
border: 1px var(--color-base-300) solid;
64
+
border-radius: 2px;
65
+
padding: 3px 5px;
66
+
font-size: inherit;
67
+
font-family: var(--sans);
68
+
width: 100%;
69
+
}
70
+
71
+
.btn-primary,
72
+
button[type="submit"],
73
+
input[type="submit"],
74
+
input[type="reset"] {
75
+
background-color: var(--color-primary);
76
+
color: var(--color-primary-content);
77
+
border-radius: 4px;
78
+
padding: 5px 10px;
79
+
font-size: 1em;
80
+
font-weight: bold;
81
+
text-align: center;
82
+
min-width: 150px;
83
+
transition: 0.3s;
84
+
position: relative;
85
+
}
86
+
87
+
.btn-primary:hover,
88
+
button[type="submit"]:hover,
89
+
input[type="submit"]:hover,
90
+
input[type="reset"]:hover {
91
+
background-color: color-mix(in srgb-linear, var(--color-primary), #000000 20%);
92
+
}
93
+
94
+
.btn-primary:active,
95
+
button[type="submit"]:active,
96
+
input[type="submit"]:active,
97
+
input[type="reset"]:active {
98
+
top: 1px;
99
+
}
100
+
101
+
.input-field {
102
+
display: block;
103
+
margin-bottom: 1em;
104
+
}
105
+
106
+
nav ul.menu {
107
+
gap: 20px;
108
+
align-items: center;
109
+
}
110
+
111
+
nav ul.menu form:hover {
112
+
background-color: transparent;
113
+
border-radius: none;
114
+
}
115
+
116
+
nav ul.menu .search-label {
117
+
width: 1px;
118
+
height: 1px;
119
+
position: absolute;
120
+
overflow: hidden;
121
+
text-indent: -100px;
122
+
}
123
+
124
+
nav ul.menu a {
125
+
padding-bottom: 5px;
126
+
border-width: 0 0 5px 0;
127
+
padding: 5px 0;
128
+
border-color: transparent;
129
+
border-style: solid;
130
+
box-shadow: none;
131
+
background-color: transparent;
132
+
border-radius: 0;
133
+
}
134
+
135
+
nav ul.menu a:hover {
136
+
border-width: 0 0 5px 0;
137
+
border-color: var(--color-secondary);
138
+
border-style: solid;
139
+
}
140
+
141
+
.ql-toolbar.ql-snow {
142
+
border-color: var(--color-base-300) !important;
143
+
border-radius: 2px 2px 0 0;
144
+
}
145
+
146
+
#content.ql-container.ql-snow {
147
+
border-color: var(--color-base-300);
148
+
border-radius: 0 0 2px 2px;
149
+
}
150
+
151
+
article.card {
152
+
border: 1px var(--color-base-300) solid;
153
+
border-radius: 5px;
154
+
}
155
+
156
+
article.card h2 {
157
+
font-size: 1.1em;
158
+
font-weight: bold;
159
+
}
160
+
161
+
article.card .author {
162
+
font-size: .8em;
163
+
font-weight: normal;
164
+
font-style: italic;
165
+
}
166
+
167
+
article.card time {
168
+
font-size: .8em;
39
169
}
+1
-1
src/layouts/Layout.astro
+1
-1
src/layouts/Layout.astro
···
37
37
<slot />
38
38
</div>
39
39
40
-
<footer class="footer sm:footer-horizontal footer-center bg-base-300 text-base-content mt-auto p-5">
40
+
<footer class="footer sm:footer-horizontal footer-center bg-base-300 text-base-content mt-5 p-5">
41
41
copyright or something ig
42
42
</footer>
43
43
</body>
+1
-1
src/pages/index.astro
+1
-1
src/pages/index.astro
+74
-48
src/pages/works/add.astro
+74
-48
src/pages/works/add.astro
···
1
1
---
2
2
import Layout from "@/layouts/Layout.astro";
3
3
import { actions, isInputError } from "astro:actions";
4
+
import "quill/dist/quill.core.css";
5
+
import "quill/dist/quill.snow.css";
4
6
5
7
const loggedInUser = Astro.locals.loggedInUser;
6
8
···
21
23
<h1>Add a new work</h1>
22
24
23
25
<form action={actions.worksActions.addWork} method="post">
24
-
<label for="title">title</label>
25
-
<input
26
-
type="text"
27
-
name="title"
28
-
id="title"
29
-
aria-describedby="title-error"
30
-
required
31
-
transition:persist
32
-
/>
33
-
{errors.title && (
34
-
<div id="title-error">
35
-
{errors.title}
36
-
</div>
37
-
)}
26
+
<div class="input-field">
27
+
<label for="title">Title</label>
28
+
<input
29
+
type="text"
30
+
name="title"
31
+
id="title"
32
+
aria-describedby="title-error"
33
+
required
34
+
transition:persist
35
+
/>
36
+
{errors.title && (
37
+
<div id="title-error">
38
+
{errors.title}
39
+
</div>
40
+
)}
41
+
</div>
38
42
39
-
<label for="tags">add tags</label>
40
-
<input
41
-
type="text"
42
-
list="tags-list"
43
-
name="tags"
44
-
id="tags"
45
-
aria-describedby="tags-error"
46
-
transition:persist
47
-
/>
48
-
<!-- could be cool to fetch tags from a tags server or smth? idk -->
49
-
<datalist id="tags-list">
50
-
<option value="test">here</option>
51
-
<option value="tag2">another</option>
52
-
<option value="tag3">try them all!</option>
53
-
</datalist>
54
-
{errors.tags && (
55
-
<div id="tags-error">
56
-
{errors.tags}
57
-
</div>
58
-
)}
43
+
<div class="input-field">
44
+
<label for="tags">Add Tags</label>
45
+
<input
46
+
type="text"
47
+
list="tags-list"
48
+
name="tags"
49
+
id="tags"
50
+
aria-describedby="tags-error"
51
+
transition:persist
52
+
/>
53
+
<!-- could be cool to fetch tags from a tags server or smth? idk -->
54
+
<!-- maybe from labelers the instance is subscribed to? - @veryroundbird.house -->
55
+
<datalist id="tags-list">
56
+
<option value="test">here</option>
57
+
<option value="tag2">another</option>
58
+
<option value="tag3">try them all!</option>
59
+
</datalist>
60
+
{errors.tags && (
61
+
<div id="tags-error">
62
+
{errors.tags}
63
+
</div>
64
+
)}
65
+
</div>
59
66
60
-
<label for="content">body</label>
61
-
<!-- replace this with a rich text editor / code editor later -->
62
-
<textarea name="content" id="content" aria-describedby="content-error" transition:persist></textarea>
63
-
{errors.content && (
64
-
<div id="content-error">
65
-
{errors.content}
66
-
</div>
67
-
)}
68
-
69
-
<label for="publish">Publish to your PDS?</label>
70
-
<input type="checkbox" name="publish" id="publish" />
71
-
72
-
<button>submit</button>
67
+
<div class="input-field">
68
+
<label for="content">Work Text</label>
69
+
<div id="content" aria-describedby="content-error" transition:persist rows="50"></div>
70
+
{errors.content && (
71
+
<div id="content-error">
72
+
{errors.content}
73
+
</div>
74
+
)}
75
+
</div>
76
+
<div class="input-field">
77
+
<label for="publish"><input type="checkbox" name="publish" id="publish" /> Publish to your PDS?</label>
78
+
</div>
79
+
<div class="input-field">
80
+
<button type="submit" class="btn-primary">Submit</button>
81
+
</div>
73
82
</form>
74
83
75
84
{result?.error && (
···
78
87
</div>
79
88
)}
80
89
</main>
81
-
</Layout>
90
+
</Layout>
91
+
92
+
<script>
93
+
import Quill from "quill";
94
+
95
+
const quill = new Quill('#content', {
96
+
theme: 'snow',
97
+
modules: {
98
+
syntax: true
99
+
}
100
+
});
101
+
</script>
102
+
103
+
<style>
104
+
#content {
105
+
min-height: 50vh;
106
+
}
107
+
</style>
+19
-10
src/pages/works/index.astro
+19
-10
src/pages/works/index.astro
···
22
22
{works.map(async ({ Works, Users }) => (
23
23
<article class="card rounded-box shadow p-5">
24
24
<header>
25
-
<div class="flex items-center justify-between">
25
+
<div class="flex items-top justify-between">
26
26
<hgroup class="flex-1">
27
27
<h2 class="card-title">
28
28
<a href={`/works/${Works.slug}`}>{Works.title}</a>
29
29
</h2>
30
-
<h3>
30
+
<p class="author">
31
31
{Users.nickname
32
32
? Users.nickname
33
33
: await didToHandle(Users.userDid)}
34
-
</h3>
34
+
</p>
35
35
</hgroup>
36
36
<time datetime={Works.createdAt.toISOString()}>
37
37
{Works.createdAt.toLocaleDateString()}
38
38
</time>
39
39
</div>
40
-
{JSON.stringify(Works.tags)}
41
-
{/* <ul class="flex flex-wrap gap-1.5">
42
-
{(Works.tags as Tag[]).map((tag: Tag) => (
43
-
<li><a class="tag" href={tag.url}>{tag.label}</a></li>
44
-
))}
45
-
</ul> */}
40
+
{Array.isArray(Works.tags) &&
41
+
<ul class="flex flex-wrap gap-1.5">
42
+
{(Works.tags as Tag[]).map((tag: Tag) => (
43
+
<li><a class="tag" href={tag.url}>{tag.label}</a></li>
44
+
))}
45
+
</ul> }
46
46
</header>
47
47
48
48
<div class="card-body prose lg:prose-xl">
···
57
57
@reference "../../assets/styles/global.css";
58
58
59
59
.tag {
60
-
@apply btn btn-accent;
60
+
@apply btn btn-accent;
61
+
padding: 3px 12px;
62
+
border-radius: 12px;
63
+
height: auto;
64
+
line-height: 1;
65
+
}
66
+
67
+
.card-body {
68
+
padding-left: 0;
69
+
padding-right: 0;
61
70
}
62
71
</style>