Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding verticalOffset property to FluentNotification #2045

Merged
merged 2 commits into from
Jun 19, 2024
Merged
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 @@ -49,6 +49,7 @@ struct NotificationDemoView: View {
@State var showFromBottom: Bool = true
@State var showBackgroundGradient: Bool = false
@State var useCustomTheme: Bool = false
@State var verticalOffset: CGFloat = 0.0
@ObservedObject var fluentTheme: FluentTheme = .shared
let customTheme: FluentTheme = {
let foregroundColor = UIColor(light: GlobalTokens.sharedColor(.lavender, .shade30),
Expand Down Expand Up @@ -175,114 +176,120 @@ struct NotificationDemoView: View {
Alert(title: Text("Button tapped"))
})

Button("Show") {
Button("Show Notification") {
if isPresented == false {
isPresented = true
DispatchQueue.main.asyncAfter(deadline: .now() + 3.0) {
isPresented = false
}
}
}
.fixedSize()
.padding()

ScrollView {
Group {
Group {
VStack(spacing: 0) {
Text("Content")
.frame(maxWidth: .infinity, alignment: .leading)
.font(.title)
Divider()
}

TextField("Title", text: $title)
.autocapitalization(.none)
.disableAutocorrection(true)
.textFieldStyle(RoundedBorderTextFieldStyle())

TextField("Message", text: $message)
.autocapitalization(.none)
.disableAutocorrection(true)
.textFieldStyle(RoundedBorderTextFieldStyle())

TextField("Action Button Title", text: $actionButtonTitle)
.autocapitalization(.none)
.disableAutocorrection(true)
.textFieldStyle(RoundedBorderTextFieldStyle())

FluentUIDemoToggle(titleKey: "Has Attributed Text: Strikethrough", isOn: $hasBlueStrikethroughAttribute)
FluentUIDemoToggle(titleKey: "Has Attributed Text: Large Red Papyrus Font", isOn: $hasLargeRedPapyrusFontAttribute)
FluentUIDemoToggle(titleKey: "Set image", isOn: $showImage)
FluentUIDemoToggle(titleKey: "Set trailing image", isOn: $showTrailingImage)
}

Group {
VStack(spacing: 0) {
Text("Action")
.frame(maxWidth: .infinity, alignment: .leading)
.font(.title)
Divider()
}
FluentUIDemoToggle(titleKey: "Has Action Button Action", isOn: $hasActionButtonAction)
FluentUIDemoToggle(titleKey: "Show Default Dismiss Button", isOn: $showDefaultDismissActionButton)
FluentUIDemoToggle(titleKey: "Has Message Action", isOn: $hasMessageAction)
}
.buttonStyle(FluentButtonStyle(style: .accent))
.fixedSize()
.padding()

Group {
VStack(spacing: 0) {
Text("Style")
.frame(maxWidth: .infinity, alignment: .leading)
.font(.title)
Divider()
}

Picker(selection: $style, label: EmptyView()) {
Text(".primaryToast").tag(MSFNotificationStyle.primaryToast)
Text(".neutralToast").tag(MSFNotificationStyle.neutralToast)
Text(".primaryBar").tag(MSFNotificationStyle.primaryBar)
Text(".primaryOutlineBar").tag(MSFNotificationStyle.primaryOutlineBar)
Text(".neutralBar").tag(MSFNotificationStyle.neutralBar)
Text(".dangerToast").tag(MSFNotificationStyle.dangerToast)
Text(".warningToast").tag(MSFNotificationStyle.warningToast)
}
.labelsHidden()
.frame(maxWidth: .infinity, alignment: .leading)

FluentUIDemoToggle(titleKey: "Override Tokens (Image Color and Horizontal Spacing)", isOn: $overrideTokens)
FluentUIDemoToggle(titleKey: "Flexible Width Toast", isOn: $isFlexibleWidthToast)
FluentUIDemoToggle(titleKey: "Present From Bottom", isOn: $showFromBottom)
FluentUIDemoToggle(titleKey: "Background Gradient", isOn: $showBackgroundGradient)
FluentUIDemoToggle(titleKey: "Custom theme", isOn: $useCustomTheme)
}
}
.padding()
}
notificationSettings
}
.presentNotification(isPresented: $isPresented,
isBlocking: false) {
FluentNotification(style: style,
isFlexibleWidthToast: $isFlexibleWidthToast.wrappedValue,
message: hasMessage ? message : nil,
attributedMessage: hasAttribute && hasMessage ? attributedMessage : nil,
isPresented: $isPresented,
title: hasTitle ? title : nil,
attributedTitle: hasAttribute && hasTitle ? attributedTitle : nil,
image: image,
trailingImage: trailingImage,
trailingImageAccessibilityLabel: trailingImageLabel,
actionButtonTitle: actionButtonTitle,
actionButtonAction: actionButtonAction,
showDefaultDismissActionButton: showDefaultDismissActionButton,
messageButtonAction: messageButtonAction,
showFromBottom: showFromBottom)
isFlexibleWidthToast: $isFlexibleWidthToast.wrappedValue,
message: hasMessage ? message : nil,
attributedMessage: hasAttribute && hasMessage ? attributedMessage : nil,
isPresented: $isPresented,
title: hasTitle ? title : nil,
attributedTitle: hasAttribute && hasTitle ? attributedTitle : nil,
image: image,
trailingImage: trailingImage,
trailingImageAccessibilityLabel: trailingImageLabel,
actionButtonTitle: actionButtonTitle,
actionButtonAction: actionButtonAction,
showDefaultDismissActionButton: showDefaultDismissActionButton,
messageButtonAction: messageButtonAction,
showFromBottom: showFromBottom,
verticalOffset: verticalOffset)
.backgroundGradient(showBackgroundGradient ? backgroundGradient : nil)
.overrideTokens($overrideTokens.wrappedValue ? notificationOverrideTokens : nil)
}
.fluentTheme(theme)
.tint(Color(theme.color(.brandForeground1)))
}

@ViewBuilder
var notificationSettings: some View {
FluentList {
FluentListSection("Content") {
LabeledContent {
TextField("Title", text: $title)
.autocapitalization(.none)
.disableAutocorrection(true)
.multilineTextAlignment(.trailing)
} label: {
Text("Title")
}

LabeledContent {
TextField("Message", text: $message)
.autocapitalization(.none)
.disableAutocorrection(true)
.multilineTextAlignment(.trailing)
} label: {
Text("Message")
}

LabeledContent {
TextField("Action Button Title", text: $actionButtonTitle)
.autocapitalization(.none)
.disableAutocorrection(true)
.multilineTextAlignment(.trailing)
} label: {
Text("Action Button Title")
}

LabeledContent {
TextField("Offset", value: $verticalOffset, format: FloatingPointFormatStyle())
.keyboardType(.numberPad)
.multilineTextAlignment(.trailing)
} label: {
Text("Vertical Offset")
}

Toggle("Has Attributed Text: Strikethrough", isOn: $hasBlueStrikethroughAttribute)
Toggle("Has Attributed Text: Large Red Papyrus Font", isOn: $hasLargeRedPapyrusFontAttribute)
Toggle("Set image", isOn: $showImage)
Toggle("Set trailing image", isOn: $showTrailingImage)
}

FluentListSection("Action") {
Toggle("Has Action Button Action", isOn: $hasActionButtonAction)
Toggle("Show Default Dismiss Button", isOn: $showDefaultDismissActionButton)
Toggle("Has Message Action", isOn: $hasMessageAction)
}

FluentListSection("Style") {

Picker(selection: $style, label: EmptyView()) {
Text(".primaryToast").tag(MSFNotificationStyle.primaryToast)
Text(".neutralToast").tag(MSFNotificationStyle.neutralToast)
Text(".primaryBar").tag(MSFNotificationStyle.primaryBar)
Text(".primaryOutlineBar").tag(MSFNotificationStyle.primaryOutlineBar)
Text(".neutralBar").tag(MSFNotificationStyle.neutralBar)
Text(".dangerToast").tag(MSFNotificationStyle.dangerToast)
Text(".warningToast").tag(MSFNotificationStyle.warningToast)
}
.labelsHidden()
.frame(maxWidth: .infinity, alignment: .leading)

Toggle("Override Tokens (Image Color and Horizontal Spacing)", isOn: $overrideTokens)
Toggle("Flexible Width Toast", isOn: $isFlexibleWidthToast)
Toggle("Present From Bottom", isOn: $showFromBottom)
Toggle("Background Gradient", isOn: $showBackgroundGradient)
Toggle("Custom theme", isOn: $useCustomTheme)
}
}
.fluentListStyle(.insetGrouped)
}

private var backgroundGradient: LinearGradientInfo {
// It's a lovely blue-to-pink gradient
let colors: [UIColor] = [UIColor(light: GlobalTokens.sharedColor(.pink, .tint50),
Expand Down
17 changes: 12 additions & 5 deletions ios/FluentUI/Notification/FluentNotification.swift
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ public struct FluentNotification: View, TokenizedControlView {
/// - showDefaultDismissActionButton: Bool to control if the Notification has a dismiss action by default.
/// - messageButtonAction: Action to be dispatched by tapping on the toast/bar notification.
/// - showFromBottom: Defines whether the notification shows from the bottom of the presenting view or the top.
/// - verticalOffset: How much to vertically offset the notification from its default position.
public init(style: MSFNotificationStyle,
shouldSelfPresent: Bool = true,
isFlexibleWidthToast: Bool = false,
Expand All @@ -95,7 +96,8 @@ public struct FluentNotification: View, TokenizedControlView {
actionButtonAction: (() -> Void)? = nil,
showDefaultDismissActionButton: Bool? = nil,
messageButtonAction: (() -> Void)? = nil,
showFromBottom: Bool = true) {
showFromBottom: Bool = true,
verticalOffset: CGFloat = 0.0) {
let state = MSFNotificationStateImpl(style: style,
message: message,
attributedMessage: attributedMessage,
Expand All @@ -108,7 +110,8 @@ public struct FluentNotification: View, TokenizedControlView {
actionButtonAction: actionButtonAction,
showDefaultDismissActionButton: showDefaultDismissActionButton,
messageButtonAction: messageButtonAction,
showFromBottom: showFromBottom)
showFromBottom: showFromBottom,
verticalOffset: verticalOffset)
self.state = state
self.shouldSelfPresent = shouldSelfPresent
self.isFlexibleWidthToast = isFlexibleWidthToast && style.isToast
Expand Down Expand Up @@ -355,7 +358,7 @@ public struct FluentNotification: View, TokenizedControlView {
withAnimation(.spring(response: state.style.animationDurationForShow / 2.0,
dampingFraction: state.style.animationDampingRatio,
blendDuration: 0)) {
bottomOffset = 0
bottomOffset = -state.verticalOffset
opacity = 1
}
}
Expand Down Expand Up @@ -400,6 +403,7 @@ class MSFNotificationStateImpl: ControlState, MSFNotificationState {
@Published var showDefaultDismissActionButton: Bool
@Published var showFromBottom: Bool
@Published var backgroundGradient: LinearGradientInfo?
@Published var verticalOffset: CGFloat

/// Title to display in the action button on the trailing edge of the control.
///
Expand Down Expand Up @@ -430,7 +434,8 @@ class MSFNotificationStateImpl: ControlState, MSFNotificationState {
actionButtonAction: nil,
showDefaultDismissActionButton: nil,
messageButtonAction: nil,
showFromBottom: true)
showFromBottom: true,
verticalOffset: 0.0)
}

init(style: MSFNotificationStyle,
Expand All @@ -445,7 +450,8 @@ class MSFNotificationStateImpl: ControlState, MSFNotificationState {
actionButtonAction: (() -> Void)? = nil,
showDefaultDismissActionButton: Bool? = nil,
messageButtonAction: (() -> Void)? = nil,
showFromBottom: Bool = true) {
showFromBottom: Bool = true,
verticalOffset: CGFloat) {
self.style = style
self.message = message
self.attributedMessage = attributedMessage
Expand All @@ -459,6 +465,7 @@ class MSFNotificationStateImpl: ControlState, MSFNotificationState {
self.messageButtonAction = messageButtonAction
self.showFromBottom = showFromBottom
self.showDefaultDismissActionButton = showDefaultDismissActionButton ?? style.isToast
self.verticalOffset = verticalOffset

super.init()
}
Expand Down
Loading