@@ -5,21 +5,28 @@ import Elementary
5
5
import Foundation
6
6
7
7
public struct HomePage : Page {
8
- struct Style : Sendable , StyleSheet {
8
+ struct Style : @ unchecked Sendable , StyleSheet {
9
9
var body : some Rule {
10
10
// TODO: Add Work-Sans font?
11
11
12
+ // General
12
13
Pseudo ( class: . root) => {
13
14
BackgroundColor ( " #1c1c1c " )
14
15
Color ( " #fafafa " )
15
- AnyProperty ( " font-family " , " ui-sans-serif, -apple-system, Helvetica Neue, Helvetica, Arial, sans-serif " )
16
16
AnyProperty ( " font-optical-sizing " , " auto " )
17
17
AnyProperty ( " font-style " , " normal " )
18
18
}
19
19
20
- // General
21
-
22
20
Element ( . body) => {
21
+ // AnyProperty("border-top", "1px solid #404040")
22
+ // AnyProperty("border-bottom", "1px solid #404040")
23
+ AnyProperty ( " margin-top " , " 2rem " )
24
+ AnyProperty ( " margin-bottom " , " 3rem " )
25
+ }
26
+
27
+ Element ( . body) > All ( ) => {
28
+ // AnyProperty("border-left", "1px solid #404040")
29
+ // AnyProperty("border-right", "1px solid #404040")
23
30
AnyProperty ( " max-width " , " 40rem " )
24
31
AnyProperty ( " margin-right " , " auto " )
25
32
AnyProperty ( " margin-left " , " auto " )
@@ -41,9 +48,13 @@ public struct HomePage: Page {
41
48
AnyProperty ( " scale " , " calc(100% * -1) 100% " )
42
49
}
43
50
44
- /// Main
51
+ /// Hero header
45
52
46
- Element ( . header) * Element( . p) => {
53
+ Class ( " hero " ) => {
54
+ AnyProperty ( " padding-bottom " , " 1.5rem " )
55
+ }
56
+
57
+ Class ( " hero " ) * Element( . p) => {
47
58
Color ( . hex( " #D0D0D0 " ) )
48
59
}
49
60
@@ -58,23 +69,31 @@ public struct HomePage: Page {
58
69
59
70
Class ( " post-tabs " ) > Element ( . li) => {
60
71
AnyProperty ( " float " , " left " )
72
+ AnyProperty ( " margin-right " , " 0.25rem " )
61
73
}
62
74
63
75
Class ( " post-tabs " ) * Element( . button) => {
64
- AnyProperty ( " border-radius " , " 9999px " )
65
- AnyProperty ( " background-color " , " #2c2c2c " )
76
+ BackgroundColor ( " #3c3c3c " )
66
77
AnyProperty ( " color " , " white " )
67
- AnyProperty ( " padding " , " 0.25rem 0.75rem " )
68
- AnyProperty ( " border-width " , " 1px " )
78
+ AnyProperty ( " border-color " , " #505050 " )
79
+ AnyProperty ( " border-radius " , " 9999px " )
69
80
AnyProperty ( " border-style " , " solid " )
70
- AnyProperty ( " border-color " , " #606060 " )
81
+ AnyProperty ( " border-width " , " 1.25px " )
82
+ AnyProperty ( " padding " , " 0.25rem 0.75rem " )
71
83
}
72
84
73
- /// Post
85
+ Class ( " post-tabs " ) * Element( . button) <> . attr( " aria-selected " , match: . exact, value: " true " ) => {
86
+ AnyProperty ( " background-color " , " #F0F0F0 " )
87
+ AnyProperty ( " color " , " #101010 " )
88
+ AnyProperty ( " border-color " , " #A0A0A0 " )
89
+ }
90
+
91
+ /// Posts
74
92
75
93
Class ( " post " ) => {
76
94
AnyProperty ( " margin-top " , " 0.75rem " )
77
95
AnyProperty ( " margin-bottom " , " 1.5rem " )
96
+ // AnyProperty("border-bottom", "1px dotted #404040")
78
97
}
79
98
80
99
Class ( " post " ) > Element ( . header) => {
@@ -83,19 +102,23 @@ public struct HomePage: Page {
83
102
AnyProperty ( " font-weight " , " 600 " )
84
103
}
85
104
86
- Class ( " post " ) > Class ( " post -title" ) => {
105
+ Class ( " post-title " ) => {
87
106
AnyProperty ( " margin-top " , " 0.5rem " )
88
107
}
89
108
90
- Class ( " post " ) > Class ( " post -content" ) * All( ) => {
109
+ Class ( " post-content " ) * All( ) => {
91
110
AnyProperty ( " margin " , " revert " )
92
111
}
93
112
94
113
/// Code blocks
95
- Element ( . pre) => {
114
+ Class ( " post " ) * Element( . pre) => {
96
115
AnyProperty ( " padding " , " 1rem " )
97
- Background ( " #2F2F2F " )
116
+ Background ( " #242424 " )
117
+ AnyProperty ( " border-color " , " #3A3A3A " )
118
+ AnyProperty ( " border-style " , " solid " )
119
+ AnyProperty ( " border-width " , " 1.5px " )
98
120
AnyProperty ( " border-radius " , " 0.75rem " )
121
+ AnyProperty ( " overflow-x " , " auto " )
99
122
}
100
123
}
101
124
}
@@ -144,21 +167,21 @@ public struct HomePage: Page {
144
167
)
145
168
}
146
169
style ( self . styling)
147
- script ( . src( " https://cdn.jsdelivr.net/npm/alpinejs@3.14.8/dist/cdn.min.js " ) )
148
170
script ( . src( " https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js " ) )
149
171
script ( . src( " https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/languages/swift.min.js " ) )
150
172
script { HTMLRaw ( " hljs.highlightAll(); " ) }
173
+ VueScript ( )
151
174
}
152
175
body {
153
- header ( . ariaLabel( " About " ) ) {
176
+ header ( . class ( " hero " ) , . ariaLabel( " About " ) ) {
154
177
hgroup {
155
- h1 { " Erik Bautista Santibanez " }
156
- p { " Swift & Web Developer " }
178
+ h1 ( . class ( " hero-title " ) ) { " Erik Bautista Santibanez " }
179
+ p ( . class ( " hero-subtitle " ) ) { " Swift & Web Developer " }
157
180
158
181
let location = self . activityClient. location ( )
159
182
let residency = location? . residency ?? . default
160
183
161
- p {
184
+ p ( . class ( " hero-location " ) ) {
162
185
span ( . ariaLabel( " Residency " ) ) {
163
186
svg ( . xmlns( ) , . fill( " currentColor " ) , . viewBox( " 0 0 256 256 " ) , . class( " svg-icon " ) , . ariaLabel( " Map pin icon " ) ) {
164
187
path (
@@ -189,29 +212,37 @@ public struct HomePage: Page {
189
212
}
190
213
}
191
214
}
192
- main ( . x . data ( " { selection: undefined } " ) ) {
215
+ main ( . v . scope ( " { selection: undefined } " ) ) {
193
216
header {
194
- ul ( . class( " post-tabs " ) ) {
195
- for kind in Post . Kind? . allCases {
196
- let value = if let kind {
197
- " ' \( kind. rawValue) ' "
198
- } else {
199
- " undefined "
200
- }
201
- li {
202
- button (
203
- . x. on ( . click, " selection = \( value) " ) ,
204
- . x. bind ( " aria-current " , " selection == \( value) && 'tab' " )
205
- ) {
206
- kind? . tabTitle ?? " All "
217
+ hgroup {
218
+ h2 { " Posts " }
219
+ ul ( . class( " post-tabs " ) ) {
220
+ for kind in Post . Kind? . allCases {
221
+ let value = if let kind {
222
+ " ' \( kind. rawValue) ' "
223
+ } else {
224
+ " undefined "
225
+ }
226
+ li {
227
+ button (
228
+ . v. on ( . click, " selection = \( value) " ) ,
229
+ . v. bind ( " aria-selected " , " selection == \( value) " ) ,
230
+ . ariaSelected( kind == nil )
231
+ ) {
232
+ kind? . tabTitle ?? " All "
233
+ }
207
234
}
208
235
}
209
236
}
210
237
}
238
+ // p { "Selected {{ selection }}" }
211
239
}
212
240
section {
213
241
for post in Post . allCases {
214
- article ( . class( " post " ) , . x. show ( " !selection || selection == ' \( post. kind. rawValue) ' " ) ) {
242
+ article (
243
+ . class( " post " ) ,
244
+ . v. show ( " !selection || selection == ' \( post. kind. rawValue) ' " )
245
+ ) {
215
246
header { post. dateFormatted }
216
247
h3 ( . class( " post-title " ) ) { post. title }
217
248
div ( . class( " post-content " ) ) {
@@ -235,94 +266,4 @@ public struct HomePage: Page {
235
266
}
236
267
}
237
268
}
238
- }
239
-
240
- struct Post {
241
- let slug : String
242
- var hero : Hero ?
243
- let title : String
244
- let content : HTMLMarkdown
245
- let date : Date
246
- let kind : Kind
247
- var actionButtons : [ LinkButton ] ?
248
-
249
- private static let dateCreatedFormatter = {
250
- let formatter = DateFormatter ( )
251
- formatter. locale = Locale ( languageCode: . english, languageRegion: . unitedStates)
252
- formatter. timeZone = TimeZone ( abbreviation: " PST " ) ?? formatter. timeZone
253
- formatter. dateFormat = " MMM, d yyyy "
254
- return formatter
255
- } ( )
256
-
257
- var dateFormatted : String {
258
- Self . dateCreatedFormatter. string ( from: self . date) . uppercased ( )
259
- }
260
-
261
- enum Hero {
262
- case link( URL )
263
- case image( String )
264
- case video( String )
265
- case code( HTMLMarkdown )
266
- }
267
-
268
- struct LinkButton {
269
- let title : String
270
- let link : String
271
- }
272
-
273
- enum Kind : String , Hashable , CaseIterable {
274
- case project
275
- case education
276
- case experience
277
-
278
- var tabTitle : String {
279
- switch self {
280
- case . project: " Projects "
281
- case . education: " Education "
282
- case . experience: " Experiences "
283
- }
284
- }
285
- }
286
- }
287
-
288
- extension Post : CaseIterable {
289
- static var allCases : [ Self ] {
290
- [
291
- Self (
292
- slug: " swift-cascadia " ,
293
- title: " A Swift DSL for type-safe CSS " ,
294
- content: """
295
- Since I started building this website using Swift, I used [elementary](https://github.com/sliemeobn/elementary " link to Swift library " ) to build \
296
- HTML pages.
297
-
298
- ```swift
299
- func test() -> Int {
300
- print( " Hey, there! " )
301
- return 0
302
- }
303
- ```
304
- """ ,
305
- date: Date ( timeIntervalSince1970: 1_738_483_200 ) , // Feb 2, 2025
306
- kind: . project
307
- ) ,
308
- Self (
309
- slug: " anime-now " ,
310
- title: " Anime Now! \u{2014} An iOS and macOS App " ,
311
- content: """
312
- TBD
313
- """ ,
314
- date: Date ( timeIntervalSince1970: 1_663_225_200 ) , // Sep 15, 2025
315
- kind: . project
316
- ) ,
317
- Self (
318
- slug: " prism-ui " ,
319
- title: " PrismUI \u{2014} Controlling MSI RGB Keyboard on mac " ,
320
- content: """
321
- TBD
322
- """ ,
323
- date: Date ( timeIntervalSince1970: 1_663_225_200 ) ,
324
- kind: . project
325
- ) ,
326
- ]
327
- }
328
- }
269
+ }
0 commit comments