Add `Toolbar` implementation for HTML renderer (#169)
`Toolbar` is new in SwiftUI. It is coupled fairly closely with `NavigationView`, so this should be integrated with that somehow (#130). It was made similar to macOS which allows more than a leading/trailing `ToolbarItem`. Resolves #316.
This commit is contained in:
parent
a8c6eae94e
commit
21c21cd328
|
@ -23,6 +23,31 @@ public extension View {
|
|||
navigationTitle(title)
|
||||
}
|
||||
|
||||
@available(
|
||||
*,
|
||||
deprecated,
|
||||
message: "Use navigationTitle(_:) with navigationBarTitleDisplayMode(_:)"
|
||||
)
|
||||
func navigationBarTitle(_ title: Text,
|
||||
displayMode: NavigationBarItem.TitleDisplayMode) -> some View
|
||||
{
|
||||
navigationTitle(title)
|
||||
.navigationBarTitleDisplayMode(displayMode)
|
||||
}
|
||||
|
||||
@available(
|
||||
*,
|
||||
deprecated,
|
||||
message: "Use navigationTitle(_:) with navigationBarTitleDisplayMode(_:)"
|
||||
)
|
||||
func navigationBarTitle<S: StringProtocol>(
|
||||
_ title: S,
|
||||
displayMode: NavigationBarItem.TitleDisplayMode
|
||||
) -> some View {
|
||||
navigationTitle(title)
|
||||
.navigationBarTitleDisplayMode(displayMode)
|
||||
}
|
||||
|
||||
func navigationTitle(_ title: Text) -> some View {
|
||||
navigationTitle { title }
|
||||
}
|
||||
|
@ -36,4 +61,10 @@ public extension View {
|
|||
{
|
||||
preference(key: NavigationTitleKey.self, value: AnyView(title()))
|
||||
}
|
||||
|
||||
func navigationBarTitleDisplayMode(_ displayMode: NavigationBarItem
|
||||
.TitleDisplayMode) -> some View
|
||||
{
|
||||
preference(key: NavigationBarItemKey.self, value: .init(displayMode: displayMode))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,6 +40,14 @@ public struct _PreferenceValue<Key> where Key: PreferenceKey {
|
|||
}
|
||||
}
|
||||
|
||||
public extension _PreferenceValue {
|
||||
func _force<V>(
|
||||
_ transform: @escaping (Key.Value) -> V
|
||||
) -> _PreferenceReadingView<Key, V> where V: View {
|
||||
_PreferenceReadingView(value: self, transform: transform)
|
||||
}
|
||||
}
|
||||
|
||||
public struct _PreferenceStore {
|
||||
/// The backing values of the `_PreferenceStore`.
|
||||
private var values: [String: Any]
|
||||
|
|
|
@ -38,6 +38,20 @@ public struct _DelayedPreferenceView<Key, Content>: View, _PreferenceReadingView
|
|||
}
|
||||
}
|
||||
|
||||
public struct _PreferenceReadingView<Key, Content>: View where Key: PreferenceKey, Content: View {
|
||||
public let value: _PreferenceValue<Key>
|
||||
public let transform: (Key.Value) -> Content
|
||||
|
||||
public init(value: _PreferenceValue<Key>, transform: @escaping (Key.Value) -> Content) {
|
||||
self.value = value
|
||||
self.transform = transform
|
||||
}
|
||||
|
||||
public var body: some View {
|
||||
transform(value.value)
|
||||
}
|
||||
}
|
||||
|
||||
public extension PreferenceKey {
|
||||
static func _delay<T>(
|
||||
_ transform: @escaping (_PreferenceValue<Self>) -> T
|
||||
|
|
|
@ -15,30 +15,60 @@
|
|||
// Created by Jed Fox on 06/30/2020.
|
||||
//
|
||||
|
||||
public protocol TextFieldStyle {}
|
||||
public struct _TextFieldStyleLabel: View {
|
||||
public let body: AnyView
|
||||
}
|
||||
|
||||
public protocol TextFieldStyle: _AnyTextFieldStyle {
|
||||
associatedtype _Body: View
|
||||
typealias _Label = _TextFieldStyleLabel
|
||||
func _body(configuration: TextField<Self._Label>) -> Self._Body
|
||||
}
|
||||
|
||||
public struct DefaultTextFieldStyle: TextFieldStyle {
|
||||
public init() {}
|
||||
public func _body(configuration: TextField<_Label>) -> some View {
|
||||
configuration
|
||||
}
|
||||
}
|
||||
|
||||
public struct PlainTextFieldStyle: TextFieldStyle {
|
||||
public init() {}
|
||||
public func _body(configuration: TextField<_Label>) -> some View {
|
||||
configuration
|
||||
}
|
||||
}
|
||||
|
||||
public struct RoundedBorderTextFieldStyle: TextFieldStyle {
|
||||
public init() {}
|
||||
public func _body(configuration: TextField<_Label>) -> some View {
|
||||
configuration
|
||||
}
|
||||
}
|
||||
|
||||
public struct SquareBorderTextFieldStyle: TextFieldStyle {
|
||||
public init() {}
|
||||
public func _body(configuration: TextField<_Label>) -> some View {
|
||||
configuration
|
||||
}
|
||||
}
|
||||
|
||||
public protocol _AnyTextFieldStyle {
|
||||
func _anyBody(configuration: TextField<_TextFieldStyleLabel>) -> AnyView
|
||||
}
|
||||
|
||||
public extension TextFieldStyle {
|
||||
func _anyBody(configuration: TextField<_TextFieldStyleLabel>) -> AnyView {
|
||||
.init(_body(configuration: configuration))
|
||||
}
|
||||
}
|
||||
|
||||
enum TextFieldStyleKey: EnvironmentKey {
|
||||
static let defaultValue: TextFieldStyle = DefaultTextFieldStyle()
|
||||
static let defaultValue: _AnyTextFieldStyle = DefaultTextFieldStyle()
|
||||
}
|
||||
|
||||
extension EnvironmentValues {
|
||||
var textFieldStyle: TextFieldStyle {
|
||||
var textFieldStyle: _AnyTextFieldStyle {
|
||||
get {
|
||||
self[TextFieldStyleKey.self]
|
||||
}
|
||||
|
@ -49,7 +79,7 @@ extension EnvironmentValues {
|
|||
}
|
||||
|
||||
public extension View {
|
||||
func textFieldStyle(_ style: TextFieldStyle) -> some View {
|
||||
func textFieldStyle<S>(_ style: S) -> some View where S: TextFieldStyle {
|
||||
environment(\.textFieldStyle, style)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
// Copyright 2020 Tokamak contributors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
// Created by Carson Katri on 1/19/21.
|
||||
//
|
||||
|
||||
public struct NavigationBarItem: Equatable {
|
||||
let displayMode: TitleDisplayMode
|
||||
|
||||
public enum TitleDisplayMode: Hashable {
|
||||
case automatic
|
||||
case inline
|
||||
case large
|
||||
}
|
||||
}
|
||||
|
||||
public struct _NavigationBarItemProxy {
|
||||
let subject: NavigationBarItem
|
||||
|
||||
public init(_ subject: NavigationBarItem) {
|
||||
self.subject = subject
|
||||
}
|
||||
|
||||
public var displayMode: NavigationBarItem.TitleDisplayMode {
|
||||
subject.displayMode
|
||||
}
|
||||
}
|
|
@ -29,6 +29,23 @@ public struct NavigationView<Content>: _PrimitiveView where Content: View {
|
|||
}
|
||||
}
|
||||
|
||||
private struct ToolbarReader<Content>: View where Content: View {
|
||||
let content: (_ title: AnyView?, _ toolbarContent: [AnyToolbarItem]?) -> Content
|
||||
|
||||
var body: some View {
|
||||
ToolbarKey._delay {
|
||||
$0._force { bar in
|
||||
NavigationTitleKey._delay {
|
||||
$0
|
||||
._force {
|
||||
content($0, bar.items.isEmpty && $0 == nil ? nil : bar.items)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// This is a helper type that works around absence of "package private" access control in Swift
|
||||
public struct _NavigationViewProxy<Content: View> {
|
||||
public let subject: NavigationView<Content>
|
||||
|
@ -37,6 +54,15 @@ public struct _NavigationViewProxy<Content: View> {
|
|||
|
||||
public var context: NavigationContext { subject.context }
|
||||
|
||||
/// Builds the content of the `NavigationView` by passing in the title and toolbar if present.
|
||||
/// If `toolbarContent` is `nil`, you shouldn't render a toolbar.
|
||||
public func makeToolbar<DeferredBar>(
|
||||
@ViewBuilder _ content: @escaping (_ title: AnyView?, _ toolbarContent: [AnyToolbarItem]?)
|
||||
-> DeferredBar
|
||||
) -> some View where DeferredBar: View {
|
||||
ToolbarReader(content: content)
|
||||
}
|
||||
|
||||
public var content: some View {
|
||||
subject.content
|
||||
.environmentObject(context)
|
||||
|
@ -69,3 +95,10 @@ struct NavigationTitleKey: PreferenceKey {
|
|||
value = nextValue()
|
||||
}
|
||||
}
|
||||
|
||||
struct NavigationBarItemKey: PreferenceKey {
|
||||
static let defaultValue: NavigationBarItem = .init(displayMode: .automatic)
|
||||
static func reduce(value: inout NavigationBarItem, nextValue: () -> NavigationBarItem) {
|
||||
value = nextValue()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,62 @@
|
|||
// Copyright 2020 Tokamak contributors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
// Created by Carson Katri on 7/7/20.
|
||||
//
|
||||
|
||||
struct ToolbarKey: PreferenceKey {
|
||||
static let defaultValue = ToolbarValue([])
|
||||
static func reduce(value: inout ToolbarValue, nextValue: () -> ToolbarValue) {
|
||||
value = nextValue()
|
||||
}
|
||||
|
||||
final class ToolbarValue: Equatable {
|
||||
let items: [AnyToolbarItem]
|
||||
init(_ items: [AnyToolbarItem]) {
|
||||
self.items = items
|
||||
}
|
||||
|
||||
static func == (lhs: ToolbarValue, rhs: ToolbarValue) -> Bool {
|
||||
lhs === rhs
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public extension View {
|
||||
@_disfavoredOverload
|
||||
func toolbar<Content>(
|
||||
@ViewBuilder content: @escaping () -> Content
|
||||
) -> some View where Content: View {
|
||||
toolbar {
|
||||
ToolbarItem(placement: .automatic, content: content)
|
||||
}
|
||||
}
|
||||
|
||||
func toolbar<Items>(@ToolbarContentBuilder<()> items: () -> ToolbarItemGroup<(), Items>)
|
||||
-> some View
|
||||
{
|
||||
preference(key: ToolbarKey.self, value: ToolbarKey.ToolbarValue(items()._items.compactMap {
|
||||
$0.view as? AnyToolbarItem
|
||||
}))
|
||||
}
|
||||
|
||||
func toolbar<Items>(
|
||||
id: String,
|
||||
@ToolbarContentBuilder<String> items: () -> ToolbarItemGroup<String, Items>
|
||||
) -> some View {
|
||||
preference(key: ToolbarKey.self, value: ToolbarKey.ToolbarValue(items()._items.compactMap {
|
||||
$0.view as? AnyToolbarItem
|
||||
}))
|
||||
}
|
||||
}
|
|
@ -72,3 +72,25 @@ public struct ToolbarItem<ID, Content>: View, AnyToolbarItem where Content: View
|
|||
content
|
||||
}
|
||||
}
|
||||
|
||||
public extension ToolbarItem where ID == () {
|
||||
init(
|
||||
placement: ToolbarItemPlacement = .automatic,
|
||||
@ViewBuilder content: () -> Content
|
||||
) {
|
||||
self.init(id: (), placement: placement, showsByDefault: true, content: content)
|
||||
}
|
||||
}
|
||||
|
||||
extension ToolbarItem: Identifiable where ID: Hashable {}
|
||||
|
||||
/// This is a helper class that works around absence of "package private" access control in Swift
|
||||
public struct _ToolbarItemProxy<ID, Content> where Content: View {
|
||||
public let subject: ToolbarItem<ID, Content>
|
||||
|
||||
public init(_ subject: ToolbarItem<ID, Content>) { self.subject = subject }
|
||||
|
||||
public var placement: ToolbarItemPlacement { subject.placement }
|
||||
public var showsByDefault: Bool { subject.showsByDefault }
|
||||
public var content: Content { subject.content }
|
||||
}
|
||||
|
|
|
@ -71,14 +71,14 @@ extension TextField: ParentView {
|
|||
}
|
||||
|
||||
/// This is a helper type that works around absence of "package private" access control in Swift
|
||||
public struct _TextFieldProxy {
|
||||
public let subject: TextField<Text>
|
||||
public struct _TextFieldProxy<Label: View> {
|
||||
public let subject: TextField<Label>
|
||||
|
||||
public init(_ subject: TextField<Text>) { self.subject = subject }
|
||||
public init(_ subject: TextField<Label>) { self.subject = subject }
|
||||
|
||||
public var label: _TextProxy { _TextProxy(subject.label) }
|
||||
public var label: Label { subject.label }
|
||||
public var textBinding: Binding<String> { subject.textBinding }
|
||||
public var onCommit: () -> () { subject.onCommit }
|
||||
public var onEditingChanged: (Bool) -> () { subject.onEditingChanged }
|
||||
public var textFieldStyle: TextFieldStyle { subject.style }
|
||||
public var textFieldStyle: _AnyTextFieldStyle { subject.style }
|
||||
}
|
||||
|
|
|
@ -161,6 +161,13 @@ public typealias View = TokamakCore.View
|
|||
public typealias AnyView = TokamakCore.AnyView
|
||||
public typealias EmptyView = TokamakCore.EmptyView
|
||||
|
||||
// MARK: Toolbars
|
||||
|
||||
public typealias ToolbarItem = TokamakCore.ToolbarItem
|
||||
public typealias ToolbarItemGroup = TokamakCore.ToolbarItemGroup
|
||||
public typealias ToolbarItemPlacement = TokamakCore.ToolbarItemPlacement
|
||||
public typealias ToolbarContentBuilder = TokamakCore.ToolbarContentBuilder
|
||||
|
||||
// MARK: Text
|
||||
|
||||
public typealias TextAlignment = TokamakCore.TextAlignment
|
||||
|
|
|
@ -18,8 +18,8 @@
|
|||
import TokamakCore
|
||||
import TokamakStaticHTML
|
||||
|
||||
extension TextField: DOMPrimitive where Label == Text {
|
||||
func css(for style: TextFieldStyle) -> String {
|
||||
extension TextField: DOMPrimitive where Label == _TextFieldStyleLabel {
|
||||
func css(for style: _AnyTextFieldStyle) -> String {
|
||||
if style is PlainTextFieldStyle {
|
||||
return """
|
||||
background: transparent;
|
||||
|
@ -30,12 +30,12 @@ extension TextField: DOMPrimitive where Label == Text {
|
|||
}
|
||||
}
|
||||
|
||||
func className(for style: TextFieldStyle) -> String {
|
||||
func className(for style: _AnyTextFieldStyle) -> String {
|
||||
switch style {
|
||||
case is DefaultTextFieldStyle, is RoundedBorderTextFieldStyle:
|
||||
return "_tokamak-formcontrol"
|
||||
default:
|
||||
return ""
|
||||
return "_tokamak-formcontrol-reset"
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -45,7 +45,9 @@ extension TextField: DOMPrimitive where Label == Text {
|
|||
return AnyView(DynamicHTML("input", [
|
||||
"type": proxy.textFieldStyle is RoundedBorderTextFieldStyle ? "search" : "text",
|
||||
.value: proxy.textBinding.wrappedValue,
|
||||
"placeholder": proxy.label.rawText,
|
||||
"placeholder": mapAnyView(proxy.label.body, transform: { (v: Text) in
|
||||
_TextProxy(v).rawText
|
||||
}) ?? "",
|
||||
"style": css(for: proxy.textFieldStyle),
|
||||
"class": className(for: proxy.textFieldStyle),
|
||||
], listeners: [
|
||||
|
|
|
@ -170,7 +170,31 @@ struct TokamakDemoView: View {
|
|||
title: "Demos"
|
||||
)
|
||||
if #available(iOS 14.0, *) {
|
||||
return AnyView(list.listStyle(SidebarListStyle()))
|
||||
return AnyView(
|
||||
list
|
||||
.listStyle(SidebarListStyle())
|
||||
.navigationTitle("Tokamak")
|
||||
.toolbar {
|
||||
ToolbarItem(placement: .cancellationAction) {
|
||||
Button("Cancellation Action") {}
|
||||
}
|
||||
ToolbarItem(placement: .confirmationAction) {
|
||||
Button("Confirmation Action") {}
|
||||
}
|
||||
ToolbarItem(placement: .destructiveAction) {
|
||||
Button("Destructive Action") {}
|
||||
}
|
||||
ToolbarItem(placement: .navigation) {
|
||||
Text("Some nav-text")
|
||||
.italic()
|
||||
}
|
||||
ToolbarItem(placement: .status) {
|
||||
Text("Status: Live")
|
||||
.bold()
|
||||
.foregroundColor(.green)
|
||||
}
|
||||
}
|
||||
)
|
||||
} else {
|
||||
return AnyView(list)
|
||||
}
|
||||
|
|
|
@ -78,11 +78,11 @@ extension TextField: GTKPrimitive where Label == Text {
|
|||
let proxy = _TextFieldProxy(self)
|
||||
return AnyView(WidgetView(
|
||||
build: { _ in
|
||||
build(textBinding: proxy.textBinding, label: proxy.label)
|
||||
build(textBinding: proxy.textBinding, label: _TextProxy(proxy.label))
|
||||
},
|
||||
update: { a in
|
||||
guard case let .widget(widget) = a.storage else { return }
|
||||
update(entry: widget, textBinding: proxy.textBinding, label: proxy.label)
|
||||
update(entry: widget, textBinding: proxy.textBinding, label: _TextProxy(proxy.label))
|
||||
}
|
||||
) {})
|
||||
}
|
||||
|
|
|
@ -90,6 +90,13 @@ public typealias View = TokamakCore.View
|
|||
public typealias AnyView = TokamakCore.AnyView
|
||||
public typealias EmptyView = TokamakCore.EmptyView
|
||||
|
||||
// MARK: Toolbars
|
||||
|
||||
public typealias ToolbarItem = TokamakCore.ToolbarItem
|
||||
public typealias ToolbarItemGroup = TokamakCore.ToolbarItemGroup
|
||||
public typealias ToolbarItemPlacement = TokamakCore.ToolbarItemPlacement
|
||||
public typealias ToolbarContentBuilder = TokamakCore.ToolbarContentBuilder
|
||||
|
||||
// MARK: App & Scene
|
||||
|
||||
public typealias App = TokamakCore.App
|
||||
|
|
|
@ -123,16 +123,90 @@ public let tokamakStyles = """
|
|||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
._tokamak-navigationview-content {
|
||||
._tokamak-navigationview-with-toolbar-content ._tokamak-scrollview {
|
||||
padding-top: 50px;
|
||||
}
|
||||
._tokamak-navigationview-destination {
|
||||
display: flex; flex-direction: column;
|
||||
align-items: center; justify-content: center;
|
||||
flex-grow: 1;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
._tokamak-formcontrol {
|
||||
._tokamak-toolbar {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100vw;
|
||||
height: 50px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
overflow: hidden;
|
||||
background: rgba(200, 200, 200, 0.2);
|
||||
-webkit-backdrop-filter: saturate(180%) blur(20px);
|
||||
backdrop-filter: saturate(180%) blur(20px);
|
||||
}
|
||||
|
||||
._tokamak-toolbar-content {
|
||||
flex: 1 1 auto;
|
||||
display: flex;
|
||||
height: 100%;
|
||||
}
|
||||
._tokamak-toolbar-leading > *, ._tokamak-toolbar-center > * {
|
||||
margin-right: 8px;
|
||||
}
|
||||
._tokamak-toolbar-trailing > * {
|
||||
margin-left: 8px;
|
||||
}
|
||||
._tokamak-toolbar-leading {
|
||||
margin-right: auto;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
padding-left: 16px;
|
||||
}
|
||||
._tokamak-toolbar-center {
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
._tokamak-toolbar-trailing {
|
||||
margin-left: auto;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
padding-right: 16px;
|
||||
}
|
||||
|
||||
._tokamak-toolbar-button {
|
||||
padding: 2px 4px;
|
||||
border-radius: 3px;
|
||||
border: 1px solid rgba(0, 0, 0, 0.05);
|
||||
height: 25px;
|
||||
padding: 0 8px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
._tokamak-toolbar-button:hover {
|
||||
border-color: transparent;
|
||||
background-color: rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
._tokamak-toolbar-button:active {
|
||||
border-color: transparent;
|
||||
background-color: rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
._tokamak-toolbar-textfield input {
|
||||
padding: 4px 4px 4px 8px;
|
||||
border-radius: 3px;
|
||||
background-color: rgba(0, 0, 0, 0.05);
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
._tokamak-formcontrol, ._tokamak-formcontrol-reset {
|
||||
color-scheme: light dark;
|
||||
}
|
||||
._tokamak-formcontrol-reset {
|
||||
background: none;
|
||||
border: none;
|
||||
}
|
||||
|
||||
._tokamak-link {
|
||||
text-decoration: none;
|
||||
|
@ -160,6 +234,23 @@ public let tokamakStyles = """
|
|||
border-right-color: rgba(255, 255, 255, 0.25);
|
||||
border-top-color: rgba(255, 255, 255, 0.25);
|
||||
}
|
||||
|
||||
._tokamak-toolbar {
|
||||
background: rgba(100, 100, 100, 0.2);
|
||||
}
|
||||
._tokamak-toolbar-button {
|
||||
border: 1px solid rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
._tokamak-toolbar-button:hover {
|
||||
background-color: rgba(255, 255, 255, 0.05);
|
||||
}
|
||||
._tokamak-toolbar-button:active {
|
||||
background-color: rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
._tokamak-toolbar-textfield input {
|
||||
background-color: rgba(255, 255, 255, 0.05);
|
||||
color: #FFFFFF;
|
||||
}
|
||||
}
|
||||
"""
|
||||
|
||||
|
|
|
@ -37,7 +37,8 @@ extension ScrollView: _HTMLPrimitive, SpacerContainer {
|
|||
\(fillCrossAxis && scrollX ? "height: 100%;" : "")
|
||||
\(fillCrossAxis && scrollY ? "width: 100%;" : "")
|
||||
""",
|
||||
"class": !showsIndicators ? "_tokamak-scrollview-hideindicators" : "",
|
||||
"class": !showsIndicators ? "_tokamak-scrollview _tokamak-scrollview-hideindicators" :
|
||||
"_tokamak-scrollview",
|
||||
]) {
|
||||
VStack {
|
||||
content
|
||||
|
|
|
@ -21,12 +21,81 @@ extension NavigationView: _HTMLPrimitive {
|
|||
return AnyView(HTML("div", [
|
||||
"class": "_tokamak-navigationview",
|
||||
]) {
|
||||
proxy.content
|
||||
HTML("div", [
|
||||
"class": "_tokamak-navigationview-content",
|
||||
]) {
|
||||
proxy.destination
|
||||
proxy.makeToolbar { title, toolbarContent in
|
||||
if let toolbarContent = toolbarContent {
|
||||
HTML("div", [
|
||||
"class": "_tokamak-toolbar",
|
||||
]) {
|
||||
Group {
|
||||
if toolbarContent.isEmpty {
|
||||
HTML("div", ["class": "_tokamak-toolbar-content _tokamak-toolbar-leading"]) {
|
||||
title.font(.headline)
|
||||
}
|
||||
} else {
|
||||
HTML("div", ["class": "_tokamak-toolbar-content _tokamak-toolbar-leading"]) {
|
||||
items(from: toolbarContent, at: .navigationBarLeading)
|
||||
items(from: toolbarContent, at: .navigation)
|
||||
title
|
||||
.font(.headline)
|
||||
items(from: toolbarContent, at: .navigationBarTrailing)
|
||||
items(from: toolbarContent, at: .automatic, .primaryAction)
|
||||
items(from: toolbarContent, at: .destructiveAction)
|
||||
.foregroundColor(.red)
|
||||
}
|
||||
HTML("div", ["class": "_tokamak-toolbar-content _tokamak-toolbar-center"]) {
|
||||
items(from: toolbarContent, at: .principal, .status)
|
||||
}
|
||||
HTML("div", ["class": "_tokamak-toolbar-content _tokamak-toolbar-trailing"]) {
|
||||
items(from: toolbarContent, at: .cancellationAction)
|
||||
items(from: toolbarContent, at: .confirmationAction)
|
||||
.foregroundColor(.accentColor)
|
||||
}
|
||||
}
|
||||
}
|
||||
.font(.caption)
|
||||
.buttonStyle(ToolbarButtonStyle())
|
||||
.textFieldStyle(ToolbarTextFieldStyle())
|
||||
}
|
||||
}
|
||||
HTML("div", [
|
||||
"class": toolbarContent != nil ? "_tokamak-navigationview-with-toolbar-content" : "",
|
||||
]) {
|
||||
proxy.content
|
||||
}
|
||||
HTML("div", [
|
||||
"class": "_tokamak-navigationview-destination",
|
||||
"style": toolbarContent != nil ? "padding-top: 50px;" : "",
|
||||
]) {
|
||||
proxy.destination
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func items(from items: [AnyToolbarItem], at placements: ToolbarItemPlacement...) -> some View {
|
||||
ForEach(
|
||||
Array(items.filter { placements.contains($0.placement) }.enumerated()),
|
||||
id: \.offset
|
||||
) { item in
|
||||
item.element.anyContent
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct ToolbarButtonStyle: ButtonStyle {
|
||||
func makeBody(configuration: Configuration) -> some View {
|
||||
HTML("div", ["class": "_tokamak-toolbar-button"]) {
|
||||
configuration.label
|
||||
.opacity(configuration.isPressed ? 1 : 0.75)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct ToolbarTextFieldStyle: TextFieldStyle {
|
||||
func _body(configuration: TextField<_Label>) -> some View {
|
||||
HTML("div", ["class": "_tokamak-toolbar-textfield"]) {
|
||||
configuration
|
||||
}
|
||||
.frame(height: 27)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -110,16 +110,90 @@
|
|||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
._tokamak-navigationview-content {
|
||||
._tokamak-navigationview-with-toolbar-content ._tokamak-scrollview {
|
||||
padding-top: 50px;
|
||||
}
|
||||
._tokamak-navigationview-destination {
|
||||
display: flex; flex-direction: column;
|
||||
align-items: center; justify-content: center;
|
||||
flex-grow: 1;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
._tokamak-formcontrol {
|
||||
._tokamak-toolbar {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100vw;
|
||||
height: 50px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
overflow: hidden;
|
||||
background: rgba(200, 200, 200, 0.2);
|
||||
-webkit-backdrop-filter: saturate(180%) blur(20px);
|
||||
backdrop-filter: saturate(180%) blur(20px);
|
||||
}
|
||||
|
||||
._tokamak-toolbar-content {
|
||||
flex: 1 1 auto;
|
||||
display: flex;
|
||||
height: 100%;
|
||||
}
|
||||
._tokamak-toolbar-leading > *, ._tokamak-toolbar-center > * {
|
||||
margin-right: 8px;
|
||||
}
|
||||
._tokamak-toolbar-trailing > * {
|
||||
margin-left: 8px;
|
||||
}
|
||||
._tokamak-toolbar-leading {
|
||||
margin-right: auto;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
padding-left: 16px;
|
||||
}
|
||||
._tokamak-toolbar-center {
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
._tokamak-toolbar-trailing {
|
||||
margin-left: auto;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
padding-right: 16px;
|
||||
}
|
||||
|
||||
._tokamak-toolbar-button {
|
||||
padding: 2px 4px;
|
||||
border-radius: 3px;
|
||||
border: 1px solid rgba(0, 0, 0, 0.05);
|
||||
height: 25px;
|
||||
padding: 0 8px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
._tokamak-toolbar-button:hover {
|
||||
border-color: transparent;
|
||||
background-color: rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
._tokamak-toolbar-button:active {
|
||||
border-color: transparent;
|
||||
background-color: rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
._tokamak-toolbar-textfield input {
|
||||
padding: 4px 4px 4px 8px;
|
||||
border-radius: 3px;
|
||||
background-color: rgba(0, 0, 0, 0.05);
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
._tokamak-formcontrol, ._tokamak-formcontrol-reset {
|
||||
color-scheme: light dark;
|
||||
}
|
||||
._tokamak-formcontrol-reset {
|
||||
background: none;
|
||||
border: none;
|
||||
}
|
||||
|
||||
._tokamak-link {
|
||||
text-decoration: none;
|
||||
|
@ -147,6 +221,23 @@
|
|||
border-right-color: rgba(255, 255, 255, 0.25);
|
||||
border-top-color: rgba(255, 255, 255, 0.25);
|
||||
}
|
||||
|
||||
._tokamak-toolbar {
|
||||
background: rgba(100, 100, 100, 0.2);
|
||||
}
|
||||
._tokamak-toolbar-button {
|
||||
border: 1px solid rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
._tokamak-toolbar-button:hover {
|
||||
background-color: rgba(255, 255, 255, 0.05);
|
||||
}
|
||||
._tokamak-toolbar-button:active {
|
||||
background-color: rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
._tokamak-toolbar-textfield input {
|
||||
background-color: rgba(255, 255, 255, 0.05);
|
||||
color: #FFFFFF;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
|
|
@ -110,16 +110,90 @@
|
|||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
._tokamak-navigationview-content {
|
||||
._tokamak-navigationview-with-toolbar-content ._tokamak-scrollview {
|
||||
padding-top: 50px;
|
||||
}
|
||||
._tokamak-navigationview-destination {
|
||||
display: flex; flex-direction: column;
|
||||
align-items: center; justify-content: center;
|
||||
flex-grow: 1;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
._tokamak-formcontrol {
|
||||
._tokamak-toolbar {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100vw;
|
||||
height: 50px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
overflow: hidden;
|
||||
background: rgba(200, 200, 200, 0.2);
|
||||
-webkit-backdrop-filter: saturate(180%) blur(20px);
|
||||
backdrop-filter: saturate(180%) blur(20px);
|
||||
}
|
||||
|
||||
._tokamak-toolbar-content {
|
||||
flex: 1 1 auto;
|
||||
display: flex;
|
||||
height: 100%;
|
||||
}
|
||||
._tokamak-toolbar-leading > *, ._tokamak-toolbar-center > * {
|
||||
margin-right: 8px;
|
||||
}
|
||||
._tokamak-toolbar-trailing > * {
|
||||
margin-left: 8px;
|
||||
}
|
||||
._tokamak-toolbar-leading {
|
||||
margin-right: auto;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
padding-left: 16px;
|
||||
}
|
||||
._tokamak-toolbar-center {
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
._tokamak-toolbar-trailing {
|
||||
margin-left: auto;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
padding-right: 16px;
|
||||
}
|
||||
|
||||
._tokamak-toolbar-button {
|
||||
padding: 2px 4px;
|
||||
border-radius: 3px;
|
||||
border: 1px solid rgba(0, 0, 0, 0.05);
|
||||
height: 25px;
|
||||
padding: 0 8px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
._tokamak-toolbar-button:hover {
|
||||
border-color: transparent;
|
||||
background-color: rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
._tokamak-toolbar-button:active {
|
||||
border-color: transparent;
|
||||
background-color: rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
._tokamak-toolbar-textfield input {
|
||||
padding: 4px 4px 4px 8px;
|
||||
border-radius: 3px;
|
||||
background-color: rgba(0, 0, 0, 0.05);
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
._tokamak-formcontrol, ._tokamak-formcontrol-reset {
|
||||
color-scheme: light dark;
|
||||
}
|
||||
._tokamak-formcontrol-reset {
|
||||
background: none;
|
||||
border: none;
|
||||
}
|
||||
|
||||
._tokamak-link {
|
||||
text-decoration: none;
|
||||
|
@ -147,6 +221,23 @@
|
|||
border-right-color: rgba(255, 255, 255, 0.25);
|
||||
border-top-color: rgba(255, 255, 255, 0.25);
|
||||
}
|
||||
|
||||
._tokamak-toolbar {
|
||||
background: rgba(100, 100, 100, 0.2);
|
||||
}
|
||||
._tokamak-toolbar-button {
|
||||
border: 1px solid rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
._tokamak-toolbar-button:hover {
|
||||
background-color: rgba(255, 255, 255, 0.05);
|
||||
}
|
||||
._tokamak-toolbar-button:active {
|
||||
background-color: rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
._tokamak-toolbar-textfield input {
|
||||
background-color: rgba(255, 255, 255, 0.05);
|
||||
color: #FFFFFF;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
|
|
@ -110,16 +110,90 @@
|
|||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
._tokamak-navigationview-content {
|
||||
._tokamak-navigationview-with-toolbar-content ._tokamak-scrollview {
|
||||
padding-top: 50px;
|
||||
}
|
||||
._tokamak-navigationview-destination {
|
||||
display: flex; flex-direction: column;
|
||||
align-items: center; justify-content: center;
|
||||
flex-grow: 1;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
._tokamak-formcontrol {
|
||||
._tokamak-toolbar {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100vw;
|
||||
height: 50px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
overflow: hidden;
|
||||
background: rgba(200, 200, 200, 0.2);
|
||||
-webkit-backdrop-filter: saturate(180%) blur(20px);
|
||||
backdrop-filter: saturate(180%) blur(20px);
|
||||
}
|
||||
|
||||
._tokamak-toolbar-content {
|
||||
flex: 1 1 auto;
|
||||
display: flex;
|
||||
height: 100%;
|
||||
}
|
||||
._tokamak-toolbar-leading > *, ._tokamak-toolbar-center > * {
|
||||
margin-right: 8px;
|
||||
}
|
||||
._tokamak-toolbar-trailing > * {
|
||||
margin-left: 8px;
|
||||
}
|
||||
._tokamak-toolbar-leading {
|
||||
margin-right: auto;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
padding-left: 16px;
|
||||
}
|
||||
._tokamak-toolbar-center {
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
._tokamak-toolbar-trailing {
|
||||
margin-left: auto;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
padding-right: 16px;
|
||||
}
|
||||
|
||||
._tokamak-toolbar-button {
|
||||
padding: 2px 4px;
|
||||
border-radius: 3px;
|
||||
border: 1px solid rgba(0, 0, 0, 0.05);
|
||||
height: 25px;
|
||||
padding: 0 8px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
._tokamak-toolbar-button:hover {
|
||||
border-color: transparent;
|
||||
background-color: rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
._tokamak-toolbar-button:active {
|
||||
border-color: transparent;
|
||||
background-color: rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
._tokamak-toolbar-textfield input {
|
||||
padding: 4px 4px 4px 8px;
|
||||
border-radius: 3px;
|
||||
background-color: rgba(0, 0, 0, 0.05);
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
._tokamak-formcontrol, ._tokamak-formcontrol-reset {
|
||||
color-scheme: light dark;
|
||||
}
|
||||
._tokamak-formcontrol-reset {
|
||||
background: none;
|
||||
border: none;
|
||||
}
|
||||
|
||||
._tokamak-link {
|
||||
text-decoration: none;
|
||||
|
@ -147,6 +221,23 @@
|
|||
border-right-color: rgba(255, 255, 255, 0.25);
|
||||
border-top-color: rgba(255, 255, 255, 0.25);
|
||||
}
|
||||
|
||||
._tokamak-toolbar {
|
||||
background: rgba(100, 100, 100, 0.2);
|
||||
}
|
||||
._tokamak-toolbar-button {
|
||||
border: 1px solid rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
._tokamak-toolbar-button:hover {
|
||||
background-color: rgba(255, 255, 255, 0.05);
|
||||
}
|
||||
._tokamak-toolbar-button:active {
|
||||
background-color: rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
._tokamak-toolbar-textfield input {
|
||||
background-color: rgba(255, 255, 255, 0.05);
|
||||
color: #FFFFFF;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
|
|
@ -110,16 +110,90 @@
|
|||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
._tokamak-navigationview-content {
|
||||
._tokamak-navigationview-with-toolbar-content ._tokamak-scrollview {
|
||||
padding-top: 50px;
|
||||
}
|
||||
._tokamak-navigationview-destination {
|
||||
display: flex; flex-direction: column;
|
||||
align-items: center; justify-content: center;
|
||||
flex-grow: 1;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
._tokamak-formcontrol {
|
||||
._tokamak-toolbar {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100vw;
|
||||
height: 50px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
overflow: hidden;
|
||||
background: rgba(200, 200, 200, 0.2);
|
||||
-webkit-backdrop-filter: saturate(180%) blur(20px);
|
||||
backdrop-filter: saturate(180%) blur(20px);
|
||||
}
|
||||
|
||||
._tokamak-toolbar-content {
|
||||
flex: 1 1 auto;
|
||||
display: flex;
|
||||
height: 100%;
|
||||
}
|
||||
._tokamak-toolbar-leading > *, ._tokamak-toolbar-center > * {
|
||||
margin-right: 8px;
|
||||
}
|
||||
._tokamak-toolbar-trailing > * {
|
||||
margin-left: 8px;
|
||||
}
|
||||
._tokamak-toolbar-leading {
|
||||
margin-right: auto;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
padding-left: 16px;
|
||||
}
|
||||
._tokamak-toolbar-center {
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
._tokamak-toolbar-trailing {
|
||||
margin-left: auto;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
padding-right: 16px;
|
||||
}
|
||||
|
||||
._tokamak-toolbar-button {
|
||||
padding: 2px 4px;
|
||||
border-radius: 3px;
|
||||
border: 1px solid rgba(0, 0, 0, 0.05);
|
||||
height: 25px;
|
||||
padding: 0 8px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
._tokamak-toolbar-button:hover {
|
||||
border-color: transparent;
|
||||
background-color: rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
._tokamak-toolbar-button:active {
|
||||
border-color: transparent;
|
||||
background-color: rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
._tokamak-toolbar-textfield input {
|
||||
padding: 4px 4px 4px 8px;
|
||||
border-radius: 3px;
|
||||
background-color: rgba(0, 0, 0, 0.05);
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
._tokamak-formcontrol, ._tokamak-formcontrol-reset {
|
||||
color-scheme: light dark;
|
||||
}
|
||||
._tokamak-formcontrol-reset {
|
||||
background: none;
|
||||
border: none;
|
||||
}
|
||||
|
||||
._tokamak-link {
|
||||
text-decoration: none;
|
||||
|
@ -147,6 +221,23 @@
|
|||
border-right-color: rgba(255, 255, 255, 0.25);
|
||||
border-top-color: rgba(255, 255, 255, 0.25);
|
||||
}
|
||||
|
||||
._tokamak-toolbar {
|
||||
background: rgba(100, 100, 100, 0.2);
|
||||
}
|
||||
._tokamak-toolbar-button {
|
||||
border: 1px solid rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
._tokamak-toolbar-button:hover {
|
||||
background-color: rgba(255, 255, 255, 0.05);
|
||||
}
|
||||
._tokamak-toolbar-button:active {
|
||||
background-color: rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
._tokamak-toolbar-textfield input {
|
||||
background-color: rgba(255, 255, 255, 0.05);
|
||||
color: #FFFFFF;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
|
|
@ -110,16 +110,90 @@
|
|||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
._tokamak-navigationview-content {
|
||||
._tokamak-navigationview-with-toolbar-content ._tokamak-scrollview {
|
||||
padding-top: 50px;
|
||||
}
|
||||
._tokamak-navigationview-destination {
|
||||
display: flex; flex-direction: column;
|
||||
align-items: center; justify-content: center;
|
||||
flex-grow: 1;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
._tokamak-formcontrol {
|
||||
._tokamak-toolbar {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100vw;
|
||||
height: 50px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
overflow: hidden;
|
||||
background: rgba(200, 200, 200, 0.2);
|
||||
-webkit-backdrop-filter: saturate(180%) blur(20px);
|
||||
backdrop-filter: saturate(180%) blur(20px);
|
||||
}
|
||||
|
||||
._tokamak-toolbar-content {
|
||||
flex: 1 1 auto;
|
||||
display: flex;
|
||||
height: 100%;
|
||||
}
|
||||
._tokamak-toolbar-leading > *, ._tokamak-toolbar-center > * {
|
||||
margin-right: 8px;
|
||||
}
|
||||
._tokamak-toolbar-trailing > * {
|
||||
margin-left: 8px;
|
||||
}
|
||||
._tokamak-toolbar-leading {
|
||||
margin-right: auto;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
padding-left: 16px;
|
||||
}
|
||||
._tokamak-toolbar-center {
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
._tokamak-toolbar-trailing {
|
||||
margin-left: auto;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
padding-right: 16px;
|
||||
}
|
||||
|
||||
._tokamak-toolbar-button {
|
||||
padding: 2px 4px;
|
||||
border-radius: 3px;
|
||||
border: 1px solid rgba(0, 0, 0, 0.05);
|
||||
height: 25px;
|
||||
padding: 0 8px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
._tokamak-toolbar-button:hover {
|
||||
border-color: transparent;
|
||||
background-color: rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
._tokamak-toolbar-button:active {
|
||||
border-color: transparent;
|
||||
background-color: rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
._tokamak-toolbar-textfield input {
|
||||
padding: 4px 4px 4px 8px;
|
||||
border-radius: 3px;
|
||||
background-color: rgba(0, 0, 0, 0.05);
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
._tokamak-formcontrol, ._tokamak-formcontrol-reset {
|
||||
color-scheme: light dark;
|
||||
}
|
||||
._tokamak-formcontrol-reset {
|
||||
background: none;
|
||||
border: none;
|
||||
}
|
||||
|
||||
._tokamak-link {
|
||||
text-decoration: none;
|
||||
|
@ -147,6 +221,23 @@
|
|||
border-right-color: rgba(255, 255, 255, 0.25);
|
||||
border-top-color: rgba(255, 255, 255, 0.25);
|
||||
}
|
||||
|
||||
._tokamak-toolbar {
|
||||
background: rgba(100, 100, 100, 0.2);
|
||||
}
|
||||
._tokamak-toolbar-button {
|
||||
border: 1px solid rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
._tokamak-toolbar-button:hover {
|
||||
background-color: rgba(255, 255, 255, 0.05);
|
||||
}
|
||||
._tokamak-toolbar-button:active {
|
||||
background-color: rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
._tokamak-toolbar-textfield input {
|
||||
background-color: rgba(255, 255, 255, 0.05);
|
||||
color: #FFFFFF;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
|
Loading…
Reference in New Issue