kozenet_ui 0.1.5 → 0.1.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +79 -16
- data/app/assets/fonts/kozenet_ui/inter-latin.woff2 +0 -0
- data/app/assets/fonts/kozenet_ui/jetbrains-mono-latin.woff2 +0 -0
- data/app/assets/fonts/kozenet_ui/source-serif-4-latin.woff2 +0 -0
- data/app/assets/javascripts/kozenet_ui/index.js +226 -17
- data/app/assets/stylesheets/kozenet_ui/base.css +5 -0
- data/app/assets/stylesheets/kozenet_ui/components/avatar.css +4 -1
- data/app/assets/stylesheets/kozenet_ui/components/badge.css +11 -1
- data/app/assets/stylesheets/kozenet_ui/components/button.css +21 -1
- data/app/assets/stylesheets/kozenet_ui/components/header.css +227 -38
- data/app/assets/stylesheets/kozenet_ui/components/utilities.css +52 -1
- data/app/assets/stylesheets/kozenet_ui/fonts.css +37 -0
- data/app/assets/stylesheets/kozenet_ui/tokens.css +150 -53
- data/app/components/kozenet_ui/base_component.rb +21 -1
- data/app/components/kozenet_ui/header_component/action_button_component.html.erb +4 -2
- data/app/components/kozenet_ui/header_component/action_button_component.rb +76 -5
- data/app/components/kozenet_ui/header_component/nav_item_component.html.erb +1 -1
- data/app/components/kozenet_ui/header_component/nav_item_component.rb +6 -0
- data/app/components/kozenet_ui/header_component/user_menu_component.html.erb +5 -7
- data/app/components/kozenet_ui/header_component.html.erb +39 -30
- data/app/components/kozenet_ui/header_component.rb +26 -4
- data/app/helpers/kozenet_ui/component_helper.rb +82 -8
- data/app/helpers/kozenet_ui/icon_helper.rb +6 -19
- data/docs/README.md +25 -0
- data/docs/components/README.md +44 -0
- data/docs/components/avatar.md +73 -0
- data/docs/components/badge.md +74 -0
- data/docs/components/button.md +95 -0
- data/docs/components/header.md +199 -0
- data/docs/foundations/README.md +14 -0
- data/docs/foundations/fonts.md +136 -0
- data/lib/generators/kozenet_ui/install/install_generator.rb +94 -8
- data/lib/generators/kozenet_ui/install/templates/kozenet_ui.rb +3 -0
- data/lib/kozenet_ui/configuration.rb +35 -0
- data/lib/kozenet_ui/engine.rb +89 -14
- data/lib/kozenet_ui/theme/palette.rb +21 -7
- data/lib/kozenet_ui/theme/variants.rb +1 -0
- data/lib/kozenet_ui/version.rb +1 -1
- data/lib/kozenet_ui.rb +2 -0
- metadata +29 -22
- data/app/assets/images/kozenet_ui/icons/cart.svg +0 -1
- data/app/assets/images/kozenet_ui/icons/heart.svg +0 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 7dba396e448979a52c6053afc1eb12bdb9a15bad47b3e84f0df956c7f825f799
|
|
4
|
+
data.tar.gz: 34168a38aeda23eb60c02c0cb3af1d9c2885fec1faa60a30d48d7c1ed779e626
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 8be433e46c7ccf17ab464e323cd2232a660c6438910e6d0de676eccf342f325774c61c0b62a080f9ecbffab5fda1cebb5688251643a2cd43990e6259ec9ed56d
|
|
7
|
+
data.tar.gz: 3ad8f9ca442520bd17598550219cb376dc70525a022918cc4e9b8dcd4742bd4b0026706989ea35a33ef93fa36ef57e04b008a93f6db16021592e81ebe0dce4cd
|
data/README.md
CHANGED
|
@@ -1,56 +1,119 @@
|
|
|
1
|
+
[](https://github.com/kozenetpro/kozenet_ui/actions/workflows/main.yml?query=branch%3Amaster+job%3Aruby)
|
|
2
|
+
[](https://github.com/kozenetpro/kozenet_ui/actions/workflows/main.yml)
|
|
1
3
|
# Kozenet UI
|
|
2
4
|
|
|
3
|
-
[](https://github.com/kozenetpro/kozenet_ui/actions/workflows/main.yml)
|
|
4
|
-

|
|
5
|
-
|
|
6
5
|
Beautiful, minimal, Apple-inspired UI components for Rails.
|
|
7
6
|
|
|
8
7
|
## Installation
|
|
9
8
|
|
|
10
|
-
|
|
9
|
+
For local gem development, point the Rails app at this checkout:
|
|
11
10
|
|
|
12
11
|
```ruby
|
|
13
|
-
gem "kozenet_ui",
|
|
12
|
+
gem "kozenet_ui", path: "../.."
|
|
14
13
|
```
|
|
15
14
|
|
|
16
15
|
Then run:
|
|
17
16
|
|
|
18
17
|
```bash
|
|
19
18
|
bundle install
|
|
19
|
+
bin/rails generate kozenet_ui:install
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
For an app outside this repository, use GitHub:
|
|
23
|
+
|
|
24
|
+
```ruby
|
|
25
|
+
gem "kozenet_ui", github: "kozenetpro/kozenet_ui"
|
|
20
26
|
```
|
|
21
27
|
|
|
22
|
-
|
|
28
|
+
Or use the released RubyGems version:
|
|
23
29
|
|
|
24
30
|
```bash
|
|
25
31
|
bundle add kozenet_ui
|
|
26
32
|
```
|
|
27
33
|
|
|
28
|
-
|
|
34
|
+
Then run:
|
|
29
35
|
|
|
30
36
|
```bash
|
|
31
|
-
|
|
37
|
+
bin/rails generate kozenet_ui:install
|
|
32
38
|
```
|
|
33
39
|
|
|
40
|
+
`gem install kozenet_ui` is not enough for a Rails app. The app must have
|
|
41
|
+
`kozenet_ui` in its `Gemfile`, because Rails generators are loaded through
|
|
42
|
+
Bundler.
|
|
43
|
+
|
|
34
44
|
## Usage in your Rails app
|
|
35
45
|
|
|
36
|
-
|
|
46
|
+
Usage guides live in [docs](docs/README.md):
|
|
47
|
+
|
|
48
|
+
- [Components](docs/components/README.md)
|
|
49
|
+
- [Fonts](docs/foundations/fonts.md)
|
|
50
|
+
|
|
51
|
+
1. **Load Kozenet UI once from your layout `<head>`:**
|
|
52
|
+
```erb
|
|
53
|
+
<%= kozenet_ui_head_tags %>
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
This loads digested CSS assets, theme variables, and JavaScript. When using
|
|
57
|
+
importmap, keep this after `javascript_importmap_tags`.
|
|
58
|
+
|
|
59
|
+
In Rails 8 apps using `stylesheet_link_tag :app`, the install generator
|
|
60
|
+
copies Kozenet UI styles into `app/assets/stylesheets/kozenet_ui` and inserts:
|
|
61
|
+
|
|
37
62
|
```erb
|
|
38
|
-
<%=
|
|
63
|
+
<%= kozenet_ui_head_tags(stylesheets: false) %>
|
|
39
64
|
```
|
|
40
65
|
|
|
41
|
-
2. **
|
|
66
|
+
2. **Customize copied styles when needed:**
|
|
67
|
+
The install generator copies Kozenet UI CSS into
|
|
68
|
+
`app/assets/stylesheets/kozenet_ui`, so developers can edit the frontend
|
|
69
|
+
without touching gem internals.
|
|
70
|
+
|
|
71
|
+
3. **Only use CSS imports when you have a CSS bundler:**
|
|
42
72
|
```css
|
|
43
73
|
@import "kozenet_ui/tokens.css";
|
|
74
|
+
@import "kozenet_ui/fonts.css";
|
|
44
75
|
@import "kozenet_ui/base.css";
|
|
45
|
-
@import "kozenet_ui/components.css";
|
|
76
|
+
@import "kozenet_ui/components/button.css";
|
|
77
|
+
@import "kozenet_ui/components/header.css";
|
|
78
|
+
@import "kozenet_ui/components/avatar.css";
|
|
79
|
+
@import "kozenet_ui/components/badge.css";
|
|
80
|
+
@import "kozenet_ui/components/utilities.css";
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
For plain Propshaft/Sprockets apps, prefer `kozenet_ui_head_tags`, because
|
|
84
|
+
stylesheet tags generate digest-safe production asset URLs.
|
|
85
|
+
|
|
86
|
+
4. **Skip direct stylesheet tags if your app bundles the CSS itself:**
|
|
87
|
+
```erb
|
|
88
|
+
<%= kozenet_ui_head_tags(stylesheets: false) %>
|
|
46
89
|
```
|
|
47
90
|
|
|
48
|
-
|
|
49
|
-
|
|
91
|
+
5. **Use Heroicons by name:**
|
|
92
|
+
```erb
|
|
93
|
+
<% header.with_action_button(href: "/saved", icon: :heart, label: "Saved") %>
|
|
94
|
+
<% header.with_action_button(href: "/cart", icon: :shopping_cart, label: "Cart") %>
|
|
95
|
+
```
|
|
50
96
|
|
|
51
|
-
|
|
97
|
+
Kozenet UI normalizes Ruby-style names like `:shopping_cart` to Heroicons'
|
|
98
|
+
`shopping-cart` name.
|
|
99
|
+
|
|
100
|
+
6. **Customize colors and component defaults in `config/initializers/kozenet_ui.rb`:**
|
|
101
|
+
```ruby
|
|
102
|
+
KozenetUi.configure do |config|
|
|
103
|
+
config.theme = :system
|
|
104
|
+
config.stimulus_prefix = "kz"
|
|
105
|
+
config.component :header, sticky: true, blur: true
|
|
106
|
+
end
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
Per-render options still win:
|
|
110
|
+
```erb
|
|
111
|
+
<%= kz_header(sticky: false) do |header| %>
|
|
112
|
+
...
|
|
113
|
+
<% end %>
|
|
114
|
+
```
|
|
52
115
|
|
|
53
|
-
|
|
116
|
+
7. **Use components in your views:**
|
|
54
117
|
```erb
|
|
55
118
|
<%= render KozenetUi::HeaderComponent.new do |header| %>
|
|
56
119
|
...
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -1,23 +1,232 @@
|
|
|
1
1
|
// Kozenet UI JavaScript Entry Point
|
|
2
|
-
import { Application } from "@hotwired/stimulus"
|
|
2
|
+
import { Application, Controller } from "@hotwired/stimulus"
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
import MobileNavController from "./controllers/mobile_nav_controller"
|
|
7
|
-
import DropdownController from "./controllers/dropdown_controller"
|
|
8
|
-
import UserMenuController from "./controllers/user_menu_controller"
|
|
4
|
+
class HeaderController extends Controller {
|
|
5
|
+
static targets = ["container"]
|
|
9
6
|
|
|
10
|
-
|
|
11
|
-
|
|
7
|
+
connect() {
|
|
8
|
+
this.scrolled = false
|
|
9
|
+
}
|
|
12
10
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
window.Stimulus = application
|
|
11
|
+
handleScroll() {
|
|
12
|
+
const scrollPosition = window.scrollY
|
|
16
13
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
14
|
+
if (scrollPosition > 10 && !this.scrolled) {
|
|
15
|
+
this.scrolled = true
|
|
16
|
+
this.element.classList.add("kz-header-scrolled")
|
|
17
|
+
} else if (scrollPosition <= 10 && this.scrolled) {
|
|
18
|
+
this.scrolled = false
|
|
19
|
+
this.element.classList.remove("kz-header-scrolled")
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
22
|
|
|
23
|
-
|
|
23
|
+
toggleSearch(event) {
|
|
24
|
+
event.preventDefault()
|
|
25
|
+
const searchCol = this.element.querySelector(".kz-search-col")
|
|
26
|
+
|
|
27
|
+
if (searchCol) {
|
|
28
|
+
searchCol.classList.toggle("hidden")
|
|
29
|
+
searchCol.classList.toggle("block")
|
|
30
|
+
const input = searchCol.querySelector("input")
|
|
31
|
+
if (input) input.focus()
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
class MobileNavController extends Controller {
|
|
37
|
+
static targets = ["panel", "trigger"]
|
|
38
|
+
|
|
39
|
+
connect() {
|
|
40
|
+
this.isOpen = false
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
toggle(event) {
|
|
44
|
+
event.preventDefault()
|
|
45
|
+
this.isOpen = !this.isOpen
|
|
46
|
+
|
|
47
|
+
if (this.isOpen) {
|
|
48
|
+
this.open()
|
|
49
|
+
} else {
|
|
50
|
+
this.close()
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
open() {
|
|
55
|
+
if (!this.hasPanelTarget || !this.hasTriggerTarget) return
|
|
56
|
+
|
|
57
|
+
this.panelTarget.classList.remove("hidden", "scale-y-0")
|
|
58
|
+
this.panelTarget.classList.add("scale-y-100")
|
|
59
|
+
this.triggerTarget.setAttribute("aria-expanded", "true")
|
|
60
|
+
document.body.style.overflow = "hidden"
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
close() {
|
|
64
|
+
if (!this.hasPanelTarget || !this.hasTriggerTarget) return
|
|
65
|
+
|
|
66
|
+
this.panelTarget.classList.add("scale-y-0")
|
|
67
|
+
this.panelTarget.classList.remove("scale-y-100")
|
|
68
|
+
this.triggerTarget.setAttribute("aria-expanded", "false")
|
|
69
|
+
|
|
70
|
+
setTimeout(() => {
|
|
71
|
+
this.panelTarget.classList.add("hidden")
|
|
72
|
+
document.body.style.overflow = ""
|
|
73
|
+
}, 300)
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
disconnect() {
|
|
77
|
+
document.body.style.overflow = ""
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
class DropdownController extends Controller {
|
|
82
|
+
static targets = ["menu"]
|
|
83
|
+
|
|
84
|
+
connect() {
|
|
85
|
+
this.isOpen = false
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
toggle(event) {
|
|
89
|
+
event.preventDefault()
|
|
90
|
+
event.stopPropagation()
|
|
91
|
+
|
|
92
|
+
this.isOpen = !this.isOpen
|
|
93
|
+
|
|
94
|
+
if (this.isOpen) {
|
|
95
|
+
this.open()
|
|
96
|
+
} else {
|
|
97
|
+
this.close()
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
open() {
|
|
102
|
+
if (!this.hasMenuTarget) return
|
|
103
|
+
|
|
104
|
+
this.menuTarget.classList.remove("hidden")
|
|
105
|
+
this.menuTarget.classList.add("animate-fadeIn")
|
|
106
|
+
this.element.setAttribute("aria-expanded", "true")
|
|
107
|
+
|
|
108
|
+
setTimeout(() => {
|
|
109
|
+
document.addEventListener("click", this.closeOnOutsideClick)
|
|
110
|
+
}, 10)
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
close() {
|
|
114
|
+
if (!this.hasMenuTarget) return
|
|
115
|
+
|
|
116
|
+
this.menuTarget.classList.add("hidden")
|
|
117
|
+
this.menuTarget.classList.remove("animate-fadeIn")
|
|
118
|
+
this.element.setAttribute("aria-expanded", "false")
|
|
119
|
+
|
|
120
|
+
document.removeEventListener("click", this.closeOnOutsideClick)
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
closeOnOutsideClick = (event) => {
|
|
124
|
+
if (!this.element.contains(event.target)) {
|
|
125
|
+
this.close()
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
disconnect() {
|
|
130
|
+
document.removeEventListener("click", this.closeOnOutsideClick)
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
class UserMenuController extends Controller {
|
|
135
|
+
static targets = ["dropdown"]
|
|
136
|
+
|
|
137
|
+
connect() {
|
|
138
|
+
this.isOpen = false
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
toggle(event) {
|
|
142
|
+
event.preventDefault()
|
|
143
|
+
event.stopPropagation()
|
|
144
|
+
|
|
145
|
+
this.isOpen = !this.isOpen
|
|
146
|
+
|
|
147
|
+
if (this.isOpen) {
|
|
148
|
+
this.open()
|
|
149
|
+
} else {
|
|
150
|
+
this.close()
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
open() {
|
|
155
|
+
if (!this.hasDropdownTarget) return
|
|
156
|
+
|
|
157
|
+
this.dropdownTarget.classList.remove("hidden")
|
|
158
|
+
this.dropdownTarget.classList.add("animate-fadeIn")
|
|
159
|
+
this.element.querySelector("button")?.setAttribute("aria-expanded", "true")
|
|
160
|
+
|
|
161
|
+
setTimeout(() => {
|
|
162
|
+
document.addEventListener("click", this.handleOutsideClick)
|
|
163
|
+
document.addEventListener("keydown", this.handleEscape)
|
|
164
|
+
}, 10)
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
close() {
|
|
168
|
+
if (!this.hasDropdownTarget) return
|
|
169
|
+
|
|
170
|
+
this.dropdownTarget.classList.add("hidden")
|
|
171
|
+
this.dropdownTarget.classList.remove("animate-fadeIn")
|
|
172
|
+
this.element.querySelector("button")?.setAttribute("aria-expanded", "false")
|
|
173
|
+
|
|
174
|
+
document.removeEventListener("click", this.handleOutsideClick)
|
|
175
|
+
document.removeEventListener("keydown", this.handleEscape)
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
handleOutsideClick = (event) => {
|
|
179
|
+
if (!this.element.contains(event.target)) {
|
|
180
|
+
this.close()
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
handleEscape = (event) => {
|
|
185
|
+
if (event.key === "Escape") {
|
|
186
|
+
this.close()
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
disconnect() {
|
|
191
|
+
document.removeEventListener("click", this.handleOutsideClick)
|
|
192
|
+
document.removeEventListener("keydown", this.handleEscape)
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
function configuredStimulusPrefix() {
|
|
197
|
+
return document.querySelector("meta[name='kozenet-ui-stimulus-prefix']")?.content?.trim() || "kz"
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// Auto-initialization function
|
|
201
|
+
function startKozenetUi() {
|
|
202
|
+
let application = window.Stimulus
|
|
203
|
+
|
|
204
|
+
if (!application) {
|
|
205
|
+
application = Application.start()
|
|
206
|
+
application.debug = false
|
|
207
|
+
window.Stimulus = application
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
window.KozenetUi = Object.assign(window.KozenetUi || {}, {
|
|
211
|
+
stimulusPrefix: configuredStimulusPrefix()
|
|
212
|
+
})
|
|
213
|
+
|
|
214
|
+
if (!window.KozenetUi.controllersRegistered) {
|
|
215
|
+
Array.from(new Set(["kz", window.KozenetUi.stimulusPrefix])).forEach(prefix => {
|
|
216
|
+
application.register(`${prefix}-header`, HeaderController)
|
|
217
|
+
application.register(`${prefix}-mobile-nav`, MobileNavController)
|
|
218
|
+
application.register(`${prefix}-dropdown`, DropdownController)
|
|
219
|
+
application.register(`${prefix}-user-menu`, UserMenuController)
|
|
220
|
+
})
|
|
221
|
+
window.KozenetUi.controllersRegistered = true
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
// Ensure we initialize after the host app has a chance to set up window.Stimulus
|
|
226
|
+
if (document.readyState === "loading") {
|
|
227
|
+
document.addEventListener("DOMContentLoaded", () => setTimeout(startKozenetUi, 10))
|
|
228
|
+
} else {
|
|
229
|
+
setTimeout(startKozenetUi, 10)
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
export { HeaderController, MobileNavController, DropdownController, UserMenuController, startKozenetUi as start }
|
|
@@ -2,6 +2,9 @@
|
|
|
2
2
|
/* Avatar base */
|
|
3
3
|
.kz-avatar {
|
|
4
4
|
position: relative;
|
|
5
|
+
display: inline-flex;
|
|
6
|
+
align-items: center;
|
|
7
|
+
justify-content: center;
|
|
5
8
|
flex-shrink: 0;
|
|
6
9
|
border-radius: var(--kz-radius-md);
|
|
7
10
|
background: linear-gradient(135deg, #6366f1, #0ea5e9);
|
|
@@ -85,4 +88,4 @@
|
|
|
85
88
|
height: 100%;
|
|
86
89
|
object-fit: cover;
|
|
87
90
|
}
|
|
88
|
-
}
|
|
91
|
+
}
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
@layer components {
|
|
2
2
|
/* Badge base */
|
|
3
3
|
.kz-badge {
|
|
4
|
+
display: inline-flex;
|
|
5
|
+
align-items: center;
|
|
6
|
+
gap: 0.25rem;
|
|
4
7
|
border-radius: var(--kz-radius-sm);
|
|
5
8
|
font-weight: var(--kz-font-weight-bold);
|
|
6
9
|
letter-spacing: 0.05em;
|
|
@@ -47,6 +50,13 @@
|
|
|
47
50
|
box-shadow: 0 2px 8px -2px rgba(139, 92, 246, 0.4);
|
|
48
51
|
}
|
|
49
52
|
|
|
53
|
+
.kz-badge.kz-badge-accent,
|
|
54
|
+
.kz-badge.kz-variant-accent {
|
|
55
|
+
background: linear-gradient(120deg, #06b6d4, #0891b2);
|
|
56
|
+
color: white;
|
|
57
|
+
box-shadow: 0 2px 8px -2px rgba(6, 182, 212, 0.4);
|
|
58
|
+
}
|
|
59
|
+
|
|
50
60
|
.kz-badge.kz-badge-success,
|
|
51
61
|
.kz-badge.kz-variant-success {
|
|
52
62
|
background: linear-gradient(120deg, #10b981, #059669);
|
|
@@ -98,4 +108,4 @@
|
|
|
98
108
|
width: 0.875em;
|
|
99
109
|
height: 0.875em;
|
|
100
110
|
}
|
|
101
|
-
}
|
|
111
|
+
}
|
|
@@ -2,6 +2,10 @@
|
|
|
2
2
|
/* Base button styles */
|
|
3
3
|
.kz-btn {
|
|
4
4
|
position: relative;
|
|
5
|
+
display: inline-flex;
|
|
6
|
+
align-items: center;
|
|
7
|
+
justify-content: center;
|
|
8
|
+
gap: 0.5rem;
|
|
5
9
|
border: 0;
|
|
6
10
|
cursor: pointer;
|
|
7
11
|
user-select: none;
|
|
@@ -136,6 +140,22 @@
|
|
|
136
140
|
background: rgba(255,255,255,0.08);
|
|
137
141
|
}
|
|
138
142
|
|
|
143
|
+
@media (prefers-color-scheme: dark) {
|
|
144
|
+
:root:not([data-theme="light"]):not(.light) .kz-btn.kz-variant-secondary {
|
|
145
|
+
background: linear-gradient(135deg, rgba(255,255,255,.12), rgba(255,255,255,.08));
|
|
146
|
+
border-color: rgba(255,255,255,0.1);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
:root:not([data-theme="light"]):not(.light) .kz-btn.kz-variant-secondary:hover:not(:disabled) {
|
|
150
|
+
background: linear-gradient(135deg, rgba(255,255,255,.18), rgba(255,255,255,.12));
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
:root:not([data-theme="light"]):not(.light) .kz-btn.kz-variant-ghost:hover:not(:disabled),
|
|
154
|
+
:root:not([data-theme="light"]):not(.light) .kz-btn.kz-variant-outline:hover:not(:disabled) {
|
|
155
|
+
background: rgba(255,255,255,0.08);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
139
159
|
/* Accent variant */
|
|
140
160
|
.kz-btn.kz-variant-accent {
|
|
141
161
|
background: linear-gradient(125deg, #6366f1, #0ea5e9 55%, #06b6d4);
|
|
@@ -227,4 +247,4 @@
|
|
|
227
247
|
transform: none;
|
|
228
248
|
}
|
|
229
249
|
}
|
|
230
|
-
}
|
|
250
|
+
}
|