WCAG: Overlay - border, keyboard, accessibility, reduced motion
This commit is contained in:
@@ -13,6 +13,8 @@ ApplicationWindow {
|
|||||||
visible: true
|
visible: true
|
||||||
flags: Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint | Qt.Tool
|
flags: Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint | Qt.Tool
|
||||||
color: "transparent"
|
color: "transparent"
|
||||||
|
title: "WhisperVoice"
|
||||||
|
Accessible.name: "WhisperVoice Overlay"
|
||||||
|
|
||||||
FontLoader {
|
FontLoader {
|
||||||
id: jetBrainsMono
|
id: jetBrainsMono
|
||||||
@@ -35,7 +37,7 @@ ApplicationWindow {
|
|||||||
property bool isActive: ui.isRecording || ui.isProcessing
|
property bool isActive: ui.isRecording || ui.isProcessing
|
||||||
|
|
||||||
SequentialAnimation {
|
SequentialAnimation {
|
||||||
running: true
|
running: !ui.reduceMotion
|
||||||
loops: Animation.Infinite
|
loops: Animation.Infinite
|
||||||
PauseAnimation { duration: 3000 }
|
PauseAnimation { duration: 3000 }
|
||||||
NumberAnimation {
|
NumberAnimation {
|
||||||
@@ -96,6 +98,7 @@ ApplicationWindow {
|
|||||||
ShaderEffect {
|
ShaderEffect {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
opacity: 0.4
|
opacity: 0.4
|
||||||
|
visible: !ui.reduceMotion
|
||||||
property real time: 0
|
property real time: 0
|
||||||
fragmentShader: "gradient_blobs.qsb"
|
fragmentShader: "gradient_blobs.qsb"
|
||||||
NumberAnimation on time { from: 0; to: 1000; duration: 100000; loops: Animation.Infinite }
|
NumberAnimation on time { from: 0; to: 1000; duration: 100000; loops: Animation.Infinite }
|
||||||
@@ -105,6 +108,7 @@ ApplicationWindow {
|
|||||||
ShaderEffect {
|
ShaderEffect {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
opacity: 0.04
|
opacity: 0.04
|
||||||
|
visible: !ui.reduceMotion
|
||||||
property real time: 0
|
property real time: 0
|
||||||
property real intensity: ui.amplitude
|
property real intensity: ui.amplitude
|
||||||
fragmentShader: "glow.qsb"
|
fragmentShader: "glow.qsb"
|
||||||
@@ -115,6 +119,7 @@ ApplicationWindow {
|
|||||||
ParticleSystem {
|
ParticleSystem {
|
||||||
id: particles
|
id: particles
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
|
running: !ui.reduceMotion
|
||||||
ItemParticle {
|
ItemParticle {
|
||||||
system: particles
|
system: particles
|
||||||
delegate: Rectangle { width: 2; height: 2; radius: 1; color: "#10ffffff" }
|
delegate: Rectangle { width: 2; height: 2; radius: 1; color: "#10ffffff" }
|
||||||
@@ -143,6 +148,7 @@ ApplicationWindow {
|
|||||||
// F. CRT Shader Effect (Overlay on chassis ONLY)
|
// F. CRT Shader Effect (Overlay on chassis ONLY)
|
||||||
ShaderEffect {
|
ShaderEffect {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
|
visible: !ui.reduceMotion
|
||||||
property real time: 0
|
property real time: 0
|
||||||
fragmentShader: "crt.qsb"
|
fragmentShader: "crt.qsb"
|
||||||
NumberAnimation on time { from: 0; to: 100; duration: 5000; loops: Animation.Infinite }
|
NumberAnimation on time { from: 0; to: 100; duration: 5000; loops: Animation.Infinite }
|
||||||
@@ -172,7 +178,7 @@ ApplicationWindow {
|
|||||||
radius: height / 2
|
radius: height / 2
|
||||||
color: "transparent"
|
color: "transparent"
|
||||||
border.width: 1
|
border.width: 1
|
||||||
border.color: "#40ffffff"
|
border.color: Qt.rgba(1, 1, 1, 0.22)
|
||||||
|
|
||||||
MouseArea {
|
MouseArea {
|
||||||
anchors.fill: parent; hoverEnabled: true
|
anchors.fill: parent; hoverEnabled: true
|
||||||
@@ -194,7 +200,7 @@ ApplicationWindow {
|
|||||||
NumberAnimation { duration: 150; easing.type: Easing.OutCubic }
|
NumberAnimation { duration: 150; easing.type: Easing.OutCubic }
|
||||||
}
|
}
|
||||||
SequentialAnimation on border.color {
|
SequentialAnimation on border.color {
|
||||||
running: ui.isRecording
|
running: ui.isRecording && !ui.reduceMotion
|
||||||
loops: Animation.Infinite
|
loops: Animation.Infinite
|
||||||
ColorAnimation { from: "#A0ff4b4b"; to: "#C0ff6b6b"; duration: 800 }
|
ColorAnimation { from: "#A0ff4b4b"; to: "#C0ff6b6b"; duration: 800 }
|
||||||
ColorAnimation { from: "#C0ff6b6b"; to: "#A0ff4b4b"; duration: 800 }
|
ColorAnimation { from: "#C0ff6b6b"; to: "#A0ff4b4b"; duration: 800 }
|
||||||
@@ -209,7 +215,12 @@ ApplicationWindow {
|
|||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.leftMargin: 10
|
anchors.leftMargin: 10
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
activeFocusOnTab: true
|
||||||
|
Accessible.name: ui.isRecording ? "Stop recording" : "Start recording"
|
||||||
|
Accessible.role: Accessible.Button
|
||||||
|
Keys.onReturnPressed: ui.toggleRecordingRequested()
|
||||||
|
Keys.onSpacePressed: ui.toggleRecordingRequested()
|
||||||
|
|
||||||
// Make entire button scale with amplitude
|
// Make entire button scale with amplitude
|
||||||
scale: ui.isRecording ? (1.0 + ui.amplitude * 0.12) : 1.0
|
scale: ui.isRecording ? (1.0 + ui.amplitude * 0.12) : 1.0
|
||||||
Behavior on scale {
|
Behavior on scale {
|
||||||
@@ -245,7 +256,7 @@ ApplicationWindow {
|
|||||||
border.width: 2; border.color: "#60ffffff"
|
border.width: 2; border.color: "#60ffffff"
|
||||||
|
|
||||||
SequentialAnimation on scale {
|
SequentialAnimation on scale {
|
||||||
running: ui.isRecording
|
running: ui.isRecording && !ui.reduceMotion
|
||||||
loops: Animation.Infinite
|
loops: Animation.Infinite
|
||||||
NumberAnimation { from: 1.0; to: 1.08; duration: 600; easing.type: Easing.InOutQuad }
|
NumberAnimation { from: 1.0; to: 1.08; duration: 600; easing.type: Easing.InOutQuad }
|
||||||
NumberAnimation { from: 1.08; to: 1.0; duration: 600; easing.type: Easing.InOutQuad }
|
NumberAnimation { from: 1.08; to: 1.0; duration: 600; easing.type: Easing.InOutQuad }
|
||||||
@@ -263,6 +274,17 @@ ApplicationWindow {
|
|||||||
fillMode: Image.PreserveAspectFit
|
fillMode: Image.PreserveAspectFit
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Focus ring
|
||||||
|
Rectangle {
|
||||||
|
anchors.fill: micCircle
|
||||||
|
anchors.margins: -4
|
||||||
|
radius: width / 2
|
||||||
|
color: "transparent"
|
||||||
|
border.width: 2
|
||||||
|
border.color: "#B794F6"
|
||||||
|
visible: micContainer.activeFocus
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- RAINBOW WAVEFORM (Shader) ---
|
// --- RAINBOW WAVEFORM (Shader) ---
|
||||||
@@ -277,6 +299,7 @@ ApplicationWindow {
|
|||||||
|
|
||||||
ShaderEffect {
|
ShaderEffect {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
|
visible: !ui.reduceMotion
|
||||||
property real time: 0
|
property real time: 0
|
||||||
property real amplitude: ui.amplitude
|
property real amplitude: ui.amplitude
|
||||||
fragmentShader: "rainbow_wave.qsb"
|
fragmentShader: "rainbow_wave.qsb"
|
||||||
@@ -341,8 +364,10 @@ ApplicationWindow {
|
|||||||
font.family: jetBrainsMono.name; font.pixelSize: 16; font.bold: true; font.letterSpacing: 2
|
font.family: jetBrainsMono.name; font.pixelSize: 16; font.bold: true; font.letterSpacing: 2
|
||||||
style: Text.Outline
|
style: Text.Outline
|
||||||
styleColor: ui.isRecording ? "#ff0000" : "#808085"
|
styleColor: ui.isRecording ? "#ff0000" : "#808085"
|
||||||
|
Accessible.role: Accessible.StaticText
|
||||||
|
Accessible.name: "Recording time: " + text
|
||||||
SequentialAnimation on opacity {
|
SequentialAnimation on opacity {
|
||||||
running: ui.isRecording; loops: Animation.Infinite
|
running: ui.isRecording && !ui.reduceMotion; loops: Animation.Infinite
|
||||||
NumberAnimation { from: 1.0; to: 0.7; duration: 800 }
|
NumberAnimation { from: 1.0; to: 0.7; duration: 800 }
|
||||||
NumberAnimation { from: 0.7; to: 1.0; duration: 800 }
|
NumberAnimation { from: 0.7; to: 1.0; duration: 800 }
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user