-
Notifications
You must be signed in to change notification settings - Fork 168
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* ListItem initial MVP (#1845) Setup new control for ListItem that is a SwiftUI version of MSFTableViewCell * List Item Demo Setup (#1853) Setup demo app to show List Item. * [ListItem] Add support for leading content size in tokens (#1855) * support custom view size * fix list item modifiers to not use an @ObservedObject * rename file * XCTests for ListItem (#1858) * update test app to have controls to change swiftui view * setup all XCTests * MVP of List Action Item (#1857) * add List Action Item * ListActionItem XCTests and demo (#1861) * add demo and XC tests for listactionitem * [ListItem] Support VoiceOver (#1864) * support VoiceOver * add modifier for handling accessibility element of trailing content * [ListItem] fix spacing and provide background color API (#1876) * [ListItem] fix horizontal spacing * Add static func for getting the list background color
- Loading branch information
1 parent
2fad550
commit c2a053a
Showing
14 changed files
with
1,463 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
88 changes: 88 additions & 0 deletions
88
ios/FluentUI.Demo/FluentUI.Demo/Demos/ListActionItemDemoController.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
// | ||
// Copyright (c) Microsoft Corporation. All rights reserved. | ||
// Licensed under the MIT License. | ||
// | ||
|
||
import FluentUI | ||
import UIKit | ||
|
||
class ListActionItemDemoController: DemoController { | ||
|
||
override func viewDidLoad() { | ||
super.viewDidLoad() | ||
let hostingController = ListActionItemDemoControllerSwiftUI() | ||
self.hostingController = hostingController | ||
addChild(hostingController) | ||
view.addSubview(hostingController.view) | ||
hostingController.didMove(toParent: self) | ||
hostingController.view.translatesAutoresizingMaskIntoConstraints = false | ||
NSLayoutConstraint.activate([hostingController.view.topAnchor.constraint(equalTo: view.topAnchor), | ||
hostingController.view.bottomAnchor.constraint(equalTo: view.bottomAnchor), | ||
hostingController.view.leadingAnchor.constraint(equalTo: view.leadingAnchor), | ||
hostingController.view.trailingAnchor.constraint(equalTo: view.trailingAnchor)]) | ||
|
||
readmeString = "A list item displays a action in list.\n\nUse for displaying full width actions in a list." | ||
} | ||
|
||
override func didMove(toParent parent: UIViewController?) { | ||
guard let parent, | ||
let window = parent.view.window, | ||
let hostingController else { | ||
return | ||
} | ||
|
||
hostingController.rootView.fluentTheme = window.fluentTheme | ||
} | ||
|
||
var hostingController: ListActionItemDemoControllerSwiftUI? | ||
} | ||
|
||
extension ListActionItemDemoController: DemoAppearanceDelegate { | ||
func themeWideOverrideDidChange(isOverrideEnabled: Bool) { | ||
guard let fluentTheme = self.view.window?.fluentTheme else { | ||
return | ||
} | ||
|
||
fluentTheme.register(tokenSetType: ListItemTokenSet.self, | ||
tokenSet: isOverrideEnabled ? themeWideOverrideListItemTokens : nil) | ||
} | ||
|
||
func perControlOverrideDidChange(isOverrideEnabled: Bool) { | ||
guard let fluentTheme = self.view.window?.fluentTheme else { | ||
return | ||
} | ||
|
||
fluentTheme.register(tokenSetType: ListItemTokenSet.self, | ||
tokenSet: isOverrideEnabled ? perControlOverrideListItemTokens : nil) | ||
} | ||
|
||
func isThemeWideOverrideApplied() -> Bool { | ||
return self.view.window?.fluentTheme.tokens(for: ListItemTokenSet.self) != nil | ||
} | ||
|
||
// MARK: - Custom tokens | ||
private var themeWideOverrideListItemTokens: [ListItemTokenSet.Tokens: ControlTokenValue] { | ||
return [ | ||
.cellBackgroundGroupedColor: .uiColor { | ||
// "Berry" | ||
return UIColor(light: GlobalTokens.sharedColor(.berry, .tint50), | ||
dark: GlobalTokens.sharedColor(.berry, .shade40)) | ||
} | ||
] | ||
} | ||
|
||
private var perControlOverrideListItemTokens: [ListItemTokenSet.Tokens: ControlTokenValue] { | ||
return [ | ||
.cellBackgroundGroupedColor: .uiColor { | ||
// "Brass" | ||
return UIColor(light: GlobalTokens.sharedColor(.brass, .tint50), | ||
dark: GlobalTokens.sharedColor(.brass, .shade40)) | ||
}, | ||
.communicationTextColor: .uiColor { | ||
// "Forest" | ||
return UIColor(light: GlobalTokens.sharedColor(.forest, .tint10), | ||
dark: GlobalTokens.sharedColor(.forest, .shade40)) | ||
} | ||
] | ||
} | ||
} |
137 changes: 137 additions & 0 deletions
137
ios/FluentUI.Demo/FluentUI.Demo/Demos/ListActionItemDemoController_SwiftUI.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,137 @@ | ||
// | ||
// Copyright (c) Microsoft Corporation. All rights reserved. | ||
// Licensed under the MIT License. | ||
// | ||
|
||
import FluentUI | ||
import SwiftUI | ||
|
||
class ListActionItemDemoControllerSwiftUI: UIHostingController<ListActionItemDemoView> { | ||
override init?(coder aDecoder: NSCoder, rootView: ListActionItemDemoView) { | ||
preconditionFailure("init(coder:) has not been implemented") | ||
} | ||
|
||
@objc required dynamic init?(coder aDecoder: NSCoder) { | ||
preconditionFailure("init(coder:) has not been implemented") | ||
} | ||
|
||
init() { | ||
super.init(rootView: ListActionItemDemoView()) | ||
} | ||
} | ||
|
||
struct ListActionItemDemoView: View { | ||
@State var showingAlert: Bool = false | ||
@ObservedObject var fluentTheme: FluentTheme = .shared | ||
@State var showSecondaryAction: Bool = false | ||
@State var primaryActionTitle: String = "Search" | ||
@State var secondaryActionTitle: String = "Cancel" | ||
@State var primaryActionType: ListActionItemActionType = .regular | ||
@State var secondaryActionType: ListActionItemActionType = .destructive | ||
@State var topSeparatorType: ListActionItemSeparatorType = .none | ||
@State var bottomSeparatorType: ListActionItemSeparatorType = .inset | ||
@State var backgroundStyleType: ListItemBackgroundStyleType = .grouped | ||
|
||
public var body: some View { | ||
|
||
@ViewBuilder | ||
var textFields: some View { | ||
TextField("Primary Action Title", text: $primaryActionTitle) | ||
.autocapitalization(.none) | ||
.disableAutocorrection(true) | ||
.textFieldStyle(.roundedBorder) | ||
.accessibilityIdentifier("primaryActionTitleTextField") | ||
if showSecondaryAction { | ||
TextField("Secondary Action Title", text: $secondaryActionTitle) | ||
.autocapitalization(.none) | ||
.disableAutocorrection(true) | ||
.textFieldStyle(.roundedBorder) | ||
.accessibilityIdentifier("secondaryActionTitleTextField") | ||
} | ||
} | ||
|
||
@ViewBuilder | ||
var pickers: some View { | ||
let actionTypePickerOptions = Group { | ||
Text(".regular").tag(ListActionItemActionType.regular) | ||
Text(".destructive").tag(ListActionItemActionType.destructive) | ||
Text(".communication").tag(ListActionItemActionType.communication) | ||
} | ||
|
||
Picker("Primary Action Type", selection: $primaryActionType) { | ||
actionTypePickerOptions | ||
} | ||
if showSecondaryAction { | ||
Picker("Secondary Action Type", selection: $secondaryActionType) { | ||
actionTypePickerOptions | ||
} | ||
} | ||
|
||
let separatorTypePickerOptions = Group { | ||
Text(".none").tag(ListActionItemSeparatorType.none) | ||
Text(".inset").tag(ListActionItemSeparatorType.inset) | ||
Text(".full").tag(ListActionItemSeparatorType.full) | ||
} | ||
|
||
Picker("Top Separator Type", selection: $topSeparatorType) { | ||
separatorTypePickerOptions | ||
} | ||
|
||
Picker("Bottom Separator Type", selection: $bottomSeparatorType) { | ||
separatorTypePickerOptions | ||
} | ||
} | ||
|
||
@ViewBuilder | ||
var content: some View { | ||
List { | ||
Section { | ||
if showSecondaryAction { | ||
ListActionItem(primaryActionTitle: primaryActionTitle, | ||
onPrimaryActionTapped: { | ||
showingAlert.toggle() | ||
}, | ||
primaryActionType: primaryActionType, | ||
secondaryActionTitle: secondaryActionTitle, | ||
onSecondaryActionTapped: { | ||
showingAlert.toggle() | ||
}, | ||
secondaryActionType: secondaryActionType) | ||
.topSeparatorType(topSeparatorType) | ||
.bottomSeparatorType(bottomSeparatorType) | ||
.backgroundStyleType(backgroundStyleType) | ||
} else { | ||
ListActionItem(title: primaryActionTitle, | ||
onTapped: { | ||
showingAlert.toggle() | ||
}, | ||
actionType: primaryActionType) | ||
.topSeparatorType(topSeparatorType) | ||
.bottomSeparatorType(bottomSeparatorType) | ||
.backgroundStyleType(backgroundStyleType) | ||
} | ||
|
||
} header: { | ||
Text("ListActionItem") | ||
} | ||
.alert("Action tapped", isPresented: $showingAlert) { | ||
Button("OK", role: .cancel) { } | ||
.accessibilityIdentifier("DismissAlertButton") | ||
} | ||
|
||
Section { | ||
FluentUIDemoToggle(titleKey: "Show secondary action", isOn: $showSecondaryAction) | ||
.accessibilityIdentifier("showSecondaryActionSwitch") | ||
textFields | ||
pickers | ||
} header: { | ||
Text("Settings") | ||
} | ||
} | ||
.fluentTheme(fluentTheme) | ||
.listStyle(.insetGrouped) | ||
} | ||
|
||
return content | ||
} | ||
} |
Oops, something went wrong.