0
# HTML/Web Libraries
1
2
Compose for Web provides a complete web development framework with type-safe DOM manipulation, CSS styling, SVG support, and testing utilities. It enables building modern web applications using Compose's declarative paradigm while maintaining direct access to web platform APIs.
3
4
## Capabilities
5
6
### DOM Elements
7
8
Type-safe HTML element creation with full attribute and event support.
9
10
```kotlin { .api }
11
/**
12
* Structural HTML elements
13
*/
14
@Composable fun Div(
15
attrs: AttrBuilderContext<HTMLDivElement>? = null,
16
content: ContentBuilder<HTMLDivElement>? = null
17
)
18
19
@Composable fun Header(
20
attrs: AttrBuilderContext<HTMLElement>? = null,
21
content: ContentBuilder<HTMLElement>? = null
22
)
23
24
@Composable fun Main(
25
attrs: AttrBuilderContext<HTMLElement>? = null,
26
content: ContentBuilder<HTMLElement>? = null
27
)
28
29
@Composable fun Section(
30
attrs: AttrBuilderContext<HTMLElement>? = null,
31
content: ContentBuilder<HTMLElement>? = null
32
)
33
34
@Composable fun Article(
35
attrs: AttrBuilderContext<HTMLElement>? = null,
36
content: ContentBuilder<HTMLElement>? = null
37
)
38
39
@Composable fun Nav(
40
attrs: AttrBuilderContext<HTMLElement>? = null,
41
content: ContentBuilder<HTMLElement>? = null
42
)
43
44
@Composable fun Footer(
45
attrs: AttrBuilderContext<HTMLElement>? = null,
46
content: ContentBuilder<HTMLElement>? = null
47
)
48
49
/**
50
* Text content elements
51
*/
52
@Composable fun H1(
53
attrs: AttrBuilderContext<HTMLHeadingElement>? = null,
54
content: ContentBuilder<HTMLHeadingElement>? = null
55
)
56
57
@Composable fun H2(
58
attrs: AttrBuilderContext<HTMLHeadingElement>? = null,
59
content: ContentBuilder<HTMLHeadingElement>? = null
60
)
61
62
@Composable fun H3(
63
attrs: AttrBuilderContext<HTMLHeadingElement>? = null,
64
content: ContentBuilder<HTMLHeadingElement>? = null
65
)
66
67
@Composable fun P(
68
attrs: AttrBuilderContext<HTMLParagraphElement>? = null,
69
content: ContentBuilder<HTMLParagraphElement>? = null
70
)
71
72
@Composable fun Span(
73
attrs: AttrBuilderContext<HTMLSpanElement>? = null,
74
content: ContentBuilder<HTMLSpanElement>? = null
75
)
76
77
@Composable fun Text(value: String)
78
79
/**
80
* Interactive elements
81
*/
82
@Composable fun Button(
83
attrs: AttrBuilderContext<HTMLButtonElement>? = null,
84
content: ContentBuilder<HTMLButtonElement>? = null
85
)
86
87
@Composable fun A(
88
href: String? = null,
89
attrs: AttrBuilderContext<HTMLAnchorElement>? = null,
90
content: ContentBuilder<HTMLAnchorElement>? = null
91
)
92
93
@Composable fun Label(
94
forId: String? = null,
95
attrs: AttrBuilderContext<HTMLLabelElement>? = null,
96
content: ContentBuilder<HTMLLabelElement>? = null
97
)
98
```
99
100
**Usage Example:**
101
102
```kotlin
103
@Composable
104
fun WebPage() {
105
Div({ style { padding(20.px) } }) {
106
Header {
107
H1 { Text("My Web Application") }
108
Nav {
109
A(href = "/home") { Text("Home") }
110
A(href = "/about") { Text("About") }
111
A(href = "/contact") { Text("Contact") }
112
}
113
}
114
115
Main {
116
Section {
117
H2 { Text("Welcome") }
118
P { Text("This is a Compose for Web application.") }
119
120
Button({
121
onClick { event ->
122
console.log("Button clicked!")
123
}
124
}) {
125
Text("Click me")
126
}
127
}
128
}
129
130
Footer {
131
P { Text("© 2024 My Company") }
132
}
133
}
134
}
135
```
136
137
### Form Elements
138
139
Comprehensive form controls with controlled and uncontrolled input support.
140
141
```kotlin { .api }
142
/**
143
* Form container
144
*/
145
@Composable fun Form(
146
action: String? = null,
147
attrs: AttrBuilderContext<HTMLFormElement>? = null,
148
content: ContentBuilder<HTMLFormElement>? = null
149
)
150
151
/**
152
* Generic input element
153
*/
154
@Composable fun <K : Any> Input(
155
type: InputType<K>,
156
attrs: AttrBuilderContext<HTMLInputElement>? = null
157
)
158
159
/**
160
* Controlled input elements
161
*/
162
@Composable fun TextInput(
163
value: String,
164
attrs: AttrBuilderContext<HTMLInputElement>? = null
165
)
166
167
@Composable fun NumberInput(
168
value: Number? = null,
169
attrs: AttrBuilderContext<HTMLInputElement>? = null
170
)
171
172
@Composable fun EmailInput(
173
value: String,
174
attrs: AttrBuilderContext<HTMLInputElement>? = null
175
)
176
177
@Composable fun PasswordInput(
178
value: String,
179
attrs: AttrBuilderContext<HTMLInputElement>? = null
180
)
181
182
@Composable fun CheckboxInput(
183
checked: Boolean,
184
attrs: AttrBuilderContext<HTMLInputElement>? = null
185
)
186
187
@Composable fun RadioInput(
188
checked: Boolean,
189
attrs: AttrBuilderContext<HTMLInputElement>? = null
190
)
191
192
@Composable fun DateInput(
193
value: String,
194
attrs: AttrBuilderContext<HTMLInputElement>? = null
195
)
196
197
@Composable fun DateTimeLocalInput(
198
value: String,
199
attrs: AttrBuilderContext<HTMLInputElement>? = null
200
)
201
202
@Composable fun TimeInput(
203
value: String,
204
attrs: AttrBuilderContext<HTMLInputElement>? = null
205
)
206
207
@Composable fun FileInput(
208
attrs: AttrBuilderContext<HTMLInputElement>? = null
209
)
210
211
@Composable fun RangeInput(
212
value: Number,
213
min: Number? = null,
214
max: Number? = null,
215
step: Number? = null,
216
attrs: AttrBuilderContext<HTMLInputElement>? = null
217
)
218
219
@Composable fun SearchInput(
220
value: String,
221
attrs: AttrBuilderContext<HTMLInputElement>? = null
222
)
223
224
@Composable fun TelInput(
225
value: String,
226
attrs: AttrBuilderContext<HTMLInputElement>? = null
227
)
228
229
@Composable fun UrlInput(
230
value: String,
231
attrs: AttrBuilderContext<HTMLInputElement>? = null
232
)
233
234
/**
235
* Text area for multi-line input
236
*/
237
@Composable fun TextArea(
238
value: String,
239
attrs: AttrBuilderContext<HTMLTextAreaElement>? = null
240
)
241
242
/**
243
* Select dropdown
244
*/
245
@Composable fun Select(
246
attrs: AttrBuilderContext<HTMLSelectElement>? = null,
247
multiple: Boolean = false,
248
content: ContentBuilder<HTMLSelectElement>? = null
249
)
250
251
@Composable fun Option(
252
value: String,
253
attrs: AttrBuilderContext<HTMLOptionElement>? = null,
254
content: ContentBuilder<HTMLOptionElement>? = null
255
)
256
257
@Composable fun OptGroup(
258
label: String,
259
attrs: AttrBuilderContext<HTMLOptGroupElement>? = null,
260
content: ContentBuilder<HTMLOptGroupElement>? = null
261
)
262
```
263
264
**Usage Example:**
265
266
```kotlin
267
@Composable
268
fun ContactForm() {
269
var name by remember { mutableStateOf("") }
270
var email by remember { mutableStateOf("") }
271
var message by remember { mutableStateOf("") }
272
var newsletter by remember { mutableStateOf(false) }
273
274
Form {
275
Div({ style { marginBottom(16.px) } }) {
276
Label(forId = "name") { Text("Name:") }
277
TextInput(
278
value = name,
279
attrs = {
280
id("name")
281
onInput { event ->
282
name = event.value
283
}
284
}
285
)
286
}
287
288
Div({ style { marginBottom(16.px) } }) {
289
Label(forId = "email") { Text("Email:") }
290
EmailInput(
291
value = email,
292
attrs = {
293
id("email")
294
onInput { event ->
295
email = event.value
296
}
297
}
298
)
299
}
300
301
Div({ style { marginBottom(16.px) } }) {
302
Label(forId = "message") { Text("Message:") }
303
TextArea(
304
value = message,
305
attrs = {
306
id("message")
307
rows(5)
308
onInput { event ->
309
message = event.value
310
}
311
}
312
)
313
}
314
315
Div({ style { marginBottom(16.px) } }) {
316
CheckboxInput(
317
checked = newsletter,
318
attrs = {
319
id("newsletter")
320
onInput { event ->
321
newsletter = event.value
322
}
323
}
324
)
325
Label(forId = "newsletter") { Text("Subscribe to newsletter") }
326
}
327
328
Button({
329
type("submit")
330
onClick { event ->
331
event.preventDefault()
332
submitForm(name, email, message, newsletter)
333
}
334
}) {
335
Text("Send Message")
336
}
337
}
338
}
339
```
340
341
### CSS Styling
342
343
Type-safe CSS styling with units, properties, and responsive design support.
344
345
```kotlin { .api }
346
/**
347
* Style scope for CSS properties
348
*/
349
interface StyleScope {
350
/** Add arbitrary CSS property */
351
fun property(propertyName: String, value: StylePropertyValue)
352
353
/** Set CSS custom property (variable) */
354
fun variable(variableName: String, value: StylePropertyValue)
355
}
356
357
/**
358
* Style scope builder implementation
359
*/
360
class StyleScopeBuilder : StyleScope, StyleHolder
361
362
/**
363
* Mount style tag with CSS rules
364
*/
365
@Composable fun Style(cssRules: CSSRuleDeclarationList)
366
367
/**
368
* Build and mount styles
369
*/
370
@Composable inline fun Style(rulesBuild: StyleSheetBuilder.() -> Unit)
371
372
/**
373
* CSS unit system
374
*/
375
interface CSSUnit
376
interface CSSUnitLength : CSSUnit
377
interface CSSUnitPercentage : CSSUnit
378
interface CSSUnitAngle : CSSUnit
379
interface CSSUnitTime : CSSUnit
380
381
/** Length units */
382
val Number.px: CSSLengthValue
383
val Number.em: CSSLengthValue
384
val Number.cssRem: CSSLengthValue
385
val Number.vw: CSSLengthValue
386
val Number.vh: CSSLengthValue
387
val Number.vmin: CSSLengthValue
388
val Number.vmax: CSSLengthValue
389
390
/** Percentage units */
391
val Number.percent: CSSPercentageValue
392
393
/** Angle units */
394
val Number.deg: CSSAngleValue
395
val Number.rad: CSSAngleValue
396
val Number.turn: CSSAngleValue
397
398
/** Time units */
399
val Number.s: CSSTimeValue
400
val Number.ms: CSSTimeValue
401
402
/**
403
* CSS variables
404
*/
405
class CSSStyleVariable<TValue : StylePropertyValue>
406
fun <TValue : StylePropertyValue> variable(): CSSStyleVariable<TValue>
407
```
408
409
**Usage Example:**
410
411
```kotlin
412
@Composable
413
fun StyledComponents() {
414
Style {
415
// Global styles
416
".card" style {
417
backgroundColor(Color.white)
418
borderRadius(8.px)
419
boxShadow(0.px, 2.px, 4.px, rgba(0, 0, 0, 0.1))
420
padding(16.px)
421
margin(8.px)
422
}
423
424
".button-primary" style {
425
backgroundColor(Color.blue)
426
color(Color.white)
427
border(0.px)
428
borderRadius(4.px)
429
padding(12.px, 24.px)
430
cursor("pointer")
431
432
hover style {
433
backgroundColor(Color.darkBlue)
434
}
435
}
436
}
437
438
Div({ classes("card") }) {
439
H3({ style { marginTop(0.px) } }) {
440
Text("Styled Card")
441
}
442
443
P { Text("This card has custom styling applied.") }
444
445
Button({ classes("button-primary") }) {
446
Text("Primary Action")
447
}
448
}
449
}
450
```
451
452
### Attributes API
453
454
Comprehensive attribute and event handling system.
455
456
```kotlin { .api }
457
/**
458
* Attributes scope for element configuration
459
*/
460
interface AttrsScope<out TElement : Element> : EventsListenerScope {
461
/** Set arbitrary HTML attribute */
462
fun attr(attr: String, value: String)
463
464
/** Add inline styles */
465
fun style(builder: StyleScope.() -> Unit)
466
467
/** Add CSS classes */
468
fun classes(classes: Collection<String>)
469
fun classes(vararg classes: String)
470
471
/** Set DOM properties directly */
472
fun <E : HTMLElement, V> prop(update: (E, V) -> Unit, value: V)
473
474
/** Get element reference for imperative operations */
475
fun ref(effect: DisposableEffectScope.(TElement) -> DisposableEffectResult)
476
}
477
478
/**
479
* Common HTML attributes
480
*/
481
fun AttrsScope<*>.id(value: String)
482
fun AttrsScope<*>.title(value: String)
483
fun AttrsScope<*>.hidden()
484
fun AttrsScope<*>.tabIndex(value: Int)
485
fun AttrsScope<*>.contentEditable(value: Boolean)
486
fun AttrsScope<*>.draggable(value: Draggable)
487
488
/**
489
* Type aliases for attribute and content builders
490
*/
491
typealias AttrBuilderContext<T> = AttrsScope<T>.() -> Unit
492
typealias ContentBuilder<T> = @Composable ElementScope<T>.() -> Unit
493
```
494
495
### Event Handling
496
497
Type-safe event handling with synthetic event wrappers.
498
499
```kotlin { .api }
500
/**
501
* Base synthetic event wrapper
502
*/
503
open class SyntheticEvent<Element : EventTarget>
504
505
/**
506
* Specific event types
507
*/
508
class SyntheticMouseEvent<Element : EventTarget> : SyntheticEvent<Element>
509
class SyntheticKeyboardEvent<Element : EventTarget> : SyntheticEvent<Element>
510
class SyntheticFocusEvent<Element : EventTarget> : SyntheticEvent<Element>
511
class SyntheticInputEvent<Element : EventTarget> : SyntheticEvent<Element>
512
class SyntheticChangeEvent<Element : EventTarget> : SyntheticEvent<Element>
513
class SyntheticSubmitEvent<Element : EventTarget> : SyntheticEvent<Element>
514
class SyntheticClipboardEvent<Element : EventTarget> : SyntheticEvent<Element>
515
class SyntheticTouchEvent<Element : EventTarget> : SyntheticEvent<Element>
516
517
/**
518
* Event listener scope
519
*/
520
interface EventsListenerScope
521
```
522
523
### SVG Support
524
525
Complete SVG creation and manipulation API for vector graphics.
526
527
```kotlin { .api }
528
/**
529
* SVG container element
530
*/
531
@ExperimentalComposeWebSvgApi
532
@Composable fun Svg(
533
viewBox: String? = null,
534
attrs: AttrBuilderContext<SVGSVGElement>? = null,
535
content: ContentBuilder<SVGSVGElement>? = null
536
)
537
538
/**
539
* SVG shape elements
540
*/
541
@ExperimentalComposeWebSvgApi
542
@Composable fun ElementScope<SVGElement>.Circle(
543
cx: CSSLengthOrPercentageValue? = null,
544
cy: CSSLengthOrPercentageValue? = null,
545
r: CSSLengthOrPercentageValue? = null,
546
attrs: AttrBuilderContext<SVGCircleElement>? = null,
547
content: ContentBuilder<SVGCircleElement>? = null
548
)
549
550
@ExperimentalComposeWebSvgApi
551
@Composable fun ElementScope<SVGElement>.Rect(
552
x: CSSLengthOrPercentageValue? = null,
553
y: CSSLengthOrPercentageValue? = null,
554
width: CSSLengthOrPercentageValue? = null,
555
height: CSSLengthOrPercentageValue? = null,
556
attrs: AttrBuilderContext<SVGRectElement>? = null,
557
content: ContentBuilder<SVGRectElement>? = null
558
)
559
560
@ExperimentalComposeWebSvgApi
561
@Composable fun ElementScope<SVGElement>.Path(
562
d: String,
563
attrs: AttrBuilderContext<SVGPathElement>? = null,
564
content: ContentBuilder<SVGPathElement>? = null
565
)
566
567
@ExperimentalComposeWebSvgApi
568
@Composable fun ElementScope<SVGElement>.Line(
569
x1: CSSLengthOrPercentageValue? = null,
570
y1: CSSLengthOrPercentageValue? = null,
571
x2: CSSLengthOrPercentageValue? = null,
572
y2: CSSLengthOrPercentageValue? = null,
573
attrs: AttrBuilderContext<SVGLineElement>? = null,
574
content: ContentBuilder<SVGLineElement>? = null
575
)
576
577
@ExperimentalComposeWebSvgApi
578
@Composable fun ElementScope<SVGElement>.Ellipse(
579
cx: CSSLengthOrPercentageValue? = null,
580
cy: CSSLengthOrPercentageValue? = null,
581
rx: CSSLengthOrPercentageValue? = null,
582
ry: CSSLengthOrPercentageValue? = null,
583
attrs: AttrBuilderContext<SVGEllipseElement>? = null,
584
content: ContentBuilder<SVGEllipseElement>? = null
585
)
586
587
@ExperimentalComposeWebSvgApi
588
@Composable fun ElementScope<SVGElement>.Polygon(
589
points: String,
590
attrs: AttrBuilderContext<SVGPolygonElement>? = null,
591
content: ContentBuilder<SVGPolygonElement>? = null
592
)
593
594
@ExperimentalComposeWebSvgApi
595
@Composable fun ElementScope<SVGElement>.Polyline(
596
points: String,
597
attrs: AttrBuilderContext<SVGPolylineElement>? = null,
598
content: ContentBuilder<SVGPolylineElement>? = null
599
)
600
601
/**
602
* SVG text elements
603
*/
604
@ExperimentalComposeWebSvgApi
605
@Composable fun ElementScope<SVGElement>.SvgText(
606
text: String,
607
x: CSSLengthOrPercentageValue? = null,
608
y: CSSLengthOrPercentageValue? = null,
609
attrs: AttrBuilderContext<SVGTextElement>? = null
610
)
611
612
/**
613
* SVG gradient elements
614
*/
615
@ExperimentalComposeWebSvgApi
616
@Composable fun ElementScope<SVGElement>.LinearGradient(
617
id: String,
618
attrs: AttrBuilderContext<SVGLinearGradientElement>? = null,
619
content: ContentBuilder<SVGLinearGradientElement>? = null
620
)
621
622
@ExperimentalComposeWebSvgApi
623
@Composable fun ElementScope<SVGElement>.RadialGradient(
624
id: String,
625
attrs: AttrBuilderContext<SVGRadialGradientElement>? = null,
626
content: ContentBuilder<SVGRadialGradientElement>? = null
627
)
628
629
@ExperimentalComposeWebSvgApi
630
@Composable fun ElementScope<SVGElement>.Stop(
631
attrs: AttrBuilderContext<SVGStopElement>? = null,
632
content: ContentBuilder<SVGStopElement>? = null
633
)
634
```
635
636
**Usage Example:**
637
638
```kotlin
639
@OptIn(ExperimentalComposeWebSvgApi::class)
640
@Composable
641
fun SvgExample() {
642
Svg(
643
viewBox = "0 0 200 200",
644
attrs = {
645
style {
646
width(200.px)
647
height(200.px)
648
border(1.px, LineStyle.Solid, Color.black)
649
}
650
}
651
) {
652
// Define gradient
653
LinearGradient(id = "myGradient") {
654
Stop {
655
attr("offset", "0%")
656
attr("stop-color", "red")
657
}
658
Stop {
659
attr("offset", "100%")
660
attr("stop-color", "blue")
661
}
662
}
663
664
// Draw shapes
665
Circle(
666
cx = 100.px,
667
cy = 100.px,
668
r = 50.px,
669
attrs = {
670
fill("url(#myGradient)")
671
attr("stroke", "black")
672
attr("stroke-width", "2")
673
}
674
)
675
676
Path(
677
d = "M 50 150 Q 100 100 150 150",
678
attrs = {
679
fill("none")
680
attr("stroke", "green")
681
attr("stroke-width", "3")
682
}
683
)
684
685
SvgText(
686
text = "SVG Text",
687
x = 100.px,
688
y = 180.px,
689
attrs = {
690
attr("text-anchor", "middle")
691
attr("font-family", "Arial")
692
attr("font-size", "16")
693
}
694
)
695
}
696
}
697
```
698
699
### Testing Utilities
700
701
Testing framework for web Compose applications with composition and DOM testing support.
702
703
```kotlin { .api }
704
/**
705
* Main test scope with coroutine support
706
*/
707
@ComposeWebExperimentalTestsApi
708
class TestScope : CoroutineScope
709
710
/**
711
* Execute test block with test scope
712
*/
713
@ComposeWebExperimentalTestsApi
714
fun runTest(block: suspend TestScope.() -> Unit)
715
716
/**
717
* Test scope API
718
*/
719
interface TestScope {
720
/** Root test element */
721
val root: HTMLElement
722
723
/** Create test composition */
724
fun composition(content: @Composable () -> Unit)
725
726
/** Get next child element */
727
fun nextChild(): HTMLElement
728
fun <T> nextChild(): T
729
730
/** Wait for recomposition to complete */
731
suspend fun waitForRecompositionComplete()
732
733
/** Wait for DOM changes */
734
suspend fun waitForChanges(elementId: String)
735
suspend fun waitForChanges(element: HTMLElement)
736
}
737
738
/**
739
* Test utilities
740
*/
741
val HTMLElement.computedStyle: CSSStyleDeclaration
742
```
743
744
**Usage Example:**
745
746
```kotlin
747
@OptIn(ComposeWebExperimentalTestsApi::class)
748
fun testMyComponent() = runTest {
749
var clicked by mutableStateOf(false)
750
751
composition {
752
Button({
753
id("test-button")
754
onClick { clicked = true }
755
}) {
756
Text(if (clicked) "Clicked!" else "Click me")
757
}
758
}
759
760
val button = nextChild<HTMLButtonElement>()
761
assertEquals("Click me", button.textContent)
762
763
button.click()
764
waitForRecompositionComplete()
765
766
assertEquals("Clicked!", button.textContent)
767
assertTrue(clicked)
768
}
769
```
770
771
## Experimental APIs
772
773
```kotlin { .api }
774
/**
775
* Marks experimental web APIs
776
*/
777
@RequiresOptIn
778
annotation class ExperimentalComposeWebApi
779
780
/**
781
* Marks experimental style APIs
782
*/
783
@RequiresOptIn
784
annotation class ExperimentalComposeWebStyleApi
785
786
/**
787
* Marks experimental SVG APIs
788
*/
789
@RequiresOptIn
790
annotation class ExperimentalComposeWebSvgApi
791
792
/**
793
* Marks experimental test APIs
794
*/
795
@RequiresOptIn
796
annotation class ComposeWebExperimentalTestsApi
797
```