>;
+ isPopup?: boolean;
+};
+
+const PrimarySocialSignIn = ({ className, connectors, isPopup = false }: Props) => {
+ const [showAll, setShowAll] = useState(false);
+ const { invokeSocialSignIn } = useSocial();
+ const isOverSize = connectors.length > 3;
+ const displayAll = showAll || isPopup || !isOverSize;
+
+ const displayConnectors = useMemo(() => {
+ if (displayAll) {
+ return connectors;
+ }
+
+ return connectors.slice(0, 3);
+ }, [connectors, displayAll]);
+
+ return (
+
+ {displayConnectors.map((connector) => (
+ {
+ void invokeSocialSignIn(connector.id);
+ }}
+ />
+ ))}
+ {!displayAll && (
+ {
+ setShowAll(true);
+ }}
+ />
+ )}
+
+ );
+};
+
+export default PrimarySocialSignIn;
diff --git a/packages/ui/src/containers/SocialSignIn/SecondarySocialSignIn.tsx b/packages/ui/src/containers/SocialSignIn/SecondarySocialSignIn.tsx
index 131cfefa9..90fb190ed 100644
--- a/packages/ui/src/containers/SocialSignIn/SecondarySocialSignIn.tsx
+++ b/packages/ui/src/containers/SocialSignIn/SecondarySocialSignIn.tsx
@@ -11,25 +11,24 @@ import * as styles from './index.module.scss';
type Props = {
className?: string;
connectors: Array>;
+ showMoreConnectors?: () => void;
};
-const SecondarySocialSignIn = ({ className, connectors }: Props) => {
+const SecondarySocialSignIn = ({ className, connectors, showMoreConnectors }: Props) => {
const { invokeSocialSignIn } = useSocial();
- const sampled = connectors.length > 4;
+ const isOverSize = connectors.length > 4;
- const sampledConnectors = useMemo(() => {
- // TODO: filter with native returned
-
- if (sampled) {
+ const displayConnectors = useMemo(() => {
+ if (isOverSize) {
return connectors.slice(0, 3);
}
return connectors;
- }, [connectors, sampled]);
+ }, [connectors, isOverSize]);
return (
- {sampledConnectors.map((connector) => (
+ {displayConnectors.map((connector) => (
{
}}
/>
))}
- {sampled && }
+ {isOverSize && }
);
};
diff --git a/packages/ui/src/containers/SocialSignIn/SocialSignInPopUp.tsx b/packages/ui/src/containers/SocialSignIn/SocialSignInPopUp.tsx
new file mode 100644
index 000000000..15581bd08
--- /dev/null
+++ b/packages/ui/src/containers/SocialSignIn/SocialSignInPopUp.tsx
@@ -0,0 +1,21 @@
+import { ConnectorMetadata } from '@logto/schemas';
+import React from 'react';
+
+import Drawer from '@/components/Drawer';
+
+import PrimarySocialSignIn from './PrimarySocialSignIn';
+
+type Props = {
+ isOpen?: boolean;
+ onClose: () => void;
+ className?: string;
+ connectors: Array>;
+};
+
+const SocialSignInPopUp = ({ isOpen = false, onClose, className, connectors }: Props) => (
+
+
+
+);
+
+export default SocialSignInPopUp;
diff --git a/packages/ui/src/containers/SocialSignIn/index.module.scss b/packages/ui/src/containers/SocialSignIn/index.module.scss
index 8e46bbb57..5abf32297 100644
--- a/packages/ui/src/containers/SocialSignIn/index.module.scss
+++ b/packages/ui/src/containers/SocialSignIn/index.module.scss
@@ -5,12 +5,23 @@
max-width: 360px;
@include _.flex-row;
justify-content: center;
-}
-.socialButton {
- margin-right: _.unit(10);
+ .socialButton {
+ margin-right: _.unit(10);
- &:last-child {
- margin-right: 0;
+ &:last-child {
+ margin-right: 0;
+ }
+ }
+}
+
+.socialLinkList {
+ width: 100%;
+ max-width: 360px;
+ @include _.flex-column;
+ margin: 0 auto;
+
+ .socialLinkButton {
+ margin-bottom: _.unit(4);
}
}
diff --git a/packages/ui/src/containers/SocialSignIn/index.ts b/packages/ui/src/containers/SocialSignIn/index.ts
index a5247871b..ae3d182ac 100644
--- a/packages/ui/src/containers/SocialSignIn/index.ts
+++ b/packages/ui/src/containers/SocialSignIn/index.ts
@@ -1 +1,3 @@
export { default as SecondarySocialSignIn } from './SecondarySocialSignIn';
+export { default as PrimarySocialSignIn } from './PrimarySocialSignIn';
+export { default as SocialSignInPopUp } from './SocialSignInPopUp';
diff --git a/packages/ui/src/pages/Passcode/index.tsx b/packages/ui/src/pages/Passcode/index.tsx
index 2d0baeabd..90a87d388 100644
--- a/packages/ui/src/pages/Passcode/index.tsx
+++ b/packages/ui/src/pages/Passcode/index.tsx
@@ -3,7 +3,7 @@ import React, { useEffect } from 'react';
import { useTranslation } from 'react-i18next';
import { useNavigate, useParams, useLocation } from 'react-router-dom';
-import NavArrowIcon from '@/components/Icons/NavArrowIcon';
+import { NavArrowIcon } from '@/components/Icons';
import PasscodeValidation from '@/containers/PasscodeValidation';
import { UserFlow } from '@/types';
diff --git a/packages/ui/src/pages/Register/index.tsx b/packages/ui/src/pages/Register/index.tsx
index 7fc35fed7..b656826ca 100644
--- a/packages/ui/src/pages/Register/index.tsx
+++ b/packages/ui/src/pages/Register/index.tsx
@@ -2,7 +2,7 @@ import React, { useMemo, useEffect } from 'react';
import { useTranslation } from 'react-i18next';
import { useNavigate, useParams } from 'react-router-dom';
-import NavArrowIcon from '@/components/Icons/NavArrowIcon';
+import { NavArrowIcon } from '@/components/Icons';
import CreateAccount from '@/containers/CreateAccount';
import { PhonePasswordless, EmailPasswordless } from '@/containers/Passwordless';
diff --git a/packages/ui/src/pages/SecondarySignIn/index.tsx b/packages/ui/src/pages/SecondarySignIn/index.tsx
index 39d3ebdd1..686875078 100644
--- a/packages/ui/src/pages/SecondarySignIn/index.tsx
+++ b/packages/ui/src/pages/SecondarySignIn/index.tsx
@@ -2,7 +2,7 @@ import React, { useMemo, useEffect } from 'react';
import { useTranslation } from 'react-i18next';
import { useNavigate, useParams } from 'react-router-dom';
-import NavArrowIcon from '@/components/Icons/NavArrowIcon';
+import { NavArrowIcon } from '@/components/Icons';
import { PhonePasswordless, EmailPasswordless } from '@/containers/Passwordless';
import UsernameSignin from '@/containers/UsernameSignin';
diff --git a/packages/ui/src/scss/modal.module.scss b/packages/ui/src/scss/modal.module.scss
index 97f10855c..75322827c 100644
--- a/packages/ui/src/scss/modal.module.scss
+++ b/packages/ui/src/scss/modal.module.scss
@@ -7,8 +7,38 @@
outline: none;
}
+.drawer {
+ position: fixed;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ max-height: 411px;
+ outline: none;
+ padding-bottom: env(safe-area-inset-bottom);
+}
+
.overlay {
position: fixed;
background: rgba(0, 0, 0, 16%);
inset: 0;
}
+
+
+// React modal animation
+/* stylelint-disable-next-line selector-pseudo-class-no-unknown */
+:global {
+ .ReactModal__Content[role='popup'] {
+ transform: translateY(100%);
+ transition: transform 0.3 ease-in-out;
+ }
+
+ /* stylelint-disable selector-class-pattern */
+ .ReactModal__Content--after-open[role='popup'] {
+ transform: translateY(0);
+ }
+
+ .ReactModal__Content--before-close[role='popup'] {
+ transform: translateY(100%);
+ }
+ /* stylelint-enable selector-class-pattern */
+}