mirror of
https://github.com/divkit/divkit.git
synced 2026-06-06 20:07:59 +00:00
support div-tooltip.mode
commit_hash:949be67575b7f3da8a6d40d3341bb8c681123d76
This commit is contained in:
@@ -18,6 +18,13 @@ extension DivTooltip {
|
||||
return await tooltipViewFactory.makeView(div: self.div, tooltipId: self.id)
|
||||
}
|
||||
|
||||
let mode: BlockTooltip.Mode = switch mode {
|
||||
case .divTooltipModeModal:
|
||||
.modal
|
||||
case .divTooltipModeNonModal:
|
||||
.nonModal
|
||||
}
|
||||
|
||||
return try BlockTooltip(
|
||||
id: id,
|
||||
// Legacy behavior. Views should be created with tooltipViewFactory.
|
||||
@@ -28,7 +35,8 @@ extension DivTooltip {
|
||||
useLegacyWidth: context.flagsInfo.useTooltipLegacyWidth,
|
||||
tooltipViewFactory: tooltipViewFactory,
|
||||
closeByTapOutside: resolveCloseByTapOutside(expressionResolver),
|
||||
tapOutsideActions: tapOutsideActions?.uiActions(context: context) ?? []
|
||||
tapOutsideActions: tapOutsideActions?.uiActions(context: context) ?? [],
|
||||
mode: mode
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,7 +82,7 @@ final class SnapshotTestRunner {
|
||||
manager: DefaultTooltipManager,
|
||||
check: CheckAction
|
||||
) async throws {
|
||||
guard let tooltipWindow = manager.tooltipWindow else {
|
||||
guard let tooltipWindow = manager.modalTooltipWindow else {
|
||||
return try check(nil)
|
||||
}
|
||||
|
||||
|
||||
@@ -21,6 +21,11 @@ public struct BlockTooltip: Equatable {
|
||||
case center
|
||||
}
|
||||
|
||||
public enum Mode: Equatable {
|
||||
case modal
|
||||
case nonModal
|
||||
}
|
||||
|
||||
public let id: String
|
||||
public let block: Block
|
||||
public let duration: TimeInterval
|
||||
@@ -30,6 +35,7 @@ public struct BlockTooltip: Equatable {
|
||||
public let tooltipViewFactory: TooltipViewFactory?
|
||||
public let closeByTapOutside: Bool
|
||||
public let tapOutsideActions: [UserInterfaceAction]
|
||||
public let mode: Mode
|
||||
|
||||
public init(
|
||||
id: String,
|
||||
@@ -40,7 +46,8 @@ public struct BlockTooltip: Equatable {
|
||||
useLegacyWidth: Bool = true,
|
||||
tooltipViewFactory: TooltipViewFactory? = nil,
|
||||
closeByTapOutside: Bool = true,
|
||||
tapOutsideActions: [UserInterfaceAction] = []
|
||||
tapOutsideActions: [UserInterfaceAction] = [],
|
||||
mode: Mode = .modal
|
||||
) {
|
||||
self.id = id
|
||||
self.block = block
|
||||
@@ -51,6 +58,7 @@ public struct BlockTooltip: Equatable {
|
||||
self.tooltipViewFactory = tooltipViewFactory
|
||||
self.closeByTapOutside = closeByTapOutside
|
||||
self.tapOutsideActions = tapOutsideActions
|
||||
self.mode = mode
|
||||
}
|
||||
|
||||
public static func ==(lhs: BlockTooltip, rhs: BlockTooltip) -> Bool {
|
||||
@@ -61,6 +69,7 @@ public struct BlockTooltip: Equatable {
|
||||
lhs.useLegacyWidth == rhs.useLegacyWidth &&
|
||||
lhs.block.equals(rhs.block) &&
|
||||
lhs.closeByTapOutside == rhs.closeByTapOutside &&
|
||||
lhs.tapOutsideActions == rhs.tapOutsideActions
|
||||
lhs.tapOutsideActions == rhs.tapOutsideActions &&
|
||||
lhs.mode == rhs.mode
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,6 +68,7 @@ public class DefaultTooltipManager: TooltipManager {
|
||||
public let duration: TimeInterval
|
||||
public let closeByTapOutside: Bool
|
||||
public let tapOutsideActions: [UserInterfaceAction]
|
||||
public let isModal: Bool
|
||||
public let view: VisibleBoundsTrackingView
|
||||
}
|
||||
|
||||
@@ -76,9 +77,14 @@ public class DefaultTooltipManager: TooltipManager {
|
||||
private var handleAction: (UIActionEvent) -> Void
|
||||
private var existingAnchorViews = WeakCollection<TooltipAnchorView>()
|
||||
private var showingTooltips = [String: TooltipContainerView]()
|
||||
private(set) var tooltipWindow: UIWindow?
|
||||
private(set) var modalTooltipWindow: UIWindow?
|
||||
private var previousOrientation = UIDevice.current.orientation
|
||||
|
||||
private var foregroundWindowScene: UIWindowScene? {
|
||||
let scenes = UIApplication.shared.connectedScenes
|
||||
return scenes.first(where: { $0.activationState == .foregroundActive }) as? UIWindowScene
|
||||
}
|
||||
|
||||
public init(
|
||||
shownTooltips: Property<Set<String>> = Property(),
|
||||
handleAction: @escaping (UIActionEvent) -> Void = { _ in }
|
||||
@@ -95,13 +101,14 @@ public class DefaultTooltipManager: TooltipManager {
|
||||
}
|
||||
|
||||
public func showTooltip(info: TooltipInfo) {
|
||||
setupTooltipWindow()
|
||||
|
||||
guard let tooltipWindow,
|
||||
setupModalTooltipWindow()
|
||||
guard let modalTooltipWindow,
|
||||
let foregroundWindowScene,
|
||||
let currentKeyWindow = foregroundWindowScene.windows.first(where: { $0.isKeyWindow }),
|
||||
!showingTooltips.keys.contains(info.id)
|
||||
else { return }
|
||||
|
||||
let windowBounds = tooltipWindow.bounds.inset(by: tooltipWindow.safeAreaInsets)
|
||||
let windowBounds = modalTooltipWindow.bounds.inset(by: modalTooltipWindow.safeAreaInsets)
|
||||
|
||||
Task { @MainActor in
|
||||
guard let tooltip = await existingAnchorViews.compactMap(
|
||||
@@ -112,23 +119,34 @@ public class DefaultTooltipManager: TooltipManager {
|
||||
tooltipView: tooltip.view,
|
||||
closeByTapOutside: tooltip.closeByTapOutside,
|
||||
tapOutsideActions: tooltip.tapOutsideActions,
|
||||
isModal: tooltip.isModal,
|
||||
handleAction: handleAction,
|
||||
onCloseAction: { [weak self] in
|
||||
self?.showingTooltips.removeValue(forKey: tooltip.id)
|
||||
self?.tooltipWindow?.isHidden = true
|
||||
guard let self else { return }
|
||||
showingTooltips.removeValue(forKey: tooltip.id)
|
||||
if !showingTooltips.contains(where: { $1.isModal }) {
|
||||
modalTooltipWindow.isHidden = true
|
||||
}
|
||||
}
|
||||
)
|
||||
// Passing the statusBarStyle control to `rootViewController` of the main window
|
||||
let vc = ProxyViewController(
|
||||
viewController: UIApplication.shared.delegate?.window??
|
||||
.rootViewController ?? UIViewController()
|
||||
)
|
||||
vc.view = view
|
||||
// Window won't rotate if `rootViewController` is not set
|
||||
tooltipWindow.rootViewController = vc
|
||||
tooltipWindow.isHidden = false
|
||||
tooltipWindow.makeKeyAndVisible()
|
||||
view.frame = tooltipWindow.bounds
|
||||
|
||||
if tooltip.isModal {
|
||||
// Passing the statusBarStyle control to `rootViewController` of the main window
|
||||
let vc = ProxyViewController(
|
||||
viewController: UIApplication.shared.delegate?.window??
|
||||
.rootViewController ?? UIViewController()
|
||||
)
|
||||
vc.view = view
|
||||
// Window won't rotate if `rootViewController` is not set
|
||||
modalTooltipWindow.rootViewController = vc
|
||||
modalTooltipWindow.isHidden = false
|
||||
modalTooltipWindow.makeKeyAndVisible()
|
||||
view.frame = modalTooltipWindow.bounds
|
||||
} else {
|
||||
currentKeyWindow.addSubview(view)
|
||||
view.frame = currentKeyWindow.bounds
|
||||
}
|
||||
|
||||
showingTooltips[info.id] = view
|
||||
if !tooltip.duration.isZero {
|
||||
try await Task.sleep(nanoseconds: UInt64(tooltip.duration.nanoseconds))
|
||||
@@ -152,7 +170,7 @@ public class DefaultTooltipManager: TooltipManager {
|
||||
|
||||
public func reset() {
|
||||
showingTooltips = [:]
|
||||
tooltipWindow = nil
|
||||
modalTooltipWindow = nil
|
||||
}
|
||||
|
||||
public func setHandler(_ handler: @escaping (UIActionEvent) -> Void) {
|
||||
@@ -176,15 +194,13 @@ public class DefaultTooltipManager: TooltipManager {
|
||||
previousOrientation = orientation
|
||||
}
|
||||
|
||||
private func setupTooltipWindow() {
|
||||
if tooltipWindow == nil {
|
||||
guard let windowScene = UIApplication.shared.connectedScenes
|
||||
.first(where: { $0.activationState == .foregroundActive }) as? UIWindowScene
|
||||
else { return }
|
||||
tooltipWindow = UIWindow(windowScene: windowScene)
|
||||
tooltipWindow?.windowLevel = UIWindow.Level.alert + 1
|
||||
tooltipWindow?.isHidden = true
|
||||
}
|
||||
private func setupModalTooltipWindow() {
|
||||
guard modalTooltipWindow == nil,
|
||||
let windowScene = foregroundWindowScene else { return }
|
||||
|
||||
modalTooltipWindow = UIWindow(windowScene: windowScene)
|
||||
modalTooltipWindow?.windowLevel = UIWindow.Level.alert + 1
|
||||
modalTooltipWindow?.isHidden = true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -215,6 +231,7 @@ extension TooltipAnchorView {
|
||||
duration: tooltip.duration,
|
||||
closeByTapOutside: tooltip.closeByTapOutside,
|
||||
tapOutsideActions: tooltip.tapOutsideActions,
|
||||
isModal: tooltip.mode == .modal,
|
||||
view: tooltipView
|
||||
)
|
||||
}
|
||||
|
||||
@@ -3,12 +3,14 @@ import UIKit
|
||||
import VGSL
|
||||
|
||||
public final class TooltipContainerView: UIView, UIActionEventPerforming {
|
||||
let isModal: Bool
|
||||
private let tooltipView: VisibleBoundsTrackingView
|
||||
private let closeByTapOutside: Bool
|
||||
private let tapOutsideActions: [UserInterfaceAction]
|
||||
private let handleAction: (LayoutKit.UIActionEvent) -> Void
|
||||
private let onCloseAction: Action
|
||||
|
||||
private var isClosing = false
|
||||
private var lastNonZeroBounds: CGRect?
|
||||
private var onVisibleBoundsChanged: Action?
|
||||
|
||||
@@ -16,12 +18,14 @@ public final class TooltipContainerView: UIView, UIActionEventPerforming {
|
||||
tooltipView: VisibleBoundsTrackingView,
|
||||
closeByTapOutside: Bool,
|
||||
tapOutsideActions: [UserInterfaceAction],
|
||||
isModal: Bool,
|
||||
handleAction: @escaping (LayoutKit.UIActionEvent) -> Void,
|
||||
onCloseAction: @escaping Action
|
||||
) {
|
||||
self.tooltipView = tooltipView
|
||||
self.closeByTapOutside = closeByTapOutside
|
||||
self.tapOutsideActions = tapOutsideActions
|
||||
self.isModal = isModal
|
||||
self.handleAction = handleAction
|
||||
self.onCloseAction = onCloseAction
|
||||
let tooltipBounds = tooltipView.bounds
|
||||
@@ -31,8 +35,10 @@ public final class TooltipContainerView: UIView, UIActionEventPerforming {
|
||||
|
||||
super.init(frame: .zero)
|
||||
|
||||
let tapRecognizer = UITapGestureRecognizer(target: self, action: #selector(handleTap))
|
||||
addGestureRecognizer(tapRecognizer)
|
||||
if isModal {
|
||||
let tapRecognizer = UITapGestureRecognizer(target: self, action: #selector(handleTap))
|
||||
addGestureRecognizer(tapRecognizer)
|
||||
}
|
||||
|
||||
addSubview(tooltipView)
|
||||
}
|
||||
@@ -44,16 +50,21 @@ public final class TooltipContainerView: UIView, UIActionEventPerforming {
|
||||
|
||||
@objc private func handleTap(_ sender: UITapGestureRecognizer) {
|
||||
let point = sender.location(in: self)
|
||||
let isPointInsideTooltip = tooltipView.point(
|
||||
inside: tooltipView.convert(point, from: self),
|
||||
with: nil
|
||||
)
|
||||
if !isPointInsideTooltip {
|
||||
if !isPointInsideTooltip(point) {
|
||||
performTapOutsideActions()
|
||||
}
|
||||
}
|
||||
|
||||
public override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
|
||||
if !isPointInsideTooltip(point, event: event), !isModal {
|
||||
if closeByTapOutside {
|
||||
close()
|
||||
DispatchQueue.main.async {
|
||||
self.close()
|
||||
}
|
||||
}
|
||||
return nil
|
||||
} else {
|
||||
return super.hitTest(point, with: event)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,6 +89,8 @@ public final class TooltipContainerView: UIView, UIActionEventPerforming {
|
||||
}
|
||||
|
||||
public func close() {
|
||||
guard !isClosing else { return }
|
||||
isClosing = true
|
||||
self.tooltipView.onVisibleBoundsChanged(from: tooltipView.bounds, to: .zero)
|
||||
removeFromParentAnimated(completion: {
|
||||
self.onCloseAction()
|
||||
@@ -89,5 +102,13 @@ public final class TooltipContainerView: UIView, UIActionEventPerforming {
|
||||
UIActionEvent(uiAction: $0, originalSender: self)
|
||||
}
|
||||
perform(uiActionEvents: uiActionEvents, from: self)
|
||||
|
||||
if closeByTapOutside {
|
||||
close()
|
||||
}
|
||||
}
|
||||
|
||||
private func isPointInsideTooltip(_ point: CGPoint, event: UIEvent? = nil) -> Bool {
|
||||
tooltipView.point(inside: tooltipView.convert(point, from: self), with: event)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,6 +43,7 @@ final class BlockTooltipTests: XCTestCase {
|
||||
tooltipView: TestView(),
|
||||
closeByTapOutside: true,
|
||||
tapOutsideActions: [],
|
||||
isModal: true,
|
||||
handleAction: { _ in },
|
||||
onCloseAction: {}
|
||||
)
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
{
|
||||
"type": "object",
|
||||
"$description": "translations.json#/div_tooltip_mode_non_modal",
|
||||
"platforms": [],
|
||||
"platforms": [
|
||||
"ios"
|
||||
],
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string",
|
||||
|
||||
@@ -565,19 +565,19 @@
|
||||
],
|
||||
"steps": [
|
||||
"Set russian language on device",
|
||||
"Turn on Screen reader and set order of elements description to '\u0421\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435,\u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435,\u0442\u0438\u043f'",
|
||||
"Set focus on '\u042d\u043b\u0435\u043c\u0435\u043d\u0442 1'",
|
||||
"Turn on Screen reader and set order of elements description to 'Состояние,название,тип'",
|
||||
"Set focus on 'Элемент 1'",
|
||||
"Listen to Screen reader",
|
||||
"Double tap on screen",
|
||||
"Set focus on '\u042d\u043b\u0435\u043c\u0435\u043d\u0442 2'",
|
||||
"Set focus on 'Элемент 2'",
|
||||
"Listen to Screen reader",
|
||||
"Set focus on '\u042d\u043b\u0435\u043c\u0435\u043d\u0442 3'"
|
||||
"Set focus on 'Элемент 3'"
|
||||
],
|
||||
"expected_results": [
|
||||
"On '\u042d\u043b\u0435\u043c\u0435\u043d\u0442 1' Screen reader should say 'C\u0435\u0439\u0447\u0430\u0441 \u0432 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0438 0; \u042d\u043b\u0435\u043c\u0435\u043d\u0442 1; \u041a\u043d\u043e\u043f\u043a\u0430; \u041a\u043e\u0441\u043d\u0438\u0442\u0435\u0441\u044c \u0434\u0432\u0430\u0436\u0434\u044b, \u0447\u0442\u043e\u0431\u044b \u0430\u043a\u0442\u0438\u0432\u0438\u0440\u043e\u0432\u0430\u0442\u044c'",
|
||||
"After double tap Screen reader should say '\u0421\u0435\u0439\u0447\u0430\u0441 \u0432 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0438 1'",
|
||||
"On '\u042d\u043b\u0435\u043c\u0435\u043d\u0442 2' Screen reader should say '\u042d\u043b\u0435\u043c\u0435\u043d\u0442 2; \u041a\u043d\u043e\u043f\u043a\u0430; \u041d\u0430\u0436\u043c\u0438\u0442\u0435 \u043d\u0430 \u043a\u043d\u043e\u043f\u043a\u0443, \u0447\u0442\u043e\u0431\u044b \u0447\u0442\u043e-\u0442\u043e \u043f\u0440\u043e\u0438\u0437\u043e\u0448\u043b\u043e'",
|
||||
"On '\u042d\u043b\u0435\u043c\u0435\u043d\u0442 3' Screen reader should say '\u042d\u043b\u0435\u043c\u0435\u043d\u0442 3; \u041a\u043d\u043e\u043f\u043a\u0430'"
|
||||
"On 'Элемент 1' Screen reader should say 'Cейчас в состоянии 0; Элемент 1; Кнопка; Коснитесь дважды, чтобы активировать'",
|
||||
"After double tap Screen reader should say 'Сейчас в состоянии 1'",
|
||||
"On 'Элемент 2' Screen reader should say 'Элемент 2; Кнопка; Нажмите на кнопку, чтобы что-то произошло'",
|
||||
"On 'Элемент 3' Screen reader should say 'Элемент 3; Кнопка'"
|
||||
],
|
||||
"file": "accessibility/descriptions.json"
|
||||
},
|
||||
@@ -651,8 +651,8 @@
|
||||
"Focus on items from top to bottom"
|
||||
],
|
||||
"expected_results": [
|
||||
"When focusing on 1 item you'll hear '\u042d\u0442\u043e \u042d\u043b\u0435\u043c\u0435\u043d\u0442 1'",
|
||||
"When focusing on group of 2 and 3 items you will hear '\u042d\u0442\u043e \u042d\u043b\u0435\u043c\u0435\u043d\u0442 2, \u042d\u0442\u043e \u042d\u043b\u0435\u043c\u0435\u043d\u0442 3'",
|
||||
"When focusing on 1 item you'll hear 'Это Элемент 1'",
|
||||
"When focusing on group of 2 and 3 items you will hear 'Это Элемент 2, Это Элемент 3'",
|
||||
"Can't focus 4 element"
|
||||
],
|
||||
"file": "accessibility/mode/default.json"
|
||||
@@ -672,9 +672,9 @@
|
||||
],
|
||||
"expected_results": [
|
||||
"Focusing on all card",
|
||||
"You will hear '\u042d\u0442\u043e \u042d\u043b\u0435\u043c\u0435\u043d\u0442 1, \u042d\u0442\u043e \u042d\u043b\u0435\u043c\u0435\u043d\u0442 2, \u042d\u0442\u043e \u042d\u043b\u0435\u043c\u0435\u043d\u0442 3'",
|
||||
"On activation menu with text '\u042d\u043b\u0435\u043c\u0435\u043d\u0442 1, \u042d\u043b\u0435\u043c\u0435\u043d\u0442 2, \u042d\u043b\u0435\u043c\u0435\u043d\u0442 3' appears",
|
||||
"On focus Screen reader should not say '\u041a\u043e\u0441\u043d\u0438\u0442\u0435\u0441\u044c \u0434\u0432\u0430\u0436\u0434\u044b \u0438 \u0443\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0439\u0442\u0435'"
|
||||
"You will hear 'Это Элемент 1, Это Элемент 2, Это Элемент 3'",
|
||||
"On activation menu with text 'Элемент 1, Элемент 2, Элемент 3' appears",
|
||||
"On focus Screen reader should not say 'Коснитесь дважды и удерживайте'"
|
||||
],
|
||||
"file": "accessibility/mode/merge.json"
|
||||
},
|
||||
@@ -693,8 +693,8 @@
|
||||
],
|
||||
"expected_results": [
|
||||
"Focus on 5-th item",
|
||||
"\u0423\u0441\u043b\u044b\u0448\u0438\u043c '\u042d\u0442\u043e \u042d\u043b\u0435\u043c\u0435\u043d\u0442 5'",
|
||||
"\u041f\u0440\u0438 \u0432\u044b\u043a\u043b\u044e\u0447\u0435\u043d\u043d\u043e\u043c Screen reader \u043d\u0430 \u043a\u0430\u0436\u0434\u043e\u0439 \u043a\u043d\u043e\u043f\u043a\u0435 \u043f\u0440\u0438 \u0442\u0430\u043f\u0435 \u0434\u043e\u043b\u0436\u043d\u043e \u043f\u043e\u044f\u0432\u043b\u044f\u0442\u044c\u0441\u044f \u043c\u0435\u043d\u044e \u0441 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435\u043c \u044d\u0442\u043e\u0439 \u043a\u043d\u043e\u043f\u043a\u0438"
|
||||
"Услышим 'Это Элемент 5'",
|
||||
"При выключенном Screen reader на каждой кнопке при тапе должно появляться меню с названием этой кнопки"
|
||||
],
|
||||
"file": "accessibility/mode/exclude.json"
|
||||
},
|
||||
@@ -2082,7 +2082,7 @@
|
||||
},
|
||||
{
|
||||
"title": "Custom card",
|
||||
"case_id": 93,
|
||||
"case_id": 93,
|
||||
"platforms": [
|
||||
"android",
|
||||
"web"
|
||||
@@ -2599,14 +2599,18 @@
|
||||
"Try to tap outside of tooltip",
|
||||
"Close tooltip by cross button",
|
||||
"Tap on second button",
|
||||
"Tap outside of tooltip"
|
||||
"Tap outside of tooltip",
|
||||
"Tap on third button",
|
||||
"Tap on other buttons"
|
||||
],
|
||||
"expected_results": [
|
||||
"First tooltip is shown",
|
||||
"First tooltip isn't closed by tapping outside of the tooltip",
|
||||
"First tooltip is closed",
|
||||
"Second tooltip is shown",
|
||||
"Label text changed to `Outside actions called: true`, label text color is green"
|
||||
"Label text changed to `Outside actions called: true`, label text color is green",
|
||||
"Third tooltip is shown",
|
||||
"First and second buttons are clickable during showing of third non modal tooltip"
|
||||
],
|
||||
"file": "tooltips-with-tap-outside-properties.json"
|
||||
},
|
||||
@@ -2764,7 +2768,7 @@
|
||||
{
|
||||
"title": "Patch gallery with typed action",
|
||||
"case_id": 192,
|
||||
"platforms": [
|
||||
"platforms": [
|
||||
"android",
|
||||
"web"
|
||||
],
|
||||
|
||||
@@ -250,6 +250,98 @@
|
||||
"type": "text",
|
||||
"text": "Outside actions called: @{outside_actions_called}",
|
||||
"text_color": "@{(outside_actions_called == 'true') ? '#00FF00' : '#000000'}"
|
||||
},
|
||||
{
|
||||
"type": "button",
|
||||
"text": "tooltip mode = non_modal",
|
||||
"tooltips": [
|
||||
{
|
||||
"id": "tooltip_3",
|
||||
"position": "bottom",
|
||||
"duration": 0,
|
||||
"offset": {
|
||||
"x": {
|
||||
"value": 0
|
||||
},
|
||||
"y": {
|
||||
"value": 50
|
||||
}
|
||||
},
|
||||
"mode": {
|
||||
"type": "non_modal"
|
||||
},
|
||||
"close_by_tap_outside": true,
|
||||
"div": {
|
||||
"type": "container",
|
||||
"orientation": "overlap",
|
||||
"items": [
|
||||
{
|
||||
"type": "container",
|
||||
"paddings": {
|
||||
"left": 16,
|
||||
"top": 16,
|
||||
"right": 16,
|
||||
"bottom": 16
|
||||
},
|
||||
"items": [
|
||||
{
|
||||
"type": "text",
|
||||
"width": {
|
||||
"type": "wrap_content"
|
||||
},
|
||||
"paddings": {
|
||||
"left": 16,
|
||||
"top": 16,
|
||||
"right": 16,
|
||||
"bottom": 16
|
||||
},
|
||||
"background": [
|
||||
{
|
||||
"type": "solid",
|
||||
"color": "#799eb7"
|
||||
}
|
||||
],
|
||||
"border": {
|
||||
"corner_radius": 6
|
||||
},
|
||||
"text_color": "#2C3E50",
|
||||
"text": "Non modal tooltip"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "image",
|
||||
"width": {
|
||||
"type": "fixed",
|
||||
"value": 20
|
||||
},
|
||||
"height": {
|
||||
"type": "fixed",
|
||||
"value": 20
|
||||
},
|
||||
"margins": {
|
||||
"left": 8,
|
||||
"top": 8
|
||||
},
|
||||
"action": {
|
||||
"log_id": "hide_tooltip",
|
||||
"url": "div-action://hide_tooltip?id=tooltip_3"
|
||||
},
|
||||
"image_url": "https://yastatic.net/s3/home/div/div_fullscreens/cross2.3.png",
|
||||
"tint_color": "#000000",
|
||||
"alignment_horizontal": "left",
|
||||
"alignment_vertical": "top"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"actions": [
|
||||
{
|
||||
"log_id": "show_tooltip",
|
||||
"url": "div-action://show_tooltip?id=tooltip_3&multiple=true"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user