From 99548460a36970bae854c71d3d74428441a81881 Mon Sep 17 00:00:00 2001 From: BQX Date: Tue, 6 Feb 2024 16:57:36 +0800 Subject: [PATCH 1/2] fix(ui): pagination #1 add zustand as currentPage store --- packages/ui/lib/Button/Button.module.scss | 10 +- packages/ui/lib/Button/Button.stories.ts | 2 +- packages/ui/lib/Button/Button.tsx | 13 +- .../ui/lib/Pagination/Pagination.module.scss | 72 ++++---- .../ui/lib/Pagination/Pagination.stories.tsx | 2 +- packages/ui/lib/Pagination/Pagination.tsx | 155 +++++++++--------- packages/ui/lib/Pagination/PaginationItem.tsx | 44 +++++ packages/ui/lib/Pagination/useCurrentPage.ts | 18 ++ packages/ui/package.json | 3 +- pnpm-lock.yaml | 3 + 10 files changed, 200 insertions(+), 122 deletions(-) create mode 100644 packages/ui/lib/Pagination/PaginationItem.tsx create mode 100644 packages/ui/lib/Pagination/useCurrentPage.ts diff --git a/packages/ui/lib/Button/Button.module.scss b/packages/ui/lib/Button/Button.module.scss index 893c098..0f9f4cf 100644 --- a/packages/ui/lib/Button/Button.module.scss +++ b/packages/ui/lib/Button/Button.module.scss @@ -24,9 +24,14 @@ color: var(--primary-color); border: 1px solid var(--primary-color); } + &.border { + border: solid 1px #f1f1f1; + background-color: var(--white-color); + color: var(--black-color); + font-weight: 500; + } &.ghost { - &:hover { - // background-color: #ffffffc4; + &:hover:not(.disabled) { filter: brightness(1); backdrop-filter: brightness(0.97); } @@ -40,6 +45,7 @@ &.disabled { filter: grayscale(1); cursor: not-allowed; + opacity: 0.4; &:hover { backdrop-filter: none; } diff --git a/packages/ui/lib/Button/Button.stories.ts b/packages/ui/lib/Button/Button.stories.ts index 01530b5..31eec98 100644 --- a/packages/ui/lib/Button/Button.stories.ts +++ b/packages/ui/lib/Button/Button.stories.ts @@ -12,7 +12,7 @@ const meta = { tags: ['autodocs'], argTypes: { color: { - options: ['primary', 'secondary', 'ghost', 'danger'], + options: ['primary', 'secondary', 'ghost', 'danger', 'border'], control: { type: 'select' }, }, size: { diff --git a/packages/ui/lib/Button/Button.tsx b/packages/ui/lib/Button/Button.tsx index b54a2d8..ed23cf2 100644 --- a/packages/ui/lib/Button/Button.tsx +++ b/packages/ui/lib/Button/Button.tsx @@ -6,7 +6,7 @@ export interface ButtonProps extends React.ButtonHTMLAttributes( - ({ color = 'primary', shadow = 'none', size = 'medium', disabled = false, ...rest }, ref) => { + ( + { color = 'primary', shadow = 'none', size = 'medium', disabled = false, className, ...rest }, + ref, + ) => { const btnClass = classnames( styles['base'], styles[color], @@ -33,7 +40,7 @@ export const Button = React.forwardRef( return ( + ); +}; diff --git a/packages/ui/lib/Pagination/useCurrentPage.ts b/packages/ui/lib/Pagination/useCurrentPage.ts new file mode 100644 index 0000000..c8fcb23 --- /dev/null +++ b/packages/ui/lib/Pagination/useCurrentPage.ts @@ -0,0 +1,18 @@ +import { create } from 'zustand'; + +type State = { + currentPage: number; +}; + +type Action = { + increaseCurrentPage: () => void; + decreaseCurrentPage: () => void; + changeCurrentPage: (currentPage: State['currentPage']) => void; +}; + +export const useCurrentPage = create((set) => ({ + currentPage: 1, + increaseCurrentPage: () => set((state) => ({ currentPage: state.currentPage + 1 })), + decreaseCurrentPage: () => set((state) => ({ currentPage: state.currentPage - 1 })), + changeCurrentPage: (newCurrentPage) => set(() => ({ currentPage: newCurrentPage })), +})); diff --git a/packages/ui/package.json b/packages/ui/package.json index 1b9c7bb..eb1bd79 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -83,6 +83,7 @@ "react-dom": "^18.2.0" }, "dependencies": { - "@types/react-transition-group": "^4.4.10" + "@types/react-transition-group": "^4.4.10", + "zustand": "^4.4.7" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index fc8d0a6..b2e705e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -115,6 +115,9 @@ importers: '@types/react-transition-group': specifier: ^4.4.10 version: 4.4.10 + zustand: + specifier: ^4.4.7 + version: 4.4.7(@types/react@18.2.43)(react@18.2.0) devDependencies: '@storybook/addon-actions': specifier: ^7.6.5 From 460ceab5d51fcc135b4a5c5d9b704d78227c1107 Mon Sep 17 00:00:00 2001 From: BQX Date: Tue, 6 Feb 2024 19:44:30 +0800 Subject: [PATCH 2/2] fix(ui): showToast #1 fix the close slide and opacity --- packages/ui/lib/Toast/Toast.tsx | 9 ++- packages/ui/lib/Toast/showToast.tsx | 100 ++++++++++------------------ 2 files changed, 39 insertions(+), 70 deletions(-) diff --git a/packages/ui/lib/Toast/Toast.tsx b/packages/ui/lib/Toast/Toast.tsx index 60b46f1..29fbb3a 100644 --- a/packages/ui/lib/Toast/Toast.tsx +++ b/packages/ui/lib/Toast/Toast.tsx @@ -1,5 +1,5 @@ import classNames from 'classnames'; -import React, { useState, type ReactNode, useEffect } from 'react'; +import React, { useState, useEffect } from 'react'; import styles from './Toast.module.scss'; export interface ToastProps { @@ -44,8 +44,6 @@ export const Toast = React.forwardRef( const [visible, setVisble] = useState(true); const [innerVisible, setInnerVisible] = useState(true); - // console.log(close); - const toastClass = classNames( styles['base'], styles[type], @@ -54,7 +52,8 @@ export const Toast = React.forwardRef( ); useEffect(() => { - if (!visible) { + if (!visible && close) { + // A delay is set here, in order to see the animation in its entirety setTimeout(() => { setInnerVisible(false); close(); @@ -74,7 +73,7 @@ export const Toast = React.forwardRef(
- {/* 将type一键大写,作为标题呈现 */} + {/* Capitalize the TYPE one-key to present it as a headline */}
{type.toUpperCase()}
{ if (!toastContainer) { toastContainer = document.createElement('div'); @@ -25,108 +23,80 @@ export const showToast = (props?: ToastProps) => { const root = createRoot(div); - const close = () => { - div.remove(); - toasts = toasts.filter((toast) => toast !== div); - state.slideToasts = toasts; // 更新 slideToasts 的值 - expandSlide(state.slideToasts, div); - }; - root.render( closeToast(div)} >, ); toasts.push(div); - state.slideToasts = toasts; // 更新 slideToasts 的值 - slide(state.slideToasts, div); - - if (toasts.length > 3) { - toasts.shift(); - const firstChild = toastContainer.childNodes[0]; - setTimeout(() => { - while (toastContainer.childNodes.length > 3) { - toastContainer.removeChild(toastContainer.firstChild!); - } - }, 300); - } + addListener(div); + hide(toasts); + moreThreeClose(); + moreTimeClose(div); +}; +const moreTimeClose = (div: HTMLDivElement) => { setTimeout(() => { const ToasthideClass: string = classNames(styles['toastHide']); div.className = ToasthideClass; setTimeout(() => { - // Only remove the toast if the mouse is not over it toastContainer?.removeChild(div); toasts = toasts.filter((toast) => toast !== div); - state.slideToasts = toasts; - }, 280); + }, 300); }, 4000); }; -const expand = (expandToasts: any) => { +const moreThreeClose = () => { + if (toasts.length > 3) { + toasts.shift(); + setTimeout(() => { + while (toastContainer && toastContainer?.childNodes.length > 3 && toastContainer.firstChild) { + toastContainer.removeChild(toastContainer.firstChild); + } + }, 300); + } +}; + +const closeToast = (div: HTMLDivElement) => { + div.remove(); + toasts = toasts.filter((toast) => toast !== div); + addListener(div); + expand(toasts); +}; + +const expand = (expandToasts: HTMLDivElement[]) => { expandToasts.forEach((toast: HTMLDivElement, index: number) => { const totalHeight = expandToasts .slice(0, expandToasts.length - index - 1) - .reduce((height: any, toast: any) => height + toast.offsetHeight, 0); + .reduce((height: number, toast: HTMLDivElement) => height + toast.offsetHeight, 0); toast.style.transform = `translateY(-${totalHeight}px)`; }); }; -const hide = (hideToasts: any) => { +const hide = (hideToasts: HTMLDivElement[]) => { hideToasts.forEach((toast: HTMLDivElement, index: number) => { toast.style.transform = `translateY(-${(hideToasts.length - index - 1) * 15}px) scale(${ 0.95 ** (hideToasts.length - index - 1) })`; - }); -}; - -const slide = (slideToasts: any, div: any) => { - state.slideToasts = slideToasts; - - const handleMouseEnter = () => { - expand(state.slideToasts); - }; - - const handleMouseLeave = () => { - hide(state.slideToasts); - }; - - state.slideToasts.forEach((toast: HTMLDivElement, index: number) => { - toast.style.transform = `translateY(-${(toasts.length - index - 1) * 15}px) scale(${ - 0.95 ** (toasts.length - index - 1) - })`; - - if (state.slideToasts.length - index === 4) { + if (hideToasts.length - index === 4) { toast.style.opacity = '0'; } - - div.addEventListener('mouseenter', handleMouseEnter); - div.addEventListener('mouseleave', handleMouseLeave); }); }; -const expandSlide = (slideToasts: any, div: any) => { - state.slideToasts = slideToasts; - +const addListener = (div: HTMLDivElement) => { const handleMouseEnter = () => { - expand(state.slideToasts); + expand(toasts); }; const handleMouseLeave = () => { - hide(state.slideToasts); + hide(toasts); }; - state.slideToasts.forEach((toast: HTMLDivElement, index: number) => { - const totalHeight = state.slideToasts - .slice(0, state.slideToasts.length - index - 1) - .reduce((height: any, toast: any) => height + toast.offsetHeight, 0); - toast.style.transform = `translateY(-${totalHeight}px)`; - - div.addEventListener('mouseenter', handleMouseEnter); - div.addEventListener('mouseleave', handleMouseLeave); - }); + div.addEventListener('mouseenter', handleMouseEnter); + div.addEventListener('mouseleave', handleMouseLeave); };