Skip to content

Commit

Permalink
Bring fluent2-tokens Segmented Control to main (#1363)
Browse files Browse the repository at this point in the history
* Bring in fluent2-token control

* Add token set to project

* Update dependent controls

* Add colored background for demo

* Update demos

* Update demo order

* Fix whitespace error
  • Loading branch information
huwilkes committed Nov 16, 2022
1 parent e0b09a5 commit 42700d7
Show file tree
Hide file tree
Showing 13 changed files with 779 additions and 366 deletions.
4 changes: 4 additions & 0 deletions ios/FluentUI.Demo/FluentUI.Demo.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@
E6842996247C350700A29C40 /* DemoColorThemes.swift in Sources */ = {isa = PBXBuildFile; fileRef = E6842995247C350700A29C40 /* DemoColorThemes.swift */; };
EC24DBC628B97EB70026EF92 /* PopupMenuObjCDemoController.m in Sources */ = {isa = PBXBuildFile; fileRef = EC24DBC528B97EB70026EF92 /* PopupMenuObjCDemoController.m */; };
EC02A5F9274EED9200E81B3E /* DividerDemoController_SwiftUI.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC02A5F8274EED9200E81B3E /* DividerDemoController_SwiftUI.swift */; };
EC1C31752923032000CF052C /* ColoredPillBackgroundView.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC1C31742923032000CF052C /* ColoredPillBackgroundView.swift */; };
EC6A71EC273DE6DF0076A586 /* DividerDemoController.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC6A71EB273DE6DF0076A586 /* DividerDemoController.swift */; };
FC414E3725888BC300069E73 /* CommandBarDemoController.swift in Sources */ = {isa = PBXBuildFile; fileRef = FC414E3625888BC300069E73 /* CommandBarDemoController.swift */; };
FDCF7C8321BF35680058E9E6 /* SegmentedControlDemoController.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDCF7C8221BF35680058E9E6 /* SegmentedControlDemoController.swift */; };
Expand Down Expand Up @@ -142,6 +143,7 @@
CCC18C2E2501C75F00BE830E /* CardViewDemoController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CardViewDemoController.swift; sourceTree = "<group>"; };
E6842973247B672000A29C40 /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = "<group>"; };
E6842995247C350700A29C40 /* DemoColorThemes.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DemoColorThemes.swift; sourceTree = "<group>"; };
EC1C31742923032000CF052C /* ColoredPillBackgroundView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ColoredPillBackgroundView.swift; sourceTree = "<group>"; };
EC24DBC428B97E950026EF92 /* PopupMenuObjCDemoController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PopupMenuObjCDemoController.h; sourceTree = "<group>"; };
EC24DBC528B97EB70026EF92 /* PopupMenuObjCDemoController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = PopupMenuObjCDemoController.m; sourceTree = "<group>"; };
EC02A5F8274EED9200E81B3E /* DividerDemoController_SwiftUI.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DividerDemoController_SwiftUI.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -372,6 +374,7 @@
B4414793228F6FDF0040E88E /* OtherCellsSampleData.swift */,
B4EF66552295F729007FEAB0 /* TableViewHeaderFooterSampleData.swift */,
B4C39551227A4AC800539EC2 /* TableViewSampleData.swift */,
EC1C31742923032000CF052C /* ColoredPillBackgroundView.swift */,
);
name = Utilities;
sourceTree = "<group>";
Expand Down Expand Up @@ -542,6 +545,7 @@
92DD1E8D279F496300FDEE0F /* DemoAppearanceView.swift in Sources */,
53097D4027028AE500A6E4DC /* PersonaButtonCarouselDemoController.swift in Sources */,
C0938E4A235F733100256251 /* ShimmerLinesViewDemoController.swift in Sources */,
EC1C31752923032000CF052C /* ColoredPillBackgroundView.swift in Sources */,
80AECC0C2630F1BB005AF2F3 /* BottomCommandingDemoController.swift in Sources */,
C038992E2359307D00265026 /* TableViewCellShimmerDemoController.swift in Sources */,
53097D3D27028AD800A6E4DC /* NavigationControllerDemoController.swift in Sources */,
Expand Down
65 changes: 65 additions & 0 deletions ios/FluentUI.Demo/FluentUI.Demo/ColoredPillBackgroundView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
//
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
//

import FluentUI
import UIKit

enum ColoredPillBackgroundStyle: Int {
case neutral
case brand
}

class ColoredPillBackgroundView: UIView {
init(style: ColoredPillBackgroundStyle) {
self.style = style
super.init(frame: .zero)
updateBackgroundColor()

NotificationCenter.default.addObserver(self,
selector: #selector(themeDidChange),
name: .didChangeTheme,
object: nil)
}

required init?(coder: NSCoder) {
preconditionFailure("init(coder:) has not been implemented")
}

override func didMoveToWindow() {
super.didMoveToWindow()
updateBackgroundColor()
}

@objc func themeDidChange() {
updateBackgroundColor()
}

func updateBackgroundColor() {
let lightColor: UIColor
let darkColor: UIColor
switch style {
case .neutral:
if let fluentTheme = window?.fluentTheme {
lightColor = UIColor(dynamicColor: fluentTheme.aliasTokens.backgroundColors[.neutral1])
darkColor = UIColor(dynamicColor: fluentTheme.aliasTokens.backgroundColors[.neutral4])
} else {
lightColor = Colors.navigationBarBackground
darkColor = Colors.navigationBarBackground
}
case .brand:
if let fluentTheme = window?.fluentTheme {
lightColor = UIColor(dynamicColor: fluentTheme.aliasTokens.backgroundColors[.brandRest])
darkColor = UIColor(dynamicColor: fluentTheme.aliasTokens.backgroundColors[.neutral4])
} else {
lightColor = Colors.communicationBlue
darkColor = Colors.navigationBarBackground
}
}

backgroundColor = UIColor(light: lightColor, dark: darkColor)
}

let style: ColoredPillBackgroundStyle
}
2 changes: 1 addition & 1 deletion ios/FluentUI.Demo/FluentUI.Demo/Demos.swift
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ struct Demos {
DemoDescriptor("NotificationView", NotificationViewDemoController.self),
DemoDescriptor("Other cells", OtherCellsDemoController.self),
DemoDescriptor("PersonaButtonCarousel", PersonaButtonCarouselDemoController.self),
DemoDescriptor("SegmentedControl", SegmentedControlDemoController.self),
DemoDescriptor("ShimmerView", ShimmerViewDemoController.self),
DemoDescriptor("TableViewCell", TableViewCellDemoController.self),
DemoDescriptor("TypographyTokens", TypographyTokensDemoController.self)
Expand All @@ -54,7 +55,6 @@ struct Demos {
DemoDescriptor("PillButtonBar", PillButtonBarDemoController.self),
DemoDescriptor("PopupMenuController", PopupMenuDemoController.self),
DemoDescriptor("SearchBar", SearchBarDemoController.self),
DemoDescriptor("SegmentedControl", SegmentedControlDemoController.self),
DemoDescriptor("SideTabBar", SideTabBarDemoController.self),
DemoDescriptor("TabBarView", TabBarViewDemoController.self),
DemoDescriptor("TableViewCellFileAccessoryView", TableViewCellFileAccessoryViewDemoController.self),
Expand Down
20 changes: 10 additions & 10 deletions ios/FluentUI.Demo/FluentUI.Demo/Demos/ColorDemoController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -147,17 +147,17 @@ class ColorDemoController: UIViewController {

private lazy var segmentedControl: SegmentedControl = {
let segmentedControl = SegmentedControl(items: DemoColorTheme.allCases.map({ return SegmentItem(title: $0.name) }), style: .primaryPill)
segmentedControl.addTarget(self, action: #selector(segmentedControlValueChanged(sender:)), for: .valueChanged)
return segmentedControl
}()

@objc private func segmentedControlValueChanged(sender: Any) {
if let segmentedControl = sender as? SegmentedControl, let window = self.view.window {
if let currentDemoListViewController = currentDemoListViewController {
currentDemoListViewController.updateColorProviderFor(window: window, theme: DemoColorTheme.allCases[segmentedControl.selectedSegmentIndex])
segmentedControl.onSelectAction = { [weak self] (_, index) in
guard let strongSelf = self,
let window = strongSelf.view.window,
let currentDemoListViewController = strongSelf.currentDemoListViewController else {
return
}

currentDemoListViewController.updateColorProviderFor(window: window, theme: DemoColorTheme.allCases[index])
}
}
return segmentedControl
}()

@objc private func didChangeTheme() {
// The controls in this controller are not fully theme-aware yet, so
Expand All @@ -167,7 +167,7 @@ class ColorDemoController: UIViewController {
colorView.updateBackgroundColor()
}
}
segmentedControl.updateWindowSpecificColors()
segmentedControl.updateColors()
}

private let tableView = UITableView(frame: .zero, style: .grouped)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,11 +99,16 @@ class PillButtonBarDemoController: DemoController {
items.forEach { bar.disableItem($0) }
}

let backgroundView = UIView()
if style == .primary {
backgroundView.backgroundColor = Colors.navigationBarBackground
}
let backgroundStyle: ColoredPillBackgroundStyle = {
switch style {
case .primary:
return .neutral
case .onBrand:
return .brand
}
}()

let backgroundView = ColoredPillBackgroundView(style: backgroundStyle)
backgroundView.addSubview(bar)
let margins = UIEdgeInsets(top: 16.0, left: 0, bottom: 16.0, right: 0.0)
fitViewIntoSuperview(bar, margins: margins)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,13 @@ class SegmentedControlDemoController: DemoController {
SegmentItem(title: "First"),
SegmentItem(title: "Second", image: UIImage(named: "Placeholder_20")),
SegmentItem(title: "Third", isUnread: true),
SegmentItem(title: "Fourth")
SegmentItem(title: "Fourth"),
SegmentItem(title: "Fifth"),
SegmentItem(title: "Sixth"),
SegmentItem(title: "Seventh"),
SegmentItem(title: "Eigth"),
SegmentItem(title: "Ninth"),
SegmentItem(title: "Tenth")
]

var controlLabels = [SegmentedControl: Label]() {
Expand All @@ -28,67 +34,153 @@ class SegmentedControlDemoController: DemoController {
container.layoutMargins.right = 0

addTitle(text: "Primary Pill")

addPillControl(items: Array(segmentItems.prefix(3)), style: .primaryPill)
addDescription(text: "fixed width, equal buttons", textAlignment: .center)
addPillControl(items: Array(segmentItems.prefix(3)),
style: .primaryPill)
container.addArrangedSubview(UIView())

addTitle(text: "Primary Pill with unequal buttons")
addTitle(text: "Primary Pill")
addDescription(text: "not fixed width, unequal buttons", textAlignment: .center)
addPillControl(items: Array(segmentItems.prefix(10)),
style: .primaryPill,
equalSegments: false,
isFixedWidth: false)
container.addArrangedSubview(UIView())

addPillControl(items: Array(segmentItems.prefix(2)), style: .primaryPill, equalSegments: false)
addTitle(text: "Primary Pill")
addDescription(text: "not fixed width, unequal buttons", textAlignment: .center)
addPillControl(items: Array(segmentItems.prefix(2)),
style: .primaryPill,
equalSegments: false,
isFixedWidth: false)
container.addArrangedSubview(UIView())

addTitle(text: "Disabled Primary Pill")

addPillControl(items: Array(segmentItems.prefix(2)), style: .primaryPill, enabled: false)
addDescription(text: "fixed width, equal buttons", textAlignment: .center)
addPillControl(items: Array(segmentItems.prefix(2)),
style: .primaryPill,
enabled: false)
container.addArrangedSubview(UIView())

addTitle(text: "On Brand Pill")

addPillControl(items: Array(segmentItems.prefix(4)), style: .onBrandPill)
addDescription(text: "not fixed width, equal buttons", textAlignment: .center)
addPillControl(items: Array(segmentItems.prefix(10)),
style: .onBrandPill,
equalSegments: true,
isFixedWidth: false)
container.addArrangedSubview(UIView())

addTitle(text: "On Brand Pill with unequal buttons")

addPillControl(items: Array(segmentItems.prefix(2)), style: .onBrandPill, equalSegments: false)
addTitle(text: "On Brand Pill")
addDescription(text: "not fixed width, equal buttons", textAlignment: .center)
addPillControl(items: Array(segmentItems.prefix(2)),
style: .onBrandPill,
isFixedWidth: false)
container.addArrangedSubview(UIView())

addTitle(text: "Disabled On Brand Pill")

addPillControl(items: Array(segmentItems.prefix(2)), style: .onBrandPill, enabled: false)
addDescription(text: "fixed width, equal buttons", textAlignment: .center)
addPillControl(items: Array(segmentItems.prefix(2)),
style: .onBrandPill,
enabled: false)
}

@objc func updateLabel(forControl control: SegmentedControl) {
controlLabels[control]?.text = "\"\(segmentItems[control.selectedSegmentIndex].title)\" segment is selected"
}

func addPillControl(items: [SegmentItem], style: SegmentedControl.Style, equalSegments: Bool = true, enabled: Bool = true) {
func addPillControl(items: [SegmentItem], style: SegmentedControlStyle, equalSegments: Bool = true, enabled: Bool = true, isFixedWidth: Bool = true) {
let pillControl = SegmentedControl(items: items, style: style)
pillControl.shouldSetEqualWidthForSegments = equalSegments
pillControl.isFixedWidth = isFixedWidth
pillControl.isEnabled = enabled
pillControl.addTarget(self, action: #selector(updateLabel(forControl:)), for: .valueChanged)
pillControl.onSelectAction = { [weak self] (_, _) in
guard let strongSelf = self else {
return
}

let backgroundView = UIView()
if style == .primaryPill {
backgroundView.backgroundColor = Colors.navigationBarBackground
} else {
backgroundView.backgroundColor = UIColor(light: Colors.communicationBlue, dark: Colors.navigationBarBackground)
strongSelf.updateLabel(forControl: pillControl)
}

let backgroundStyle: ColoredPillBackgroundStyle = {
switch style {
case .primaryPill:
return .neutral
case .onBrandPill:
return .brand
}
}()
let backgroundView = ColoredPillBackgroundView(style: backgroundStyle)
segmentedControls.append(pillControl)

backgroundView.translatesAutoresizingMaskIntoConstraints = false
pillControl.translatesAutoresizingMaskIntoConstraints = false
backgroundView.addSubview(pillControl)
container.addArrangedSubview(backgroundView)
let margins = UIEdgeInsets(top: 16.0, left: 0, bottom: 16.0, right: 0)
var constraints = [backgroundView.topAnchor.constraint(equalTo: pillControl.topAnchor, constant: -margins.top),
backgroundView.bottomAnchor.constraint(equalTo: pillControl.bottomAnchor, constant: margins.bottom)]
var constraints = [backgroundView.topAnchor.constraint(equalTo: pillControl.topAnchor,
constant: -margins.top),
backgroundView.bottomAnchor.constraint(equalTo: pillControl.bottomAnchor,
constant: margins.bottom)]
if equalSegments {
constraints.append(pillControl.centerXAnchor.constraint(equalTo: backgroundView.centerXAnchor))
}
if isFixedWidth {
constraints.append(contentsOf: [
backgroundView.leadingAnchor.constraint(lessThanOrEqualTo: pillControl.leadingAnchor),
backgroundView.trailingAnchor.constraint(greaterThanOrEqualTo: pillControl.trailingAnchor)
])
} else {
constraints.append(contentsOf: [
backgroundView.leadingAnchor.constraint(equalTo: pillControl.leadingAnchor),
backgroundView.trailingAnchor.constraint(equalTo: pillControl.trailingAnchor)
])
}

NSLayoutConstraint.activate(constraints)

if enabled {
controlLabels[pillControl] = addDescription(text: "", textAlignment: .center)
}
}

private var segmentedControls: [SegmentedControl] = []
}

extension SegmentedControlDemoController: DemoAppearanceDelegate {
func themeWideOverrideDidChange(isOverrideEnabled: Bool) {
guard let fluentTheme = self.view.window?.fluentTheme else {
return
}

fluentTheme.register(tokenSetType: SegmentedControlTokenSet.self,
tokenSet: isOverrideEnabled ? themeWideOverrideSegmentedControlTokens : nil)
}

func perControlOverrideDidChange(isOverrideEnabled: Bool) {
self.segmentedControls.forEach({ segmentedControl in
segmentedControl.tokenSet.replaceAllOverrides(with: isOverrideEnabled ? perControlOverrideSegmentedControlTokens : nil)
})
}

func isThemeWideOverrideApplied() -> Bool {
return self.view.window?.fluentTheme.tokens(for: SegmentedControlTokenSet.self) != nil
}

// MARK: - Custom tokens

private var themeWideOverrideSegmentedControlTokens: [SegmentedControlTokenSet.Tokens: ControlTokenValue] {
return [
.font: .fontInfo {
return FontInfo(name: "Times", size: 20.0, weight: .regular)
}
]
}

private var perControlOverrideSegmentedControlTokens: [SegmentedControlTokenSet.Tokens: ControlTokenValue] {
return [
.font: .fontInfo {
return FontInfo(name: "Papyrus", size: 10.0, weight: .regular)
}
]
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,15 @@ class TableViewHeaderFooterViewDemoController: DemoController {
private let divider = MSFDivider()

private lazy var segmentedControl: SegmentedControl = {
let tabTitles = TableViewHeaderFooterSampleData.tabTitles
let segmentedControl = SegmentedControl(items: tabTitles.map({ return SegmentItem(title: $0) }),
style: .primaryPill)
segmentedControl.addTarget(self,
action: #selector(updateActiveTabContent),
for: .valueChanged)
let segmentedControl = SegmentedControl(items: TableViewHeaderFooterSampleData.tabTitles.map({return SegmentItem(title: $0)}), style: .primaryPill)
segmentedControl.onSelectAction = { [weak self] (_, _) in
guard let strongSelf = self else {
return
}

strongSelf.updateActiveTabContent()
}

return segmentedControl
}()
private lazy var groupedTableView: UITableView = createTableView(style: .grouped)
Expand Down
Loading

0 comments on commit 42700d7

Please sign in to comment.