phlex_kit 0.3.0 → 0.5.0
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 +15 -2
- data/app/assets/stylesheets/phlex_kit/_tokens.css +16 -0
- data/app/assets/stylesheets/phlex_kit/phlex_kit.css +1 -0
- data/app/components/phlex_kit/alert/alert.css +60 -22
- data/app/components/phlex_kit/alert/alert.rb +11 -7
- data/app/components/phlex_kit/alert/alert_action.rb +14 -0
- data/app/components/phlex_kit/alert/alert_title.rb +3 -2
- data/app/components/phlex_kit/alert_dialog/alert_dialog.css +5 -2
- data/app/components/phlex_kit/avatar/avatar.css +80 -9
- data/app/components/phlex_kit/avatar/avatar.rb +6 -4
- data/app/components/phlex_kit/avatar/avatar_badge.rb +15 -0
- data/app/components/phlex_kit/avatar/avatar_group_count.rb +14 -0
- data/app/components/phlex_kit/badge/badge.css +61 -39
- data/app/components/phlex_kit/badge/badge.rb +24 -7
- data/app/components/phlex_kit/breadcrumb/breadcrumb.css +2 -2
- data/app/components/phlex_kit/bubble/bubble.css +49 -8
- data/app/components/phlex_kit/button/button.css +71 -26
- data/app/components/phlex_kit/button/button.rb +20 -13
- data/app/components/phlex_kit/button_group/button_group.css +59 -8
- data/app/components/phlex_kit/button_group/button_group.rb +11 -5
- data/app/components/phlex_kit/button_group/button_group_separator.rb +14 -0
- data/app/components/phlex_kit/button_group/button_group_text.rb +14 -0
- data/app/components/phlex_kit/calendar/calendar.css +66 -15
- data/app/components/phlex_kit/calendar/calendar.rb +87 -19
- data/app/components/phlex_kit/calendar/calendar_controller.js +226 -75
- data/app/components/phlex_kit/calendar/calendar_days.rb +7 -6
- data/app/components/phlex_kit/calendar/calendar_weekdays.rb +3 -1
- data/app/components/phlex_kit/checkbox/checkbox.css +52 -7
- data/app/components/phlex_kit/collapsible/collapsible.css +10 -1
- data/app/components/phlex_kit/collapsible/collapsible_controller.js +9 -2
- data/app/components/phlex_kit/combobox/combobox.css +37 -3
- data/app/components/phlex_kit/combobox/combobox.rb +3 -1
- data/app/components/phlex_kit/combobox/combobox_controller.js +9 -1
- data/app/components/phlex_kit/combobox/combobox_input_trigger.rb +7 -2
- data/app/components/phlex_kit/command/command.css +58 -22
- data/app/components/phlex_kit/command/command_controller.js +3 -1
- data/app/components/phlex_kit/command/command_input.rb +29 -25
- data/app/components/phlex_kit/command/command_separator.rb +18 -0
- data/app/components/phlex_kit/command/command_shortcut.rb +13 -0
- data/app/components/phlex_kit/context_menu/context_menu.css +78 -6
- data/app/components/phlex_kit/context_menu/context_menu_checkbox_item.rb +27 -0
- data/app/components/phlex_kit/context_menu/context_menu_group.rb +10 -0
- data/app/components/phlex_kit/context_menu/context_menu_item.rb +13 -3
- data/app/components/phlex_kit/context_menu/context_menu_radio_group.rb +10 -0
- data/app/components/phlex_kit/context_menu/context_menu_radio_item.rb +30 -0
- data/app/components/phlex_kit/context_menu/context_menu_shortcut.rb +11 -0
- data/app/components/phlex_kit/context_menu/context_menu_sub.rb +11 -0
- data/app/components/phlex_kit/context_menu/context_menu_sub_content.rb +12 -0
- data/app/components/phlex_kit/context_menu/context_menu_sub_trigger.rb +17 -0
- data/app/components/phlex_kit/dialog/dialog.css +34 -16
- data/app/components/phlex_kit/dialog/dialog_close.rb +13 -0
- data/app/components/phlex_kit/dialog/dialog_content.rb +13 -5
- data/app/components/phlex_kit/drawer/drawer.css +56 -17
- data/app/components/phlex_kit/drawer/drawer_content.rb +8 -4
- data/app/components/phlex_kit/empty/empty.css +13 -8
- data/app/components/phlex_kit/field/field.css +152 -0
- data/app/components/phlex_kit/field/field.rb +35 -0
- data/app/components/phlex_kit/field/field_content.rb +11 -0
- data/app/components/phlex_kit/field/field_description.rb +10 -0
- data/app/components/phlex_kit/field/field_error.rb +29 -0
- data/app/components/phlex_kit/field/field_group.rb +12 -0
- data/app/components/phlex_kit/field/field_label.rb +12 -0
- data/app/components/phlex_kit/field/field_legend.rb +17 -0
- data/app/components/phlex_kit/field/field_separator.rb +15 -0
- data/app/components/phlex_kit/field/field_set.rb +10 -0
- data/app/components/phlex_kit/field/field_title.rb +11 -0
- data/app/components/phlex_kit/hover_card/hover_card.css +12 -4
- data/app/components/phlex_kit/hover_card/hover_card_content.rb +11 -2
- data/app/components/phlex_kit/input/input.css +45 -11
- data/app/components/phlex_kit/input_group/input_group.css +88 -12
- data/app/components/phlex_kit/input_group/input_group_addon.rb +11 -4
- data/app/components/phlex_kit/input_group/input_group_button.rb +18 -0
- data/app/components/phlex_kit/input_otp/input_otp.css +29 -5
- data/app/components/phlex_kit/item/item.css +56 -8
- data/app/components/phlex_kit/item/item.rb +13 -3
- data/app/components/phlex_kit/item/item_footer.rb +8 -0
- data/app/components/phlex_kit/item/item_header.rb +8 -0
- data/app/components/phlex_kit/item/item_media.rb +13 -3
- data/app/components/phlex_kit/item/item_separator.rb +10 -0
- data/app/components/phlex_kit/kbd/kbd.css +10 -0
- data/app/components/phlex_kit/marker/marker.css +29 -9
- data/app/components/phlex_kit/marker/marker.rb +13 -3
- data/app/components/phlex_kit/menubar/menubar.css +88 -17
- data/app/components/phlex_kit/menubar/menubar_checkbox_item.rb +26 -0
- data/app/components/phlex_kit/menubar/menubar_group.rb +10 -0
- data/app/components/phlex_kit/menubar/menubar_item.rb +9 -4
- data/app/components/phlex_kit/menubar/menubar_label.rb +10 -0
- data/app/components/phlex_kit/menubar/menubar_radio_group.rb +10 -0
- data/app/components/phlex_kit/menubar/menubar_radio_item.rb +29 -0
- data/app/components/phlex_kit/menubar/menubar_shortcut.rb +10 -0
- data/app/components/phlex_kit/menubar/menubar_sub.rb +10 -0
- data/app/components/phlex_kit/menubar/menubar_sub_content.rb +11 -0
- data/app/components/phlex_kit/menubar/menubar_sub_trigger.rb +17 -0
- data/app/components/phlex_kit/message/message.css +8 -1
- data/app/components/phlex_kit/message_scroller/message_scroller.css +18 -0
- data/app/components/phlex_kit/native_select/native_select.css +25 -5
- data/app/components/phlex_kit/navigation_menu/navigation_menu.css +9 -6
- data/app/components/phlex_kit/pagination/pagination.css +10 -3
- data/app/components/phlex_kit/pagination/pagination_link.rb +21 -0
- data/app/components/phlex_kit/pagination/pagination_next.rb +20 -0
- data/app/components/phlex_kit/pagination/pagination_previous.rb +21 -0
- data/app/components/phlex_kit/popover/popover.css +15 -4
- data/app/components/phlex_kit/popover/popover_content.rb +11 -2
- data/app/components/phlex_kit/popover/popover_description.rb +10 -0
- data/app/components/phlex_kit/popover/popover_header.rb +10 -0
- data/app/components/phlex_kit/popover/popover_title.rb +10 -0
- data/app/components/phlex_kit/progress/progress.css +5 -5
- data/app/components/phlex_kit/radio_button/radio_button.css +46 -2
- data/app/components/phlex_kit/radio_group/radio_group.css +2 -2
- data/app/components/phlex_kit/resizable/resizable.css +17 -0
- data/app/components/phlex_kit/resizable/resizable_handle.rb +7 -3
- data/app/components/phlex_kit/select/select.css +46 -10
- data/app/components/phlex_kit/select/select_separator.rb +10 -0
- data/app/components/phlex_kit/select/select_trigger.rb +5 -2
- data/app/components/phlex_kit/sheet/sheet.css +18 -9
- data/app/components/phlex_kit/sheet/sheet_close.rb +10 -0
- data/app/components/phlex_kit/sheet/sheet_content.rb +8 -4
- data/app/components/phlex_kit/sidebar/sidebar.css +126 -2
- data/app/components/phlex_kit/sidebar/sidebar.rb +5 -5
- data/app/components/phlex_kit/sidebar/sidebar_controller.js +39 -0
- data/app/components/phlex_kit/sidebar/sidebar_menu_button.rb +8 -3
- data/app/components/phlex_kit/sidebar/sidebar_rail.rb +21 -0
- data/app/components/phlex_kit/sidebar/sidebar_trigger.rb +23 -0
- data/app/components/phlex_kit/sidebar/sidebar_wrapper.rb +54 -2
- data/app/components/phlex_kit/skeleton/skeleton.css +1 -1
- data/app/components/phlex_kit/slider/slider.css +33 -12
- data/app/components/phlex_kit/switch/switch.css +50 -13
- data/app/components/phlex_kit/switch/switch.rb +5 -2
- data/app/components/phlex_kit/table/table.css +8 -4
- data/app/components/phlex_kit/tabs/tabs.css +72 -8
- data/app/components/phlex_kit/tabs/tabs.rb +7 -2
- data/app/components/phlex_kit/tabs/tabs_list.rb +11 -2
- data/app/components/phlex_kit/textarea/textarea.css +33 -13
- data/app/components/phlex_kit/toast/toast.css +1 -1
- data/app/components/phlex_kit/toggle/toggle.css +25 -10
- data/app/components/phlex_kit/toggle_group/toggle_group.css +7 -6
- data/app/components/phlex_kit/tooltip/tooltip.css +37 -10
- data/app/components/phlex_kit/tooltip/tooltip_content.rb +9 -4
- data/app/javascript/phlex_kit/controllers/index.js +2 -0
- data/lib/phlex_kit/version.rb +1 -1
- metadata +52 -1
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
module PhlexKit
|
|
2
|
+
# Invisible grab strip along the sidebar's trailing edge — clicking it
|
|
3
|
+
# toggles the collapse, like shadcn/ui's SidebarRail. Place it as the last
|
|
4
|
+
# child of a Sidebar inside a collapsible wrapper. See sidebar.rb.
|
|
5
|
+
class SidebarRail < BaseComponent
|
|
6
|
+
def initialize(**attrs)
|
|
7
|
+
@attrs = attrs
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def view_template
|
|
11
|
+
button(**mix({
|
|
12
|
+
type: :button,
|
|
13
|
+
class: "pk-sidebar-rail",
|
|
14
|
+
aria_label: "Toggle sidebar",
|
|
15
|
+
tabindex: "-1",
|
|
16
|
+
title: "Toggle sidebar",
|
|
17
|
+
data: { action: "click->phlex-kit--sidebar#toggle" }
|
|
18
|
+
}, @attrs))
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
module PhlexKit
|
|
2
|
+
# The hamburger that toggles an offcanvas sidebar, ported from shadcn/ui's
|
|
3
|
+
# SidebarTrigger. Place it anywhere inside a
|
|
4
|
+
# SidebarWrapper(collapsible: :offcanvas) — typically at the top of the
|
|
5
|
+
# SidebarInset. Renders the :menu icon unless a block supplies its own
|
|
6
|
+
# content. Hidden by CSS unless the wrapper is offcanvas. See sidebar.rb.
|
|
7
|
+
class SidebarTrigger < BaseComponent
|
|
8
|
+
def initialize(**attrs)
|
|
9
|
+
@attrs = attrs
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def view_template(&block)
|
|
13
|
+
button(**mix({
|
|
14
|
+
type: :button,
|
|
15
|
+
class: "pk-sidebar-trigger",
|
|
16
|
+
aria_label: "Toggle sidebar",
|
|
17
|
+
data: { action: "click->phlex-kit--sidebar#toggle" }
|
|
18
|
+
}, @attrs)) do
|
|
19
|
+
block ? yield : render(Icon.new(:menu, size: nil))
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -1,13 +1,65 @@
|
|
|
1
1
|
module PhlexKit
|
|
2
2
|
# The page-level flex row that holds a PhlexKit::Sidebar + a PhlexKit::SidebarInset.
|
|
3
|
+
#
|
|
4
|
+
# `collapsible:` (shadcn/ui's Sidebar `collapsible` prop, held here because the
|
|
5
|
+
# wrapper is the Stimulus scope shared by rail, trigger and scrim):
|
|
6
|
+
# :none — static rail (default).
|
|
7
|
+
# :offcanvas — the rail hides/reveals via a PhlexKit::SidebarTrigger. On
|
|
8
|
+
# desktop it slides out of the layout; below 768px it overlays
|
|
9
|
+
# as a fixed drawer behind a click-to-close scrim, closed by
|
|
10
|
+
# Escape and before Turbo caches the page.
|
|
11
|
+
# :icon — like :offcanvas, but on desktop the rail collapses to a
|
|
12
|
+
# 3rem icon strip instead of leaving: labels hide, menu
|
|
13
|
+
# buttons become icon squares (add `tooltip:` to
|
|
14
|
+
# SidebarMenuButton for hover labels), groups/badges/subs
|
|
15
|
+
# disappear. Mobile behaves like :offcanvas.
|
|
16
|
+
#
|
|
17
|
+
# State is DOM-only: `data-collapsed` (desktop) / `data-open` (mobile
|
|
18
|
+
# drawer). ⌘B/Ctrl+B toggles. The desktop state persists in a
|
|
19
|
+
# `pk_sidebar_state` cookie ("collapsed"/"expanded") — pass
|
|
20
|
+
# `default_collapsed: cookies[:pk_sidebar_state] == "collapsed"` from the
|
|
21
|
+
# host layout to render the collapsed rail server-side with no flash.
|
|
22
|
+
# Add a PhlexKit::SidebarRail inside the Sidebar for the edge grab-strip.
|
|
3
23
|
# See sidebar.rb.
|
|
4
24
|
class SidebarWrapper < BaseComponent
|
|
5
|
-
|
|
25
|
+
COLLAPSIBLE = { none: nil, offcanvas: "collapsible-offcanvas", icon: "collapsible-icon" }.freeze
|
|
26
|
+
|
|
27
|
+
def initialize(collapsible: :none, default_collapsed: false, **attrs)
|
|
28
|
+
@collapsible = collapsible.to_sym
|
|
29
|
+
@default_collapsed = default_collapsed
|
|
6
30
|
@attrs = attrs
|
|
7
31
|
end
|
|
8
32
|
|
|
9
33
|
def view_template(&block)
|
|
10
|
-
|
|
34
|
+
unless collapsible?
|
|
35
|
+
return div(**mix({ class: classes }, @attrs), &block)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
base = {
|
|
39
|
+
class: classes,
|
|
40
|
+
data: {
|
|
41
|
+
controller: "phlex-kit--sidebar",
|
|
42
|
+
action: "keydown.esc@window->phlex-kit--sidebar#closeMobile " \
|
|
43
|
+
"keydown.meta+b@window->phlex-kit--sidebar#toggle:prevent " \
|
|
44
|
+
"keydown.ctrl+b@window->phlex-kit--sidebar#toggle:prevent " \
|
|
45
|
+
"turbo:before-cache@window->phlex-kit--sidebar#closeMobile"
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
base["data-collapsed"] = "" if @default_collapsed
|
|
49
|
+
|
|
50
|
+
div(**mix(base, @attrs)) do
|
|
51
|
+
yield if block
|
|
52
|
+
button(type: :button, class: "pk-sidebar-scrim", aria_label: "Close sidebar",
|
|
53
|
+
tabindex: "-1", data: { action: "click->phlex-kit--sidebar#closeMobile" })
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
private
|
|
58
|
+
|
|
59
|
+
def collapsible? = @collapsible != :none
|
|
60
|
+
|
|
61
|
+
def classes
|
|
62
|
+
[ "pk-sidebar-wrapper", COLLAPSIBLE.fetch(@collapsible) ].compact.join(" ")
|
|
11
63
|
end
|
|
12
64
|
end
|
|
13
65
|
end
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/* Co-located with skeleton.rb. Theme tokens come from the global stylesheet. */
|
|
2
2
|
.pk-skeleton {
|
|
3
3
|
border-radius: calc(var(--pk-radius) - 2px);
|
|
4
|
-
background:
|
|
4
|
+
background: var(--pk-surface-2);
|
|
5
5
|
animation: pk-pulse 1.5s cubic-bezier(.4, 0, .6, 1) infinite;
|
|
6
6
|
}
|
|
7
7
|
@keyframes pk-pulse { 50% { opacity: .5; } }
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
}
|
|
13
13
|
.pk-slider:focus-visible { outline: none; }
|
|
14
14
|
.pk-slider::-webkit-slider-runnable-track {
|
|
15
|
-
height: .
|
|
15
|
+
height: .25rem;
|
|
16
16
|
border-radius: 9999px;
|
|
17
17
|
background: linear-gradient(to right,
|
|
18
18
|
var(--pk-brand) var(--pk-slider-progress, 50%),
|
|
@@ -20,33 +20,54 @@
|
|
|
20
20
|
}
|
|
21
21
|
.pk-slider::-webkit-slider-thumb {
|
|
22
22
|
-webkit-appearance: none;
|
|
23
|
-
width:
|
|
24
|
-
height:
|
|
25
|
-
margin-top: -0.
|
|
23
|
+
width: .75rem;
|
|
24
|
+
height: .75rem;
|
|
25
|
+
margin-top: -0.25rem;
|
|
26
26
|
border-radius: 9999px;
|
|
27
|
-
border: 1px solid var(--pk-
|
|
28
|
-
background:
|
|
27
|
+
border: 1px solid var(--pk-ring);
|
|
28
|
+
background: #fff;
|
|
29
29
|
box-shadow: 0 1px 2px rgb(0 0 0 / .25);
|
|
30
30
|
transition: box-shadow .15s ease;
|
|
31
31
|
}
|
|
32
|
+
.pk-slider:hover::-webkit-slider-thumb,
|
|
33
|
+
.pk-slider:active::-webkit-slider-thumb {
|
|
34
|
+
box-shadow: 0 0 0 3px color-mix(in oklab, var(--pk-ring) 50%, transparent);
|
|
35
|
+
}
|
|
32
36
|
.pk-slider:focus-visible::-webkit-slider-thumb {
|
|
33
37
|
box-shadow: 0 0 0 3px color-mix(in oklab, var(--pk-ring) 50%, transparent);
|
|
34
38
|
}
|
|
35
39
|
.pk-slider::-moz-range-track {
|
|
36
|
-
height: .
|
|
40
|
+
height: .25rem;
|
|
37
41
|
border-radius: 9999px;
|
|
38
42
|
background: var(--pk-surface-2);
|
|
39
43
|
}
|
|
40
44
|
.pk-slider::-moz-range-progress {
|
|
41
|
-
height: .
|
|
45
|
+
height: .25rem;
|
|
42
46
|
border-radius: 9999px;
|
|
43
47
|
background: var(--pk-brand);
|
|
44
48
|
}
|
|
45
49
|
.pk-slider::-moz-range-thumb {
|
|
46
|
-
width:
|
|
47
|
-
height:
|
|
50
|
+
width: .75rem;
|
|
51
|
+
height: .75rem;
|
|
48
52
|
border-radius: 9999px;
|
|
49
|
-
border: 1px solid var(--pk-
|
|
50
|
-
background:
|
|
53
|
+
border: 1px solid var(--pk-ring);
|
|
54
|
+
background: #fff;
|
|
55
|
+
}
|
|
56
|
+
.pk-slider:hover::-moz-range-thumb,
|
|
57
|
+
.pk-slider:active::-moz-range-thumb {
|
|
58
|
+
box-shadow: 0 0 0 3px color-mix(in oklab, var(--pk-ring) 50%, transparent);
|
|
51
59
|
}
|
|
52
60
|
.pk-slider:disabled { opacity: .5; cursor: not-allowed; }
|
|
61
|
+
/* Vertical: modern writing-mode flip (min-h-40 like theirs). */
|
|
62
|
+
.pk-slider.vertical {
|
|
63
|
+
writing-mode: vertical-lr;
|
|
64
|
+
direction: rtl;
|
|
65
|
+
width: 1rem;
|
|
66
|
+
height: auto;
|
|
67
|
+
min-height: 10rem;
|
|
68
|
+
}
|
|
69
|
+
.pk-slider.vertical::-webkit-slider-runnable-track {
|
|
70
|
+
background: linear-gradient(to top,
|
|
71
|
+
var(--pk-brand) var(--pk-slider-progress, 50%),
|
|
72
|
+
var(--pk-surface-2) var(--pk-slider-progress, 50%));
|
|
73
|
+
}
|
|
@@ -1,28 +1,65 @@
|
|
|
1
|
-
/* Co-located with switch.rb.
|
|
1
|
+
/* Co-located with switch.rb. Matched to shadcn/ui's current switch (nova):
|
|
2
|
+
32×18.4px track (sm 24×14) with a size-4 thumb sliding calc(100%-2px);
|
|
3
|
+
unchecked fills with the input tone (stronger in dark), checked with the
|
|
4
|
+
brand; the thumb is the page background in light, foreground in dark
|
|
5
|
+
(brand-ink when checked). Pure CSS (:has(:checked)), no Stimulus. */
|
|
2
6
|
.pk-switch {
|
|
7
|
+
position: relative;
|
|
3
8
|
display: inline-flex;
|
|
4
|
-
height:
|
|
5
|
-
width:
|
|
9
|
+
height: 18.4px;
|
|
10
|
+
width: 32px;
|
|
6
11
|
flex: none;
|
|
7
12
|
cursor: pointer;
|
|
8
13
|
align-items: center;
|
|
9
|
-
border:
|
|
14
|
+
border: 1px solid transparent;
|
|
10
15
|
border-radius: 9999px;
|
|
11
|
-
background: var(--pk-
|
|
12
|
-
transition: background-color .15s ease;
|
|
16
|
+
background: color-mix(in oklab, var(--pk-input) 80%, transparent);
|
|
17
|
+
transition: background-color .15s ease, box-shadow .15s ease;
|
|
13
18
|
}
|
|
19
|
+
.pk-switch.sm { height: 14px; width: 24px; }
|
|
14
20
|
.pk-switch:has(.pk-switch-input:checked) { background: var(--pk-brand); }
|
|
15
21
|
.pk-switch:has(.pk-switch-input:disabled) { cursor: not-allowed; opacity: .5; }
|
|
16
|
-
.pk-switch-input {
|
|
22
|
+
.pk-switch:has(.pk-switch-input:focus-visible) {
|
|
23
|
+
border-color: var(--pk-ring);
|
|
24
|
+
box-shadow: 0 0 0 3px color-mix(in oklab, var(--pk-ring) 50%, transparent);
|
|
25
|
+
}
|
|
26
|
+
.pk-switch:has(.pk-switch-input[aria-invalid="true"]) {
|
|
27
|
+
border-color: var(--pk-red);
|
|
28
|
+
box-shadow: 0 0 0 3px color-mix(in oklab, var(--pk-red) 40%, transparent);
|
|
29
|
+
}
|
|
30
|
+
.pk-switch-input {
|
|
31
|
+
position: absolute;
|
|
32
|
+
width: 1px;
|
|
33
|
+
height: 1px;
|
|
34
|
+
opacity: 0;
|
|
35
|
+
pointer-events: none;
|
|
36
|
+
}
|
|
17
37
|
.pk-switch-thumb {
|
|
18
38
|
pointer-events: none;
|
|
19
39
|
display: block;
|
|
20
|
-
height:
|
|
21
|
-
width:
|
|
40
|
+
height: 1rem;
|
|
41
|
+
width: 1rem;
|
|
22
42
|
border-radius: 9999px;
|
|
23
|
-
background: var(--pk-
|
|
24
|
-
|
|
25
|
-
transition: transform .15s ease;
|
|
43
|
+
background: var(--pk-text);
|
|
44
|
+
transition: transform .15s ease, background-color .15s ease;
|
|
26
45
|
transform: translateX(0);
|
|
27
46
|
}
|
|
28
|
-
.pk-switch
|
|
47
|
+
.pk-switch.sm .pk-switch-thumb { height: .75rem; width: .75rem; }
|
|
48
|
+
.pk-switch:has(.pk-switch-input:checked) .pk-switch-thumb {
|
|
49
|
+
transform: translateX(calc(100% - 2px));
|
|
50
|
+
background: var(--pk-brand-ink);
|
|
51
|
+
}
|
|
52
|
+
:root[data-theme="light"] .pk-switch { background: var(--pk-input); }
|
|
53
|
+
:root[data-theme="light"] .pk-switch:has(.pk-switch-input:checked) { background: var(--pk-brand); }
|
|
54
|
+
:root[data-theme="light"] .pk-switch-thumb { background: var(--pk-bg) !important; }
|
|
55
|
+
:root[data-theme="light"] .pk-switch:has(.pk-switch-input[aria-invalid="true"]) {
|
|
56
|
+
box-shadow: 0 0 0 3px color-mix(in oklab, var(--pk-red) 20%, transparent);
|
|
57
|
+
}
|
|
58
|
+
@media (prefers-color-scheme: light) {
|
|
59
|
+
:root[data-theme="system"] .pk-switch { background: var(--pk-input); }
|
|
60
|
+
:root[data-theme="system"] .pk-switch:has(.pk-switch-input:checked) { background: var(--pk-brand); }
|
|
61
|
+
:root[data-theme="system"] .pk-switch-thumb { background: var(--pk-bg) !important; }
|
|
62
|
+
:root[data-theme="system"] .pk-switch:has(.pk-switch-input[aria-invalid="true"]) {
|
|
63
|
+
box-shadow: 0 0 0 3px color-mix(in oklab, var(--pk-red) 20%, transparent);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
@@ -3,15 +3,18 @@ module PhlexKit
|
|
|
3
3
|
# ruby_ui's RubyUI::Switch — pure CSS (`:has(:checked)`), no Stimulus. Emits an
|
|
4
4
|
# optional hidden field so an unchecked box still posts a value (Rails idiom).
|
|
5
5
|
class Switch < BaseComponent
|
|
6
|
-
|
|
6
|
+
SIZES = { md: nil, sm: "sm" }.freeze
|
|
7
|
+
|
|
8
|
+
def initialize(include_hidden: true, checked_value: "1", unchecked_value: "0", size: :md, **attrs)
|
|
7
9
|
@include_hidden = include_hidden
|
|
8
10
|
@checked_value = checked_value
|
|
9
11
|
@unchecked_value = unchecked_value
|
|
12
|
+
@size = size.to_sym
|
|
10
13
|
@attrs = attrs
|
|
11
14
|
end
|
|
12
15
|
|
|
13
16
|
def view_template
|
|
14
|
-
label(**mix({ role: "switch", class: "pk-switch" }, {})) do
|
|
17
|
+
label(**mix({ role: "switch", class: [ "pk-switch", SIZES.fetch(@size) ].compact.join(" ") }, {})) do
|
|
15
18
|
input(type: "hidden", name: @attrs[:name], value: @unchecked_value) if @include_hidden
|
|
16
19
|
input(**mix({ class: "pk-switch-input" }, @attrs).merge(type: "checkbox", value: @checked_value))
|
|
17
20
|
span(class: "pk-switch-thumb")
|
|
@@ -7,10 +7,11 @@
|
|
|
7
7
|
|
|
8
8
|
.pk-table-header .pk-table-row { border-bottom: 1px solid var(--pk-border); }
|
|
9
9
|
.pk-table-body .pk-table-row:last-child { border-bottom: 0; }
|
|
10
|
-
.pk-table-footer { border-top: 1px solid var(--pk-border); font-weight: 500; }
|
|
10
|
+
.pk-table-footer { border-top: 1px solid var(--pk-border); font-weight: 500; background: color-mix(in oklab, var(--pk-surface-2) 50%, transparent); }
|
|
11
11
|
|
|
12
12
|
.pk-table-row { border-bottom: 1px solid var(--pk-border); transition: background-color .12s ease; }
|
|
13
|
-
.pk-table-row:hover { background: color-mix(in oklab, var(--pk-surface-2)
|
|
13
|
+
.pk-table-row:hover { background: color-mix(in oklab, var(--pk-surface-2) 50%, transparent); }
|
|
14
|
+
.pk-table-row[data-state="selected"] { background: var(--pk-surface-2); }
|
|
14
15
|
|
|
15
16
|
.pk-table-head {
|
|
16
17
|
height: 2.5rem;
|
|
@@ -18,7 +19,10 @@
|
|
|
18
19
|
text-align: left;
|
|
19
20
|
vertical-align: middle;
|
|
20
21
|
font-weight: 500;
|
|
21
|
-
|
|
22
|
+
white-space: nowrap;
|
|
23
|
+
color: var(--pk-text);
|
|
22
24
|
}
|
|
23
|
-
.pk-table-
|
|
25
|
+
.pk-table-head:has([role="checkbox"]),
|
|
26
|
+
.pk-table-cell:has([role="checkbox"]) { padding-right: 0; }
|
|
27
|
+
.pk-table-cell { padding: .5rem; vertical-align: middle; white-space: nowrap; }
|
|
24
28
|
.pk-table-caption { margin-top: 1rem; font-size: .875rem; color: var(--pk-muted); }
|
|
@@ -1,13 +1,77 @@
|
|
|
1
|
-
/* Co-located with tabs.rb.
|
|
1
|
+
/* Co-located with tabs.rb. Matched to nova: h-8 list with 3px padding,
|
|
2
|
+
rounded-md px-1.5 triggers with data-icon insets and svg-4 glyphs, active
|
|
3
|
+
fill (translucent input in dark) with a soft shadow; the `line` variant is
|
|
4
|
+
transparent with an animated underline; `orientation: :vertical` stacks
|
|
5
|
+
the list (underline moves to the right edge). Tokens global. */
|
|
6
|
+
.pk-tabs { display: flex; flex-direction: column; gap: .5rem; }
|
|
7
|
+
.pk-tabs.vertical { flex-direction: row; align-items: flex-start; }
|
|
2
8
|
.pk-tabs-list {
|
|
3
|
-
display: inline-flex; height:
|
|
4
|
-
border-radius: var(--pk-radius); background: var(--pk-surface-2); padding:
|
|
9
|
+
display: inline-flex; width: fit-content; height: 2rem; align-items: center; justify-content: center;
|
|
10
|
+
border-radius: var(--pk-radius); background: var(--pk-surface-2); padding: 3px; color: var(--pk-muted);
|
|
5
11
|
}
|
|
12
|
+
.pk-tabs.vertical .pk-tabs-list { height: fit-content; flex-direction: column; align-items: stretch; }
|
|
6
13
|
.pk-tabs-trigger {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
14
|
+
position: relative;
|
|
15
|
+
display: inline-flex; align-items: center; justify-content: center; gap: .375rem;
|
|
16
|
+
white-space: nowrap; flex: 1;
|
|
17
|
+
border: 1px solid transparent;
|
|
18
|
+
border-radius: calc(var(--pk-radius) - 2px); padding: 2px .375rem; font-size: .875rem; font-weight: 500;
|
|
19
|
+
background: none; cursor: pointer; color: inherit; transition: all .15s ease;
|
|
20
|
+
}
|
|
21
|
+
.pk-tabs.vertical .pk-tabs-trigger { width: 100%; justify-content: flex-start; }
|
|
22
|
+
.pk-tabs-trigger:hover { color: var(--pk-text); }
|
|
23
|
+
.pk-tabs-trigger svg { pointer-events: none; flex-shrink: 0; }
|
|
24
|
+
.pk-tabs-trigger svg:not([class*="size-"]) { width: 1rem; height: 1rem; }
|
|
25
|
+
.pk-tabs-trigger:has(> [data-icon="inline-start"]) { padding-left: .25rem; }
|
|
26
|
+
.pk-tabs-trigger:has(> [data-icon="inline-end"]) { padding-right: .25rem; }
|
|
27
|
+
.pk-tabs-trigger:focus-visible {
|
|
28
|
+
outline: none;
|
|
29
|
+
border-color: var(--pk-ring);
|
|
30
|
+
box-shadow: 0 0 0 3px color-mix(in oklab, var(--pk-ring) 50%, transparent);
|
|
31
|
+
}
|
|
32
|
+
.pk-tabs-trigger[data-state="active"] {
|
|
33
|
+
background: color-mix(in oklab, var(--pk-input) 30%, transparent);
|
|
34
|
+
border-color: var(--pk-input);
|
|
35
|
+
color: var(--pk-text);
|
|
36
|
+
box-shadow: 0 1px 2px rgb(0 0 0 / .1);
|
|
10
37
|
}
|
|
11
|
-
.pk-tabs-trigger[data-state="active"] { background: var(--pk-bg); color: var(--pk-text); box-shadow: 0 1px 2px rgb(0 0 0 / .1); }
|
|
12
38
|
.pk-tabs-trigger:disabled { pointer-events: none; opacity: .5; }
|
|
13
|
-
|
|
39
|
+
|
|
40
|
+
/* line variant: transparent list, underline on the active trigger. */
|
|
41
|
+
.pk-tabs-list.line { background: transparent; border-radius: 0; gap: .25rem; padding: 0; }
|
|
42
|
+
.pk-tabs-list.line .pk-tabs-trigger[data-state="active"] {
|
|
43
|
+
background: transparent;
|
|
44
|
+
border-color: transparent;
|
|
45
|
+
box-shadow: none;
|
|
46
|
+
}
|
|
47
|
+
.pk-tabs-trigger::after {
|
|
48
|
+
content: "";
|
|
49
|
+
position: absolute;
|
|
50
|
+
inset-inline: 0;
|
|
51
|
+
bottom: -5px;
|
|
52
|
+
height: 2px;
|
|
53
|
+
background: var(--pk-text);
|
|
54
|
+
opacity: 0;
|
|
55
|
+
transition: opacity .15s ease;
|
|
56
|
+
}
|
|
57
|
+
.pk-tabs.vertical .pk-tabs-trigger::after {
|
|
58
|
+
inset-inline: auto;
|
|
59
|
+
inset-block: 0;
|
|
60
|
+
right: -.25rem;
|
|
61
|
+
width: 2px;
|
|
62
|
+
height: auto;
|
|
63
|
+
}
|
|
64
|
+
.pk-tabs-list.line .pk-tabs-trigger[data-state="active"]::after { opacity: 1; }
|
|
65
|
+
|
|
66
|
+
.pk-tabs-content { flex: 1; font-size: .875rem; }
|
|
67
|
+
|
|
68
|
+
:root[data-theme="light"] .pk-tabs-trigger[data-state="active"] {
|
|
69
|
+
background: var(--pk-bg);
|
|
70
|
+
border-color: transparent;
|
|
71
|
+
}
|
|
72
|
+
@media (prefers-color-scheme: light) {
|
|
73
|
+
:root[data-theme="system"] .pk-tabs-trigger[data-state="active"] {
|
|
74
|
+
background: var(--pk-bg);
|
|
75
|
+
border-color: transparent;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
@@ -2,12 +2,17 @@ module PhlexKit
|
|
|
2
2
|
# Tabbed panels. Ported from ruby_ui's RubyUI::Tabs. Compose Tabs(default:) >
|
|
3
3
|
# (TabsList > TabsTrigger(value:)) + TabsContent(value:). phlex-kit--tabs.
|
|
4
4
|
class Tabs < BaseComponent
|
|
5
|
-
|
|
5
|
+
ORIENTATIONS = { horizontal: nil, vertical: "vertical" }.freeze
|
|
6
|
+
|
|
7
|
+
def initialize(default: nil, orientation: :horizontal, **attrs)
|
|
6
8
|
@default = default
|
|
9
|
+
@orientation = orientation.to_sym
|
|
7
10
|
@attrs = attrs
|
|
8
11
|
end
|
|
12
|
+
|
|
9
13
|
def view_template(&)
|
|
10
|
-
|
|
14
|
+
classes = [ "pk-tabs", ORIENTATIONS.fetch(@orientation) ].compact.join(" ")
|
|
15
|
+
div(**mix({ class: classes, data: { controller: "phlex-kit--tabs", phlex_kit__tabs_active_value: @default } }, @attrs), &)
|
|
11
16
|
end
|
|
12
17
|
end
|
|
13
18
|
end
|
|
@@ -1,6 +1,15 @@
|
|
|
1
1
|
module PhlexKit
|
|
2
2
|
class TabsList < BaseComponent
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
VARIANTS = { default: nil, line: "line" }.freeze
|
|
4
|
+
|
|
5
|
+
def initialize(variant: :default, **attrs)
|
|
6
|
+
@variant = variant.to_sym
|
|
7
|
+
@attrs = attrs
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def view_template(&)
|
|
11
|
+
classes = [ "pk-tabs-list", VARIANTS.fetch(@variant) ].compact.join(" ")
|
|
12
|
+
div(**mix({ class: classes, role: "tablist" }, @attrs), &)
|
|
13
|
+
end
|
|
5
14
|
end
|
|
6
15
|
end
|
|
@@ -1,27 +1,47 @@
|
|
|
1
|
-
/* Co-located with textarea.rb —
|
|
2
|
-
.pk-input (input.css):
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
stylesheet. */
|
|
1
|
+
/* Co-located with textarea.rb — PhlexKit::Textarea. Same nova treatment as
|
|
2
|
+
.pk-input (input.css): rounded-lg, translucent dark fill / transparent
|
|
3
|
+
light, ring focus, invalid + disabled states, text-base on small screens
|
|
4
|
+
(iOS zoom guard) dropping to text-sm from md. Height stays with `rows`. */
|
|
6
5
|
.pk-textarea {
|
|
7
6
|
width: 100%;
|
|
8
|
-
border-radius:
|
|
7
|
+
border-radius: var(--pk-radius);
|
|
9
8
|
border: 1px solid var(--pk-input);
|
|
10
|
-
background: var(--pk-
|
|
9
|
+
background: color-mix(in oklab, var(--pk-input) 30%, transparent);
|
|
11
10
|
color: var(--pk-text);
|
|
12
|
-
padding: .5rem .
|
|
11
|
+
padding: .5rem .625rem;
|
|
13
12
|
font: inherit;
|
|
14
|
-
font-size:
|
|
15
|
-
|
|
13
|
+
font-size: 1rem;
|
|
14
|
+
transition: color .15s ease, border-color .15s ease, box-shadow .15s ease, background-color .15s ease;
|
|
15
|
+
}
|
|
16
|
+
@media (min-width: 768px) {
|
|
17
|
+
.pk-textarea { font-size: .875rem; }
|
|
16
18
|
}
|
|
17
19
|
.pk-textarea::placeholder { color: var(--pk-muted); }
|
|
18
20
|
.pk-textarea:focus-visible {
|
|
19
21
|
outline: none;
|
|
20
|
-
border-color: var(--pk-
|
|
22
|
+
border-color: var(--pk-ring);
|
|
21
23
|
box-shadow: 0 0 0 3px color-mix(in oklab, var(--pk-ring) 50%, transparent);
|
|
22
24
|
}
|
|
23
|
-
.pk-textarea:disabled {
|
|
25
|
+
.pk-textarea:disabled {
|
|
26
|
+
cursor: not-allowed;
|
|
27
|
+
opacity: .5;
|
|
28
|
+
background: color-mix(in oklab, var(--pk-input) 80%, transparent);
|
|
29
|
+
}
|
|
24
30
|
.pk-textarea[aria-invalid="true"] {
|
|
31
|
+
border-color: color-mix(in oklab, var(--pk-red) 50%, transparent);
|
|
32
|
+
box-shadow: 0 0 0 3px color-mix(in oklab, var(--pk-red) 40%, transparent);
|
|
33
|
+
}
|
|
34
|
+
:root[data-theme="light"] .pk-textarea { background: transparent; }
|
|
35
|
+
:root[data-theme="light"] .pk-textarea:disabled { background: color-mix(in oklab, var(--pk-input) 50%, transparent); }
|
|
36
|
+
:root[data-theme="light"] .pk-textarea[aria-invalid="true"] {
|
|
25
37
|
border-color: var(--pk-red);
|
|
26
|
-
box-shadow: 0 0 0 3px color-mix(in oklab, var(--pk-red)
|
|
38
|
+
box-shadow: 0 0 0 3px color-mix(in oklab, var(--pk-red) 20%, transparent);
|
|
39
|
+
}
|
|
40
|
+
@media (prefers-color-scheme: light) {
|
|
41
|
+
:root[data-theme="system"] .pk-textarea { background: transparent; }
|
|
42
|
+
:root[data-theme="system"] .pk-textarea:disabled { background: color-mix(in oklab, var(--pk-input) 50%, transparent); }
|
|
43
|
+
:root[data-theme="system"] .pk-textarea[aria-invalid="true"] {
|
|
44
|
+
border-color: var(--pk-red);
|
|
45
|
+
box-shadow: 0 0 0 3px color-mix(in oklab, var(--pk-red) 20%, transparent);
|
|
46
|
+
}
|
|
27
47
|
}
|
|
@@ -1,16 +1,31 @@
|
|
|
1
|
-
/* Co-located with toggle.rb.
|
|
1
|
+
/* Co-located with toggle.rb. Matched to nova: h-8/h-7/h-9 sizes with min-w,
|
|
2
|
+
rounded-lg (sm capped), muted hover + on-state fills, gap-1, data-icon
|
|
3
|
+
insets, svg-4 (3.5 at sm). Theme tokens from the global stylesheet. */
|
|
2
4
|
.pk-contents { display: contents; }
|
|
3
5
|
.pk-toggle {
|
|
4
|
-
display: inline-flex; align-items: center; justify-content: center; gap: .
|
|
5
|
-
height:
|
|
6
|
-
border-radius:
|
|
6
|
+
display: inline-flex; align-items: center; justify-content: center; gap: .25rem;
|
|
7
|
+
height: 2rem; min-width: 2rem; padding-inline: .625rem;
|
|
8
|
+
border-radius: var(--pk-radius); border: 1px solid transparent; background: transparent;
|
|
7
9
|
font-size: .875rem; font-weight: 500; white-space: nowrap; color: var(--pk-text);
|
|
8
10
|
cursor: pointer; outline: none; transition: color .15s ease, background-color .15s ease, box-shadow .15s ease;
|
|
9
11
|
}
|
|
10
|
-
.pk-toggle:hover { background: var(--pk-
|
|
12
|
+
.pk-toggle:hover { background: var(--pk-surface-2); color: var(--pk-text); }
|
|
11
13
|
.pk-toggle:disabled { pointer-events: none; opacity: .5; }
|
|
12
|
-
.pk-toggle[data-state="on"] { background: var(--pk-surface-2); color: var(--pk-text); }
|
|
13
|
-
.pk-toggle
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
14
|
+
.pk-toggle[data-state="on"], .pk-toggle[aria-pressed="true"] { background: var(--pk-surface-2); color: var(--pk-text); }
|
|
15
|
+
.pk-toggle:focus-visible {
|
|
16
|
+
border-color: var(--pk-ring);
|
|
17
|
+
box-shadow: 0 0 0 3px color-mix(in oklab, var(--pk-ring) 50%, transparent);
|
|
18
|
+
}
|
|
19
|
+
.pk-toggle.outline { border-color: var(--pk-input); }
|
|
20
|
+
.pk-toggle.sm {
|
|
21
|
+
height: 1.75rem; min-width: 1.75rem; font-size: .8rem;
|
|
22
|
+
border-radius: min(calc(var(--pk-radius) - 2px), 12px);
|
|
23
|
+
}
|
|
24
|
+
.pk-toggle.lg { height: 2.25rem; min-width: 2.25rem; }
|
|
25
|
+
.pk-toggle svg { pointer-events: none; flex-shrink: 0; }
|
|
26
|
+
.pk-toggle svg:not([class*="size-"]) { width: 1rem; height: 1rem; }
|
|
27
|
+
.pk-toggle.sm svg:not([class*="size-"]) { width: .875rem; height: .875rem; }
|
|
28
|
+
.pk-toggle:has(> [data-icon="inline-start"]) { padding-left: .5rem; }
|
|
29
|
+
.pk-toggle:has(> [data-icon="inline-end"]) { padding-right: .5rem; }
|
|
30
|
+
.pk-toggle.sm:has(> [data-icon="inline-start"]) { padding-left: .375rem; }
|
|
31
|
+
.pk-toggle.sm:has(> [data-icon="inline-end"]) { padding-right: .375rem; }
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
/* Co-located with toggle_group.rb. Theme tokens from the global stylesheet. */
|
|
2
|
-
.pk-toggle-group { display: inline-flex; width: fit-content; align-items: center; border-radius:
|
|
2
|
+
.pk-toggle-group { display: inline-flex; width: fit-content; align-items: center; border-radius: var(--pk-radius); }
|
|
3
3
|
.pk-toggle-group.vertical { flex-direction: column; align-items: stretch; }
|
|
4
4
|
.pk-toggle-group.spaced { gap: .25rem; }
|
|
5
|
-
/* Joined (default, unspaced): square the inner corners. */
|
|
5
|
+
/* Joined (default, unspaced): square the inner corners, tighten padding. */
|
|
6
|
+
.pk-toggle-group:not(.spaced) .pk-toggle-group-item { padding-inline: .5rem; }
|
|
6
7
|
.pk-toggle-group:not(.spaced) .pk-toggle-group-item { border-radius: 0; }
|
|
7
|
-
.pk-toggle-group:not(.spaced):not(.vertical) .pk-toggle-group-item:first-of-type { border-top-left-radius:
|
|
8
|
-
.pk-toggle-group:not(.spaced):not(.vertical) .pk-toggle-group-item:last-of-type { border-top-right-radius:
|
|
9
|
-
.pk-toggle-group.vertical:not(.spaced) .pk-toggle-group-item:first-of-type { border-top-left-radius:
|
|
10
|
-
.pk-toggle-group.vertical:not(.spaced) .pk-toggle-group-item:last-of-type { border-bottom-left-radius:
|
|
8
|
+
.pk-toggle-group:not(.spaced):not(.vertical) .pk-toggle-group-item:first-of-type { border-top-left-radius: var(--pk-radius); border-bottom-left-radius: var(--pk-radius); }
|
|
9
|
+
.pk-toggle-group:not(.spaced):not(.vertical) .pk-toggle-group-item:last-of-type { border-top-right-radius: var(--pk-radius); border-bottom-right-radius: var(--pk-radius); }
|
|
10
|
+
.pk-toggle-group.vertical:not(.spaced) .pk-toggle-group-item:first-of-type { border-top-left-radius: var(--pk-radius); border-top-right-radius: var(--pk-radius); }
|
|
11
|
+
.pk-toggle-group.vertical:not(.spaced) .pk-toggle-group-item:last-of-type { border-bottom-left-radius: var(--pk-radius); border-bottom-right-radius: var(--pk-radius); }
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
/* Co-located with tooltip.rb — UI::Tooltip (+ Trigger / Content). CSS-only:
|
|
2
|
-
the bubble is absolutely positioned
|
|
3
|
-
|
|
4
|
-
|
|
2
|
+
the bubble is absolutely positioned and revealed on the wrapper's :hover /
|
|
3
|
+
:focus-within (no JS, no @floating-ui). Matched to nova: INVERTED surface
|
|
4
|
+
(foreground bg, background text) with a rotated-square arrow, rounded-md,
|
|
5
|
+
px-3 py-1.5 text-xs, gap for inline kbd chips (kbd.css tints them). */
|
|
5
6
|
.pk-tooltip { position: relative; display: inline-flex; }
|
|
6
7
|
.pk-tooltip-trigger { display: inline-flex; }
|
|
7
8
|
.pk-tooltip-content {
|
|
@@ -10,19 +11,45 @@
|
|
|
10
11
|
left: 50%;
|
|
11
12
|
transform: translateX(-50%);
|
|
12
13
|
z-index: 50;
|
|
14
|
+
display: inline-flex;
|
|
15
|
+
align-items: center;
|
|
16
|
+
gap: .375rem;
|
|
13
17
|
width: max-content;
|
|
14
|
-
max-width: min(
|
|
15
|
-
padding: .
|
|
18
|
+
max-width: min(20rem, calc(100vw - 2rem));
|
|
19
|
+
padding: .375rem .75rem;
|
|
16
20
|
border-radius: calc(var(--pk-radius) - 2px);
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
font-size: .8rem;
|
|
21
|
-
box-shadow: 0 4px 16px rgba(0, 0, 0, .4);
|
|
21
|
+
background: var(--pk-text);
|
|
22
|
+
color: var(--pk-bg);
|
|
23
|
+
font-size: .75rem;
|
|
22
24
|
opacity: 0;
|
|
23
25
|
visibility: hidden;
|
|
24
26
|
pointer-events: none;
|
|
25
27
|
transition: opacity .12s ease;
|
|
26
28
|
}
|
|
29
|
+
.pk-tooltip-content:has(kbd) { padding-right: .375rem; }
|
|
30
|
+
.pk-tooltip-content::after {
|
|
31
|
+
content: "";
|
|
32
|
+
position: absolute;
|
|
33
|
+
z-index: -1;
|
|
34
|
+
width: .625rem;
|
|
35
|
+
height: .625rem;
|
|
36
|
+
border-radius: 2px;
|
|
37
|
+
background: inherit;
|
|
38
|
+
top: 100%;
|
|
39
|
+
left: 50%;
|
|
40
|
+
transform: translate(-50%, calc(-50% - 2px)) rotate(45deg);
|
|
41
|
+
}
|
|
42
|
+
.pk-tooltip-content.bottom { bottom: auto; top: calc(100% + 6px); }
|
|
43
|
+
.pk-tooltip-content.bottom::after { top: 0; transform: translate(-50%, calc(-50% + 2px)) rotate(45deg); }
|
|
44
|
+
.pk-tooltip-content.left {
|
|
45
|
+
bottom: auto; left: auto; right: calc(100% + 6px); top: 50%;
|
|
46
|
+
transform: translateY(-50%);
|
|
47
|
+
}
|
|
48
|
+
.pk-tooltip-content.left::after { top: 50%; left: 100%; transform: translate(calc(-50% - 2px), -50%) rotate(45deg); }
|
|
49
|
+
.pk-tooltip-content.right {
|
|
50
|
+
bottom: auto; right: auto; left: calc(100% + 6px); top: 50%;
|
|
51
|
+
transform: translateY(-50%);
|
|
52
|
+
}
|
|
53
|
+
.pk-tooltip-content.right::after { top: 50%; left: 0; transform: translate(calc(-50% + 2px), -50%) rotate(45deg); }
|
|
27
54
|
.pk-tooltip:hover .pk-tooltip-content,
|
|
28
55
|
.pk-tooltip:focus-within .pk-tooltip-content { opacity: 1; visibility: visible; }
|