Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ import com.lightningkite.kiteui.Log
import com.lightningkite.kiteui.OverrideOnly
import com.lightningkite.kiteui.afterTimeout
import com.lightningkite.kiteui.debugPrint
import com.lightningkite.kiteui.models.AccessibleSemantic
import com.lightningkite.kiteui.models.Align
import com.lightningkite.kiteui.models.CornerRadii
import com.lightningkite.kiteui.models.DragData
Expand Down Expand Up @@ -119,15 +118,6 @@ actual abstract class NativeElement actual constructor(context: ElementContext)
native.contentDescription = value
}

override var accessibleSemantic: AccessibleSemantic?
get() = super.accessibleSemantic
set(value) {
super.accessibleSemantic = value
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
native.isAccessibilityHeading = value is AccessibleSemantic.Heading
}
}

override var accessibleLiveRegion: LiveRegionMode
get() = super.accessibleLiveRegion
set(value) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -587,3 +587,27 @@ internal object TypedValueAnimator {
}
}
}

@ViewModifierDsl3
actual fun ElementWriter.CanAddTheme.asHeading(level: Int): ElementWriter.CanAddTheme =
beforeSetup {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) native.isAccessibilityHeading = true
}

@ViewModifierDsl3 actual val ElementWriter.CanAddTheme.asMain: ElementWriter.CanAddTheme get() = this
@ViewModifierDsl3 actual val ElementWriter.CanAddTheme.asNavigation: ElementWriter.CanAddTheme get() = this
@ViewModifierDsl3 actual val ElementWriter.CanAddTheme.asBanner: ElementWriter.CanAddTheme get() = this
@ViewModifierDsl3 actual val ElementWriter.CanAddTheme.asContentInfo: ElementWriter.CanAddTheme get() = this
@ViewModifierDsl3 actual val ElementWriter.CanAddTheme.asComplementary: ElementWriter.CanAddTheme get() = this
@ViewModifierDsl3 actual val ElementWriter.CanAddTheme.asSearch: ElementWriter.CanAddTheme get() = this

@ViewModifierDsl3
actual val ElementWriter.CanAddTheme.asPresentation: ElementWriter.CanAddTheme get() =
beforeSetup { native.importantForAccessibility = View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS }

@ViewModifierDsl3 actual val ElementWriter.CanAddTheme.asList: ElementWriter.CanAddTheme get() = this

@ViewModifierDsl3 actual val ElementWriter.CanAddAlignment.asListItem: ElementWriter.CanAddAlignment get() = this

@InternalKiteUi
internal actual fun ContainerElement.setupAsListContainer() {} // TalkBack infers list structure from content
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import com.lightningkite.kiteui.checkLeakAfterDelay
import com.lightningkite.kiteui.dom.Event
import com.lightningkite.kiteui.models.*
import com.lightningkite.kiteui.models.DropTargetDelegate
import com.lightningkite.kiteui.views.NativeElementCommonCode.ThemePipeline

private var labelForIdCounter = 0

Expand Down Expand Up @@ -58,22 +57,6 @@ actual abstract class NativeElement actual constructor(context: ElementContext)
native.setAttribute("aria-label", value)
}

override var accessibleSemantic: AccessibleSemantic?
get() = super.accessibleSemantic
set(value) {
super.accessibleSemantic = value
when (value) {
is AccessibleSemantic.Heading -> native.tag = "h${value.level.coerceIn(1, 6)}"
is AccessibleSemantic.Main -> native.tag = "main"
is AccessibleSemantic.Navigation -> native.tag = "nav"
is AccessibleSemantic.Banner -> native.tag = "header"
is AccessibleSemantic.ContentInfo -> native.tag = "footer"
is AccessibleSemantic.Complementary -> native.tag = "aside"
is AccessibleSemantic.Search -> native.tag = "search"
null -> {} // Don't reset tag — we don't know the original
}
}

override var accessibleLiveRegion: LiveRegionMode
get() = super.accessibleLiveRegion
set(value) {
Expand All @@ -88,18 +71,22 @@ actual abstract class NativeElement actual constructor(context: ElementContext)
override var labelFor: Element?
get() = super.labelFor
set(value) {
val previous = super.labelFor
super.labelFor = value
if (value != null) {
val targetNative = value.underlyingNativeElement.native
if (targetNative.id == null) {
targetNative.id = "kiteui-a11y-${labelForIdCounter++}"
}
if (native.tag == "span") {
if (native.tag == "span" || native.tag == "p") {
native.tag = "label"
native.setAttribute("for", targetNative.id!!)
} else {
targetNative.setAttribute("aria-labelledby", targetNative.id!!)
}
native.setAttribute("for", targetNative.id!!)
} else {
native.setAttribute("for", null)
if(native.tag == "label") native.setAttribute("for", null)
else previous?.underlyingNativeElement?.native?.setAttribute("aria-labelledby", null)
}
}

Expand Down Expand Up @@ -217,6 +204,8 @@ actual abstract class NativeElement actual constructor(context: ElementContext)
}
}

// TODO: transform this to point to the _STYLE PARTICIPATING_ element, not necessarily the direct element
// That's what we're using it for in every case it's used...
val Element.native: FutureElement get() = underlyingNativeElement.native

expect class FutureElementStyle
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ actual class IconView actual constructor(context: ElementContext) : NativeElemen
native.appendChild(FutureElement().apply {
tag = "svg"
xmlns = "http://www.w3.org/2000/svg"
setAttribute("aria-hidden", "true")
style.width = value.width.value.toString()
style.height = value.height.value.toString()
setStyleProperty("fill", "currentColor")
Expand Down Expand Up @@ -50,13 +51,20 @@ actual class IconView actual constructor(context: ElementContext) : NativeElemen
actual var description: String? = null
set(value) {
field = value
native.children.firstOrNull()?.let {
it.children.find { it.tag == "title" }
?.let { it.content = value }
?: it.appendChild(FutureElement().apply {
tag = "title"
content = value
})
if (value == "") {
accessibleLabel = null
native.setAttribute("aria-hidden", "true")
} else {
accessibleLabel = value
native.setAttribute("aria-hidden", null)
}
// native.children.firstOrNull()?.let {
// it.children.find { it.tag == "title" }
// ?.let { it.content = value }
// ?: it.appendChild(FutureElement().apply {
// tag = "title"
// content = value
// })
// }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ package com.lightningkite.kiteui.views.direct

import com.lightningkite.kiteui.ExperimentalKiteUi
import com.lightningkite.kiteui.InternalKiteUi
import com.lightningkite.kiteui.OverrideOnly
import com.lightningkite.kiteui.models.*
import com.lightningkite.kiteui.reactive.Action
import com.lightningkite.kiteui.views.*
Expand Down Expand Up @@ -240,4 +241,59 @@ internal expect fun ContainerElement.nativeAnimateHide(transition: ScreenTransit
internal expect fun ContainerElement.nativeAnimateWeight(fromWeight: Float, toWeight: Float)

@PublishedApi
internal expect fun Element.nativeSetupPullToRefresh(refreshAction: Action)
internal expect fun Element.nativeSetupPullToRefresh(refreshAction: Action)

private class ApplyTag(
val tag: String,
val wraps: ElementWriter,
) : ViewWriter, ElementWriter by wraps {

var wrapperElement: NativeContainerElement? = null

@OverrideOnly
override fun willAddChild(element: Element) {
if (element.native.tag == "span" || element.native.tag == "div") {
wrapperElement = null
element.native.tag = tag
wraps.willAddChild(element)
} else {
val we: NativeContainerElement = PassthroughContainer(wraps.context)
we.native.tag = tag
wraps.willAddChild(we)
we.willAddChild(element)
wrapperElement = we
}
}

@OverrideOnly
override fun addChild(element: Element) {
wrapperElement?.let {
it.addChild(element)
it.onStartup()
wraps.addChild(it)
} ?: wraps.addChild(element)
}
}

internal class PassthroughContainer(context: ElementContext): NativeContainerElement(context) {
init {
native.tag = "div"
native.style.display = "block"
}
}

@ViewModifierDsl3 actual fun ElementWriter.CanAddTheme.asHeading(level: Int): ElementWriter.CanAddTheme = ApplyTag("h${level.coerceIn(1, 6)}", this)
@ViewModifierDsl3 actual val ElementWriter.CanAddTheme.asMain: ElementWriter.CanAddTheme get() = ApplyTag("main", this)
@ViewModifierDsl3 actual val ElementWriter.CanAddTheme.asNavigation: ElementWriter.CanAddTheme get() = ApplyTag("nav", this)
@ViewModifierDsl3 actual val ElementWriter.CanAddTheme.asBanner: ElementWriter.CanAddTheme get() = ApplyTag("header", this)
@ViewModifierDsl3 actual val ElementWriter.CanAddTheme.asContentInfo: ElementWriter.CanAddTheme get() = ApplyTag("footer", this)
@ViewModifierDsl3 actual val ElementWriter.CanAddTheme.asComplementary: ElementWriter.CanAddTheme get() = ApplyTag("aside", this)
@ViewModifierDsl3 actual val ElementWriter.CanAddTheme.asSearch: ElementWriter.CanAddTheme get() = ApplyTag("search", this)
@ViewModifierDsl3 actual val ElementWriter.CanAddTheme.asPresentation: ElementWriter.CanAddTheme get() =
beforeSetup { native.setAttribute("aria-hidden", "true") }
@ViewModifierDsl3 actual val ElementWriter.CanAddTheme.asList: ElementWriter.CanAddTheme get() = ApplyTag("ul", this)
@ViewModifierDsl3 actual val ElementWriter.CanAddAlignment.asListItem: ElementWriter.CanAddAlignment get() = ApplyTag("li", this)

internal actual fun ContainerElement.setupAsListContainer() {
if (native.tag == "div" || native.tag == "span") native.tag = "ul"
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -438,16 +438,6 @@ interface Element : KiteUiCoroutineScopeHelpers, StatusListener {
*/
var accessibleLabel: String?

/**
* Semantic role for assistive technologies and HTML semantic elements.
*
* On web, changes the HTML tag for proper semantics and SEO (e.g., `<h2>`, `<nav>`, `<main>`).
* On iOS, sets accessibility traits (header, etc.). On Android, sets heading/landmark properties.
*
* Use via modifiers like `heading(level)`, or set automatically by theme modifiers like `nav`.
*/
var accessibleSemantic: AccessibleSemantic?

/**
* Marks this element as a live region for screen reader announcements of dynamic content.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -698,7 +698,6 @@ abstract class NativeElementCommonCode internal constructor(override val context

// --- ACCESSIBILITY ---
override var accessibleLabel: String? = null
override var accessibleSemantic: AccessibleSemantic? = null
override var accessibleLiveRegion: LiveRegionMode = LiveRegionMode.None
override var labelFor: Element? = null
override var describedBy: Element? = null
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.lightningkite.kiteui.views.direct

import com.lightningkite.kiteui.models.AccessibleSemantic
import com.lightningkite.kiteui.models.LiveRegionMode
import com.lightningkite.kiteui.views.*

Expand All @@ -13,8 +12,7 @@ import com.lightningkite.kiteui.views.*
* ```
*/
@ViewModifierDsl3
fun ElementWriter.CanAddTheme.heading(level: Int): ElementWriter.CanAddTheme =
beforeSetup { accessibleSemantic = AccessibleSemantic.Heading(level) }
fun ElementWriter.CanAddTheme.heading(level: Int): ElementWriter.CanAddTheme = asHeading(level)

/**
* Marks the next element as a live region so screen readers announce content changes.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -166,3 +166,18 @@ val ElementWriter.CanAddTheme.unpadded: ElementWriter.CanAddTheme get() = before

@ViewModifierDsl3
expect fun ElementWriter.CanAddShownWhen.shownWhen(default: Boolean = false, transition: ScreenTransition = ScreenTransition.None, condition: ReactiveContext.() -> Boolean): ElementWriter.CanAddSizing



@ViewModifierDsl3 expect fun ElementWriter.CanAddTheme.asHeading(level: Int): ElementWriter.CanAddTheme
@ViewModifierDsl3 expect val ElementWriter.CanAddTheme.asMain: ElementWriter.CanAddTheme
@ViewModifierDsl3 expect val ElementWriter.CanAddTheme.asNavigation: ElementWriter.CanAddTheme
@ViewModifierDsl3 expect val ElementWriter.CanAddTheme.asBanner: ElementWriter.CanAddTheme
@ViewModifierDsl3 expect val ElementWriter.CanAddTheme.asContentInfo: ElementWriter.CanAddTheme
@ViewModifierDsl3 expect val ElementWriter.CanAddTheme.asComplementary: ElementWriter.CanAddTheme
@ViewModifierDsl3 expect val ElementWriter.CanAddTheme.asSearch: ElementWriter.CanAddTheme
@ViewModifierDsl3 expect val ElementWriter.CanAddTheme.asPresentation: ElementWriter.CanAddTheme
@ViewModifierDsl3 expect val ElementWriter.CanAddTheme.asList: ElementWriter.CanAddTheme
@ViewModifierDsl3 expect val ElementWriter.CanAddAlignment.asListItem: ElementWriter.CanAddAlignment

internal expect fun ContainerElement.setupAsListContainer()
Loading
Loading