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
260 changes: 207 additions & 53 deletions Sources/Showcase/AlertPlayground.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,14 @@ struct AlertPlayground: View {
@State var data: Int? = nil
@State var titleIsPresented = false
@State var titleMessageIsPresented = false
@State var longMessageIsPresented = false
@State var longButtonTitlesIsPresented = false
@State var twoButtonsIsPresented = false
@State var titleDialogIsPresented = false
@State var titleMessageDialogIsPresented = false
@State var longMessageDialogIsPresented = false
@State var longButtonTitlesDialogIsPresented = false
@State var twoButtonsDialogIsPresented = false
@State var threeButtonsIsPresented = false
@State var fiveButtonsIsPresented = false
@State var textFieldIsPresented = false
Expand All @@ -18,66 +25,95 @@ struct AlertPlayground: View {
@State var dataIsPresented = false

var body: some View {
VStack(spacing: 16) {
Text(value).bold()
Group {
Button("Title") {
titleIsPresented = true
}
Button("Title + Message") {
titleMessageIsPresented = true
}
Button("Two Buttons") {
twoButtonsIsPresented = true
}
Button("Three Buttons") {
threeButtonsIsPresented = true
}
Button("Five Buttons") {
fiveButtonsIsPresented = true
}
}
Divider()
Group {
Button("Text Field") {
textFieldIsPresented = true
}
Button("Secure Field") {
secureFieldIsPresented = true
ScrollView(.vertical) {
VStack(spacing: 16) {
Text(value).bold()
Group {
Button("Title") {
titleIsPresented = true
}
Button("Title + Message") {
titleMessageIsPresented = true
}
Button("Long Message") {
longMessageIsPresented = true
}
Button("Long Button Titles") {
longButtonTitlesIsPresented = true
}
Button("Two Buttons") {
twoButtonsIsPresented = true
}
Button("Three Buttons") {
threeButtonsIsPresented = true
}
Button("Five Buttons") {
fiveButtonsIsPresented = true
}
}
}
Divider()
// Group {
// Text("Present with error")
// Button("Error: \(String(describing: error))") {
// error = AlertPlaygroundError.testError
// }
// Button("Nil error") {
// error = nil
// }
// Button("Present") {
// errorIsPresented = true
// }
// }
// Divider()
Group {
Text("Present with data")
Button("Data: \(String(describing: data))") {
if data == nil {
data = 1
} else {
data = data! + 1
#if SKIP
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this in an #if SKIP block?

Divider()
Group {
Text("AlertDialog (Material3)")
Button("Title (Dialog)") {
titleDialogIsPresented = true
}
Button("Title + Message (Dialog)") {
titleMessageDialogIsPresented = true
}
Button("Long Message (Dialog)") {
longMessageDialogIsPresented = true
}
Button("Long Button Titles (Dialog)") {
longButtonTitlesDialogIsPresented = true
}
Button("Two Buttons (Dialog)") {
twoButtonsDialogIsPresented = true
}
}
Button("Nil data") {
data = nil
Divider()
#endif
Group {
Button("Text Field") {
textFieldIsPresented = true
}
Button("Secure Field") {
secureFieldIsPresented = true
}
}
Button("Present") {
dataIsPresented = true
Divider()
// Group {
// Text("Present with error")
// Button("Error: \(String(describing: error))") {
// error = AlertPlaygroundError.testError
// }
// Button("Nil error") {
// error = nil
// }
// Button("Present") {
// errorIsPresented = true
// }
// }
// Divider()
Group {
Text("Present with data")
Button("Data: \(String(describing: data))") {
if data == nil {
data = 1
} else {
data = data! + 1
}
}
Button("Nil data") {
data = nil
}
Button("Present") {
dataIsPresented = true
}
}
}
.padding()
}
.padding()
.toolbar {
PlaygroundSourceLink(file: "AlertPlayground.swift")
}
Expand All @@ -87,6 +123,18 @@ struct AlertPlayground: View {
} message: {
Text("This is the alert message to show beneath the title")
}
.alert("Long Message", isPresented: $longMessageIsPresented) {
} message: {
Text("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed commodo consectetur odio. Proin tempus orci ut tortor tincidunt elementum. Morbi finibus neque eget ullamcorper convallis. Suspendisse metus est, rhoncus vitae commodo non, ultricies ac leo. Proin scelerisque eros sed dolor dignissim accumsan id a nulla. Nulla tempor consequat nulla vel consequat. Etiam congue pretium sagittis. Quisque quis commodo velit, ac cursus massa. Aenean commodo congue velit in vestibulum. Proin viverra orci efficitur faucibus aliquet. Ut dignissim justo at dolor placerat, venenatis pulvinar dui consectetur. Nunc eget diam nec eros finibus finibus. Mauris et risus sit amet diam sagittis dapibus eu ac odio. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed commodo consectetur odio. Proin tempus orci ut tortor tincidunt elementum. Morbi finibus neque eget ullamcorper convallis. Suspendisse metus est, rhoncus vitae commodo non, ultricies ac leo. Proin scelerisque eros sed dolor dignissim accumsan id a nulla. Nulla tempor consequat nulla vel consequat. Etiam congue pretium sagittis. Quisque quis commodo velit, ac cursus massa. Aenean commodo congue velit in vestibulum. Proin viverra orci efficitur faucibus aliquet. Ut dignissim justo at dolor placerat, venenatis pulvinar dui consectetur. Nunc eget diam nec eros finibus finibus. Mauris et risus sit amet diam sagittis dapibus eu ac odio. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed commodo consectetur odio. Proin tempus orci ut tortor tincidunt elementum. Morbi finibus neque eget ullamcorper convallis. Suspendisse metus est, rhoncus vitae commodo non, ultricies ac leo. Proin scelerisque eros sed dolor dignissim accumsan id a nulla. Nulla tempor consequat nulla vel consequat. Etiam congue pretium sagittis. Quisque quis commodo velit, ac cursus massa. Aenean commodo congue velit in vestibulum. Proin viverra orci efficitur faucibus aliquet. Ut dignissim justo at dolor placerat, venenatis pulvinar dui consectetur. Nunc eget diam nec eros finibus finibus. Mauris et risus sit amet diam sagittis dapibus eu ac odio.")
}
.alert("Alert Title?", isPresented: $longButtonTitlesIsPresented) {
Button("Long destructive button text", role: .destructive) {
}
Button("Long cancel button text", role: .cancel) {
}
} message: {
Text("Long message body for the alert which is displayed in skip")
}
.alert("Two Buttons", isPresented: $twoButtonsIsPresented) {
Button("Option") {
value = "Option"
Expand Down Expand Up @@ -144,6 +192,112 @@ struct AlertPlayground: View {
// error = nil
// }
// }
#if SKIP
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Was this SKIP block just for your own Compose experimentation? Can we remove it?

Copy link
Contributor Author

@dfabulich dfabulich Mar 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These display the original Material 3 AlertDialog dialogs, which were the basis of my work in skiptools/skip-ui#336.

It seems plausible to me that we'd do some regression testing on this in the future (e.g. Material 4 or something).

I think it's good to leave these in, but I'll remove them if you insist…?

if titleDialogIsPresented {
ComposeView { context in
androidx.compose.material3.AlertDialog(
onDismissRequest: { titleDialogIsPresented = false },
modifier: context.modifier,
confirmButton: {
androidx.compose.material3.TextButton(modifier: androidx.compose.ui.Modifier.logLayoutModifier(tag: "AlertDialogTextButton"), onClick: { titleDialogIsPresented = false }) {
androidx.compose.material3.Text(modifier: androidx.compose.ui.Modifier.logLayoutModifier(tag: "AlertDialogTitleOKText"), text: "OK")
}
},
title: {
androidx.compose.material3.Text("Title")
}
)
}
.composeModifier { $0.logLayout(tag: "AlertDialogTitle") }
}
if titleMessageDialogIsPresented {
ComposeView { _ in
androidx.compose.material3.AlertDialog(
onDismissRequest: { titleMessageDialogIsPresented = false },
confirmButton: {
androidx.compose.material3.TextButton(onClick: { titleMessageDialogIsPresented = false }) {
androidx.compose.material3.Text(modifier: androidx.compose.ui.Modifier.logLayoutModifier(tag: "AlertDialogTitleMessageOKText"), text: "OK")
}
},
title: {
androidx.compose.material3.Text("Title + Message")
},
text: {
let messageColor = androidx.compose.material3.LocalContentColor.current
androidx.compose.runtime.SideEffect {
android.util.Log.d("AlertDialogMessageColor", "color=\(messageColor)")
}
androidx.compose.material3.Text(modifier: androidx.compose.ui.Modifier.logLayoutModifier(tag: "AlertDialogTitleMessageText"), text: "This is the alert message to show beneath the title")
}
)
}
}
if longMessageDialogIsPresented {
ComposeView { _ in
androidx.compose.material3.AlertDialog(
onDismissRequest: { longMessageDialogIsPresented = false },
confirmButton: {
androidx.compose.material3.TextButton(onClick: { longMessageDialogIsPresented = false }) {
androidx.compose.material3.Text(modifier: androidx.compose.ui.Modifier.logLayoutModifier(tag: "AlertDialogLongMessageOKText"), text: "OK")
}
},
title: {
androidx.compose.material3.Text("Long Message")
},
text: {
androidx.compose.material3.Text("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed commodo consectetur odio. Proin tempus orci ut tortor tincidunt elementum. Morbi finibus neque eget ullamcorper convallis. Suspendisse metus est, rhoncus vitae commodo non, ultricies ac leo. Proin scelerisque eros sed dolor dignissim accumsan id a nulla. Nulla tempor consequat nulla vel consequat. Etiam congue pretium sagittis. Quisque quis commodo velit, ac cursus massa. Aenean commodo congue velit in vestibulum. Proin viverra orci efficitur faucibus aliquet. Ut dignissim justo at dolor placerat, venenatis pulvinar dui consectetur. Nunc eget diam nec eros finibus finibus. Mauris et risus sit amet diam sagittis dapibus eu ac odio. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed commodo consectetur odio. Proin tempus orci ut tortor tincidunt elementum. Morbi finibus neque eget ullamcorper convallis. Suspendisse metus est, rhoncus vitae commodo non, ultricies ac leo. Proin scelerisque eros sed dolor dignissim accumsan id a nulla. Nulla tempor consequat nulla vel consequat. Etiam congue pretium sagittis. Quisque quis commodo velit, ac cursus massa. Aenean commodo congue velit in vestibulum. Proin viverra orci efficitur faucibus aliquet. Ut dignissim justo at dolor placerat, venenatis pulvinar dui consectetur. Nunc eget diam nec eros finibus finibus. Mauris et risus sit amet diam sagittis dapibus eu ac odio. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed commodo consectetur odio. Proin tempus orci ut tortor tincidunt elementum. Morbi finibus neque eget ullamcorper convallis. Suspendisse metus est, rhoncus vitae commodo non, ultricies ac leo. Proin scelerisque eros sed dolor dignissim accumsan id a nulla. Nulla tempor consequat nulla vel consequat. Etiam congue pretium sagittis. Quisque quis commodo velit, ac cursus massa. Aenean commodo congue velit in vestibulum. Proin viverra orci efficitur faucibus aliquet. Ut dignissim justo at dolor placerat, venenatis pulvinar dui consectetur. Nunc eget diam nec eros finibus finibus. Mauris et risus sit amet diam sagittis dapibus eu ac odio.")
}
)
}
}
if longButtonTitlesDialogIsPresented {
ComposeView { _ in
androidx.compose.material3.AlertDialog(
onDismissRequest: { longButtonTitlesDialogIsPresented = false },
modifier: androidx.compose.ui.Modifier.logLayoutModifier(tag: "AlertDialogLongTitles"),
confirmButton: {
androidx.compose.material3.TextButton(
onClick: { longButtonTitlesDialogIsPresented = false },
colors: androidx.compose.material3.ButtonDefaults.textButtonColors(contentColor: androidx.compose.material3.MaterialTheme.colorScheme.error)
) {
androidx.compose.material3.Text(modifier: androidx.compose.ui.Modifier.logLayoutModifier(tag: "AlertDialogLongTitlesDestructiveText"), text: "Long destructive button text")
}
},
dismissButton: {
androidx.compose.material3.TextButton(onClick: { longButtonTitlesDialogIsPresented = false }) {
androidx.compose.material3.Text(modifier: androidx.compose.ui.Modifier.logLayoutModifier(tag: "AlertDialogLongTitlesCancelText"), text: "Long cancel button text")
}
},
title: {
androidx.compose.material3.Text("Alert Title?")
},
text: {
androidx.compose.material3.Text("Long message body for the alert which is displayed in skip")
}
)
}
}
if twoButtonsDialogIsPresented {
ComposeView { _ in
androidx.compose.material3.AlertDialog(
onDismissRequest: { twoButtonsDialogIsPresented = false },
confirmButton: {
androidx.compose.material3.TextButton(onClick: { twoButtonsDialogIsPresented = false; value = "Option" }) {
androidx.compose.material3.Text(modifier: androidx.compose.ui.Modifier.logLayoutModifier(tag: "AlertDialogTwoButtonsOptionText"), text: "Option")
}
},
dismissButton: {
androidx.compose.material3.TextButton(onClick: { twoButtonsDialogIsPresented = false; value = "Custom Cancel" }) {
androidx.compose.material3.Text(modifier: androidx.compose.ui.Modifier.logLayoutModifier(tag: "AlertDialogTwoButtonsCancelText"), text: "Cancel")
}
},
title: {
androidx.compose.material3.Text("Two Buttons")
}
)
}
}
#endif
}
}

Expand Down
21 changes: 21 additions & 0 deletions Sources/Showcase/Resources/Localizable.xcstrings
Original file line number Diff line number Diff line change
Expand Up @@ -705,6 +705,9 @@
},
"Alert" : {

},
"Alert Title?" : {

},
"alignment: .bottomTrailing" : {

Expand Down Expand Up @@ -1897,6 +1900,21 @@
},
"Localization" : {

},
"Long Button Titles" : {

},
"Long cancel button text" : {

},
"Long destructive button text" : {

},
"Long Message" : {

},
"Long message body for the alert which is displayed in skip" : {

},
"Long press: %lld" : {

Expand All @@ -1912,6 +1930,9 @@
},
"Looping Clip" : {

},
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed commodo consectetur odio. Proin tempus orci ut tortor tincidunt elementum. Morbi finibus neque eget ullamcorper convallis. Suspendisse metus est, rhoncus vitae commodo non, ultricies ac leo. Proin scelerisque eros sed dolor dignissim accumsan id a nulla. Nulla tempor consequat nulla vel consequat. Etiam congue pretium sagittis. Quisque quis commodo velit, ac cursus massa. Aenean commodo congue velit in vestibulum. Proin viverra orci efficitur faucibus aliquet. Ut dignissim justo at dolor placerat, venenatis pulvinar dui consectetur. Nunc eget diam nec eros finibus finibus. Mauris et risus sit amet diam sagittis dapibus eu ac odio. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed commodo consectetur odio. Proin tempus orci ut tortor tincidunt elementum. Morbi finibus neque eget ullamcorper convallis. Suspendisse metus est, rhoncus vitae commodo non, ultricies ac leo. Proin scelerisque eros sed dolor dignissim accumsan id a nulla. Nulla tempor consequat nulla vel consequat. Etiam congue pretium sagittis. Quisque quis commodo velit, ac cursus massa. Aenean commodo congue velit in vestibulum. Proin viverra orci efficitur faucibus aliquet. Ut dignissim justo at dolor placerat, venenatis pulvinar dui consectetur. Nunc eget diam nec eros finibus finibus. Mauris et risus sit amet diam sagittis dapibus eu ac odio. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed commodo consectetur odio. Proin tempus orci ut tortor tincidunt elementum. Morbi finibus neque eget ullamcorper convallis. Suspendisse metus est, rhoncus vitae commodo non, ultricies ac leo. Proin scelerisque eros sed dolor dignissim accumsan id a nulla. Nulla tempor consequat nulla vel consequat. Etiam congue pretium sagittis. Quisque quis commodo velit, ac cursus massa. Aenean commodo congue velit in vestibulum. Proin viverra orci efficitur faucibus aliquet. Ut dignissim justo at dolor placerat, venenatis pulvinar dui consectetur. Nunc eget diam nec eros finibus finibus. Mauris et risus sit amet diam sagittis dapibus eu ac odio." : {

},
"Lottie Animation" : {

Expand Down