~whereswaldon/gio-x

bc95442aa5225c3fb91025d6eb3e69a140bdf08b — Chris Waldon a month ago 1e327c9
component: implement tooltip component visually

This commit introduces a pre-styled tooltip component. It does not
include logic for displaying tooltips on hover or other interactions.

Signed-off-by: Chris Waldon <christopher.waldon.dev@gmail.com>
3 files changed, 108 insertions(+), 0 deletions(-)

A component/tooltip.go
A component/tooltip_desktop.go
A component/tooltip_mobile.go
A component/tooltip.go => component/tooltip.go +84 -0
@@ 0,0 1,84 @@
package component

import (
	"image/color"

	"gioui.org/f32"
	"gioui.org/layout"
	"gioui.org/op/clip"
	"gioui.org/op/paint"
	"gioui.org/unit"
	"gioui.org/widget/material"
)

// Tooltip implements a material design tool tip as defined at:
// https://material.io/components/tooltips#specs
type Tooltip struct {
	// Inset defines the interior padding of the Tooltip.
	layout.Inset
	// CornerRadius defines the corner radius of the RRect background.
	// of the tooltip.
	CornerRadius unit.Value
	// Text defines the content of the tooltip.
	Text material.LabelStyle
	// Bg defines the color of the RRect background.
	Bg color.NRGBA
}

// MobileTooltip constructs a tooltip suitable for use on mobile devices.
func MobileTooltip(th *material.Theme, text string) Tooltip {
	txt := material.Body1(th, text)
	txt.Color = th.Bg
	txt.TextSize = unit.Dp(16)
	return Tooltip{
		Inset: layout.Inset{
			Top:    unit.Dp(8),
			Bottom: unit.Dp(8),
			Left:   unit.Dp(16),
			Right:  unit.Dp(16),
		},
		Bg:           WithAlpha(th.Fg, 220),
		CornerRadius: unit.Dp(4),
		Text:         txt,
	}
}

// DesktopTooltip constructs a tooltip suitable for use on desktop devices.
func DesktopTooltip(th *material.Theme, text string) Tooltip {
	txt := material.Body2(th, text)
	txt.Color = th.Bg
	txt.TextSize = unit.Dp(12)
	return Tooltip{
		Inset: layout.Inset{
			Top:    unit.Dp(6),
			Bottom: unit.Dp(6),
			Left:   unit.Dp(8),
			Right:  unit.Dp(8),
		},
		Bg:           WithAlpha(th.Fg, 220),
		CornerRadius: unit.Dp(4),
		Text:         txt,
	}
}

// Layout renders the tooltip.
func (t Tooltip) Layout(gtx C) D {
	return layout.Stack{}.Layout(gtx,
		layout.Expanded(func(gtx C) D {
			radius := float32(gtx.Px(t.CornerRadius))
			paint.FillShape(gtx.Ops, t.Bg, clip.RRect{
				Rect: f32.Rectangle{
					Max: layout.FPt(gtx.Constraints.Min),
				},
				NW: radius,
				NE: radius,
				SW: radius,
				SE: radius,
			}.Op(gtx.Ops))
			return D{}
		}),
		layout.Stacked(func(gtx C) D {
			return t.Inset.Layout(gtx, t.Text.Layout)
		}),
	)
}

A component/tooltip_desktop.go => component/tooltip_desktop.go +12 -0
@@ 0,0 1,12 @@
//+build !android,!ios

package component

import "gioui.org/widget/material"

// PlatformTooltip creates a tooltip styled to the current platform
// (desktop or mobile) by choosing based on the OS. This choice may
// not always be appropriate as it only uses the OS to decide.
func PlatformTooltip(th *material.Theme, text string) Tooltip {
    return DesktopTooltip(th, text)
}

A component/tooltip_mobile.go => component/tooltip_mobile.go +12 -0
@@ 0,0 1,12 @@
//+build ios android

package component

import "gioui.org/widget/material"

// PlatformTooltip creates a tooltip styled to the current platform
// (desktop or mobile) by choosing based on the OS. This choice may
// not always be appropriate as it only uses the OS to decide.
func PlatformTooltip(th *material.Theme, text string) Tooltip {
    return MobileTooltip(th, text)
}