diff --git a/CharcoalSwiftUISample/Sources/CharcoalSwiftUISample/ContentView.swift b/CharcoalSwiftUISample/Sources/CharcoalSwiftUISample/ContentView.swift index 6b656fe99..2c7c45bf4 100644 --- a/CharcoalSwiftUISample/Sources/CharcoalSwiftUISample/ContentView.swift +++ b/CharcoalSwiftUISample/Sources/CharcoalSwiftUISample/ContentView.swift @@ -49,6 +49,9 @@ public struct ContentView: View { NavigationLink(destination: ToastsView().charcoalOverlayContainer()) { Text("Toasts") } + NavigationLink(destination: HintsView()) { + Text("Hints") + } NavigationLink(destination: SpinnersView()) { Text("Spinners") } diff --git a/CharcoalSwiftUISample/Sources/CharcoalSwiftUISample/HintsView.swift b/CharcoalSwiftUISample/Sources/CharcoalSwiftUISample/HintsView.swift new file mode 100644 index 000000000..fcbd4545a --- /dev/null +++ b/CharcoalSwiftUISample/Sources/CharcoalSwiftUISample/HintsView.swift @@ -0,0 +1,31 @@ +import Charcoal +import SwiftUI + +public struct HintsView: View { + @State var isPresented = true + + @State var isPresented2 = true + + @State var isPresented3 = true + + public var body: some View { + ScrollView { + VStack { + CharcoalHint(text: "ヒントテキストヒントテキスト", isPresenting: $isPresented, action: CharcoalAction(title: "Button") { + isPresented = false + }) + + CharcoalHint(text: "ヒントテキストヒントテキスト", isPresenting: $isPresented2) + + CharcoalHint(text: "ヒントテキストヒントテキスト", maxWidth: .infinity, isPresenting: $isPresented3) + } + .padding() + } + .navigationBarTitle("Hints") + } +} + +@available(iOS 17, *) +#Preview { + HintsView() +} diff --git a/CharcoalUIKitSample/Sources/CharcoalUIKitSample/Views/Balloons/Balloons.swift b/CharcoalUIKitSample/Sources/CharcoalUIKitSample/Views/Balloons/Balloons.swift index 66a1ee16c..2d4a190b6 100644 --- a/CharcoalUIKitSample/Sources/CharcoalUIKitSample/Views/Balloons/Balloons.swift +++ b/CharcoalUIKitSample/Sources/CharcoalUIKitSample/Views/Balloons/Balloons.swift @@ -125,11 +125,11 @@ extension BalloonsViewController: UITableViewDelegate, UITableViewDataSource { case .leading: // use on: self.view to stick the balloon to the view // so balloons will dismiss with the view - CharcoalBalloon.show(text: titleCase.text, anchorView: cell.leadingImageView, on: self.view) + CharcoalBalloon.show(text: titleCase.text, anchorView: cell.leadingImageView, on: view) case .trailing: - CharcoalBalloon.show(text: titleCase.text, anchorView: cell.accessoryImageView, on: self.view) + CharcoalBalloon.show(text: titleCase.text, anchorView: cell.accessoryImageView, on: view) case .bottom: - CharcoalBalloon.show(text: titleCase.text, anchorView: bottomInfoImage, on: self.view) + CharcoalBalloon.show(text: titleCase.text, anchorView: bottomInfoImage, on: view) } } diff --git a/Sources/CharcoalUIKit/Components/Toast/CharcoalAction.swift b/Sources/CharcoalShared/CharcoalAction.swift similarity index 75% rename from Sources/CharcoalUIKit/Components/Toast/CharcoalAction.swift rename to Sources/CharcoalShared/CharcoalAction.swift index 89383f5bc..4e8e31b93 100644 --- a/Sources/CharcoalUIKit/Components/Toast/CharcoalAction.swift +++ b/Sources/CharcoalShared/CharcoalAction.swift @@ -1,8 +1,8 @@ public typealias ActionCallback = () -> Void public struct CharcoalAction { - let title: String - let actionCallback: ActionCallback + public let title: String + public let actionCallback: ActionCallback public init(title: String, actionCallback: @escaping ActionCallback) { self.title = title diff --git a/Sources/CharcoalShared/Extensions/CGSize+Extension.swift b/Sources/CharcoalShared/Extensions/CGSize+Extension.swift deleted file mode 100644 index 911fe3390..000000000 --- a/Sources/CharcoalShared/Extensions/CGSize+Extension.swift +++ /dev/null @@ -1,7 +0,0 @@ -import Foundation - -public extension CGSize { - var area: CGFloat { - return width * height - } -} diff --git a/Sources/CharcoalSwiftUI/Components/Hint/CharcoalHint.swift b/Sources/CharcoalSwiftUI/Components/Hint/CharcoalHint.swift new file mode 100644 index 000000000..bb376c9e5 --- /dev/null +++ b/Sources/CharcoalSwiftUI/Components/Hint/CharcoalHint.swift @@ -0,0 +1,86 @@ +import SwiftUI + +public struct CharcoalHint: View { + /// The text of the tooltip + let text: String + + /// The text of the tooltip + let subtitle: String? + + let icon: CharcoalAsset.Images = .info16 + + /// The corner radius of the tooltip + let cornerRadius: CGFloat = 8 + + let maxWidth: CGFloat? + + /// A binding to whether the overlay is presented. + @Binding var isPresenting: Bool + + let action: CharcoalAction? + + @State var timer: Timer? + + public init( + text: String, + subtitle: String? = nil, + maxWidth: CGFloat? = nil, + isPresenting: Binding, + action: CharcoalAction? = nil + ) { + self.text = text + self.subtitle = subtitle + self.maxWidth = maxWidth + _isPresenting = isPresenting + self.action = action + } + + public var body: some View { + if isPresenting { + HStack(spacing: 4) { + Image(charocalIcon: icon) + + VStack { + Text(text).charcoalTypography14Regular() + if let subtitle = subtitle { + Text(subtitle).charcoalTypography14Regular() + } + } + + if let action = action { + Spacer() + Button(action: { + action.actionCallback() + }) { + Text(action.title) + } + .charcoalPrimaryButton(size: .small) + } + } + .frame(maxWidth: maxWidth) + .padding(EdgeInsets(top: 12, leading: 16, bottom: 12, trailing: 16)) + .background(charcoalColor: .surface3) + .cornerRadius(cornerRadius, corners: .allCorners) + } + } +} + +@available(iOS 17, *) +#Preview { + @Previewable @State var isPresenting = true + @Previewable @State var isPresenting2 = true + @Previewable @State var isPresenting3 = true + + @Previewable @State var textOfLabel = "Hello" + + VStack { + CharcoalHint(text: "ヒントテキストヒントテキスト", isPresenting: $isPresenting, action: CharcoalAction(title: "Button", actionCallback: { + isPresenting = false + })) + + CharcoalHint(text: "ヒントテキストヒントテキスト", isPresenting: $isPresenting2) + + CharcoalHint(text: "ヒントテキストヒントテキスト", maxWidth: .infinity, isPresenting: $isPresenting3) + + }.padding() +} diff --git a/Sources/CharcoalSwiftUI/Extensions/Rect+Extension.swift b/Sources/CharcoalSwiftUI/Extensions/Rect+Extension.swift index 58e414d40..c1314f362 100644 --- a/Sources/CharcoalSwiftUI/Extensions/Rect+Extension.swift +++ b/Sources/CharcoalSwiftUI/Extensions/Rect+Extension.swift @@ -1,11 +1,10 @@ import Foundation - extension CGRect { // Calculate the intersection area of two rectangles func intersectionArea(_ rect: CGRect) -> CGFloat { - let rect = self.intersection(rect) - + let rect = intersection(rect) + return rect.width * rect.height } } diff --git a/Sources/CharcoalUIKit/Components/Balloon/CharcoalAnchorTrackingView.swift b/Sources/CharcoalUIKit/Components/Balloon/CharcoalAnchorTrackingView.swift index 6646e8578..bc49cafe4 100644 --- a/Sources/CharcoalUIKit/Components/Balloon/CharcoalAnchorTrackingView.swift +++ b/Sources/CharcoalUIKit/Components/Balloon/CharcoalAnchorTrackingView.swift @@ -28,7 +28,7 @@ class CharcoalAnchorTrackingView: UIView { displayLink?.invalidate() displayLink = nil } - + func tearDown() { invalidate() removeFromSuperview() diff --git a/Sources/CharcoalUIKit/Components/Balloon/CharcoalBalloon.swift b/Sources/CharcoalUIKit/Components/Balloon/CharcoalBalloon.swift index 39fdd80a2..69b51d2ca 100644 --- a/Sources/CharcoalUIKit/Components/Balloon/CharcoalBalloon.swift +++ b/Sources/CharcoalUIKit/Components/Balloon/CharcoalBalloon.swift @@ -4,23 +4,23 @@ public class CharcoalBalloon {} public extension CharcoalBalloon { /** - Show a balloon anchored to a view. - - - Parameters: - - text: The text to be displayed in the tooltip. - - anchorView: The view to which the tooltip will be anchored. - - interactionMode: The interaction mode of the tooltip. The default value is `.passThrough`. - - spacingToScreen: The spacing between the tooltip and the screen. The default value is `16`. - - gap: The spacing between the tooltip and the anchor view. The default value is `4`. - - on: The view on which the tooltip will be displayed. If not provided, the tooltip will be displayed on the window. - - - Returns: The identifier of the tooltip. - - # Example - ```swift - CharcoalTooltip.show(text: "This is a tooltip", anchorView: someView) - ``` - */ + Show a balloon anchored to a view. + + - Parameters: + - text: The text to be displayed in the tooltip. + - anchorView: The view to which the tooltip will be anchored. + - interactionMode: The interaction mode of the tooltip. The default value is `.passThrough`. + - spacingToScreen: The spacing between the tooltip and the screen. The default value is `16`. + - gap: The spacing between the tooltip and the anchor view. The default value is `4`. + - on: The view on which the tooltip will be displayed. If not provided, the tooltip will be displayed on the window. + + - Returns: The identifier of the tooltip. + + # Example + ```swift + CharcoalTooltip.show(text: "This is a tooltip", anchorView: someView) + ``` + */ @discardableResult static func show( text: String,