Refactor: popups share overlayStyle and overlayEnter
internal.PopIn is gone. Breadcrumb, NavigationMenu, Pagination, Menubar panels, CommandPalette, Select (and the other selectPanel users), datetime popups, ColorPicker and the StatusBar overflow now style their panel with overlayStyle(c, panel, overlayEnter(c, panel)): one shadow (0 6 18, 16% black, scaled by entry) and one 160 ms entry fade. Snapshots: color_picker and command_palette (light and dark) change only in the panel shadow. ColorPicker loses its 0 4 12 18% shadow for the softer shared one; CommandPalette loses its heavy 0 12 32 30% shadow, and its backdrop now fades by alpha with the panel instead of through the backdrop's opacity. Fade and reduced-motion tests pass unchanged.
No files matched your search
@@ -135,9 +135,8 @@ func breadcrumbMore(c *ui.Context, hidden []BreadcrumbItem, choose func(int)) {
|
||||
}
|
||||
b.Children(func() { ui.Icon(c, icons.Must("ellipsis")).Size(16, 16) })
|
||||
ui.PopoverBase(c, b, open, func(panel *ui.Element) {
|
||||
internal.PopIn(c, panel, Motion(c, theme.PopupDuration))
|
||||
panel.Margin(u, 0, 0, 0).Padding(u).Gap(u*0.5).Radius(theme.PopupRadius).Background(k.Surface).
|
||||
Border(theme.BorderWidth, k.Border).Shadow(0, 4, 12, 0, ui.RGBA(0, 0, 0, 0.16)).MinWidth(160).MaxWidth(320)
|
||||
overlayStyle(c, panel, overlayEnter(c, panel))
|
||||
panel.Margin(u, 0, 0, 0).Padding(u).Gap(u * 0.5).MinWidth(160).MaxWidth(320)
|
||||
for j, it := range hidden {
|
||||
item := ui.ButtonBase(c).Role(ui.RoleLink).Justify(ui.Start).Gap(u*2).Padding(u*1.5, u*2).
|
||||
Radius(theme.ControlRadius).MinHeight(Density(c).ControlHeight() - u*2).Label(it.Label).TextColor(k.Text)
|
||||
|
||||
@@ -114,8 +114,8 @@ func ColorPicker(c *ui.Context, color *ui.Color, opts ColorPickerOptions) ColorP
|
||||
})
|
||||
opened := st.open && !st.wasOpen
|
||||
ui.PopoverBase(c, trigger, &st.open, func(panel *ui.Element) {
|
||||
panel.Margin(d.Unit(), 0, 0, 0).Padding(d.Unit()*3).Gap(d.Unit()*3).Width(260).Radius(theme.PopupRadius).
|
||||
Background(k.Surface).Border(theme.BorderWidth, k.Border).Shadow(0, 4, 12, 0, ui.RGBA(0, 0, 0, 0.18))
|
||||
overlayStyle(c, panel, overlayEnter(c, panel))
|
||||
panel.Margin(d.Unit(), 0, 0, 0).Padding(d.Unit() * 3).Gap(d.Unit() * 3).Width(260)
|
||||
colorPickerSquare(c, st, set, opened)
|
||||
x := st.hsv
|
||||
h := x.h
|
||||
|
||||
@@ -80,11 +80,11 @@ func CommandPalette(c *ui.Context, open *bool, commands []Command, opts CommandP
|
||||
u := d.Unit()
|
||||
res.Element = ui.DialogBase(c, open, func(back, panel *ui.Element) {
|
||||
ww, wh := c.Size()
|
||||
back.Background(ui.RGBA(0, 0, 0, 0.4)).Justify(ui.Start)
|
||||
internal.PopIn(c, back, Motion(c, theme.PopupDuration))
|
||||
panel.Margin(wh*0.12, 0, 0, 0).Width(560).MaxWidth(ww-32).MaxHeight(wh*0.76).
|
||||
Radius(theme.PopupRadius).Background(k.Surface).Border(theme.BorderWidth, k.Border).
|
||||
Shadow(0, 12, 32, 0, ui.RGBA(0, 0, 0, 0.3)).AlignItems(ui.Stretch).Label(msg(c, "command_palette.label"))
|
||||
p := overlayEnter(c, panel)
|
||||
back.Background(ui.RGBA(0, 0, 0, 0.4*p)).Justify(ui.Start)
|
||||
overlayStyle(c, panel, p)
|
||||
panel.Margin(wh*0.12, 0, 0, 0).Width(560).MaxWidth(ww - 32).MaxHeight(wh * 0.76).
|
||||
AlignItems(ui.Stretch).Label(msg(c, "command_palette.label"))
|
||||
found := commandPaletteFilter(commands, st.query)
|
||||
var in *ui.Element
|
||||
ui.Row(c).AlignItems(ui.Center).Gap(u*3).Padding(u*3, u*4).Children(func() {
|
||||
|
||||
@@ -163,22 +163,14 @@ func datetimeTrigger(c *ui.Context, text, placeholder, icon string) *ui.Element
|
||||
|
||||
// datetimePopup shows fn below anchor while *open; a disabled or read-only anchor closes it.
|
||||
func datetimePopup(c *ui.Context, anchor *ui.Element, open *bool, readOnly bool, fn func()) *ui.Element {
|
||||
k := Tokens(c)
|
||||
d := Density(c)
|
||||
if *open && (readOnly || anchor.IsDisabled()) {
|
||||
slog.Debug("mujica: datetime popup closed by state", "readOnly", readOnly)
|
||||
*open = false
|
||||
}
|
||||
return ui.PopoverBase(c, anchor, open, func(panel *ui.Element) {
|
||||
born := ui.Local(panel, "datetime-born", func() bool { return true })
|
||||
if *born {
|
||||
panel.Animate("datetime-fade", 0, 0)
|
||||
*born = false
|
||||
}
|
||||
fade := panel.Animate("datetime-fade", 1, Motion(c, theme.PopupDuration))
|
||||
panel.MaxWidth(d.ControlHeight()*7+d.Unit()*6+2*theme.BorderWidth).Margin(d.Unit(), 0, 0, 0).Padding(d.Unit()*3).Gap(d.Unit()*3).Radius(theme.PopupRadius).
|
||||
Background(k.Surface).Border(theme.BorderWidth, k.Border).
|
||||
Shadow(0, 6, 18, 0, ui.RGBA(0, 0, 0, 0.16)).Opacity(fade)
|
||||
overlayStyle(c, panel, overlayEnter(c, panel))
|
||||
panel.MaxWidth(d.ControlHeight()*7+d.Unit()*6+2*theme.BorderWidth).Margin(d.Unit(), 0, 0, 0).Padding(d.Unit() * 3).Gap(d.Unit() * 3)
|
||||
fn()
|
||||
})
|
||||
}
|
||||
|
||||
@@ -17,15 +17,3 @@ func Ease(e *ui.Element, d time.Duration, fg ui.Color) *ui.Element {
|
||||
}
|
||||
return e.TextColor(ui.Color{R: ch("mujica.fg.r", fg.R), G: ch("mujica.fg.g", fg.G), B: ch("mujica.fg.b", fg.B), A: ch("mujica.fg.a", fg.A)})
|
||||
}
|
||||
|
||||
// PopIn fades popup e in over d from the frame it appeared and returns the progress, 0 to 1.
|
||||
func PopIn(c *ui.Context, e *ui.Element, d time.Duration) float32 {
|
||||
born := ui.Local(e, "mujica.popin", func() time.Time { return c.Now() })
|
||||
p := float32(1)
|
||||
if t := float32(c.Now().Sub(*born)) / float32(max(d, 1)); d > 0 && t < 1 {
|
||||
p = ui.EaseOut(t)
|
||||
c.AnimationFrame()
|
||||
}
|
||||
e.Opacity(p)
|
||||
return p
|
||||
}
|
||||
@@ -67,10 +67,8 @@ func (m *menubarRun) panel(l int, x, y float32, parent ui.Rect) (*ui.Element, *u
|
||||
items := m.items(l)
|
||||
ww, wh := c.Size()
|
||||
// Long menus scroll within the window instead of running off it.
|
||||
panel := ui.Scroll(c).Absolute().Padding(u).MinWidth(200).MaxHeight(wh-8).AlignItems(ui.Stretch).Role(ui.RolePopup).
|
||||
Radius(theme.PopupRadius).Background(k.Surface).Border(theme.BorderWidth, k.Border).
|
||||
Shadow(0, 6, 16, 0, ui.RGBA(0, 0, 0, 0.18))
|
||||
internal.PopIn(c, panel, Motion(c, theme.PopupDuration))
|
||||
panel := ui.Scroll(c).Absolute().Padding(u).MinWidth(200).MaxHeight(wh - 8).AlignItems(ui.Stretch).Role(ui.RolePopup)
|
||||
overlayStyle(c, panel, overlayEnter(c, panel))
|
||||
pb := panel.Bounds()
|
||||
if x+pb.W > ww-4 {
|
||||
x = ww - 4 - pb.W
|
||||
|
||||
@@ -147,12 +147,11 @@ func navigationMenuTop(c *ui.Context, l NavigationLink, path string, push func(s
|
||||
*open = true
|
||||
}
|
||||
ui.PopoverBase(c, b, open, func(panel *ui.Element) {
|
||||
internal.PopIn(c, panel, Motion(c, theme.PopupDuration))
|
||||
overlayStyle(c, panel, overlayEnter(c, panel))
|
||||
// Capped to the room beside the anchor; the links scroll inside.
|
||||
_, wh := c.Size()
|
||||
r := b.Bounds()
|
||||
panel.Margin(u, 0, 0, 0).Padding(u*2).Radius(theme.PopupRadius).Background(k.Surface).MaxHeight(max(r.Y, wh-r.Y-r.H)-16).
|
||||
Border(theme.BorderWidth, k.Border).Shadow(0, 4, 12, 0, ui.RGBA(0, 0, 0, 0.16)).MinWidth(240).MaxWidth(360)
|
||||
panel.Margin(u, 0, 0, 0).Padding(u * 2).MaxHeight(max(r.Y, wh-r.Y-r.H) - 16).MinWidth(240).MaxWidth(360)
|
||||
ui.Scroll(c).Shrink(1).Gap(u).FocusGroup(ui.Vertical).Children(func() {
|
||||
navigationMenuPanel(c, l.Items, path, open, push)
|
||||
})
|
||||
|
||||
@@ -175,9 +175,8 @@ func paginationSizes(c *ui.Context, page, pageSize *int, sizes []int, res *Choic
|
||||
ui.Icon(c, icons.Must("chevron-down")).Size(14, 14).TextColor(k.TextMuted)
|
||||
})
|
||||
sel.Popup(func(panel *ui.Element) {
|
||||
internal.PopIn(c, panel, Motion(c, theme.PopupDuration))
|
||||
panel.Margin(u, 0, 0, 0).Padding(u).Radius(theme.PopupRadius).Background(k.Surface).
|
||||
Border(theme.BorderWidth, k.Border).Shadow(0, 4, 12, 0, ui.RGBA(0, 0, 0, 0.16))
|
||||
overlayStyle(c, panel, overlayEnter(c, panel))
|
||||
panel.Margin(u, 0, 0, 0).Padding(u)
|
||||
for _, s := range sizes {
|
||||
it := sel.Item(s).Padding(u*1.5, u*3).Radius(theme.ControlRadius).Gap(u * 2)
|
||||
if it.Highlighted() {
|
||||
|
||||
@@ -239,9 +239,8 @@ func selectCheck(c *ui.Context, on bool) {
|
||||
|
||||
// selectPanel styles a popup panel.
|
||||
func selectPanel(c *ui.Context, panel *ui.Element) {
|
||||
k := Tokens(c)
|
||||
panel.Margin(4, 0, 0, 0).Padding(4).Radius(theme.PopupRadius).Background(k.Surface).
|
||||
Border(theme.BorderWidth, k.Border).Shadow(0, 4, 12, 0, ui.RGBA(0, 0, 0, 0.14))
|
||||
overlayStyle(c, panel, overlayEnter(c, panel))
|
||||
panel.Margin(4, 0, 0, 0).Padding(4)
|
||||
}
|
||||
|
||||
// selectRow styles an option row: chosen has the selection fill and a check, highlighted a side bar.
|
||||
|
||||
@@ -108,9 +108,8 @@ func StatusBar(c *ui.Context, opts StatusBarOptions) StatusBarResult {
|
||||
}
|
||||
if *open {
|
||||
ui.PopoverBase(c, more, open, func(panel *ui.Element) {
|
||||
panel.Margin(d.Unit(), 0, 0, 0).Padding(d.Unit()).Gap(d.Unit()).AlignItems(ui.Stretch).
|
||||
Radius(theme.PopupRadius).Background(k.Surface).Border(theme.BorderWidth, k.Border).
|
||||
Shadow(0, 4, 12, 0, ui.RGBA(0, 0, 0, 0.16))
|
||||
overlayStyle(c, panel, overlayEnter(c, panel))
|
||||
panel.Margin(d.Unit(), 0, 0, 0).Padding(d.Unit()).Gap(d.Unit()).AlignItems(ui.Stretch)
|
||||
for _, it := range statusBarAll(opts) {
|
||||
if hidden[it.ID] {
|
||||
item(it)
|
||||
|
||||
|
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 27 KiB |
|
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 28 KiB |
|
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 21 KiB |