Skip to content

Commit

Permalink
feat(tooltip): leftTopOver supports autoAdjustOverflow DouyinFE#294 (D…
Browse files Browse the repository at this point in the history
  • Loading branch information
shijiatongxue authored Feb 11, 2022
1 parent c33c463 commit 19d7acc
Show file tree
Hide file tree
Showing 9 changed files with 181 additions and 19 deletions.
8 changes: 4 additions & 4 deletions .github/workflows/cypress.yml
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,8 @@ jobs:
with:
# we have already installed all dependencies above
install: true
start: npx http-server -p 6009 storybook-static
wait-on: 'http://localhost:6009'
start: npx http-server -p 6006 storybook-static
wait-on: 'http://localhost:6006'
wait-on-timeout: 120
browser: chrome
record: true
Expand Down Expand Up @@ -103,8 +103,8 @@ jobs:
with:
# we have already installed all dependencies above
install: true
start: npx http-server -p 6009 storybook-static
wait-on: 'http://localhost:6009'
start: npx http-server -p 6006 storybook-static
wait-on: 'http://localhost:6006'
wait-on-timeout: 120
browser: firefox
record: true
Expand Down
3 changes: 2 additions & 1 deletion cypress.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
{
"projectId": "k83u7j"
"projectId": "k83u7j",
"scrollBehavior": false
}
12 changes: 6 additions & 6 deletions cypress/integration/datePicker.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
*/
describe('DatePicker', () => {
it('dateTime needConfirm cancel', () => {
cy.visit('http://127.0.0.1:6009/iframe.html?id=datepicker--fix-need-confirm&args=&viewMode=story');
cy.visit('http://127.0.0.1:6006/iframe.html?id=datepicker--fix-need-confirm&args=&viewMode=story');
cy.get('[data-cy=1] .semi-input-wrapper').click();
cy.get('.semi-datepicker-footer > .semi-button-borderless')
.then(($btn) => {
Expand All @@ -22,7 +22,7 @@ describe('DatePicker', () => {
});

it('dateTime needConfirm confirm', () => {
cy.visit('http://127.0.0.1:6009/iframe.html?id=datepicker--fix-need-confirm&args=&viewMode=story');
cy.visit('http://127.0.0.1:6006/iframe.html?id=datepicker--fix-need-confirm&args=&viewMode=story');
cy.get('[data-cy=1] .semi-input-wrapper').click();
cy.get('.semi-datepicker-day').contains('15')
.then($day => {
Expand All @@ -36,7 +36,7 @@ describe('DatePicker', () => {
});

it('dateTime needConfirm select+cancel', () => {
cy.visit('http://127.0.0.1:6009/iframe.html?id=datepicker--fix-need-confirm&args=&viewMode=story');
cy.visit('http://127.0.0.1:6006/iframe.html?id=datepicker--fix-need-confirm&args=&viewMode=story');
cy.get('[data-cy=1] .semi-input-wrapper').click();
cy.get('.semi-datepicker-day').contains('15')
.then($day => {
Expand All @@ -51,7 +51,7 @@ describe('DatePicker', () => {
});

it('dateTimeRange needConfirm cancel', () => {
cy.visit('http://127.0.0.1:6009/iframe.html?id=datepicker--fix-need-confirm&args=&viewMode=story');
cy.visit('http://127.0.0.1:6006/iframe.html?id=datepicker--fix-need-confirm&args=&viewMode=story');
cy.get('[data-cy=3] .semi-datepicker-range-input-wrapper-start .semi-input-wrapper').click();
cy.get('.semi-datepicker-footer > .semi-button-borderless')
.then($btn => {
Expand All @@ -61,7 +61,7 @@ describe('DatePicker', () => {
});

it('dateTimeRange needConfirm select+cancel', () => {
cy.visit('http://127.0.0.1:6009/iframe.html?id=datepicker--fix-need-confirm&args=&viewMode=story');
cy.visit('http://127.0.0.1:6006/iframe.html?id=datepicker--fix-need-confirm&args=&viewMode=story');
cy.get('[data-cy=3] .semi-datepicker-range-input-wrapper-start .semi-input-wrapper').click();
cy.get('.semi-datepicker-month-grid-left .semi-datepicker-day').contains('15')
.then($day => {
Expand All @@ -80,7 +80,7 @@ describe('DatePicker', () => {
});

it('dateTimeRange needConfirm confirm', () => {
cy.visit('http://127.0.0.1:6009/iframe.html?id=datepicker--fix-need-confirm&args=&viewMode=story');
cy.visit('http://127.0.0.1:6006/iframe.html?id=datepicker--fix-need-confirm&args=&viewMode=story');
cy.get('[data-cy=3] .semi-datepicker-range-input-wrapper-start .semi-input-wrapper').click();
cy.get('.semi-datepicker-month-grid-left .semi-datepicker-day').contains('15')
.then($day => {
Expand Down
4 changes: 2 additions & 2 deletions cypress/integration/table.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

describe('table', () => {
it('row selection', () => {
cy.visit('http://127.0.0.1:6009/iframe.html?id=table--selection-table&args=&viewMode=story');
cy.visit('http://127.0.0.1:6006/iframe.html?id=table--selection-table&args=&viewMode=story');
cy.get('.semi-table-row-head .semi-checkbox-inner-display').click();
cy.get('.semi-checkbox-checked').should('have.length', 4);
});
Expand All @@ -17,7 +17,7 @@ describe('table', () => {
* 即更新 columns 不影响 currentPage
*/
it('columns change ', () => {
cy.visit('http://localhost:6009/iframe.html?id=table--fixed-columns-change&viewMode=story');
cy.visit('http://localhost:6006/iframe.html?id=table--fixed-columns-change&viewMode=story');
cy.get('.semi-page-item').contains('2').click();
cy.get('.semi-table-tbody .semi-checkbox').eq(1).click()
.then(() => {
Expand Down
29 changes: 29 additions & 0 deletions cypress/integration/tooltip.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// tooltip.spec.js created with Cypress
//
// Start writing your Cypress tests below!
// If you're unfamiliar with how Cypress works,
// check out the link below and learn how to write your first test:
// https://on.cypress.io/writing-first-test

/**
* Cypress will default scroll element into view
* @see https://docs.cypress.io/guides/core-concepts/interacting-with-elements#Scrolling
*/
describe('tooltip', () => {
it('leftTopOver autoAdjustOverflow', () => {
const viewportWidth = 1200;
const viewportHeight = 660;
const triggerWidth = 200;
const triggerHeight = 32;
const leftTopPosition = { offset: { top: 0, left: 0 }};
const rightBottomPosition = { offset: { top: -viewportHeight + triggerHeight, left: -viewportWidth + triggerWidth }};
cy.visit('http://127.0.0.1:6006/iframe.html?id=tooltip--left-top-over-auto-adjust-overflow&args=&viewMode=story');
cy.viewport(viewportWidth, viewportHeight);
const dataSelector = `[data-cy=leftTopOver]`;
cy.get(dataSelector).scrollIntoView(leftTopPosition);
cy.get(dataSelector).click({force: true});
cy.get('[x-placement="leftTopOver"]').should('have.length', 1);
cy.get(dataSelector).scrollIntoView(rightBottomPosition);
cy.get('[x-placement="rightBottomOver"]').should('have.length', 1);
});
});
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
"test:story": "cross-env NODE_ENV=test type=story ./node_modules/.bin/jest --silent --notify --maxWorkers=4",
"test:coverage": "cross-env TZ=Asia/Shanghai NODE_ENV=test type=unit ./node_modules/.bin/jest --silent --coverage --notify",
"test:storyUpdate": "cross-env NODE_ENV=test type=story ./node_modules/.bin/jest --silent -u --notify --maxWorkers=4",
"test:cy": "npx http-server storybook-static -p 6009 && npx wait-on http://127.0.0.1:6009 && cypress open",
"test:cy": "npx wait-on http://127.0.0.1:6006 && ./node_modules/.bin/cypress open",
"build:lib": "lerna run build:lib",
"build:js": "lerna run build:js",
"build:css": "lerna run build:css",
Expand Down
2 changes: 2 additions & 0 deletions packages/semi-foundation/tooltip/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ const strings = {
'bottomRight',
'leftTopOver',
'rightTopOver',
'leftBottomOver',
'rightBottomOver',
],
TRIGGER_SET: ['hover', 'focus', 'click', 'custom'],
STATUS_DISABLED: 'disabled',
Expand Down
56 changes: 52 additions & 4 deletions packages/semi-foundation/tooltip/foundation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -434,6 +434,17 @@ export default class Tooltip<P = Record<string, any>, S = Record<string, any>> e
top = triggerRect.top;
translateX = -1;
break;
case 'leftBottomOver':
left = triggerRect.left;
top = triggerRect.bottom;
translateY = -1;
break;
case 'rightBottomOver':
left = triggerRect.right;
top = triggerRect.bottom;
translateX = -1;
translateY = -1;
break;
default:
break;
}
Expand Down Expand Up @@ -602,14 +613,19 @@ export default class Tooltip<P = Record<string, any>, S = Record<string, any>> e

const shouldReverseTop = clientTop < wrapperRect.height + spacing && restClientBottom > wrapperRect.height + spacing;
const shouldReverseLeft = clientLeft < wrapperRect.width + spacing && restClientRight > wrapperRect.width + spacing;
const sholdReverseBottom = restClientBottom < wrapperRect.height + spacing && clientTop > wrapperRect.height + spacing;
const shouldReverseBottom = restClientBottom < wrapperRect.height + spacing && clientTop > wrapperRect.height + spacing;
const shouldReverseRight = restClientRight < wrapperRect.width + spacing && clientLeft > wrapperRect.width + spacing;
const shouldReverseTopOver = restClientTop < wrapperRect.height + spacing && clientBottom > wrapperRect.height + spacing;
const shouldReverseBottomOver = clientBottom < wrapperRect.height + spacing && restClientTop > wrapperRect.height + spacing;

const shouldReverseTopSide = restClientTop < wrapperRect.height && clientBottom > wrapperRect.height;
const shouldReverseBottomSide = clientBottom < wrapperRect.height && restClientTop > wrapperRect.height;
const shouldReverseLeftSide = restClientLeft < wrapperRect.width && clientRight > wrapperRect.width;
const shouldReverseRightSide = clientRight < wrapperRect.width && restClientLeft > wrapperRect.width;

const shouldReverseLeftOver = restClientLeft < wrapperRect.width && clientRight > wrapperRect.width;
const shouldReverseRightOver = clientRight < wrapperRect.width && restClientLeft > wrapperRect.width;

switch (position) {
case 'top':
if (shouldReverseTop) {
Expand Down Expand Up @@ -654,20 +670,20 @@ export default class Tooltip<P = Record<string, any>, S = Record<string, any>> e
}
break;
case 'bottom':
if (sholdReverseBottom) {
if (shouldReverseBottom) {
position = this._reversePos(position, true);
}
break;
case 'bottomLeft':
if (sholdReverseBottom) {
if (shouldReverseBottom) {
position = this._reversePos(position, true);
}
if (shouldReverseLeftSide && widthIsBigger) {
position = this._reversePos(position);
}
break;
case 'bottomRight':
if (sholdReverseBottom) {
if (shouldReverseBottom) {
position = this._reversePos(position, true);
}
if (shouldReverseRightSide && widthIsBigger) {
Expand Down Expand Up @@ -695,6 +711,38 @@ export default class Tooltip<P = Record<string, any>, S = Record<string, any>> e
position = this._reversePos(position, true);
}
break;
case 'leftTopOver':
if (shouldReverseTopOver) {
position = this._reversePos(position, true);
}
if (shouldReverseLeftOver) {
position = this._reversePos(position);
}
break;
case 'leftBottomOver':
if (shouldReverseBottomOver) {
position = this._reversePos(position, true);
}
if (shouldReverseLeftOver) {
position = this._reversePos(position);
}
break;
case 'rightTopOver':
if (shouldReverseTopOver) {
position = this._reversePos(position, true);
}
if (shouldReverseRightOver) {
position = this._reversePos(position);
}
break;
case 'rightBottomOver':
if (shouldReverseBottomOver) {
position = this._reversePos(position, true);
}
if (shouldReverseRightOver) {
position = this._reversePos(position);
}
break;
default:
break;
}
Expand Down
84 changes: 83 additions & 1 deletion packages/semi-ui/tooltip/_story/tooltip.stories.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React, { useState, useMemo } from 'react';
import Tooltip from '../index';
import './story.scss';
import { Tag, Icon, IconButton, Switch, Checkbox, Radio, Button, Select, InputNumber } from '@douyinfe/semi-ui';
import { Tag, Icon, IconButton, Switch, Checkbox, Radio, Button, Select, InputNumber, Space } from '@douyinfe/semi-ui';

import InTableDemo from './InTable';
import EdgeDemo from './Edge';
Expand Down Expand Up @@ -736,3 +736,85 @@ export const AutoAdjustWithSpacing = () => {
AutoAdjustWithSpacing.story = {
name: 'AutoAdjustWithSpacing',
};

/**
* Chromatic UI test
*/
export const leftTopOverDemo = () => {
const [visible, setVisible] = useState(true);
const content = (
<div style={{ height: 200, width: 200 }}>
Semi Design
</div>
);

const commonProps = {
content,
trigger: 'click',
showArrow: false,
visible,
trigger: 'custom',
motion: false,
};
const buttonStyle = {
width: 200,
};

return (
<div data-cy='wrapper'>
<Button onClick={() => setVisible(!visible)}>toggle visible</Button>
<div style={{ paddingTop: 200 }}>
<Space spacing={80}>
<Tooltip {...commonProps} position='leftTopOver' >
<Button data-cy='leftTopOver' style={buttonStyle}>leftTopOver</Button>
</Tooltip>
<Tooltip {...commonProps} position='leftBottomOver'>
<Button data-cy='leftBottomOver' style={buttonStyle}>leftBottomOver</Button>
</Tooltip>
<Tooltip {...commonProps} position='rightTopOver'>
<Button data-cy='rightTopOver' style={buttonStyle}>rightTopOver</Button>
</Tooltip>
<Tooltip {...commonProps} position='rightBottomOver'>
<Button data-cy='rightBottomOver' style={buttonStyle}>rightBottomOver</Button>
</Tooltip>
</Space>
</div>
</div>
)
};
leftTopOverDemo.storyName = `leftTopOver visible`;
leftTopOverDemo.parameters = {
chromatic: {
disableSnapshot: false,
delay: 3000,
viewports: [1200]
}
};

/**
* Cypress test
*/
export const leftTopOverAutoAdjustOverflow = () => {
const content = (
<div style={{ height: 200, width: 200 }}>
Semi Design
</div>
);

const commonProps = {
content,
trigger: 'click',
showArrow: false,
};

return (
<div data-cy='wrapper' style={{ width: '200vw', height: '200vw', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
<div>
<Tooltip {...commonProps} position='leftTopOver' >
<Button data-cy='leftTopOver' style={{ width: 200 }}>leftTopOver</Button>
</Tooltip>
</div>
</div>
)
};
leftTopOverAutoAdjustOverflow.storyName = `leftTopOver autoAdjustOverflow`;

0 comments on commit 19d7acc

Please sign in to comment.