From 7222b51ef3a3043c1d71fced7151157e7cc7cd6c Mon Sep 17 00:00:00 2001 From: Sam Foo Date: Wed, 21 Apr 2021 00:37:13 -0700 Subject: [PATCH] Add tooltip to icon component Signed-off-by: Sam Foo --- changelogs/unreleased/2350-GuessWhoSamFoo | 1 + pkg/view/component/icon.go | 62 +++++++++++++++---- pkg/view/component/icon_test.go | 32 +++++++++- pkg/view/component/signpost.go | 2 +- .../presentation/button/button.component.ts | 2 +- .../presentation/icon/icon.component.html | 44 +++++++++---- .../presentation/icon/icon.component.ts | 20 +++++- web/src/app/modules/shared/models/content.ts | 7 +++ web/src/stories/icon.stories.mdx | 40 ++++++++++++ 9 files changed, 183 insertions(+), 27 deletions(-) create mode 100644 changelogs/unreleased/2350-GuessWhoSamFoo diff --git a/changelogs/unreleased/2350-GuessWhoSamFoo b/changelogs/unreleased/2350-GuessWhoSamFoo new file mode 100644 index 0000000000..b4dcfa3553 --- /dev/null +++ b/changelogs/unreleased/2350-GuessWhoSamFoo @@ -0,0 +1 @@ +Added tooltips for icons diff --git a/pkg/view/component/icon.go b/pkg/view/component/icon.go index 5936d253ec..683748e5cf 100644 --- a/pkg/view/component/icon.go +++ b/pkg/view/component/icon.go @@ -10,17 +10,18 @@ type Icon struct { } type IconConfig struct { - Shape string `json:"shape"` - Size string `json:"size"` - Direction Direction `json:"direction"` - Flip Flip `json:"flip"` - Solid bool `json:"solid"` - Status Status `json:"status"` - Inverse bool `json:"inverse"` - Badge Badge `json:"badge"` - Color string `json:"color"` - BadgeColor string `json:"badgeColor"` - Label string `json:"label"` + Shape string `json:"shape"` + Size string `json:"size"` + Direction Direction `json:"direction"` + Flip Flip `json:"flip"` + Solid bool `json:"solid"` + Status Status `json:"status"` + Inverse bool `json:"inverse"` + Badge Badge `json:"badge"` + Color string `json:"color"` + BadgeColor string `json:"badgeColor"` + Label string `json:"label"` + Tooltip *TooltipConfig `json:"tooltip,omitempty"` } type Direction string @@ -60,6 +61,34 @@ const ( BadgeInheritTriangle Badge = "inherit-triangle" ) +type IconOption func(icon *Icon) + +type TooltipConfig struct { + Message string `json:"message"` + Size TooltipSize `json:"size"` + Position TooltipPosition `json:"position"` +} + +type TooltipSize string + +const ( + TooltipExtraSmall TooltipSize = "xs" + TooltipSmall TooltipSize = "sm" + TooltipMedium TooltipSize = "md" + TooltipLarge TooltipSize = "lg" +) + +type TooltipPosition string + +const ( + TooltipLeft TooltipPosition = "left" + TooltipRight TooltipPosition = "right" + TooltipTopLeft TooltipPosition = "top-left" + TooltipTopRight TooltipPosition = "top-right" + TooltipBottomLeft TooltipPosition = "bottom-left" + TooltipBottomRight TooltipPosition = "bottom-right" +) + func NewIcon(shape string, options ...func(*Icon)) *Icon { i := &Icon{ Base: newBase(TypeIcon, nil), @@ -87,6 +116,17 @@ func (i *Icon) MarshalJSON() ([]byte, error) { return json.Marshal(&m) } +// WithTooltip configures an icon with a tooltip +func WithTooltip(message string, size TooltipSize, position TooltipPosition) IconOption { + return func(icon *Icon) { + icon.Config.Tooltip = &TooltipConfig{ + Message: message, + Size: size, + Position: position, + } + } +} + // AddLabel adds an aria-label for screen readers func (i *Icon) AddLabel(label string) { i.Config.Label = label diff --git a/pkg/view/component/icon_test.go b/pkg/view/component/icon_test.go index ec48e75a55..f942176f47 100644 --- a/pkg/view/component/icon_test.go +++ b/pkg/view/component/icon_test.go @@ -15,7 +15,7 @@ import ( func Test_Icon_Marshal(t *testing.T) { test := []struct { name string - input Component + input *Icon expectedPath string isErr bool }{ @@ -55,3 +55,33 @@ func Test_Icon_Marshal(t *testing.T) { }) } } + +func Test_Icon_Options(t *testing.T) { + test := []struct { + name string + optsFunc IconOption + expected *Icon + }{ + { + name: "Icon with tooltip", + optsFunc: WithTooltip("hello", TooltipLarge, TooltipTopRight), + expected: &Icon{ + Base: newBase(TypeIcon, nil), + Config: IconConfig{ + Tooltip: &TooltipConfig{ + Message: "hello", + Size: TooltipLarge, + Position: TooltipTopRight, + }, + }, + }, + }, + } + + for _, tc := range test { + t.Run(tc.name, func(t *testing.T) { + result := NewIcon("", tc.optsFunc) + assert.Equal(t, tc.expected, result) + }) + } +} diff --git a/pkg/view/component/signpost.go b/pkg/view/component/signpost.go index a956ae3628..59a8b3893f 100644 --- a/pkg/view/component/signpost.go +++ b/pkg/view/component/signpost.go @@ -55,7 +55,7 @@ func NewSignpost(t Component, m string) *Signpost { return so } -// SetStatus sets the status of the text component. +// SetPosition sets the status of the text component. func (t *Signpost) SetPosition(position Position) { t.Config.Position = position } diff --git a/web/src/app/modules/shared/components/presentation/button/button.component.ts b/web/src/app/modules/shared/components/presentation/button/button.component.ts index 29e51105f9..25ded291ae 100644 --- a/web/src/app/modules/shared/components/presentation/button/button.component.ts +++ b/web/src/app/modules/shared/components/presentation/button/button.component.ts @@ -47,7 +47,7 @@ export class ButtonComponent extends AbstractViewComponent { } update() { - let button = this.v.config; + const button = this.v.config; if (button.modal) { this.modalView = this.v.config.modal; const modal = this.modalView as ModalView; diff --git a/web/src/app/modules/shared/components/presentation/icon/icon.component.html b/web/src/app/modules/shared/components/presentation/icon/icon.component.html index 0103681808..fdd7684b92 100644 --- a/web/src/app/modules/shared/components/presentation/icon/icon.component.html +++ b/web/src/app/modules/shared/components/presentation/icon/icon.component.html @@ -1,12 +1,32 @@ - + + + + + + + + {{ tooltip.message }} + + diff --git a/web/src/app/modules/shared/components/presentation/icon/icon.component.ts b/web/src/app/modules/shared/components/presentation/icon/icon.component.ts index 36e6f9e3e0..504f90c740 100644 --- a/web/src/app/modules/shared/components/presentation/icon/icon.component.ts +++ b/web/src/app/modules/shared/components/presentation/icon/icon.component.ts @@ -16,7 +16,7 @@ import { loadTechnologyIconSet, loadChartIconSet, } from '@cds/core/icon'; -import { IconView } from '../../../models/content'; +import { IconView, Tooltip } from '../../../models/content'; @Component({ selector: 'app-view-icon', @@ -35,6 +35,8 @@ export class IconComponent extends AbstractViewComponent { status: string; iconStyle: string; label: string; + tooltip: Tooltip; + tooltipClass: string; constructor(private cdr: ChangeDetectorRef) { super(); @@ -51,6 +53,11 @@ export class IconComponent extends AbstractViewComponent { protected update(): void { const view = this.v; + this.tooltip = view.config.tooltip; + + if (this.tooltip) { + this.generateTooltipClassStyles(); + } this.shape = view.config.shape; this.flip = view.config.flip; @@ -72,4 +79,15 @@ export class IconComponent extends AbstractViewComponent { this.label = view.config.label; this.cdr.markForCheck(); } + + generateTooltipClassStyles() { + this.tooltipClass = 'tooltip'; + if (this.tooltip.size !== '') { + this.tooltipClass += ' tooltip-' + this.tooltip.size; + } + if (this.tooltip.position !== '') { + this.tooltipClass += ' tooltip-' + this.tooltip.position; + } + return this.tooltipClass; + } } diff --git a/web/src/app/modules/shared/models/content.ts b/web/src/app/modules/shared/models/content.ts index 586691049e..c804ed62f8 100644 --- a/web/src/app/modules/shared/models/content.ts +++ b/web/src/app/modules/shared/models/content.ts @@ -594,6 +594,7 @@ export interface IconView extends View { color?: string; badgeColor?: string; label?: string; + tooltip?: Tooltip; }; } @@ -605,6 +606,12 @@ export interface SignpostView extends View { }; } +export interface Tooltip { + message: string; + size: string; + position: string; +} + export interface ButtonView extends View { config: { payload: {}; diff --git a/web/src/stories/icon.stories.mdx b/web/src/stories/icon.stories.mdx index ca5386ea27..8ad94cc3b3 100644 --- a/web/src/stories/icon.stories.mdx +++ b/web/src/stories/icon.stories.mdx @@ -11,6 +11,10 @@ c.Config.Badge = component.BadgeDanger c.Config.AddLabel("label for accessibility") `}} +export const iconWithTooltipDocs = {source: {code: ` +component.NewIcon("user", component.WithTooltip("hello", component.TooltipMedium, component.TooltipRight) +`}} +

Icon Component

Description

An Icon component is use to display icons use the API from Clarity 5

@@ -47,5 +51,41 @@ c.Config.AddLabel("label for accessibility") +

Icon with tooltip

+

An icon can be configured with a tooltip to display a message on hover.

+ + + + {{ + props: { + view: object('View', { + metadata: { + type: 'icon', + }, + config: { + shape: "user", + size: "", + direction: "", + flip: "", + solid: false, + status: "", + inverse: false, + badge: "", + color: "", + badgeColor: "", + label: "", + tooltip: { + message: "hello", + size: "md", + position: "right", + } + } + }), + }, + component: IconComponent, + }} + + +

Props