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) })
|
b.Children(func() { ui.Icon(c, icons.Must("ellipsis")).Size(16, 16) })
|
||||||
ui.PopoverBase(c, b, open, func(panel *ui.Element) {
|
ui.PopoverBase(c, b, open, func(panel *ui.Element) {
|
||||||
internal.PopIn(c, panel, Motion(c, theme.PopupDuration))
|
overlayStyle(c, panel, overlayEnter(c, panel))
|
||||||
panel.Margin(u, 0, 0, 0).Padding(u).Gap(u*0.5).Radius(theme.PopupRadius).Background(k.Surface).
|
panel.Margin(u, 0, 0, 0).Padding(u).Gap(u * 0.5).MinWidth(160).MaxWidth(320)
|
||||||
Border(theme.BorderWidth, k.Border).Shadow(0, 4, 12, 0, ui.RGBA(0, 0, 0, 0.16)).MinWidth(160).MaxWidth(320)
|
|
||||||
for j, it := range hidden {
|
for j, it := range hidden {
|
||||||
item := ui.ButtonBase(c).Role(ui.RoleLink).Justify(ui.Start).Gap(u*2).Padding(u*1.5, u*2).
|
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)
|
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
|
opened := st.open && !st.wasOpen
|
||||||
ui.PopoverBase(c, trigger, &st.open, func(panel *ui.Element) {
|
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).
|
overlayStyle(c, panel, overlayEnter(c, panel))
|
||||||
Background(k.Surface).Border(theme.BorderWidth, k.Border).Shadow(0, 4, 12, 0, ui.RGBA(0, 0, 0, 0.18))
|
panel.Margin(d.Unit(), 0, 0, 0).Padding(d.Unit() * 3).Gap(d.Unit() * 3).Width(260)
|
||||||
colorPickerSquare(c, st, set, opened)
|
colorPickerSquare(c, st, set, opened)
|
||||||
x := st.hsv
|
x := st.hsv
|
||||||
h := x.h
|
h := x.h
|
||||||
|
|||||||
@@ -80,11 +80,11 @@ func CommandPalette(c *ui.Context, open *bool, commands []Command, opts CommandP
|
|||||||
u := d.Unit()
|
u := d.Unit()
|
||||||
res.Element = ui.DialogBase(c, open, func(back, panel *ui.Element) {
|
res.Element = ui.DialogBase(c, open, func(back, panel *ui.Element) {
|
||||||
ww, wh := c.Size()
|
ww, wh := c.Size()
|
||||||
back.Background(ui.RGBA(0, 0, 0, 0.4)).Justify(ui.Start)
|
p := overlayEnter(c, panel)
|
||||||
internal.PopIn(c, back, Motion(c, theme.PopupDuration))
|
back.Background(ui.RGBA(0, 0, 0, 0.4*p)).Justify(ui.Start)
|
||||||
panel.Margin(wh*0.12, 0, 0, 0).Width(560).MaxWidth(ww-32).MaxHeight(wh*0.76).
|
overlayStyle(c, panel, p)
|
||||||
Radius(theme.PopupRadius).Background(k.Surface).Border(theme.BorderWidth, k.Border).
|
panel.Margin(wh*0.12, 0, 0, 0).Width(560).MaxWidth(ww - 32).MaxHeight(wh * 0.76).
|
||||||
Shadow(0, 12, 32, 0, ui.RGBA(0, 0, 0, 0.3)).AlignItems(ui.Stretch).Label(msg(c, "command_palette.label"))
|
AlignItems(ui.Stretch).Label(msg(c, "command_palette.label"))
|
||||||
found := commandPaletteFilter(commands, st.query)
|
found := commandPaletteFilter(commands, st.query)
|
||||||
var in *ui.Element
|
var in *ui.Element
|
||||||
ui.Row(c).AlignItems(ui.Center).Gap(u*3).Padding(u*3, u*4).Children(func() {
|
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.
|
// 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 {
|
func datetimePopup(c *ui.Context, anchor *ui.Element, open *bool, readOnly bool, fn func()) *ui.Element {
|
||||||
k := Tokens(c)
|
|
||||||
d := Density(c)
|
d := Density(c)
|
||||||
if *open && (readOnly || anchor.IsDisabled()) {
|
if *open && (readOnly || anchor.IsDisabled()) {
|
||||||
slog.Debug("mujica: datetime popup closed by state", "readOnly", readOnly)
|
slog.Debug("mujica: datetime popup closed by state", "readOnly", readOnly)
|
||||||
*open = false
|
*open = false
|
||||||
}
|
}
|
||||||
return ui.PopoverBase(c, anchor, open, func(panel *ui.Element) {
|
return ui.PopoverBase(c, anchor, open, func(panel *ui.Element) {
|
||||||
born := ui.Local(panel, "datetime-born", func() bool { return true })
|
overlayStyle(c, panel, overlayEnter(c, panel))
|
||||||
if *born {
|
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)
|
||||||
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)
|
|
||||||
fn()
|
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)})
|
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)
|
items := m.items(l)
|
||||||
ww, wh := c.Size()
|
ww, wh := c.Size()
|
||||||
// Long menus scroll within the window instead of running off it.
|
// 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).
|
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).
|
overlayStyle(c, panel, overlayEnter(c, panel))
|
||||||
Shadow(0, 6, 16, 0, ui.RGBA(0, 0, 0, 0.18))
|
|
||||||
internal.PopIn(c, panel, Motion(c, theme.PopupDuration))
|
|
||||||
pb := panel.Bounds()
|
pb := panel.Bounds()
|
||||||
if x+pb.W > ww-4 {
|
if x+pb.W > ww-4 {
|
||||||
x = ww - 4 - pb.W
|
x = ww - 4 - pb.W
|
||||||
|
|||||||
@@ -147,12 +147,11 @@ func navigationMenuTop(c *ui.Context, l NavigationLink, path string, push func(s
|
|||||||
*open = true
|
*open = true
|
||||||
}
|
}
|
||||||
ui.PopoverBase(c, b, open, func(panel *ui.Element) {
|
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.
|
// Capped to the room beside the anchor; the links scroll inside.
|
||||||
_, wh := c.Size()
|
_, wh := c.Size()
|
||||||
r := b.Bounds()
|
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).
|
panel.Margin(u, 0, 0, 0).Padding(u * 2).MaxHeight(max(r.Y, wh-r.Y-r.H) - 16).MinWidth(240).MaxWidth(360)
|
||||||
Border(theme.BorderWidth, k.Border).Shadow(0, 4, 12, 0, ui.RGBA(0, 0, 0, 0.16)).MinWidth(240).MaxWidth(360)
|
|
||||||
ui.Scroll(c).Shrink(1).Gap(u).FocusGroup(ui.Vertical).Children(func() {
|
ui.Scroll(c).Shrink(1).Gap(u).FocusGroup(ui.Vertical).Children(func() {
|
||||||
navigationMenuPanel(c, l.Items, path, open, push)
|
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)
|
ui.Icon(c, icons.Must("chevron-down")).Size(14, 14).TextColor(k.TextMuted)
|
||||||
})
|
})
|
||||||
sel.Popup(func(panel *ui.Element) {
|
sel.Popup(func(panel *ui.Element) {
|
||||||
internal.PopIn(c, panel, Motion(c, theme.PopupDuration))
|
overlayStyle(c, panel, overlayEnter(c, panel))
|
||||||
panel.Margin(u, 0, 0, 0).Padding(u).Radius(theme.PopupRadius).Background(k.Surface).
|
panel.Margin(u, 0, 0, 0).Padding(u)
|
||||||
Border(theme.BorderWidth, k.Border).Shadow(0, 4, 12, 0, ui.RGBA(0, 0, 0, 0.16))
|
|
||||||
for _, s := range sizes {
|
for _, s := range sizes {
|
||||||
it := sel.Item(s).Padding(u*1.5, u*3).Radius(theme.ControlRadius).Gap(u * 2)
|
it := sel.Item(s).Padding(u*1.5, u*3).Radius(theme.ControlRadius).Gap(u * 2)
|
||||||
if it.Highlighted() {
|
if it.Highlighted() {
|
||||||
|
|||||||
@@ -239,9 +239,8 @@ func selectCheck(c *ui.Context, on bool) {
|
|||||||
|
|
||||||
// selectPanel styles a popup panel.
|
// selectPanel styles a popup panel.
|
||||||
func selectPanel(c *ui.Context, panel *ui.Element) {
|
func selectPanel(c *ui.Context, panel *ui.Element) {
|
||||||
k := Tokens(c)
|
overlayStyle(c, panel, overlayEnter(c, panel))
|
||||||
panel.Margin(4, 0, 0, 0).Padding(4).Radius(theme.PopupRadius).Background(k.Surface).
|
panel.Margin(4, 0, 0, 0).Padding(4)
|
||||||
Border(theme.BorderWidth, k.Border).Shadow(0, 4, 12, 0, ui.RGBA(0, 0, 0, 0.14))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// selectRow styles an option row: chosen has the selection fill and a check, highlighted a side bar.
|
// 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 {
|
if *open {
|
||||||
ui.PopoverBase(c, more, open, func(panel *ui.Element) {
|
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).
|
overlayStyle(c, panel, overlayEnter(c, panel))
|
||||||
Radius(theme.PopupRadius).Background(k.Surface).Border(theme.BorderWidth, k.Border).
|
panel.Margin(d.Unit(), 0, 0, 0).Padding(d.Unit()).Gap(d.Unit()).AlignItems(ui.Stretch)
|
||||||
Shadow(0, 4, 12, 0, ui.RGBA(0, 0, 0, 0.16))
|
|
||||||
for _, it := range statusBarAll(opts) {
|
for _, it := range statusBarAll(opts) {
|
||||||
if hidden[it.ID] {
|
if hidden[it.ID] {
|
||||||
item(it)
|
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 |