Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(component): add tooltip #367

Merged
merged 38 commits into from
Nov 12, 2024
Merged
Show file tree
Hide file tree
Changes from 34 commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
d50e0ad
chore: add tooltip folder
igorwessel Oct 10, 2023
186f29f
chore: add popperjs/core
igorwessel Jan 10, 2024
80d9e2b
feat: initial stage for tooltip component
igorwessel Jan 10, 2024
4254271
feat(tooltip): add styles
igorwessel Jan 11, 2024
f5e0c8d
feat(tooltip): change mode to click when is mobile
igorwessel Jan 11, 2024
ee6100e
refactor(tooltip): add method with responsible for attach events
igorwessel Jan 12, 2024
9316a49
chore(tooltip): change sccs to include media query
igorwessel Jan 12, 2024
68d492f
chore(tooltip): types for tooltip
igorwessel Jan 12, 2024
c82eb46
chore(tooltip): improve docs, alter role when is mobile
igorwessel Jan 12, 2024
0c4082c
test(tooltip): fix tests aafter add button when is mobile
igorwessel Jan 12, 2024
46693eb
refactor(tooltip): use rupture for media query
igorwessel Jan 12, 2024
9d8ac12
refactor(tooltip): use class to style close button
igorwessel Jan 12, 2024
7e018cb
refactor(tooltip): use var to define square range for arrow
igorwessel Jan 12, 2024
99079d1
refactor(tooltip): use for each loop to define arrow position stylerule
igorwessel Jan 12, 2024
56fe6c6
test(tooltip): add class for close button
igorwessel Jan 12, 2024
a9fe3bb
docs(tooltip): change description and add with actions decorator
igorwessel Jan 12, 2024
9a06d12
feat(tooltip): add shift away animation
igorwessel Jan 15, 2024
d5bf6d9
feat(tooltip): hide when click outside
igorwessel Jan 18, 2024
b3a98cb
fix(tooltip): remove blur event listener when is mobile
igorwessel Jan 19, 2024
bbacf0a
feat(tooltip): add text control in storybook
igorwessel Jan 19, 2024
fafc8af
fix(tooltip): wrong placement when is auto
igorwessel Jan 19, 2024
10626d4
Merge branch 'main' of github.com:juntossomosmais/atomium into feat/a…
igorwessel Mar 4, 2024
3c2d19f
Merge branch 'main' of github.com:juntossomosmais/atomium into feat/a…
igorwessel Nov 5, 2024
8c8a7a0
feat(tooltip): add click trigger
igorwessel Nov 5, 2024
e5dcb16
fix(tooltip): sonar issues about readonly properties
igorwessel Nov 5, 2024
c84acab
docs(adr): add adr about popperjs
igorwessel Nov 5, 2024
2df4d06
chore(tooltip): decrease popperjs dep
igorwessel Nov 5, 2024
37d194a
feat(tooltip): controlled open state, and shadowdom
igorwessel Nov 6, 2024
cadbb3a
fix(tooltip): duplicate selector scss
igorwessel Nov 6, 2024
319e613
fix(tooltip): not able to render tooltip in docs page
igorwessel Nov 6, 2024
4b6bf6c
docs(tooltip): add semicolon in lists
igorwessel Nov 6, 2024
cb3839f
Merge branch 'main' of github.com:juntossomosmais/atomium into feat/a…
igorwessel Nov 6, 2024
eb215be
chore(deps): add vitejs-pluginvue
igorwessel Nov 6, 2024
ef47c06
Merge branch 'main' into feat/add-tooltip-component
igorwessel Nov 6, 2024
72caf35
chore(docs): fix typo
igorwessel Nov 7, 2024
751948e
Merge branch 'main' into feat/add-tooltip-component
igorwessel Nov 11, 2024
4cd7f1c
Merge branch 'main' into feat/add-tooltip-component
igorwessel Nov 11, 2024
a1dc729
Merge branch 'main' into feat/add-tooltip-component
igorwessel Nov 11, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion .stylelintrc.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,12 @@
{
"extends": ["@juntossomosmais/linters/stylelint.config.scss.js"],
"ignoreFiles": ["utils/scss/**"]
"ignoreFiles": ["utils/scss/**"],
"rules": {
"at-rule-no-unknown": [
true,
{
"ignoreAtRules": ["function", "if", "each", "include", "mixin", "else"]
}
]
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { Meta } from '@storybook/addon-docs'

<Meta title='Docs/Architecture Decision Records/ADR 0014: Why PopperJS' />
gabrielduete marked this conversation as resolved.
Show resolved Hide resolved

# ADR 0014: Why PopperJS

🗓️ 2024-11 · ✍️ [@igorwessel](https://github.com/igorwessel)

## Context

It was necessary due to the complexity of modifying the `ion-popover` to meet the tooltip requirements. This involved many changes to the `ion-popover` component to make it behave like a tooltip.

## Problems

These changes included things like:

- Removing a class that locks the scroll on the site (added to the body) when using the `ion-popover`;
- Adding scroll tracking;
- Ensuring responsiveness in terms of automatically changing side/directio;

## Decision Drivers

- Bundle Size: The size of the library was considered. If the size was too large, it would be a NO-GO for inclusion in the project. As the entire library currently (2024/11/05) only 8.9KB, we understood that the size would not negatively impact the user experience;
- Popularity and Maintenance: PopperJS is the most well-known library for handling this type of work. Many libraries that implement some type of "popper" use it to provide this functionality;

## Decision

Based on this, we understood that it does not make sense to spend effort recreating many of the functionalities that PopperJS offers. Given that the library size is small, we decided to add the library to the project to implement our tooltip.
10 changes: 10 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
},
"dependencies": {
"@ionic/core": "^7.8.6",
"@popperjs/core": "^2.11.8",
MayaraRMA marked this conversation as resolved.
Show resolved Hide resolved
"@stencil/core": "~4.17.2"
},
"devDependencies": {
Expand All @@ -57,7 +58,6 @@
"@storybook/theming": "^7.6.17",
"@storybook/vue3": "^7.6.6",
"@storybook/vue3-vite": "^7.6.6",
"@vitejs/plugin-vue": "^5.1.3",
"@storybook/web-components": "^7.6.17",
"@storybook/web-components-webpack5": "^7.6.17",
"@testing-library/jest-dom": "^6.4.8",
Expand Down Expand Up @@ -104,6 +104,7 @@
"tslib": "^2.8.1",
"typescript": "^5.5.4",
"vite": "^5.4.2",
"@vitejs/plugin-vue": "^5.1.3",
"vue": "^3.4.38"
},
"lint-staged": {
Expand Down
65 changes: 65 additions & 0 deletions packages/core/src/components.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,22 @@ export namespace Components {
"value"?: IonTypes.IonTextarea['value'];
"wrap"?: 'hard' | 'soft' | 'off';
}
interface AtomTooltip {
"action": 'hover' | 'click';
"element": string;
"open": boolean;
"placement": | 'auto'
| 'auto-start'
| 'auto-end'
| 'top'
| 'top-start'
| 'top-end'
| 'bottom'
| 'bottom-start'
| 'bottom-end'
| 'right'
| 'left';
}
}
export interface AtomAlertCustomEvent<T> extends CustomEvent<T> {
detail: T;
Expand Down Expand Up @@ -306,6 +322,10 @@ export interface AtomTextareaCustomEvent<T> extends CustomEvent<T> {
detail: T;
target: HTMLAtomTextareaElement;
}
export interface AtomTooltipCustomEvent<T> extends CustomEvent<T> {
detail: T;
target: HTMLAtomTooltipElement;
}
declare global {
interface HTMLAtomAlertElementEventMap {
"atomClose": any;
Expand Down Expand Up @@ -561,6 +581,24 @@ declare global {
prototype: HTMLAtomTextareaElement;
new (): HTMLAtomTextareaElement;
};
interface HTMLAtomTooltipElementEventMap {
"atomClose": any;
"atomOpen": any;
}
interface HTMLAtomTooltipElement extends Components.AtomTooltip, HTMLStencilElement {
addEventListener<K extends keyof HTMLAtomTooltipElementEventMap>(type: K, listener: (this: HTMLAtomTooltipElement, ev: AtomTooltipCustomEvent<HTMLAtomTooltipElementEventMap[K]>) => any, options?: boolean | AddEventListenerOptions): void;
addEventListener<K extends keyof DocumentEventMap>(type: K, listener: (this: Document, ev: DocumentEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void;
addEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void;
addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void;
removeEventListener<K extends keyof HTMLAtomTooltipElementEventMap>(type: K, listener: (this: HTMLAtomTooltipElement, ev: AtomTooltipCustomEvent<HTMLAtomTooltipElementEventMap[K]>) => any, options?: boolean | EventListenerOptions): void;
removeEventListener<K extends keyof DocumentEventMap>(type: K, listener: (this: Document, ev: DocumentEventMap[K]) => any, options?: boolean | EventListenerOptions): void;
removeEventListener<K extends keyof HTMLElementEventMap>(type: K, listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any, options?: boolean | EventListenerOptions): void;
removeEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | EventListenerOptions): void;
}
var HTMLAtomTooltipElement: {
prototype: HTMLAtomTooltipElement;
new (): HTMLAtomTooltipElement;
};
interface HTMLElementTagNameMap {
"atom-alert": HTMLAtomAlertElement;
"atom-badge": HTMLAtomBadgeElement;
Expand All @@ -582,6 +620,7 @@ declare global {
"atom-steps-modal": HTMLAtomStepsModalElement;
"atom-tag": HTMLAtomTagElement;
"atom-textarea": HTMLAtomTextareaElement;
"atom-tooltip": HTMLAtomTooltipElement;
}
}
declare namespace LocalJSX {
Expand Down Expand Up @@ -865,6 +904,30 @@ declare namespace LocalJSX {
"value"?: IonTypes.IonTextarea['value'];
"wrap"?: 'hard' | 'soft' | 'off';
}
interface AtomTooltip {
"action"?: 'hover' | 'click';
"element"?: string;
/**
* Event is dispatched when: 1. Mouse leave event in selector 2. Click "Close" button when is mobile
*/
"onAtomClose"?: (event: AtomTooltipCustomEvent<any>) => void;
/**
* Event is dispatched when: 1. Mouse enter event in selector 2. Click in element when is mobile
*/
"onAtomOpen"?: (event: AtomTooltipCustomEvent<any>) => void;
"open"?: boolean;
"placement"?: | 'auto'
| 'auto-start'
| 'auto-end'
| 'top'
| 'top-start'
| 'top-end'
| 'bottom'
| 'bottom-start'
| 'bottom-end'
| 'right'
| 'left';
}
interface IntrinsicElements {
"atom-alert": AtomAlert;
"atom-badge": AtomBadge;
Expand All @@ -886,6 +949,7 @@ declare namespace LocalJSX {
"atom-steps-modal": AtomStepsModal;
"atom-tag": AtomTag;
"atom-textarea": AtomTextarea;
"atom-tooltip": AtomTooltip;
}
}
export { LocalJSX as JSX };
Expand All @@ -912,6 +976,7 @@ declare module "@stencil/core" {
"atom-steps-modal": LocalJSX.AtomStepsModal & JSXBase.HTMLAttributes<HTMLAtomStepsModalElement>;
"atom-tag": LocalJSX.AtomTag & JSXBase.HTMLAttributes<HTMLAtomTagElement>;
"atom-textarea": LocalJSX.AtomTextarea & JSXBase.HTMLAttributes<HTMLAtomTextareaElement>;
"atom-tooltip": LocalJSX.AtomTooltip & JSXBase.HTMLAttributes<HTMLAtomTooltipElement>;
}
}
}
94 changes: 94 additions & 0 deletions packages/core/src/components/tooltip/stories/tooltip.args.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import { Category } from '@atomium/storybook-utils/enums/table'
import { withActions } from '@storybook/addon-actions/decorator'

export const TooltipStoryArgs = {
parameters: {
actions: {
handles: ['atomOpen', 'atomClose'],
},
decorators: [withActions],
docs: {
description: {
component:
'Tooltip is a small pop-up box that appears when a user moves a mouse over an element',
},
},
layout: 'centered',
},
argTypes: {
placement: {
control: 'select',
defaultValue: { summary: 'top' },
options: [
'auto',
'auto-start',
'auto-end',
'top',
'top-start',
'top-end',
'bottom',
'bottom-start',
'bottom-end',
'right',
'left',
],
description: 'Determines placement for tooltip',
table: {
category: Category.PROPERTIES,
},
},
action: {
control: 'select',
defaultValue: { summary: 'hover' },
options: ['hover', 'click'],
description:
'Determines the trigger action for the tooltip: `hover` or `click`.',
table: {
category: Category.PROPERTIES,
},
},
element: {
control: 'text',
description:
'Specifies the element responsible for opening/closing the tooltip.',
table: {
category: Category.PROPERTIES,
},
},
open: {
control: 'boolean',
description: 'Controls whether the tooltip is open or closed.',
table: {
category: Category.PROPERTIES,
},
},
text: {
control: 'text',
description: 'Determines a text for tooltip.',
table: {
category: Category.PROPERTIES,
},
},
atomOpen: {
description:
'Event emitted when hover element, but for mobile when click in element.',
table: {
category: Category.EVENTS,
},
},
atomClose: {
description: 'Event emitted when the tooltip is closed.',
table: {
category: Category.EVENTS,
},
},
},
}

export const TooltipComponentArgs = {
element: 'atomium-element',
placement: 'top',
text: 'Tooltip',
action: 'hover',
open: false,
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import { Meta, StoryObj } from '@storybook/web-components'
import { html } from 'lit'

import { TooltipComponentArgs, TooltipStoryArgs } from './tooltip.args'

const createTooltip = (args, buttonText = 'hover') => {
return html`
<atom-button
fill="solid"
size="large"
id="${args.element}"
aria-describedby="atom-tooltip"
>
${buttonText}
</atom-button>

<atom-tooltip
id="atom-tooltip"
placement="${args.placement}"
element="${args.element}"
action="${args.action}"
open="${args.open}"
>
${args.text}
</atom-tooltip>
`
}

export default {
title: 'Components/Tooltip',
component: 'atom-tooltip',
...TooltipStoryArgs,
} as Meta

export const Hover: StoryObj = {
render: (args) => createTooltip(args, 'Hover'),
args: {
...TooltipComponentArgs,
element: 'hover',
placement: 'top',
open: false,
},
}

export const Click: StoryObj = {
render: (args) => createTooltip(args, 'Click'),
args: {
...TooltipComponentArgs,
element: 'click',
placement: 'top',
action: 'click',
open: false,
},
}

export const Opened: StoryObj = {
render: (args) => createTooltip(args, 'Opened'),
args: {
...TooltipComponentArgs,
element: 'opened',
placement: 'left',
action: 'click',
open: true,
},
}
Loading
Loading