diff --git a/.github/workflows/changelog.yml b/.github/workflows/changelog.yml index 1b1502a2..62b05735 100644 --- a/.github/workflows/changelog.yml +++ b/.github/workflows/changelog.yml @@ -1,4 +1,4 @@ -name: "CHANGELOG entry secretary" +name: 'CHANGELOG entry secretary' on: pull_request: branches: [main, development] @@ -9,8 +9,9 @@ on: types: [opened, synchronize, reopened, ready_for_review, labeled, unlabeled] jobs: - # Enforces the update of a changelog file on every pull request + # Enforces the update of a changelog file on every pull request changelog: runs-on: ubuntu-latest + if: ${{ !github.event.pull_request.draft }} steps: - - uses: dangoslen/changelog-enforcer@v3 \ No newline at end of file + - uses: dangoslen/changelog-enforcer@v3 diff --git a/.github/workflows/npm-publish.yml b/.github/workflows/npm-publish.yml index af4fd785..ee1f3f2c 100644 --- a/.github/workflows/npm-publish.yml +++ b/.github/workflows/npm-publish.yml @@ -47,6 +47,28 @@ jobs: id: package uses: andreigiura/action-nodejs-package-info@v1.0.2 + - name: Create GitHub Release + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + if: ${{ steps.package.outputs.is-prerelease == 'false' }} + run: | + RELEASE_TAG=v${{ steps.package.outputs.version }} + echo "Creating release for version: $RELEASE_TAG" + + changelog_content=$(awk "/^## \[\[?${RELEASE_TAG#v}[^\]]*\]/{flag=1; next} /^## \[/{flag=0} flag" CHANGELOG.md) + + cat > release_notes.md << EOF + ## What's Changed + + $changelog_content + EOF + + # Create the release + gh release create "$RELEASE_TAG" \ + --target=$GITHUB_SHA \ + --title="$RELEASE_TAG" \ + --notes-file release_notes.md + - name: Publish to npmjs next version env: NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}} diff --git a/.github/workflows/pre-merge-unit-tests.yml b/.github/workflows/pre-merge-unit-tests.yml index 8f425221..eac7af96 100644 --- a/.github/workflows/pre-merge-unit-tests.yml +++ b/.github/workflows/pre-merge-unit-tests.yml @@ -1,6 +1,7 @@ name: 'Stencil Unit Tests' on: pull_request: + types: [opened, synchronize, reopened, ready_for_review] branches: [main, development] paths: - 'src/**' @@ -18,6 +19,7 @@ concurrency: jobs: run-unit-tests: runs-on: ubuntu-latest + if: ${{ !github.event.pull_request.draft }} steps: - name: Fix permissions run: | diff --git a/CHANGELOG.md b/CHANGELOG.md index aa665ca9..588e475e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [[0.1.3](https://github.com/multiversx/mx-sdk-dapp-ui/pull/266)] - 2025-11-12 + +- [Added skip tests if PR is in draft](https://github.com/multiversx/mx-sdk-dapp-ui/pull/265) +- [Refactored unlock panel components](https://github.com/multiversx/mx-sdk-dapp-ui/pull/255) +- [Added github release on publish](https://github.com/multiversx/mx-sdk-dapp-ui/pull/264) + ## [[0.1.2](https://github.com/multiversx/mx-sdk-dapp-ui/pull/263)] - 2025-11-06 - [Added expose EventBus from utils](https://github.com/multiversx/mx-sdk-dapp-ui/pull/262) diff --git a/package.json b/package.json index 64bc24ad..9b775316 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@multiversx/sdk-dapp-ui", - "version": "0.1.2", + "version": "0.1.3", "description": "A library to hold UI components for a dApp on the MultiversX blockchain", "author": "MultiversX", "license": "MIT", @@ -141,4 +141,4 @@ "typescript": "^5.7.3", "vite": "^7.0.6" } -} +} \ No newline at end of file diff --git a/src/common/Trim/Trim.tsx b/src/common/Trim/Trim.tsx index 9bdd61b3..8a671942 100644 --- a/src/common/Trim/Trim.tsx +++ b/src/common/Trim/Trim.tsx @@ -22,6 +22,8 @@ export function Trim({ let currentTrimFontSize = '1rem'; let trimFullElement: HTMLDivElement; let trimWrapperElement: HTMLDivElement; + let isCurrentlyOverflowing: boolean | null = null; + let isCheckingOverflow = false; const handleTrimElementReference = (element: HTMLDivElement) => { if (element) { @@ -64,43 +66,94 @@ export function Trim({ } const checkOverflow = () => { - if (!fullWidthUntrimmedElementReference || !trimElementReference || !trimFullElement || !trimWrapperElement) { + if (isCheckingOverflow) { return; } - const hiddenFullWidthElementWidth = fullWidthUntrimmedElementReference.scrollWidth; - const trimmedElementWidth = trimElementReference.clientWidth; - const isTrimElementOverflowing = hiddenFullWidthElementWidth > trimmedElementWidth; - - if (safeWindow) { - currentTrimFontSize = safeWindow.getComputedStyle(trimElementReference).fontSize; + if (!fullWidthUntrimmedElementReference || !trimElementReference || !trimFullElement || !trimWrapperElement) { + return; } - const getIdentifierClass = (classes: string) => classes.split(' ')[0]; - - const trimLeftSelector = `.${getIdentifierClass(styles.trimLeft)}`; - const trimRightSelector = `.${getIdentifierClass(styles.trimRight)}`; + isCheckingOverflow = true; - const trimLeftElement = trimElementReference.querySelector(trimLeftSelector) as HTMLElement; - const trimRightElement = trimElementReference.querySelector(trimRightSelector) as HTMLElement; - if (trimLeftElement) { - trimLeftElement.style.fontSize = currentTrimFontSize; + if (resizeObserver) { + resizeObserver.disconnect(); } - if (trimRightElement) { - trimRightElement.style.fontSize = currentTrimFontSize; - } + + const getIdentifierClass = (classes: string) => classes.split(' ')[0]; const trimFullVisibleClasses = styles.trimFullVisible.split(/\s+/); const trimWrapperVisibleClasses = styles.trimWrapperVisible.split(/\s+/); - if (isTrimElementOverflowing) { + const hasFullVisible = trimFullElement.classList.contains(getIdentifierClass(styles.trimFullVisible)); + const hasWrapperVisible = trimWrapperElement.classList.contains(getIdentifierClass(styles.trimWrapperVisible)); + + if (hasFullVisible) { trimFullElement.classList.remove(...trimFullVisibleClasses); - trimWrapperElement.classList.add(...trimWrapperVisibleClasses); - } else { - trimFullElement.classList.add(...trimFullVisibleClasses); + } + if (hasWrapperVisible) { trimWrapperElement.classList.remove(...trimWrapperVisibleClasses); } + + const hiddenFullWidthElementWidth = fullWidthUntrimmedElementReference.scrollWidth; + const trimmedElementWidth = trimElementReference.clientWidth; + const isTrimElementOverflowing = hiddenFullWidthElementWidth > trimmedElementWidth; + + if (isCurrentlyOverflowing === isTrimElementOverflowing) { + if (hasFullVisible) { + trimFullElement.classList.add(...trimFullVisibleClasses); + } + if (hasWrapperVisible) { + trimWrapperElement.classList.add(...trimWrapperVisibleClasses); + } + + isCheckingOverflow = false; + + setTimeout(() => { + if (resizeObserver && trimElementReference) { + resizeObserver.observe(trimElementReference); + } + }); + return; + } + + isCurrentlyOverflowing = isTrimElementOverflowing; + + requestAnimationFrame(() => { + if (safeWindow) { + currentTrimFontSize = safeWindow.getComputedStyle(trimElementReference).fontSize; + } + + const trimLeftSelector = `.${getIdentifierClass(styles.trimLeft)}`; + const trimRightSelector = `.${getIdentifierClass(styles.trimRight)}`; + + const trimLeftElement = trimElementReference.querySelector(trimLeftSelector) as HTMLElement; + const trimRightElement = trimElementReference.querySelector(trimRightSelector) as HTMLElement; + if (trimLeftElement) { + trimLeftElement.style.fontSize = currentTrimFontSize; + } + + if (trimRightElement) { + trimRightElement.style.fontSize = currentTrimFontSize; + } + + if (isTrimElementOverflowing) { + trimFullElement.classList.remove(...trimFullVisibleClasses); + trimWrapperElement.classList.add(...trimWrapperVisibleClasses); + } else { + trimFullElement.classList.add(...trimFullVisibleClasses); + trimWrapperElement.classList.remove(...trimWrapperVisibleClasses); + } + + isCheckingOverflow = false; + + requestAnimationFrame(() => { + if (resizeObserver && trimElementReference) { + resizeObserver.observe(trimElementReference); + } + }); + }); }; const middleTextIndex = Math.floor(text.length / 2); diff --git a/src/common/UnlockButton/UnlockButton.tsx b/src/common/UnlockButton/UnlockButton.tsx index 1f6d8faa..480e6979 100644 --- a/src/common/UnlockButton/UnlockButton.tsx +++ b/src/common/UnlockButton/UnlockButton.tsx @@ -13,17 +13,7 @@ import { safeWindow } from 'constants/window.constants'; import type { IProviderBase } from 'types/provider.types'; import { ProviderTypeEnum } from 'types/provider.types'; import { getDetectedBrowser } from 'utils/getDetectedBrowser'; - -// prettier-ignore -const styles = { - unlockButton: 'unlock-button mvx:pl-3 mvx:pr-4 mvx:h-15 mvx:flex! mvx:gap-4 mvx:cursor-pointer mvx:items-center mvx:transition-all mvx:duration-200 mvx:ease-in-out mvx:bg-secondary mvx:hover:bg-hover', - unlockButtonIcon: 'unlock-button-icon mvx:-order-1 mvx:h-10 mvx:flex mvx:relative mvx:z-1 mvx:items-center mvx:justify-center mvx:w-10', - unlockButtonIconClipped: 'mvx:items-end mvx:justify-start', - unlockButtonLabel: 'unlock-button-label mvx:text-base mvx:relative mvx:z-1 mvx:text-primary mvx:leading-none', - unlockButtonStatus: 'unlock-button-status mvx:ml-auto mvx:relative mvx:rounded-3xl mvx:z-1 mvx:leading-none mvx:flex mvx:items-center mvx:py-1 mvx:px-2 mvx:font-medium mvx:gap-1 mvx:text-xs mvx:bg-surface mvx:border mvx:border-solid mvx:border-outline', - unlockButtonStatusText: 'unlock-button-status-text mvx:text-accent', - unlockButtonStatusIcon: 'unlock-button-status-icon mvx:flex mvx:items-center mvx:text-accent mvx:w-2.5 mvx:h-2.5', -} satisfies Record; +import styles from './unlockButton.styles'; interface UnlockButtonPropsType { label: string; diff --git a/src/common/UnlockButton/unlockButton.styles.ts b/src/common/UnlockButton/unlockButton.styles.ts new file mode 100644 index 00000000..87dd6af7 --- /dev/null +++ b/src/common/UnlockButton/unlockButton.styles.ts @@ -0,0 +1,10 @@ +// prettier-ignore +export default { + unlockButton: 'unlock-button mvx:pl-3 mvx:pr-4 mvx:h-15 mvx:flex mvx:gap-4 mvx:cursor-pointer mvx:items-center mvx:transition-all mvx:duration-200 mvx:ease-in-out mvx:bg-secondary mvx:hover:bg-hover', + unlockButtonIcon: 'unlock-button-icon mvx:-order-1 mvx:h-10 mvx:flex mvx:relative mvx:z-1 mvx:items-center mvx:justify-center mvx:w-10', + unlockButtonIconClipped: 'mvx:items-end mvx:justify-start', + unlockButtonLabel: 'unlock-button-label mvx:text-base mvx:relative mvx:z-1 mvx:text-primary mvx:leading-none', + unlockButtonStatus: 'unlock-button-status mvx:ml-auto mvx:relative mvx:rounded-3xl mvx:z-1 mvx:leading-none mvx:flex mvx:items-center mvx:py-1 mvx:px-2 mvx:font-medium mvx:gap-1 mvx:text-xs mvx:bg-surface mvx:border mvx:border-solid mvx:border-outline', + unlockButtonStatusText: 'unlock-button-status-text mvx:text-accent', + unlockButtonStatusIcon: 'unlock-button-status-icon mvx:flex mvx:items-center mvx:text-accent mvx:w-2.5 mvx:h-2.5', +} satisfies Record; \ No newline at end of file diff --git a/src/components.d.ts b/src/components.d.ts index eec3481b..3d50c26c 100644 --- a/src/components.d.ts +++ b/src/components.d.ts @@ -17,7 +17,7 @@ import { ITransactionListItem as ITransactionListItem1 } from "./components/visu import { IToastDataState, ITransactionProgressState } from "./components/functional/toasts-list/components/transaction-toast/transaction-toast.type"; import { TransactionStatusEnum } from "./constants/transactionStatus.enum"; import { TransactionRowType } from "./components/controlled/transactions-table/transactions-table.type"; -import { IProviderBase, ProviderTypeEnum } from "./types/provider.types"; +import { IProviderBase } from "./types/provider.types"; import { IEventBus as IEventBus1, unknown as IWalletConnectPanelData } from "./components.d"; export { IAddressTableData } from "./types/address-table.types"; export { ButtonSizeEnum, ButtonVariantEnum } from "./components/visual/button/button.types"; @@ -31,7 +31,7 @@ export { ITransactionListItem as ITransactionListItem1 } from "./components/visu export { IToastDataState, ITransactionProgressState } from "./components/functional/toasts-list/components/transaction-toast/transaction-toast.type"; export { TransactionStatusEnum } from "./constants/transactionStatus.enum"; export { TransactionRowType } from "./components/controlled/transactions-table/transactions-table.type"; -export { IProviderBase, ProviderTypeEnum } from "./types/provider.types"; +export { IProviderBase } from "./types/provider.types"; export { IEventBus as IEventBus1, unknown as IWalletConnectPanelData } from "./components.d"; export namespace Components { interface MvxAddressTable { @@ -397,20 +397,6 @@ export namespace Components { "closeWithAnimation": () => Promise; "getEventBus": () => Promise; } - interface MvxUnlockPanelFooter { - "walletAddress": string; - } - interface MvxUnlockPanelGroup { - "class"?: string; - /** - * @default [] - */ - "providers": IProviderBase[]; - } - interface MvxUnlockProviderButton { - "class"?: string; - "provider": IProviderBase; - } interface MvxWalletConnect { /** * @default { wcURI: '' } @@ -514,10 +500,6 @@ export interface MvxTransactionToastContentCustomEvent extends CustomEvent detail: T; target: HTMLMvxTransactionToastContentElement; } -export interface MvxUnlockPanelGroupCustomEvent extends CustomEvent { - detail: T; - target: HTMLMvxUnlockPanelGroupElement; -} export interface MvxWalletConnectScanCustomEvent extends CustomEvent { detail: T; target: HTMLMvxWalletConnectScanElement; @@ -1024,35 +1006,6 @@ declare global { prototype: HTMLMvxUnlockPanelElement; new (): HTMLMvxUnlockPanelElement; }; - interface HTMLMvxUnlockPanelFooterElement extends Components.MvxUnlockPanelFooter, HTMLStencilElement { - } - var HTMLMvxUnlockPanelFooterElement: { - prototype: HTMLMvxUnlockPanelFooterElement; - new (): HTMLMvxUnlockPanelFooterElement; - }; - interface HTMLMvxUnlockPanelGroupElementEventMap { - "login": IProviderBase; - } - interface HTMLMvxUnlockPanelGroupElement extends Components.MvxUnlockPanelGroup, HTMLStencilElement { - addEventListener(type: K, listener: (this: HTMLMvxUnlockPanelGroupElement, ev: MvxUnlockPanelGroupCustomEvent) => any, options?: boolean | AddEventListenerOptions): void; - addEventListener(type: K, listener: (this: Document, ev: DocumentEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void; - addEventListener(type: K, listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void; - addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void; - removeEventListener(type: K, listener: (this: HTMLMvxUnlockPanelGroupElement, ev: MvxUnlockPanelGroupCustomEvent) => any, options?: boolean | EventListenerOptions): void; - removeEventListener(type: K, listener: (this: Document, ev: DocumentEventMap[K]) => any, options?: boolean | EventListenerOptions): void; - removeEventListener(type: K, listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any, options?: boolean | EventListenerOptions): void; - removeEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | EventListenerOptions): void; - } - var HTMLMvxUnlockPanelGroupElement: { - prototype: HTMLMvxUnlockPanelGroupElement; - new (): HTMLMvxUnlockPanelGroupElement; - }; - interface HTMLMvxUnlockProviderButtonElement extends Components.MvxUnlockProviderButton, HTMLStencilElement { - } - var HTMLMvxUnlockProviderButtonElement: { - prototype: HTMLMvxUnlockProviderButtonElement; - new (): HTMLMvxUnlockProviderButtonElement; - }; interface HTMLMvxWalletConnectElement extends Components.MvxWalletConnect, HTMLStencilElement { } var HTMLMvxWalletConnectElement: { @@ -1176,9 +1129,6 @@ declare global { "mvx-trim": HTMLMvxTrimElement; "mvx-unlock-button": HTMLMvxUnlockButtonElement; "mvx-unlock-panel": HTMLMvxUnlockPanelElement; - "mvx-unlock-panel-footer": HTMLMvxUnlockPanelFooterElement; - "mvx-unlock-panel-group": HTMLMvxUnlockPanelGroupElement; - "mvx-unlock-provider-button": HTMLMvxUnlockProviderButtonElement; "mvx-wallet-connect": HTMLMvxWalletConnectElement; "mvx-wallet-connect-app-gallery-icon": HTMLMvxWalletConnectAppGalleryIconElement; "mvx-wallet-connect-app-store-icon": HTMLMvxWalletConnectAppStoreIconElement; @@ -1561,21 +1511,6 @@ declare namespace LocalJSX { } interface MvxUnlockPanel { } - interface MvxUnlockPanelFooter { - "walletAddress"?: string; - } - interface MvxUnlockPanelGroup { - "class"?: string; - "onLogin"?: (event: MvxUnlockPanelGroupCustomEvent) => void; - /** - * @default [] - */ - "providers"?: IProviderBase[]; - } - interface MvxUnlockProviderButton { - "class"?: string; - "provider"?: IProviderBase; - } interface MvxWalletConnect { /** * @default { wcURI: '' } @@ -1680,9 +1615,6 @@ declare namespace LocalJSX { "mvx-trim": MvxTrim; "mvx-unlock-button": MvxUnlockButton; "mvx-unlock-panel": MvxUnlockPanel; - "mvx-unlock-panel-footer": MvxUnlockPanelFooter; - "mvx-unlock-panel-group": MvxUnlockPanelGroup; - "mvx-unlock-provider-button": MvxUnlockProviderButton; "mvx-wallet-connect": MvxWalletConnect; "mvx-wallet-connect-app-gallery-icon": MvxWalletConnectAppGalleryIcon; "mvx-wallet-connect-app-store-icon": MvxWalletConnectAppStoreIcon; @@ -1755,9 +1687,6 @@ declare module "@stencil/core" { "mvx-trim": LocalJSX.MvxTrim & JSXBase.HTMLAttributes; "mvx-unlock-button": LocalJSX.MvxUnlockButton & JSXBase.HTMLAttributes; "mvx-unlock-panel": LocalJSX.MvxUnlockPanel & JSXBase.HTMLAttributes; - "mvx-unlock-panel-footer": LocalJSX.MvxUnlockPanelFooter & JSXBase.HTMLAttributes; - "mvx-unlock-panel-group": LocalJSX.MvxUnlockPanelGroup & JSXBase.HTMLAttributes; - "mvx-unlock-provider-button": LocalJSX.MvxUnlockProviderButton & JSXBase.HTMLAttributes; "mvx-wallet-connect": LocalJSX.MvxWalletConnect & JSXBase.HTMLAttributes; "mvx-wallet-connect-app-gallery-icon": LocalJSX.MvxWalletConnectAppGalleryIcon & JSXBase.HTMLAttributes; "mvx-wallet-connect-app-store-icon": LocalJSX.MvxWalletConnectAppStoreIcon & JSXBase.HTMLAttributes; diff --git a/src/components/functional/unlock-panel/components/UnlockPanelFooter/UnlockPanelFooter.tsx b/src/components/functional/unlock-panel/components/UnlockPanelFooter/UnlockPanelFooter.tsx new file mode 100644 index 00000000..3c167cf2 --- /dev/null +++ b/src/components/functional/unlock-panel/components/UnlockPanelFooter/UnlockPanelFooter.tsx @@ -0,0 +1,45 @@ +import { h } from '@stencil/core'; +import { Icon } from 'common/Icon'; +import styles from './unlockPanelFooter.styles' + +import unlockPanelWalletImg from '../../../../../assets/unlock-panel-wallet.webp'; + +export function UnlockPanelFooter({ walletAddress }: { walletAddress: string }) { + const handleWalletClick = (event: MouseEvent) => { + event.preventDefault(); + event.stopPropagation(); + window.open(walletAddress, '_blank'); + }; + + const noProtocolWalletAddress = String(walletAddress).replace('https://', ''); + + return ( +
+ + +
+
Don't have a wallet?
+ +
+ Take full control of
your assets. +
+ +
+ See which one to get on + + + {noProtocolWalletAddress} + +
+ + +
+
+ ); + +} diff --git a/src/components/functional/unlock-panel/components/UnlockPanelFooter/index.ts b/src/components/functional/unlock-panel/components/UnlockPanelFooter/index.ts new file mode 100644 index 00000000..51d58d9a --- /dev/null +++ b/src/components/functional/unlock-panel/components/UnlockPanelFooter/index.ts @@ -0,0 +1 @@ +export * from './UnlockPanelFooter'; \ No newline at end of file diff --git a/src/components/functional/unlock-panel/components/UnlockPanelFooter/unlockPanelFooter.styles.ts b/src/components/functional/unlock-panel/components/UnlockPanelFooter/unlockPanelFooter.styles.ts new file mode 100644 index 00000000..9fe36958 --- /dev/null +++ b/src/components/functional/unlock-panel/components/UnlockPanelFooter/unlockPanelFooter.styles.ts @@ -0,0 +1,12 @@ +// prettier-ignore +export default { + unlockButton: 'unlock-panel-footer-icon mvx:text-primary mvx:w-4 mvx:h-auto mvx:hidden mvx:xs:flex mvx:ml-auto mvx:mt-auto', + unlockPanelFooter: 'unlock-panel-footer mvx:mt-auto mvx:flex mvx:cursor-pointer mvx:relative mvx:p-6 mvx:z-1 mvx:rounded-2xl mvx:overflow-hidden mvx:border mvx:border-outline mvx:bg-emphasize mvx:shadow-[0px_-8px_12px_12px_surface] group', + unlockPanelFooterImage: 'unlock-panel-footer-image mvx:pointer-events-none mvx:-mt-8 mvx:mr-12 mvx:-mb-8 mvx:-ml-20 mvx:hidden mvx:max-h-48 mvx:xs:flex', + unlockPanelFooterWrapper: 'unlock-panel-footer-wrapper mvx:flex mvx:flex-col mvx:transition-all mvx:duration-200 mvx:gap-2 mvx:flex-1 mvx:ease-in-out mvx:xs:gap-4 group-hover:mvx:opacity-75', + unlockPanelFooterTitle: 'unlock-panel-footer-title mvx:font-medium mvx:leading-none mvx:text-base mvx:text-primary mvx:xs:pt-4 mvx:xs:text-xl', + unlockPanelFooterSubtitle: 'unlock-panel-footer-subtitle mvx:text-base mvx:leading-tight mvx:opacity-40 mvx:text-primary', + unlockPanelFooterSubtitleDesktop: 'unlock-panel-footer-subtitle-desktop mvx:hidden mvx:xs:flex', + unlockPanelFooterSubtitleMobile: 'unlock-panel-footer-subtitle-mobile mvx:text-xs mvx:xs:hidden', + unlockPanelFooterSubtitleLink: 'unlock-panel-footer-subtitle-link mvx:text-accent' +} satisfies Record; \ No newline at end of file diff --git a/src/components/functional/unlock-panel/components/UnlockPanelGroup/UnlockPanelGroup.tsx b/src/components/functional/unlock-panel/components/UnlockPanelGroup/UnlockPanelGroup.tsx new file mode 100644 index 00000000..b6b1a91e --- /dev/null +++ b/src/components/functional/unlock-panel/components/UnlockPanelGroup/UnlockPanelGroup.tsx @@ -0,0 +1,48 @@ +import { h } from '@stencil/core'; +import classNames from 'classnames'; +import { type IProviderBase, ProviderTypeEnum } from 'types/provider.types'; +import styles from './unlockPanelGroup.styles'; +import { UnlockProviderButton } from '../UnlockProviderButton'; + +export enum UnlockPanelGroupSlotEnum { + groupLabel = 'group-label', +} + +interface UnlockPanelGroupPropsType { + providers: IProviderBase[]; + class?: string; + onLogin?: (provider: IProviderBase) => void; + groupLabel?: JSX.Element; +} + +export function UnlockPanelGroup({ providers = [], class: className, onLogin, groupLabel }: UnlockPanelGroupPropsType) { + const handleLogin = (provider: IProviderBase) => { + onLogin?.(provider); + }; + + const isInstallableExtension = (provider: IProviderBase) => + [ProviderTypeEnum.extension, ProviderTypeEnum.metamask].includes(provider.type as ProviderTypeEnum); + + return ( +
+
+
+ {groupLabel} +
+ +
+ {providers.map((provider, providerIndex) => ( + handleLogin(provider)} + class={classNames({ + [styles.detectedPanelGroup]: isInstallableExtension(provider), + [styles.lastProviderButton]: providerIndex === providers.length - 1, + })} + /> + ))} +
+
+
+ ); +} diff --git a/src/components/functional/unlock-panel/components/UnlockPanelGroup/index.ts b/src/components/functional/unlock-panel/components/UnlockPanelGroup/index.ts new file mode 100644 index 00000000..385d1c8f --- /dev/null +++ b/src/components/functional/unlock-panel/components/UnlockPanelGroup/index.ts @@ -0,0 +1 @@ +export * from './UnlockPanelGroup'; \ No newline at end of file diff --git a/src/components/functional/unlock-panel/components/UnlockPanelGroup/unlockPanelGroup.styles.ts b/src/components/functional/unlock-panel/components/UnlockPanelGroup/unlockPanelGroup.styles.ts new file mode 100644 index 00000000..8b4a8c3e --- /dev/null +++ b/src/components/functional/unlock-panel/components/UnlockPanelGroup/unlockPanelGroup.styles.ts @@ -0,0 +1,9 @@ +// prettier-ignore +export default { + unlockPanelGroupContainer: 'unlock-panel-group-container mvx:overflow-hidden mvx:flex mvx:sm:overflow-visible', + unlockPanelGroup: 'unlock-panel-group mvx:flex mvx:flex-col mvx:flex-1 mvx:overflow-hidden', + unlockPanelGroupLabel: 'unlock-panel-group-label mvx:leading-none mvx:relative mvx:text-secondary-text', + unlockPanelGroupProviders: 'unlock-panel-group-providers mvx:flex mvx:flex-col mvx:gap-0.5 mvx:rounded-tl-lg mvx:rounded-tr-lg mvx:overflow-auto mvx:pb-6 mvx:mt-3 mvx:scrollbar-hide', + detectedPanelGroup: 'mvx:hidden mvx:sm:flex', + lastProviderButton: 'mvx:rounded-bl-lg mvx:rounded-br-lg mvx:overflow-hidden', +} satisfies Record; \ No newline at end of file diff --git a/src/components/functional/unlock-panel/components/UnlockProviderButton/UnlockProviderButton.tsx b/src/components/functional/unlock-panel/components/UnlockProviderButton/UnlockProviderButton.tsx new file mode 100644 index 00000000..37b0502c --- /dev/null +++ b/src/components/functional/unlock-panel/components/UnlockProviderButton/UnlockProviderButton.tsx @@ -0,0 +1,40 @@ +import { h } from '@stencil/core'; +import classNames from 'classnames'; +import { UnlockButton } from 'common/UnlockButton/UnlockButton'; +import type { IProviderBase } from 'types/provider.types'; +import type { ProviderTypeEnum } from 'types/provider.types'; + +import { getProviderButtonIcon } from '../../helpers'; + +const unlockProviderButtonClasses: Record = { + button: 'mvx:w-full', +}; + +interface UnlockProviderButtonPropsType { + provider: IProviderBase; + class?: string; + onClick?: () => void; +} + +export function UnlockProviderButton({ provider, class: className, onClick }: UnlockProviderButtonPropsType) { + if (!provider) { + return null; + } + + const icon: HTMLElement | null = !provider.iconUrl + ? getProviderButtonIcon({ providerType: provider.type }) + : null; + + return ( +
+ +
+ ); +} diff --git a/src/components/functional/unlock-panel/components/UnlockProviderButton/index.ts b/src/components/functional/unlock-panel/components/UnlockProviderButton/index.ts new file mode 100644 index 00000000..54c0f59c --- /dev/null +++ b/src/components/functional/unlock-panel/components/UnlockProviderButton/index.ts @@ -0,0 +1 @@ +export * from './UnlockProviderButton'; \ No newline at end of file diff --git a/src/components/functional/unlock-panel/components/index.ts b/src/components/functional/unlock-panel/components/index.ts new file mode 100644 index 00000000..92aa6a2e --- /dev/null +++ b/src/components/functional/unlock-panel/components/index.ts @@ -0,0 +1,3 @@ +export * from './UnlockPanelFooter'; +export * from './UnlockPanelGroup'; +export * from './UnlockProviderButton'; \ No newline at end of file diff --git a/src/components/functional/unlock-panel/components/unlock-panel-footer/unlock-panel-footer.scss b/src/components/functional/unlock-panel/components/unlock-panel-footer/unlock-panel-footer.scss deleted file mode 100644 index d2fee893..00000000 --- a/src/components/functional/unlock-panel/components/unlock-panel-footer/unlock-panel-footer.scss +++ /dev/null @@ -1,60 +0,0 @@ -.unlock-panel-footer { - @apply mvx:mt-auto mvx:flex mvx:cursor-pointer mvx:relative mvx:p-6 mvx:z-1 mvx:rounded-2xl mvx:overflow-hidden; - border: 1px solid var(--mvx-border-color-primary); - background: var(--mvx-bg-accent-color); - box-shadow: 0px -8px 12px 12px var(--mvx-bg-color-primary); - - &:hover .unlock-panel-footer-wrapper { - @apply mvx:opacity-75; - } - - .unlock-panel-footer-image { - @apply mvx:pointer-events-none mvx:-mt-8 mvx:mr-12 mvx:-mb-8 mvx:-ml-20 mvx:hidden mvx:max-h-48; - - @media (min-width: 480px) { - @apply mvx:flex; - } - } - - .unlock-panel-footer-wrapper { - @apply mvx:flex mvx:flex-col mvx:transition-all mvx:duration-200 mvx:gap-2 mvx:flex-1 mvx:ease-in-out; - - @media (min-width: 480px) { - @apply mvx:gap-4; - } - - .unlock-panel-footer-title { - @apply mvx:font-medium mvx:leading-none mvx:text-base; - color: var(--mvx-text-color-primary); - - @media (min-width: 480px) { - @apply mvx:pt-4 mvx:text-xl; - } - } - - .unlock-panel-footer-subtitle { - @apply mvx:text-base mvx:leading-tight mvx:opacity-40; - color: var(--mvx-text-color-primary); - - &.desktop { - @apply mvx:hidden; - - @media (min-width: 480px) { - @apply mvx:flex; - } - } - - &.mobile { - @apply mvx:text-xs; - - @media (min-width: 480px) { - @apply mvx:hidden; - } - } - - .unlock-panel-footer-subtitle-link { - color: var(--mvx-text-accent-color); - } - } - } -} diff --git a/src/components/functional/unlock-panel/components/unlock-panel-footer/unlock-panel-footer.tsx b/src/components/functional/unlock-panel/components/unlock-panel-footer/unlock-panel-footer.tsx deleted file mode 100644 index 566f9a74..00000000 --- a/src/components/functional/unlock-panel/components/unlock-panel-footer/unlock-panel-footer.tsx +++ /dev/null @@ -1,57 +0,0 @@ -import { Component, h, Prop } from '@stencil/core'; -import { Icon } from 'common/Icon'; - -import unlockPanelWalletImg from '../../../../../assets/unlock-panel-wallet.webp'; - -// prettier-ignore -const styles = { - unlockButton: 'unlock-panel-footer-icon mvx:text-primary mvx:w-4 mvx:h-auto mvx:hidden mvx:xs:flex mvx:ml-auto mvx:mt-auto', -} satisfies Record; - -@Component({ - tag: 'mvx-unlock-panel-footer', - styleUrl: 'unlock-panel-footer.scss', - shadow: true, -}) -export class UnlockPanel { - @Prop() walletAddress: string; - - handleWalletClick = (event: MouseEvent) => { - event.preventDefault(); - event.stopPropagation(); - window.open(this.walletAddress, '_blank'); - }; - - render() { - const processedWalletAddress = String(this.walletAddress).replace('https://', ''); - - return ( - - ); - } -} diff --git a/src/components/functional/unlock-panel/components/unlock-panel-group/unlock-panel-group.scss b/src/components/functional/unlock-panel/components/unlock-panel-group/unlock-panel-group.scss deleted file mode 100644 index 40b240b4..00000000 --- a/src/components/functional/unlock-panel/components/unlock-panel-group/unlock-panel-group.scss +++ /dev/null @@ -1,25 +0,0 @@ -:host { - @apply mvx:overflow-hidden mvx:flex; - - @media (min-width: 640px) { - @apply mvx:overflow-visible; - } - - .unlock-panel-group { - @apply mvx:flex mvx:flex-col mvx:flex-1 mvx:overflow-hidden; - - .unlock-panel-group-label { - @apply mvx:leading-none mvx:relative; - color: var(--mvx-text-color-secondary); - } - - .unlock-panel-group-providers { - @apply mvx:flex mvx:flex-col mvx:gap-0.5 mvx:rounded-tl-lg mvx:rounded-tr-lg mvx:overflow-auto; - @apply mvx:pb-6 mvx:mt-3; - - &::-webkit-scrollbar { - @apply mvx:hidden; - } - } - } -} diff --git a/src/components/functional/unlock-panel/components/unlock-panel-group/unlock-panel-group.tsx b/src/components/functional/unlock-panel/components/unlock-panel-group/unlock-panel-group.tsx deleted file mode 100644 index bc21c63e..00000000 --- a/src/components/functional/unlock-panel/components/unlock-panel-group/unlock-panel-group.tsx +++ /dev/null @@ -1,57 +0,0 @@ -import type { EventEmitter } from '@stencil/core'; -import { Component, Event, h, Prop } from '@stencil/core'; -import classNames from 'classnames'; -import { type IProviderBase, ProviderTypeEnum } from 'types/provider.types'; - -export enum UnlockPanelGroupSlotEnum { - groupLabel = 'group-label', -} - -const unlockPanelGroupClasses: Record = { - detectedPanelGroup: 'mvx:hidden mvx:sm:block', - lastProviderButton: 'mvx:rounded-bl-lg mvx:rounded-br-lg mvx:overflow-hidden', -}; - -@Component({ - tag: 'mvx-unlock-panel-group', - styleUrl: 'unlock-panel-group.scss', - shadow: true, -}) -export class UnlockPanelGroup { - @Event({ composed: false, bubbles: false }) login: EventEmitter; - - @Prop() providers: IProviderBase[] = []; - @Prop() class?: string; - - private handleLogin = (provider: IProviderBase) => { - this.login.emit(provider); - }; - - render() { - const isInstallableExtension = (provider: IProviderBase) => - [ProviderTypeEnum.extension, ProviderTypeEnum.metamask].includes(provider.type as ProviderTypeEnum); - - return ( -
-
- -
- -
- {this.providers.map((provider, providerIndex) => ( - this.handleLogin(provider)} - class={classNames({ - [unlockPanelGroupClasses.detectedPanelGroup]: isInstallableExtension(provider), - [unlockPanelGroupClasses.lastProviderButton]: providerIndex === this.providers.length - 1, - })} - /> - ))} - - -
-
- ); - } -} diff --git a/src/components/functional/unlock-panel/components/unlock-provider-button/unlock-provider-button.scss b/src/components/functional/unlock-panel/components/unlock-provider-button/unlock-provider-button.scss deleted file mode 100644 index 21b0cbc1..00000000 --- a/src/components/functional/unlock-panel/components/unlock-provider-button/unlock-provider-button.scss +++ /dev/null @@ -1 +0,0 @@ -// This is needed to trigger the Stecil Tailwind compilation for inline Tailwind classes. diff --git a/src/components/functional/unlock-panel/components/unlock-provider-button/unlock-provider-button.tsx b/src/components/functional/unlock-panel/components/unlock-provider-button/unlock-provider-button.tsx deleted file mode 100644 index e55cb4d0..00000000 --- a/src/components/functional/unlock-panel/components/unlock-provider-button/unlock-provider-button.tsx +++ /dev/null @@ -1,42 +0,0 @@ -import { Component, h, Prop } from '@stencil/core'; -import classNames from 'classnames'; -import { UnlockButton } from 'common/UnlockButton/UnlockButton'; -import type { IProviderBase } from 'types/provider.types'; -import type { ProviderTypeEnum } from 'types/provider.types'; - -import { getProviderButtonIcon } from '../../helpers'; - -const unlockProviderButtonClasses: Record = { - button: 'mvx:w-full', -}; - -@Component({ - tag: 'mvx-unlock-provider-button', - styleUrl: 'unlock-provider-button.scss', - shadow: true, -}) -export class UnlockProviderButton { - @Prop() provider: IProviderBase; - @Prop() class?: string; - - render() { - if (!this.provider) { - return null; - } - - const icon: HTMLElement | null = !this.provider.iconUrl - ? getProviderButtonIcon({ providerType: this.provider.type }) - : null; - - return ( - - ); - } -} diff --git a/src/components/functional/unlock-panel/unlock-panel.scss b/src/components/functional/unlock-panel/unlock-panel.scss index 42e63fe3..ff1190ee 100644 --- a/src/components/functional/unlock-panel/unlock-panel.scss +++ b/src/components/functional/unlock-panel/unlock-panel.scss @@ -1,15 +1 @@ -.unlock-panel-anchor { - @apply mvx:flex mvx:flex-col mvx:flex-1 mvx:overflow-hidden; -} - -.unlock-panel { - @apply mvx:flex mvx:flex-col mvx:h-full mvx:justify-between mvx:overflow-auto mvx:pb-6; - - .unlock-panel-groups { - @apply mvx:flex mvx:flex-col mvx:gap-4 mvx:pt-6; - } - - &::-webkit-scrollbar { - @apply mvx:hidden; - } -} +// This is needed to trigger the Stecil Tailwind compilation for inline Tailwind classes. \ No newline at end of file diff --git a/src/components/functional/unlock-panel/unlock-panel.styles.ts b/src/components/functional/unlock-panel/unlock-panel.styles.ts new file mode 100644 index 00000000..401b0782 --- /dev/null +++ b/src/components/functional/unlock-panel/unlock-panel.styles.ts @@ -0,0 +1,12 @@ +// prettier-ignore +export default { + unlockPanelAnchor: 'unlock-panel-anchor mvx:flex mvx:flex-col mvx:flex-1 mvx:overflow-hidden', + unlockPanel: 'unlock-panel mvx:flex mvx:flex-col mvx:h-full mvx:justify-between mvx:overflow-auto mvx:pb-6 mvx:scrollbar-hide', + unlockPanelGroups: 'unlock-panel-groups mvx:flex mvx:flex-col mvx:gap-4 mvx:pt-6', + unlockButton: 'unlock-button mvx:flex mvx:pl-3 mvx:pr-4 mvx:h-15 mvx:bg-secondary mvx:hover:bg-hover', + unlockButtonIcon: 'unlock-button-icon mvx:-order-1 mvx:h-10 mvx:w-10', + unlockButtonStatus: 'unlock-button-status mvx:rounded-3xl mvx:py-1 mvx:px-2 mvx:bg-surface', + detectedPanelGroup: 'mvx:hidden mvx:sm:flex mvx:sm:flex-col', + desktopPanelGroupTitle: 'mvx:hidden mvx:sm:flex', + mobilePanelGroupTitle: 'mvx:sm:hidden', +} satisfies Record; \ No newline at end of file diff --git a/src/components/functional/unlock-panel/unlock-panel.tsx b/src/components/functional/unlock-panel/unlock-panel.tsx index 689ba13c..788d755b 100644 --- a/src/components/functional/unlock-panel/unlock-panel.tsx +++ b/src/components/functional/unlock-panel/unlock-panel.tsx @@ -7,16 +7,11 @@ import { ConnectionMonitor } from 'utils/ConnectionMonitor'; import type { IEventBus } from 'utils/EventBus'; import { EventBus } from 'utils/EventBus'; -import { UnlockPanelGroupSlotEnum } from './components/unlock-panel-group/unlock-panel-group'; import { getIsExtensionAvailable, getIsMetaMaskAvailable } from './helpers'; import type { IUnlockPanelManagerData } from './unlock-panel.types'; import { UnlockPanelEventsEnum } from './unlock-panel.types'; - -const unlockPanelClasses: Record = { - detectedPanelGroup: 'mvx:hidden mvx:sm:flex', - desktopPanelGroupTitle: 'mvx:hidden mvx:sm:flex', - mobilePanelGroupTitle: 'mvx:sm:hidden', -}; +import { UnlockPanelFooter, UnlockPanelGroup } from './components'; +import styles from './unlock-panel.styles'; @Component({ tag: 'mvx-unlock-panel', @@ -175,7 +170,7 @@ export class UnlockPanel {
this.setAnchor(element)} - class={{ 'unlock-panel-anchor': this.isLoggingIn || this.isIntroScreenVisible }} + class={{ [styles.unlockPanelAnchor]: this.isLoggingIn || this.isIntroScreenVisible }} > {this.isIntroScreenVisible && ( {isProviderScreenVisible && ( -
-
+
+
{hasDetectedProviders && ( - this.handleLogin(event.detail)} - class={unlockPanelClasses.detectedPanelGroup} - > -
Detected
-
+ onLogin={(provider) => this.handleLogin(provider)} + class={styles.detectedPanelGroup} + groupLabel={ +
Detected
+ } + /> )} - this.handleLogin(event.detail)} - > -
-
Options
-
- {hasDetectedProviders ? 'Other Options' : 'Options'} + onLogin={(provider) => this.handleLogin(provider)} + groupLabel={ +
+
Options
+
+ {hasDetectedProviders ? 'Other Options' : 'Options'} +
-
- - - + } + />
- +
)} diff --git a/src/global/tailwind.css b/src/global/tailwind.css index 3f703de6..35760edb 100644 --- a/src/global/tailwind.css +++ b/src/global/tailwind.css @@ -31,6 +31,7 @@ --color-gray-200: var(--mvx-gray-200); --color-thumb: var(--mvx-scrollbar-thumb); --color-outline-variant: var(--mvx-border-color-secondary); + --color-emphasize: var(--mvx-bg-accent-color); } @layer utilities {