Files
letro-ios/compound-ios/Sources/Compound/Buttons/SendButton.swift
Aaron Thornburgh b4d6fe43c3 Update Send button bg color (#5170)
* Update Send button bg color

Change the gradient bg to accent/rest.

* Tidy-up ComposerToolbar to match iOS 18 Figma.

Also simplifies the tests a bit.

* Add a .glassEffect to Compound's SendButton.

* Add a border to TimelineReplyView.

Also use the same sizes in both the message bubbles and the composer.

* Change icon size and container in message bubbles

- Container size = 36x36px
- Icon size = 24x24px

* Update icon of reply contents to be 24x24

* Update the VoiceMessageButton to match the designs.

* Adopt Liquid Glass in the ComposerToolbar.

* Generate and fix snapshots.

---------

Co-authored-by: Doug <douglase@element.io>
2026-03-25 17:42:10 +00:00

96 lines
2.8 KiB
Swift

//
// Copyright 2024 New Vector Ltd
//
// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
// Please see LICENSE files in the repository root for full details.
//
import SwiftUI
/// The button component for sending messages and media.
///
/// The button's size is 44pt x 44pt on iOS 26 and later, and 36pt x 36pt on iOS 18 and earlier.
public struct SendButton: View {
@Environment(\.isEnabled) private var isEnabled
@Environment(\.colorScheme) private var colorScheme
public enum Mode { case send, edit }
/// Whether the button is for sending a new message or editing an existing one.
private let mode: Mode
/// The action to perform when the user triggers the button.
private let action: () -> Void
private var icon: KeyPath<CompoundIcons, Image> {
switch mode {
case .send: \.sendSolid
case .edit: \.check
}
}
private var iconColor: Color {
guard isEnabled else { return .compound.iconQuaternary }
return colorScheme == .light ? .compound.iconOnSolidPrimary : .compound.iconPrimary
}
private var backgroundColor: Color {
isEnabled ? .compound.bgAccentRest : .clear
}
/// Creates a send button that performs the provided action.
public init(mode: Mode = .send, action: @escaping () -> Void) {
self.mode = mode
self.action = action
}
public var body: some View {
Button(action: action) {
label
.compositingGroup()
}
}
@ViewBuilder
public var label: some View {
if #available(iOS 26, *), isEnabled, !ProcessInfo.processInfo.isRunningTests {
baseIcon
.glassEffect(.regular.tint(backgroundColor).interactive(), in: .circle)
} else {
baseIcon
.background(backgroundColor, in: .circle)
}
}
var baseIcon: some View {
CompoundIcon(icon, size: .medium, relativeTo: .compound.headingLG)
.foregroundStyle(iconColor)
.scaledPadding(Compound.supportsGlass ? 10 : 6, relativeTo: .compound.headingLG)
}
}
// MARK: - Previews
public struct SendButton_Previews: PreviewProvider, TestablePreview {
public static var previews: some View {
VStack(spacing: 0) {
states
.padding(20)
.background(.compound.bgCanvasDefault)
states
.padding(20)
.background(.compound.bgCanvasDefault)
.environment(\.colorScheme, .dark)
}
.cornerRadius(20)
}
public static var states: some View {
HStack(spacing: 30) {
SendButton { }
.disabled(true)
SendButton { }
SendButton(mode: .edit) { }
}
}
}