mirror of
https://github.com/samsonjs/AccessibilityTalk.git
synced 2026-03-25 09:25:52 +00:00
Add a calendar grid example
This commit is contained in:
parent
f74b1c3362
commit
fa0554d94f
14 changed files with 343 additions and 5 deletions
|
|
@ -21,10 +21,15 @@
|
|||
96088D862B799B1400E062FB /* TextSizingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96088D852B799B1400E062FB /* TextSizingView.swift */; };
|
||||
96088D882B7AFE7D00E062FB /* BadGoodView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96088D872B7AFE7D00E062FB /* BadGoodView.swift */; };
|
||||
96088D8A2B7B009400E062FB /* FlexibleSizingUIView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96088D892B7B009400E062FB /* FlexibleSizingUIView.swift */; };
|
||||
96088D8E2B7B1BF300E062FB /* BadDayView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96088D8D2B7B1BF300E062FB /* BadDayView.swift */; };
|
||||
96088D902B7B20FE00E062FB /* DayState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96088D8F2B7B20FE00E062FB /* DayState.swift */; };
|
||||
96088D922B7B220200E062FB /* GoodDayView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96088D912B7B220200E062FB /* GoodDayView.swift */; };
|
||||
96088D942B7B286E00E062FB /* CalendarBadView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96088D932B7B286E00E062FB /* CalendarBadView.swift */; };
|
||||
96088D962B7B300C00E062FB /* CalendarGoodView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96088D952B7B300C00E062FB /* CalendarGoodView.swift */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
96088D5E2B797B7700E062FB /* AccessibilityTalk.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = AccessibilityTalk.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
96088D5E2B797B7700E062FB /* Accesibility Demo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Accesibility Demo.app"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
96088D612B797B7700E062FB /* AccessibilityTalkApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccessibilityTalkApp.swift; sourceTree = "<group>"; };
|
||||
96088D632B797B7700E062FB /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; };
|
||||
96088D652B797B7900E062FB /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
||||
|
|
@ -39,6 +44,11 @@
|
|||
96088D852B799B1400E062FB /* TextSizingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextSizingView.swift; sourceTree = "<group>"; };
|
||||
96088D872B7AFE7D00E062FB /* BadGoodView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BadGoodView.swift; sourceTree = "<group>"; };
|
||||
96088D892B7B009400E062FB /* FlexibleSizingUIView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FlexibleSizingUIView.swift; sourceTree = "<group>"; };
|
||||
96088D8D2B7B1BF300E062FB /* BadDayView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BadDayView.swift; sourceTree = "<group>"; };
|
||||
96088D8F2B7B20FE00E062FB /* DayState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DayState.swift; sourceTree = "<group>"; };
|
||||
96088D912B7B220200E062FB /* GoodDayView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GoodDayView.swift; sourceTree = "<group>"; };
|
||||
96088D932B7B286E00E062FB /* CalendarBadView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CalendarBadView.swift; sourceTree = "<group>"; };
|
||||
96088D952B7B300C00E062FB /* CalendarGoodView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CalendarGoodView.swift; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
|
|
@ -63,7 +73,7 @@
|
|||
96088D5F2B797B7700E062FB /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
96088D5E2B797B7700E062FB /* AccessibilityTalk.app */,
|
||||
96088D5E2B797B7700E062FB /* Accesibility Demo.app */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
|
|
@ -74,6 +84,11 @@
|
|||
96088D612B797B7700E062FB /* AccessibilityTalkApp.swift */,
|
||||
96088D652B797B7900E062FB /* Assets.xcassets */,
|
||||
96088D872B7AFE7D00E062FB /* BadGoodView.swift */,
|
||||
96088D8D2B7B1BF300E062FB /* BadDayView.swift */,
|
||||
96088D912B7B220200E062FB /* GoodDayView.swift */,
|
||||
96088D932B7B286E00E062FB /* CalendarBadView.swift */,
|
||||
96088D952B7B300C00E062FB /* CalendarGoodView.swift */,
|
||||
96088D8F2B7B20FE00E062FB /* DayState.swift */,
|
||||
96088D632B797B7700E062FB /* ContentView.swift */,
|
||||
96088D732B7980D700E062FB /* DynamicTypeAdaptiveView.swift */,
|
||||
96088D792B79827D00E062FB /* ExampleFormBadView.swift */,
|
||||
|
|
@ -114,7 +129,7 @@
|
|||
);
|
||||
name = AccessibilityTalk;
|
||||
productName = AccessibilityTalk;
|
||||
productReference = 96088D5E2B797B7700E062FB /* AccessibilityTalk.app */;
|
||||
productReference = 96088D5E2B797B7700E062FB /* Accesibility Demo.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
/* End PBXNativeTarget section */
|
||||
|
|
@ -168,17 +183,22 @@
|
|||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
96088D762B7981DC00E062FB /* FlexibleSizingView.swift in Sources */,
|
||||
96088D962B7B300C00E062FB /* CalendarGoodView.swift in Sources */,
|
||||
96088D742B7980D700E062FB /* DynamicTypeAdaptiveView.swift in Sources */,
|
||||
96088D642B797B7700E062FB /* ContentView.swift in Sources */,
|
||||
96088D622B797B7700E062FB /* AccessibilityTalkApp.swift in Sources */,
|
||||
96088D722B797FBA00E062FB /* FlipLayoutAxisView.swift in Sources */,
|
||||
96088D822B79925200E062FB /* FlexibleSizingGoodUIView.swift in Sources */,
|
||||
96088D8E2B7B1BF300E062FB /* BadDayView.swift in Sources */,
|
||||
96088D7A2B79827D00E062FB /* ExampleFormBadView.swift in Sources */,
|
||||
96088D782B7981EB00E062FB /* ExampleFormGoodView.swift in Sources */,
|
||||
96088D882B7AFE7D00E062FB /* BadGoodView.swift in Sources */,
|
||||
96088D8A2B7B009400E062FB /* FlexibleSizingUIView.swift in Sources */,
|
||||
96088D802B798DBE00E062FB /* FlexibleSizingBadUIView.swift in Sources */,
|
||||
96088D902B7B20FE00E062FB /* DayState.swift in Sources */,
|
||||
96088D922B7B220200E062FB /* GoodDayView.swift in Sources */,
|
||||
96088D862B799B1400E062FB /* TextSizingView.swift in Sources */,
|
||||
96088D942B7B286E00E062FB /* CalendarBadView.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
|
@ -326,7 +346,7 @@
|
|||
);
|
||||
MARKETING_VERSION = 1.0;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = co.1se.AccessibilityTalk;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
PRODUCT_NAME = "Accesibility Demo";
|
||||
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||
SWIFT_VERSION = 5.0;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
|
|
@ -355,7 +375,7 @@
|
|||
);
|
||||
MARKETING_VERSION = 1.0;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = co.1se.AccessibilityTalk;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
PRODUCT_NAME = "Accesibility Demo";
|
||||
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||
SWIFT_VERSION = 5.0;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
|
|
|
|||
|
|
@ -1,6 +1,10 @@
|
|||
{
|
||||
"colors" : [
|
||||
{
|
||||
"color" : {
|
||||
"platform" : "universal",
|
||||
"reference" : "systemPurpleColor"
|
||||
},
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
|
|
|
|||
Binary file not shown.
|
After Width: | Height: | Size: 648 KiB |
|
|
@ -1,6 +1,7 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "AccessibilityTalkAppIcon-1024.png",
|
||||
"idiom" : "universal",
|
||||
"platform" : "ios",
|
||||
"size" : "1024x1024"
|
||||
|
|
|
|||
12
AccessibilityTalk/Assets.xcassets/Geese.imageset/Contents.json
vendored
Normal file
12
AccessibilityTalk/Assets.xcassets/Geese.imageset/Contents.json
vendored
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "geese.jpg",
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
BIN
AccessibilityTalk/Assets.xcassets/Geese.imageset/geese.jpg
vendored
Normal file
BIN
AccessibilityTalk/Assets.xcassets/Geese.imageset/geese.jpg
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 303 KiB |
12
AccessibilityTalk/Assets.xcassets/IceCube.imageset/Contents.json
vendored
Normal file
12
AccessibilityTalk/Assets.xcassets/IceCube.imageset/Contents.json
vendored
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "good-day.jpeg",
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
BIN
AccessibilityTalk/Assets.xcassets/IceCube.imageset/good-day.jpeg
vendored
Normal file
BIN
AccessibilityTalk/Assets.xcassets/IceCube.imageset/good-day.jpeg
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 230 KiB |
76
AccessibilityTalk/BadDayView.swift
Normal file
76
AccessibilityTalk/BadDayView.swift
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
//
|
||||
// DayView.swift
|
||||
// AccessibilityTalk
|
||||
//
|
||||
// Created by Work on 2024-02-12.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
struct BadDayView: View {
|
||||
@State var state: DayState = DayState()
|
||||
|
||||
var body: some View {
|
||||
ZStack {
|
||||
if state.snippetCount == 0 {
|
||||
Color(.systemGray3)
|
||||
} else {
|
||||
Image("Geese")
|
||||
.resizable()
|
||||
.scaledToFill()
|
||||
.clipped()
|
||||
}
|
||||
|
||||
date
|
||||
.font(.headline)
|
||||
.bold()
|
||||
.foregroundStyle(.thickMaterial)
|
||||
.padding(4)
|
||||
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topLeading)
|
||||
|
||||
if state.hasJournal {
|
||||
Image(systemName: "pencil.circle")
|
||||
.font(.headline)
|
||||
.bold()
|
||||
.foregroundStyle(.thickMaterial)
|
||||
.padding(4)
|
||||
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .bottomTrailing)
|
||||
}
|
||||
|
||||
snippetDescription
|
||||
.font(.headline)
|
||||
.bold()
|
||||
.foregroundStyle(.thickMaterial)
|
||||
.padding(4)
|
||||
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .bottomLeading)
|
||||
}
|
||||
}
|
||||
|
||||
private var date: some View {
|
||||
Text("\(state.date.formatted(date: .abbreviated, time: .omitted))")
|
||||
}
|
||||
|
||||
@ViewBuilder
|
||||
private var snippetDescription: some View {
|
||||
switch state.snippetCount {
|
||||
case 0:
|
||||
EmptyView()
|
||||
|
||||
case 1:
|
||||
Text("1 snippet")
|
||||
|
||||
default:
|
||||
Text("\(state.snippetCount) snippets")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#Preview {
|
||||
VStack {
|
||||
BadDayView()
|
||||
|
||||
BadDayView(state: DayState(hasJournal: false, snippetCount: 1))
|
||||
|
||||
BadDayView(state: DayState(hasJournal: true, snippetCount: 2))
|
||||
}
|
||||
}
|
||||
35
AccessibilityTalk/CalendarBadView.swift
Normal file
35
AccessibilityTalk/CalendarBadView.swift
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
//
|
||||
// CalendarBadView.swift
|
||||
// AccessibilityTalk
|
||||
//
|
||||
// Created by Work on 2024-02-12.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
struct CalendarBadView: View {
|
||||
var body: some View {
|
||||
LazyVGrid(columns: gridColumns, spacing: 0) {
|
||||
Group {
|
||||
BadDayView()
|
||||
|
||||
BadDayView(state: DayState(hasJournal: false, snippetCount: 1))
|
||||
|
||||
BadDayView(state: DayState(hasJournal: true, snippetCount: 2))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private var gridColumns: [GridItem] {
|
||||
let item = GridItem(.flexible(), spacing: 0)
|
||||
return Array(repeating: item, count: 3)
|
||||
}
|
||||
}
|
||||
|
||||
#Preview {
|
||||
NavigationStack {
|
||||
CalendarBadView()
|
||||
.navigationTitle("❌ Calendar Grid")
|
||||
.navigationBarTitleDisplayMode(.inline)
|
||||
}
|
||||
}
|
||||
40
AccessibilityTalk/CalendarGoodView.swift
Normal file
40
AccessibilityTalk/CalendarGoodView.swift
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
//
|
||||
// CalendarGoodView.swift
|
||||
// AccessibilityTalk
|
||||
//
|
||||
// Created by Work on 2024-02-12.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
struct CalendarGoodView: View {
|
||||
@Environment(\.dynamicTypeSize) var typeSize
|
||||
|
||||
var body: some View {
|
||||
ScrollView {
|
||||
LazyVGrid(columns: gridColumns, spacing: 0) {
|
||||
Group {
|
||||
GoodDayView()
|
||||
|
||||
GoodDayView(state: DayState(hasJournal: false, snippetCount: 1))
|
||||
|
||||
GoodDayView(state: DayState(hasJournal: true, snippetCount: 2))
|
||||
}
|
||||
}
|
||||
}
|
||||
.navigationTitle("✅ Calendar Grid")
|
||||
.navigationBarTitleDisplayMode(.inline)
|
||||
}
|
||||
|
||||
private var gridColumns: [GridItem] {
|
||||
let item = GridItem(.flexible(), spacing: 0)
|
||||
let count = typeSize.isAccessibilitySize ? 1 : 3
|
||||
return Array(repeating: item, count: count)
|
||||
}
|
||||
}
|
||||
|
||||
#Preview {
|
||||
NavigationStack {
|
||||
CalendarGoodView()
|
||||
}
|
||||
}
|
||||
|
|
@ -28,6 +28,13 @@ struct ContentView: View {
|
|||
.accessibilityLabel("Good SwiftUI Form")
|
||||
}
|
||||
}
|
||||
Section("5. Calendar Grid") {
|
||||
NavigationLink("❌ Bad SwiftUI Grid") { CalendarBadView() }
|
||||
NavigationLink(destination: CalendarGoodView()) {
|
||||
Text("✅ Good SwiftUI Grid")
|
||||
.accessibilityLabel("Good SwiftUI Grid")
|
||||
}
|
||||
}
|
||||
}
|
||||
.navigationTitle("Accessibility Demo")
|
||||
.navigationBarTitleDisplayMode(.inline)
|
||||
|
|
|
|||
16
AccessibilityTalk/DayState.swift
Normal file
16
AccessibilityTalk/DayState.swift
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
//
|
||||
// DayState.swift
|
||||
// AccessibilityTalk
|
||||
//
|
||||
// Created by Work on 2024-02-12.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
struct DayState: Hashable {
|
||||
var date: Date = .now
|
||||
var hasJournal: Bool = false
|
||||
var snippetCount: Int = 0
|
||||
|
||||
var isEmpty: Bool { !hasJournal && snippetCount == 0 }
|
||||
}
|
||||
115
AccessibilityTalk/GoodDayView.swift
Normal file
115
AccessibilityTalk/GoodDayView.swift
Normal file
|
|
@ -0,0 +1,115 @@
|
|||
//
|
||||
// GoodDayView.swift
|
||||
// AccessibilityTalk
|
||||
//
|
||||
// Created by Work on 2024-02-12.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
struct GoodDayView: View {
|
||||
@State var state: DayState = DayState()
|
||||
|
||||
@Environment(\.dynamicTypeSize) var typeSize
|
||||
|
||||
var body: some View {
|
||||
VStack(spacing: 4) {
|
||||
ZStack {
|
||||
if state.snippetCount == 0 {
|
||||
if !typeSize.isAccessibilitySize {
|
||||
Color(.systemGray3)
|
||||
}
|
||||
} else {
|
||||
Image("IceCube")
|
||||
.resizable()
|
||||
.scaledToFit()
|
||||
.clipped()
|
||||
}
|
||||
|
||||
if !typeSize.isAccessibilitySize {
|
||||
Group {
|
||||
date
|
||||
.font(.headline)
|
||||
.bold()
|
||||
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topLeading)
|
||||
|
||||
journalIndicator
|
||||
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topTrailing)
|
||||
|
||||
description
|
||||
.font(.headline)
|
||||
.bold()
|
||||
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .bottomLeading)
|
||||
}
|
||||
.foregroundStyle(.thickMaterial)
|
||||
.padding(4)
|
||||
}
|
||||
}
|
||||
.accessibilityElement()
|
||||
|
||||
if typeSize.isAccessibilitySize {
|
||||
date
|
||||
.bold()
|
||||
.padding(4)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
|
||||
HStack {
|
||||
description
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
|
||||
journalIndicator
|
||||
}
|
||||
.padding(4)
|
||||
}
|
||||
}
|
||||
.accessibilityElement()
|
||||
.accessibilityLabel(accessibilityDescription)
|
||||
}
|
||||
|
||||
private var date: some View {
|
||||
Text("\(state.date.formatted(date: .abbreviated, time: .omitted))")
|
||||
}
|
||||
|
||||
@ViewBuilder
|
||||
private var description: some View {
|
||||
switch state.snippetCount {
|
||||
case 0:
|
||||
EmptyView()
|
||||
|
||||
case 1:
|
||||
Text("1 snippet")
|
||||
|
||||
default:
|
||||
Text("\(state.snippetCount) snippets")
|
||||
}
|
||||
}
|
||||
|
||||
@ViewBuilder
|
||||
private var journalIndicator: some View {
|
||||
if state.hasJournal {
|
||||
Image(systemName: "pencil.circle")
|
||||
}
|
||||
}
|
||||
|
||||
private var accessibilityDescription: String {
|
||||
[
|
||||
state.date.formatted(date: .abbreviated, time: .omitted),
|
||||
state.isEmpty ? "empty" : nil,
|
||||
state.snippetCount == 1 ? "1 snippet" : nil,
|
||||
state.snippetCount > 1 ? "\(state.snippetCount) snippets" : nil,
|
||||
state.hasJournal ? "journal entry" : nil,
|
||||
].compactMap { $0 }.joined(separator: ", ")
|
||||
}
|
||||
}
|
||||
|
||||
#Preview {
|
||||
ScrollView {
|
||||
VStack {
|
||||
GoodDayView()
|
||||
|
||||
GoodDayView(state: DayState(hasJournal: false, snippetCount: 1))
|
||||
|
||||
GoodDayView(state: DayState(hasJournal: true, snippetCount: 2))
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue