Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
12 changes: 6 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ yarn add @untemps/svelte-use-tooltip
border-radius: 6px;
padding: 0.5rem;
}

:global(.tooltip::after) {
content: '';
position: absolute;
Expand All @@ -100,7 +100,7 @@ yarn add @untemps/svelte-use-tooltip
## API

| Props | Type | Default | Description |
|----------------------|---------|---------|-----------------------------------------------------------------------------------------------------------------|
| -------------------- | ------- | ------- | --------------------------------------------------------------------------------------------------------------- |
| `contentSelector` | string | null | Selector of the content to display in the tooltip. |
| `contentClone` | boolean | null | Flag to clone the content to display in the tooltip. If false, the content is removed from its previous parent. |
| `contentActions` | object | null | Configuration of the tooltip actions (see [Content Actions](#content-actions)). |
Expand All @@ -110,7 +110,7 @@ yarn add @untemps/svelte-use-tooltip

### Content Actions

The `contentActions` prop allow handling interactions within the tooltip content.
The `contentActions` prop allow handling interactions within the tooltip content.

Each element inside the content parent may configure its own action since it can be queried using the key-selector.

Expand Down Expand Up @@ -146,11 +146,11 @@ One event by element is possible so far as elements are referenced by selector.
```

| Props | Type | Default | Description |
|-------------------|----------|---------|----------------------------------------------------------------------------------------------------------|
| ----------------- | -------- | ------- | -------------------------------------------------------------------------------------------------------- | --- |
| `eventType` | string | null | Type of the event. All available [events](https://developer.mozilla.org/fr/docs/Web/Events) can be used. |
| `callback` | function | null | Function to be used as event handler. |
| `callbackParams` | array | null | List of arguments to pass to the event handler in. |
| `closeOnCallback` | boolean | false | Flag to automatically close the tooltip when the event handler is triggered. | |
| `closeOnCallback` | boolean | false | Flag to automatically close the tooltip when the event handler is triggered. | |

## Development

Expand All @@ -169,4 +169,4 @@ Contributions are warmly welcomed:
- Develop the feature AND write the tests (or write the tests AND develop the feature)
- Commit your changes
using [Angular Git Commit Guidelines](https://github.com/angular/angular.js/blob/master/DEVELOPERS.md#-git-commit-guidelines)
- Submit a Pull Request
- Submit a Pull Request
146 changes: 100 additions & 46 deletions dev/src/App.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -4,55 +4,84 @@
let tooltipPosition = 'top'
let useCustomTooltipClass = false
let isTooltipDisabled = false
let animateTooltip = false
let useCustomAnimationEnterClass = false
let useCustomAnimationLeaveClass = false

const _onTooltipClick = (arg, event) => {
const _onTooltipClick = (arg, event) => {
console.log(arg)
}
}
</script>

<main>
<div class="container">
<div use:useTooltip={{
position: tooltipPosition,
contentSelector: '.tooltip__button',
contentClone: false,
contentActions: {
'*': {
eventType: 'click',
callback: _onTooltipClick,
callbackParams: ['ok'],
closeOnCallback: true
},
<div
use:useTooltip={{
position: tooltipPosition,
contentSelector: '.tooltip__button',
contentClone: false,
contentActions: {
'*': {
eventType: 'click',
callback: _onTooltipClick,
callbackParams: ['ok'],
closeOnCallback: true,
},
contentClassName: useCustomTooltipClass ? 'tooltip' : null,
disabled: isTooltipDisabled,
}} class="target">Hover me</div>
<span class="tooltip__button">Hi! I'm a fancy tooltip!</span>
},
contentClassName: useCustomTooltipClass ? 'tooltip' : null,
disabled: isTooltipDisabled,
animated: animateTooltip,
animationEnterClassName: useCustomAnimationEnterClass ? 'tooltip-enter' : null,
animationLeaveClassName: useCustomAnimationLeaveClass ? 'tooltip-leave' : null,
}}
class="target"
>
Hover me
</div>
<span class="tooltip__button">Hi! I'm a fancy tooltip!</span>
<form class="settings__form">
<h1>Settings</h1>
<fieldset>
<label>
Use Custom Tooltip Class:
<input type="checkbox" bind:checked={useCustomTooltipClass} />
</label>
</fieldset>
<fieldset>
<label>
Use Custom Tooltip Class:
<input type="checkbox" bind:checked={useCustomTooltipClass} />
</label>
</fieldset>
<fieldset>
<label>
Tooltip Position:
<select bind:value={tooltipPosition}>
<option value="left">Left</option>
<option value="right">Right</option>
<option value="top">Top</option>
<option value="bottom">Bottom</option>
</select>
<option value="left">Left</option>
<option value="right">Right</option>
<option value="top">Top</option>
<option value="bottom">Bottom</option>
</select>
</label>
</fieldset>
<fieldset>
<label>
Animate tooltip:
<input type="checkbox" bind:checked={animateTooltip} />
</label>
</fieldset>
<fieldset>
<label>
Use Custom Animation Enter Class:
<input type="checkbox" bind:checked={useCustomAnimationEnterClass} />
</label>
</fieldset>
<fieldset>
<label>
Use Custom Animation Leave Class:
<input type="checkbox" bind:checked={useCustomAnimationLeaveClass} />
</label>
</fieldset>
<fieldset>
<label>
Disable Tooltip:
<input type="checkbox" bind:checked={isTooltipDisabled} />
</label>
</fieldset>
<fieldset>
<label>
Disable Tooltip:
<input type="checkbox" bind:checked={isTooltipDisabled} />
</label>
</fieldset>
</form>
</div>
</main>
Expand All @@ -75,20 +104,20 @@

.target {
width: 10rem;
height: 3rem;
background-color: white;
color: black;
display: flex;
align-items: center;
justify-content: center;
box-shadow: 0 0 5px 0 rgba(0,0,0,0.5);
height: 3rem;
background-color: white;
color: black;
display: flex;
align-items: center;
justify-content: center;
box-shadow: 0 0 5px 0 rgba(0, 0, 0, 0.5);
}

.target:hover {
cursor: pointer;
background-color: black;
color: white;
}
.target:hover {
cursor: pointer;
background-color: black;
color: white;
}

.settings__form {
display: flex;
Expand Down Expand Up @@ -140,4 +169,29 @@
border-style: solid;
border-color: #ee7008 transparent transparent transparent;
}

:global(.tooltip-enter) {
animation: fadeIn 0.2s linear forwards;
}

:global(.tooltip-leave) {
animation: fadeOut 0.2s linear forwards;
}

@keyframes fadeIn {
from {
opacity: 0;
transform: translateX(50px);
}
to {
opacity: 1;
transform: translateX(0);
}
}
@keyframes fadeOut {
to {
opacity: 0;
transform: translateX(-50px);
}
}
</style>
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@
"build:cjs": "cross-env NODE_ENV=production BABEL_ENV=cjs rollup -c",
"build:es": "cross-env NODE_ENV=production BABEL_ENV=es rollup -c",
"build:umd": "cross-env NODE_ENV=production BABEL_ENV=umd rollup -c",
"prettier": "prettier \"*/**/*.js\" --ignore-path ./.prettierignore --write && git add . && git status"
"prettier": "prettier \"*/**/*.js\" --ignore-path ./.prettierignore --write && git add . && git status",
"prepare": "husky install"
}
}
43 changes: 35 additions & 8 deletions src/__tests__/useTooltip.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,15 +48,27 @@ describe('useTooltip', () => {
action = useTooltip(target, options)
await fireEvent.mouseOver(target) // fireEvent.mouseEnter only works if mouseOver is triggered before
await fireEvent.mouseEnter(target)
expect(template).toBeVisible()
expect(template).toBeInTheDocument()
})

it('Hides tooltip on mouse leave', async () => {
action = useTooltip(target, options)
await fireEvent.mouseOver(target) // fireEvent.mouseEnter only works if mouseOver is triggered before
await fireEvent.mouseEnter(target)
await fireEvent.mouseLeave(target)
expect(template).not.toBeVisible()
expect(template).not.toBeInTheDocument()
await fireEvent.animationEnd(template.parentNode)
expect(template).not.toBeInTheDocument()
})

it('Hides tooltip on mouse leave when animated', async () => {
action = useTooltip(target, { ...options, animated: true })
await fireEvent.mouseOver(target) // fireEvent.mouseEnter only works if mouseOver is triggered before
await fireEvent.mouseEnter(target)
await fireEvent.mouseLeave(target)
expect(template).toBeInTheDocument()
await fireEvent.animationEnd(template.parentNode)
expect(template).not.toBeInTheDocument()
})
})

Expand All @@ -70,7 +82,7 @@ describe('useTooltip', () => {
const newTemplate = _createElement('new-template')
action.update({
...options,
contentSelector: '#new-template'
contentSelector: '#new-template',
})
await fireEvent.mouseOver(target) // fireEvent.mouseEnter only works if mouseOver is triggered before
await fireEvent.mouseEnter(target)
Expand All @@ -97,9 +109,9 @@ describe('useTooltip', () => {
await fireEvent.mouseEnter(target)
await fireEvent.click(template)
expect(contentAction.callback).toHaveBeenCalledWith(contentAction.callbackParams[0], expect.any(Event))
expect(template).toBeVisible()
expect(template).toBeInTheDocument()
})

it('Closes tooltip after triggering callback', async () => {
action = useTooltip(target, options)
options.contentActions['*'].closeOnCallback = true
Expand All @@ -108,7 +120,22 @@ describe('useTooltip', () => {
await fireEvent.mouseEnter(target)
await fireEvent.click(template)
expect(contentAction.callback).toHaveBeenCalledWith(contentAction.callbackParams[0], expect.any(Event))
expect(template).not.toBeVisible()
expect(template).not.toBeInTheDocument()
await fireEvent.animationEnd(template.parentNode)
expect(template).not.toBeInTheDocument()
})

it('Closes tooltip after triggering callback when animated', async () => {
action = useTooltip(target, { ...options, animated: true })
options.contentActions['*'].closeOnCallback = true
const contentAction = options.contentActions['*']
await fireEvent.mouseOver(target) // fireEvent.mouseEnter only works if mouseOver is triggered before
await fireEvent.mouseEnter(target)
await fireEvent.click(template)
expect(contentAction.callback).toHaveBeenCalledWith(contentAction.callbackParams[0], expect.any(Event))
expect(template).toBeInTheDocument()
await fireEvent.animationEnd(template.parentNode)
expect(template).not.toBeInTheDocument()
})

it('Triggers new callback on tooltip click after update', async () => {
Expand Down Expand Up @@ -142,14 +169,14 @@ describe('useTooltip', () => {
action = useTooltip(target, options)
await fireEvent.mouseOver(target) // fireEvent.mouseEnter only works if mouseOver is triggered before
await fireEvent.mouseEnter(target)
expect(template.parentNode).toHaveClass('__tooltip__default')
expect(template.parentNode).toHaveClass('__tooltip')
})

it('Sets new tooltip class after update', async () => {
action = useTooltip(target, options)
await fireEvent.mouseOver(target) // fireEvent.mouseEnter only works if mouseOver is triggered before
await fireEvent.mouseEnter(target)
expect(template.parentNode).toHaveClass('__tooltip__default')
expect(template.parentNode).toHaveClass('__tooltip')
action.update({
...options,
contentClassName: 'foo',
Expand Down
2 changes: 1 addition & 1 deletion src/index.js
Original file line number Diff line number Diff line change
@@ -1 +1 @@
export { default as useTooltip } from './useTooltip'
export { default as useTooltip } from './useTooltip'
Loading