@12-apps/ui 6.28.0 → 6.29.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/_internal/social-login-button/social-login-button.js +1 -1
- package/dist/{chunk-2WSU6OGE.js → chunk-T7WU7JGC.js} +25 -5
- package/dist/chunk-T7WU7JGC.js.map +1 -0
- package/dist/social-login-button.js +1 -1
- package/dist/types/social-login-button/social-login-button.d.ts +10 -0
- package/dist/types/social-login-button/social-login-button.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/social-login-button/social-login-button.tsx +68 -1
- package/dist/chunk-2WSU6OGE.js.map +0 -1
|
@@ -61,6 +61,15 @@ var FacebookIcon = () => /* @__PURE__ */ jsx("svg", { width: "20", height: "20",
|
|
|
61
61
|
}
|
|
62
62
|
) });
|
|
63
63
|
var AppleIcon = () => /* @__PURE__ */ jsx("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "currentColor", xmlns: "http://www.w3.org/2000/svg", children: /* @__PURE__ */ jsx("path", { d: "M17.05 20.28c-.98.95-2.05.8-3.08.35-1.09-.46-2.09-.48-3.24 0-1.44.62-2.2.44-3.06-.35C2.79 15.25 3.51 7.59 9.05 7.31c1.35.07 2.29.74 3.08.8 1.18-.24 2.31-.93 3.57-.84 1.51.12 2.65.72 3.4 1.8-3.12 1.87-2.38 5.98.48 7.13-.57 1.5-1.31 2.99-2.54 4.09l.01-.01zM12.03 7.25c-.15-2.23 1.66-4.07 3.74-4.25.29 2.58-2.34 4.5-3.74 4.25z" }) });
|
|
64
|
+
var GOOGLE_LOGO_WHEN_DISABLED_SX = {
|
|
65
|
+
"&.Mui-disabled .MuiButton-startIcon": {
|
|
66
|
+
filter: "brightness(0)",
|
|
67
|
+
opacity: (theme) => theme.palette.action.disabledOpacity
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
var FACEBOOK_LOGO_IN_BUTTON_COLOUR_SX = {
|
|
71
|
+
"& .MuiButton-startIcon path": { fill: "currentColor" }
|
|
72
|
+
};
|
|
64
73
|
var providerConfig = {
|
|
65
74
|
google: {
|
|
66
75
|
Icon: GoogleIcon,
|
|
@@ -73,7 +82,8 @@ var providerConfig = {
|
|
|
73
82
|
"&:hover": {
|
|
74
83
|
backgroundColor: "#f5f5f5",
|
|
75
84
|
borderColor: "#dadce0"
|
|
76
|
-
}
|
|
85
|
+
},
|
|
86
|
+
...GOOGLE_LOGO_WHEN_DISABLED_SX
|
|
77
87
|
}
|
|
78
88
|
},
|
|
79
89
|
facebook: {
|
|
@@ -85,7 +95,8 @@ var providerConfig = {
|
|
|
85
95
|
color: "#ffffff",
|
|
86
96
|
"&:hover": {
|
|
87
97
|
backgroundColor: "#166fe5"
|
|
88
|
-
}
|
|
98
|
+
},
|
|
99
|
+
...FACEBOOK_LOGO_IN_BUTTON_COLOUR_SX
|
|
89
100
|
}
|
|
90
101
|
},
|
|
91
102
|
apple: {
|
|
@@ -101,6 +112,11 @@ var providerConfig = {
|
|
|
101
112
|
}
|
|
102
113
|
}
|
|
103
114
|
};
|
|
115
|
+
var ICON_ONLY_SX = {
|
|
116
|
+
justifyContent: "center",
|
|
117
|
+
gap: 0,
|
|
118
|
+
"& .MuiButton-startIcon": { margin: 0 }
|
|
119
|
+
};
|
|
104
120
|
var SocialLoginButton = React.forwardRef(
|
|
105
121
|
({
|
|
106
122
|
provider,
|
|
@@ -109,9 +125,11 @@ var SocialLoginButton = React.forwardRef(
|
|
|
109
125
|
disabled = false,
|
|
110
126
|
fullWidth = true,
|
|
111
127
|
copy = EN_US_SOCIAL_LOGIN_COPY,
|
|
112
|
-
dataTestId
|
|
128
|
+
dataTestId,
|
|
129
|
+
iconOnly = false
|
|
113
130
|
}, ref) => {
|
|
114
131
|
const config = providerConfig[provider];
|
|
132
|
+
const label = copy[provider];
|
|
115
133
|
return /* @__PURE__ */ jsx(
|
|
116
134
|
Button,
|
|
117
135
|
{
|
|
@@ -125,13 +143,15 @@ var SocialLoginButton = React.forwardRef(
|
|
|
125
143
|
icon: /* @__PURE__ */ jsx(config.Icon, {}),
|
|
126
144
|
dataTestId,
|
|
127
145
|
fullWidth,
|
|
146
|
+
...iconOnly ? { "aria-label": label, title: label } : {},
|
|
128
147
|
sx: {
|
|
129
148
|
minHeight: 48,
|
|
130
149
|
justifyContent: "flex-start",
|
|
131
150
|
gap: 2,
|
|
151
|
+
...iconOnly ? ICON_ONLY_SX : {},
|
|
132
152
|
...config.sx
|
|
133
153
|
},
|
|
134
|
-
children:
|
|
154
|
+
children: iconOnly ? void 0 : label
|
|
135
155
|
}
|
|
136
156
|
);
|
|
137
157
|
}
|
|
@@ -174,4 +194,4 @@ export {
|
|
|
174
194
|
SocialLoginButton,
|
|
175
195
|
SocialLoginContainer
|
|
176
196
|
};
|
|
177
|
-
//# sourceMappingURL=chunk-
|
|
197
|
+
//# sourceMappingURL=chunk-T7WU7JGC.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/social-login-button/social-login-button.tsx"],"sourcesContent":["\"use client\";\n\nimport * as React from 'react';\nimport Box from '@mui/material/Box/index.js';\nimport Stack from '@mui/material/Stack/index.js';\nimport type { Theme } from '@mui/material/styles/index.js';\nimport { Button } from '../components/form/Button';\nimport { Card, CardContent } from '../components/layout/Card';\nimport { Heading } from '../components/typography/Heading';\nimport { Text } from '../components/typography/Text';\nimport { Separator } from '../components/layout/Separator';\nimport type { SocialLoginCopy } from '../copy/form';\nimport { EN_US_SOCIAL_LOGIN_COPY } from '../en-US.form';\n\nexport type SocialProvider = 'google' | 'facebook' | 'apple';\n\n/**\n * SVG Icons for social providers\n */\nconst GoogleIcon = (): React.ReactElement => (\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path\n d=\"M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92c-.26 1.37-1.04 2.53-2.21 3.31v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.09z\"\n fill=\"#4285F4\"\n />\n <path\n d=\"M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z\"\n fill=\"#34A853\"\n />\n <path\n d=\"M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z\"\n fill=\"#FBBC05\"\n />\n <path\n d=\"M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z\"\n fill=\"#EA4335\"\n />\n </svg>\n);\n\nconst FacebookIcon = (): React.ReactElement => (\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path\n d=\"M24 12c0-6.627-5.373-12-12-12S0 5.373 0 12c0 5.99 4.388 10.954 10.125 11.854V15.47H7.078V12h3.047V9.356c0-3.007 1.792-4.668 4.533-4.668 1.312 0 2.686.234 2.686.234v2.953H15.83c-1.491 0-1.956.925-1.956 1.874V12h3.328l-.532 3.469h-2.796v8.385C19.612 22.954 24 17.99 24 12z\"\n fill=\"#1877F2\"\n />\n </svg>\n);\n\nconst AppleIcon = (): React.ReactElement => (\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"currentColor\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M17.05 20.28c-.98.95-2.05.8-3.08.35-1.09-.46-2.09-.48-3.24 0-1.44.62-2.2.44-3.06-.35C2.79 15.25 3.51 7.59 9.05 7.31c1.35.07 2.29.74 3.08.8 1.18-.24 2.31-.93 3.57-.84 1.51.12 2.65.72 3.4 1.8-3.12 1.87-2.38 5.98.48 7.13-.57 1.5-1.31 2.99-2.54 4.09l.01-.01zM12.03 7.25c-.15-2.23 1.66-4.07 3.74-4.25.29 2.58-2.34 4.5-3.74 4.25z\" />\n </svg>\n);\n\n/**\n * Google's logo on a disabled button: one flat grey, faded (FUT-2393).\n *\n * The G is drawn in Google's four colours, hard-coded in its SVG, so MUI\n * greying a disabled button's label left a full-colour G beside it. The grey\n * label still said the button could not be pressed; an icon-only button has no\n * label, and read as ready to tap.\n *\n * `brightness(0)` draws the G in one flat colour, as Google's own disabled\n * button does, and the theme's `disabledOpacity` fades it, the step MUI dims a\n * disabled control by. `grayscale` would not do: it turns the four colours four\n * different greys, and the yellow arc all but vanished (1.26:1 against white).\n *\n * Google's alone: Facebook's and Apple's logos are drawn in the button's\n * `currentColor`, so they grey with the label by themselves, and fading them\n * again would all but erase them. Keyed on `.Mui-disabled`, the class MUI greys\n * the label by, so the logo and the label always agree. A loading button\n * carries it too, but its spinner replaces the logo slot.\n */\nconst GOOGLE_LOGO_WHEN_DISABLED_SX = {\n '&.Mui-disabled .MuiButton-startIcon': {\n filter: 'brightness(0)',\n opacity: (theme: Theme) => theme.palette.action.disabledOpacity,\n },\n} as const;\n\n/**\n * Facebook's logo in its button's own colour (FUT-2393).\n *\n * `FacebookIcon` is the blue roundel, drawn in #1877F2 with the \"f\" cut out of\n * it. On the button's own #1877F2 the roundel vanished: a label beside nothing,\n * and an icon-only button an empty blue slab. In `currentColor` it is the white\n * roundel Facebook's own button carries, and a disabled button greys it with\n * the label. Set on the button rather than in `FacebookIcon`, which a host may\n * draw on a white page.\n */\nconst FACEBOOK_LOGO_IN_BUTTON_COLOUR_SX = {\n '& .MuiButton-startIcon path': { fill: 'currentColor' },\n} as const;\n\ninterface ProviderConfig {\n Icon: () => React.ReactElement;\n variant: 'solid' | 'outline' | 'ghost';\n color: 'primary' | 'secondary' | 'neutral';\n sx?: object;\n}\n\nconst providerConfig: Record<SocialProvider, ProviderConfig> = {\n google: {\n Icon: GoogleIcon,\n variant: 'outline',\n color: 'neutral',\n sx: {\n backgroundColor: '#ffffff',\n color: '#1f1f1f',\n borderColor: '#dadce0',\n '&:hover': {\n backgroundColor: '#f5f5f5',\n borderColor: '#dadce0',\n },\n ...GOOGLE_LOGO_WHEN_DISABLED_SX,\n },\n },\n facebook: {\n Icon: FacebookIcon,\n variant: 'solid',\n color: 'primary',\n sx: {\n backgroundColor: '#1877F2',\n color: '#ffffff',\n '&:hover': {\n backgroundColor: '#166fe5',\n },\n ...FACEBOOK_LOGO_IN_BUTTON_COLOUR_SX,\n },\n },\n apple: {\n Icon: AppleIcon,\n variant: 'solid',\n color: 'neutral',\n sx: {\n backgroundColor: '#000000',\n color: '#ffffff',\n '&:hover': {\n backgroundColor: '#1a1a1a',\n },\n },\n },\n};\n\nexport interface SocialLoginButtonProps {\n provider: SocialProvider;\n onClick?: () => void;\n loading?: boolean;\n disabled?: boolean;\n fullWidth?: boolean;\n /**\n * The three provider labels (FUT-1263). `SOCIAL_LOGIN_COPY` ships both\n * languages, so a host passes `SOCIAL_LOGIN_COPY[\"pt-BR\"]` rather than\n * authoring a word.\n *\n * These used to be English string literals inside `providerConfig`, reachable\n * by nothing: a pt-BR storefront rendered \"Continue with Google\" on an\n * otherwise Portuguese sign-in screen and had no way to change it.\n *\n * OPTIONAL, unlike every other `copy` in this package, and defaulted to the\n * en-US pack. That is a deliberate exception so this ships as a MINOR: making\n * it required would break every existing caller on a routine update. The cost\n * is the one this package's convention exists to avoid — a host that says\n * nothing still renders English — so a consumer wanting Portuguese must pass\n * the pack, and FUT-1263 is not closed until it does.\n */\n copy?: SocialLoginCopy;\n /**\n * Per-provider test hook. Without one all three buttons render the same\n * `data-testid`, leaving their visible text as the only selector — which is\n * exactly the text a host is now expected to translate.\n */\n dataTestId?: string;\n /**\n * The provider's logo alone, centred (FUT-2393).\n *\n * For a row of providers in a narrow block, where \"Continuar com o Google\"\n * wraps to two lines at 320px and two providers cannot share a line. The\n * label is not dropped: it stays the button's accessible name, so a screen\n * reader still announces the provider, and its `title`, so a pointer\n * hovering the logo reads it too.\n */\n iconOnly?: boolean;\n}\n\n/**\n * What an icon-only social button changes: the logo centred, with no gap\n * reserved for a label and no margin MUI keeps beside a start icon.\n */\nconst ICON_ONLY_SX = {\n justifyContent: 'center',\n gap: 0,\n '& .MuiButton-startIcon': { margin: 0 },\n} as const;\n\n/**\n * Social login button using UI package Button component\n */\nexport const SocialLoginButton = React.forwardRef<HTMLButtonElement, SocialLoginButtonProps>(\n (\n {\n provider,\n onClick,\n loading = false,\n disabled = false,\n fullWidth = true,\n copy = EN_US_SOCIAL_LOGIN_COPY,\n dataTestId,\n iconOnly = false,\n },\n ref,\n ) => {\n const config = providerConfig[provider];\n const label = copy[provider];\n\n return (\n <Button\n ref={ref}\n variant={config.variant}\n color={config.color}\n size=\"lg\"\n loading={loading}\n disabled={disabled}\n onClick={onClick}\n icon={<config.Icon />}\n dataTestId={dataTestId}\n fullWidth={fullWidth}\n {...(iconOnly ? { 'aria-label': label, title: label } : {})}\n sx={{\n minHeight: 48,\n justifyContent: 'flex-start',\n gap: 2,\n ...(iconOnly ? ICON_ONLY_SX : {}),\n ...config.sx,\n }}\n >\n {iconOnly ? undefined : label}\n </Button>\n );\n }\n);\n\nSocialLoginButton.displayName = 'SocialLoginButton';\n\n/**\n * Container for social login buttons with optional divider\n */\nexport interface SocialLoginContainerProps {\n children: React.ReactNode;\n title?: string;\n subtitle?: string;\n showDivider?: boolean;\n dividerText?: string;\n /**\n * How wide the card is allowed to get. Defaults to the 400 it has always\n * intended, so nothing that does not ask for a width moves.\n *\n * Worth passing for a card holding a FORM rather than a row of provider\n * buttons: 400 was chosen for the latter, and an e-mail + password pair reads\n * cramped in it.\n */\n maxWidth?: number | string;\n}\n\nexport function SocialLoginContainer({\n children,\n title = \"Sign in to continue\",\n subtitle,\n showDivider = false,\n dividerText = \"or\",\n maxWidth = 400,\n}: SocialLoginContainerProps): React.ReactElement {\n return (\n // `width: 100%` is what makes the cap below mean anything. Every caller\n // centres this card in a flex column (`Container variant=\"centered\"` does),\n // and a flex item under `align-items: center` sizes to its CONTENT — so the\n // card sat at whatever the longest label happened to need, ~267px, at every\n // viewport from 390 to 1280. The 400 was never reached, which is why raising\n // it would have changed nothing; the card had no width to cap.\n <Card variant=\"elevated\" borderRadius=\"lg\" sx={{ width: '100%', maxWidth }}>\n <CardContent>\n <Stack spacing={3} sx={{ width: '100%' }}>\n {title && (\n <Box sx={{ textAlign: 'center' }}>\n <Heading level=\"h2\">\n {title}\n </Heading>\n {subtitle && (\n <Text color=\"secondary\" size=\"sm\">\n {subtitle}\n </Text>\n )}\n </Box>\n )}\n\n <Stack spacing={2}>\n {children}\n </Stack>\n\n {showDivider && (\n <Box sx={{ display: 'flex', alignItems: 'center', gap: 2 }}>\n <Separator />\n <Text color=\"secondary\" size=\"sm\">\n {dividerText}\n </Text>\n <Separator />\n </Box>\n )}\n </Stack>\n </CardContent>\n </Card>\n );\n}\n\nexport { GoogleIcon, FacebookIcon, AppleIcon };\n"],"mappings":"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","names":[]}
|
|
@@ -36,6 +36,16 @@ export interface SocialLoginButtonProps {
|
|
|
36
36
|
* exactly the text a host is now expected to translate.
|
|
37
37
|
*/
|
|
38
38
|
dataTestId?: string;
|
|
39
|
+
/**
|
|
40
|
+
* The provider's logo alone, centred (FUT-2393).
|
|
41
|
+
*
|
|
42
|
+
* For a row of providers in a narrow block, where "Continuar com o Google"
|
|
43
|
+
* wraps to two lines at 320px and two providers cannot share a line. The
|
|
44
|
+
* label is not dropped: it stays the button's accessible name, so a screen
|
|
45
|
+
* reader still announces the provider, and its `title`, so a pointer
|
|
46
|
+
* hovering the logo reads it too.
|
|
47
|
+
*/
|
|
48
|
+
iconOnly?: boolean;
|
|
39
49
|
}
|
|
40
50
|
/**
|
|
41
51
|
* Social login button using UI package Button component
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"social-login-button.d.ts","sourceRoot":"","sources":["../../../src/social-login-button/social-login-button.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"social-login-button.d.ts","sourceRoot":"","sources":["../../../src/social-login-button/social-login-button.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAS/B,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAGpD,MAAM,MAAM,cAAc,GAAG,QAAQ,GAAG,UAAU,GAAG,OAAO,CAAC;AAE7D;;GAEG;AACH,QAAA,MAAM,UAAU,QAAO,KAAK,CAAC,YAmB5B,CAAC;AAEF,QAAA,MAAM,YAAY,QAAO,KAAK,CAAC,YAO9B,CAAC;AAEF,QAAA,MAAM,SAAS,QAAO,KAAK,CAAC,YAI3B,CAAC;AA4FF,MAAM,WAAW,sBAAsB;IACrC,QAAQ,EAAE,cAAc,CAAC;IACzB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB;;;;;;;;;;;;;;;OAeG;IACH,IAAI,CAAC,EAAE,eAAe,CAAC;IACvB;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;;;;;;OAQG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAYD;;GAEG;AACH,eAAO,MAAM,iBAAiB,kGA0C7B,CAAC;AAIF;;GAEG;AACH,MAAM,WAAW,yBAAyB;IACxC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;;;;OAOG;IACH,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;CAC5B;AAED,wBAAgB,oBAAoB,CAAC,EACnC,QAAQ,EACR,KAA6B,EAC7B,QAAQ,EACR,WAAmB,EACnB,WAAkB,EAClB,QAAc,GACf,EAAE,yBAAyB,GAAG,KAAK,CAAC,YAAY,CAyChD;AAED,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,SAAS,EAAE,CAAC"}
|
package/package.json
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
import * as React from 'react';
|
|
4
4
|
import Box from '@mui/material/Box/index.js';
|
|
5
5
|
import Stack from '@mui/material/Stack/index.js';
|
|
6
|
+
import type { Theme } from '@mui/material/styles/index.js';
|
|
6
7
|
import { Button } from '../components/form/Button';
|
|
7
8
|
import { Card, CardContent } from '../components/layout/Card';
|
|
8
9
|
import { Heading } from '../components/typography/Heading';
|
|
@@ -52,6 +53,46 @@ const AppleIcon = (): React.ReactElement => (
|
|
|
52
53
|
</svg>
|
|
53
54
|
);
|
|
54
55
|
|
|
56
|
+
/**
|
|
57
|
+
* Google's logo on a disabled button: one flat grey, faded (FUT-2393).
|
|
58
|
+
*
|
|
59
|
+
* The G is drawn in Google's four colours, hard-coded in its SVG, so MUI
|
|
60
|
+
* greying a disabled button's label left a full-colour G beside it. The grey
|
|
61
|
+
* label still said the button could not be pressed; an icon-only button has no
|
|
62
|
+
* label, and read as ready to tap.
|
|
63
|
+
*
|
|
64
|
+
* `brightness(0)` draws the G in one flat colour, as Google's own disabled
|
|
65
|
+
* button does, and the theme's `disabledOpacity` fades it, the step MUI dims a
|
|
66
|
+
* disabled control by. `grayscale` would not do: it turns the four colours four
|
|
67
|
+
* different greys, and the yellow arc all but vanished (1.26:1 against white).
|
|
68
|
+
*
|
|
69
|
+
* Google's alone: Facebook's and Apple's logos are drawn in the button's
|
|
70
|
+
* `currentColor`, so they grey with the label by themselves, and fading them
|
|
71
|
+
* again would all but erase them. Keyed on `.Mui-disabled`, the class MUI greys
|
|
72
|
+
* the label by, so the logo and the label always agree. A loading button
|
|
73
|
+
* carries it too, but its spinner replaces the logo slot.
|
|
74
|
+
*/
|
|
75
|
+
const GOOGLE_LOGO_WHEN_DISABLED_SX = {
|
|
76
|
+
'&.Mui-disabled .MuiButton-startIcon': {
|
|
77
|
+
filter: 'brightness(0)',
|
|
78
|
+
opacity: (theme: Theme) => theme.palette.action.disabledOpacity,
|
|
79
|
+
},
|
|
80
|
+
} as const;
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Facebook's logo in its button's own colour (FUT-2393).
|
|
84
|
+
*
|
|
85
|
+
* `FacebookIcon` is the blue roundel, drawn in #1877F2 with the "f" cut out of
|
|
86
|
+
* it. On the button's own #1877F2 the roundel vanished: a label beside nothing,
|
|
87
|
+
* and an icon-only button an empty blue slab. In `currentColor` it is the white
|
|
88
|
+
* roundel Facebook's own button carries, and a disabled button greys it with
|
|
89
|
+
* the label. Set on the button rather than in `FacebookIcon`, which a host may
|
|
90
|
+
* draw on a white page.
|
|
91
|
+
*/
|
|
92
|
+
const FACEBOOK_LOGO_IN_BUTTON_COLOUR_SX = {
|
|
93
|
+
'& .MuiButton-startIcon path': { fill: 'currentColor' },
|
|
94
|
+
} as const;
|
|
95
|
+
|
|
55
96
|
interface ProviderConfig {
|
|
56
97
|
Icon: () => React.ReactElement;
|
|
57
98
|
variant: 'solid' | 'outline' | 'ghost';
|
|
@@ -72,6 +113,7 @@ const providerConfig: Record<SocialProvider, ProviderConfig> = {
|
|
|
72
113
|
backgroundColor: '#f5f5f5',
|
|
73
114
|
borderColor: '#dadce0',
|
|
74
115
|
},
|
|
116
|
+
...GOOGLE_LOGO_WHEN_DISABLED_SX,
|
|
75
117
|
},
|
|
76
118
|
},
|
|
77
119
|
facebook: {
|
|
@@ -84,6 +126,7 @@ const providerConfig: Record<SocialProvider, ProviderConfig> = {
|
|
|
84
126
|
'&:hover': {
|
|
85
127
|
backgroundColor: '#166fe5',
|
|
86
128
|
},
|
|
129
|
+
...FACEBOOK_LOGO_IN_BUTTON_COLOUR_SX,
|
|
87
130
|
},
|
|
88
131
|
},
|
|
89
132
|
apple: {
|
|
@@ -129,8 +172,28 @@ export interface SocialLoginButtonProps {
|
|
|
129
172
|
* exactly the text a host is now expected to translate.
|
|
130
173
|
*/
|
|
131
174
|
dataTestId?: string;
|
|
175
|
+
/**
|
|
176
|
+
* The provider's logo alone, centred (FUT-2393).
|
|
177
|
+
*
|
|
178
|
+
* For a row of providers in a narrow block, where "Continuar com o Google"
|
|
179
|
+
* wraps to two lines at 320px and two providers cannot share a line. The
|
|
180
|
+
* label is not dropped: it stays the button's accessible name, so a screen
|
|
181
|
+
* reader still announces the provider, and its `title`, so a pointer
|
|
182
|
+
* hovering the logo reads it too.
|
|
183
|
+
*/
|
|
184
|
+
iconOnly?: boolean;
|
|
132
185
|
}
|
|
133
186
|
|
|
187
|
+
/**
|
|
188
|
+
* What an icon-only social button changes: the logo centred, with no gap
|
|
189
|
+
* reserved for a label and no margin MUI keeps beside a start icon.
|
|
190
|
+
*/
|
|
191
|
+
const ICON_ONLY_SX = {
|
|
192
|
+
justifyContent: 'center',
|
|
193
|
+
gap: 0,
|
|
194
|
+
'& .MuiButton-startIcon': { margin: 0 },
|
|
195
|
+
} as const;
|
|
196
|
+
|
|
134
197
|
/**
|
|
135
198
|
* Social login button using UI package Button component
|
|
136
199
|
*/
|
|
@@ -144,10 +207,12 @@ export const SocialLoginButton = React.forwardRef<HTMLButtonElement, SocialLogin
|
|
|
144
207
|
fullWidth = true,
|
|
145
208
|
copy = EN_US_SOCIAL_LOGIN_COPY,
|
|
146
209
|
dataTestId,
|
|
210
|
+
iconOnly = false,
|
|
147
211
|
},
|
|
148
212
|
ref,
|
|
149
213
|
) => {
|
|
150
214
|
const config = providerConfig[provider];
|
|
215
|
+
const label = copy[provider];
|
|
151
216
|
|
|
152
217
|
return (
|
|
153
218
|
<Button
|
|
@@ -161,14 +226,16 @@ export const SocialLoginButton = React.forwardRef<HTMLButtonElement, SocialLogin
|
|
|
161
226
|
icon={<config.Icon />}
|
|
162
227
|
dataTestId={dataTestId}
|
|
163
228
|
fullWidth={fullWidth}
|
|
229
|
+
{...(iconOnly ? { 'aria-label': label, title: label } : {})}
|
|
164
230
|
sx={{
|
|
165
231
|
minHeight: 48,
|
|
166
232
|
justifyContent: 'flex-start',
|
|
167
233
|
gap: 2,
|
|
234
|
+
...(iconOnly ? ICON_ONLY_SX : {}),
|
|
168
235
|
...config.sx,
|
|
169
236
|
}}
|
|
170
237
|
>
|
|
171
|
-
{
|
|
238
|
+
{iconOnly ? undefined : label}
|
|
172
239
|
</Button>
|
|
173
240
|
);
|
|
174
241
|
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/social-login-button/social-login-button.tsx"],"sourcesContent":["\"use client\";\n\nimport * as React from 'react';\nimport Box from '@mui/material/Box/index.js';\nimport Stack from '@mui/material/Stack/index.js';\nimport { Button } from '../components/form/Button';\nimport { Card, CardContent } from '../components/layout/Card';\nimport { Heading } from '../components/typography/Heading';\nimport { Text } from '../components/typography/Text';\nimport { Separator } from '../components/layout/Separator';\nimport type { SocialLoginCopy } from '../copy/form';\nimport { EN_US_SOCIAL_LOGIN_COPY } from '../en-US.form';\n\nexport type SocialProvider = 'google' | 'facebook' | 'apple';\n\n/**\n * SVG Icons for social providers\n */\nconst GoogleIcon = (): React.ReactElement => (\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path\n d=\"M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92c-.26 1.37-1.04 2.53-2.21 3.31v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.09z\"\n fill=\"#4285F4\"\n />\n <path\n d=\"M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z\"\n fill=\"#34A853\"\n />\n <path\n d=\"M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z\"\n fill=\"#FBBC05\"\n />\n <path\n d=\"M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z\"\n fill=\"#EA4335\"\n />\n </svg>\n);\n\nconst FacebookIcon = (): React.ReactElement => (\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path\n d=\"M24 12c0-6.627-5.373-12-12-12S0 5.373 0 12c0 5.99 4.388 10.954 10.125 11.854V15.47H7.078V12h3.047V9.356c0-3.007 1.792-4.668 4.533-4.668 1.312 0 2.686.234 2.686.234v2.953H15.83c-1.491 0-1.956.925-1.956 1.874V12h3.328l-.532 3.469h-2.796v8.385C19.612 22.954 24 17.99 24 12z\"\n fill=\"#1877F2\"\n />\n </svg>\n);\n\nconst AppleIcon = (): React.ReactElement => (\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"currentColor\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M17.05 20.28c-.98.95-2.05.8-3.08.35-1.09-.46-2.09-.48-3.24 0-1.44.62-2.2.44-3.06-.35C2.79 15.25 3.51 7.59 9.05 7.31c1.35.07 2.29.74 3.08.8 1.18-.24 2.31-.93 3.57-.84 1.51.12 2.65.72 3.4 1.8-3.12 1.87-2.38 5.98.48 7.13-.57 1.5-1.31 2.99-2.54 4.09l.01-.01zM12.03 7.25c-.15-2.23 1.66-4.07 3.74-4.25.29 2.58-2.34 4.5-3.74 4.25z\" />\n </svg>\n);\n\ninterface ProviderConfig {\n Icon: () => React.ReactElement;\n variant: 'solid' | 'outline' | 'ghost';\n color: 'primary' | 'secondary' | 'neutral';\n sx?: object;\n}\n\nconst providerConfig: Record<SocialProvider, ProviderConfig> = {\n google: {\n Icon: GoogleIcon,\n variant: 'outline',\n color: 'neutral',\n sx: {\n backgroundColor: '#ffffff',\n color: '#1f1f1f',\n borderColor: '#dadce0',\n '&:hover': {\n backgroundColor: '#f5f5f5',\n borderColor: '#dadce0',\n },\n },\n },\n facebook: {\n Icon: FacebookIcon,\n variant: 'solid',\n color: 'primary',\n sx: {\n backgroundColor: '#1877F2',\n color: '#ffffff',\n '&:hover': {\n backgroundColor: '#166fe5',\n },\n },\n },\n apple: {\n Icon: AppleIcon,\n variant: 'solid',\n color: 'neutral',\n sx: {\n backgroundColor: '#000000',\n color: '#ffffff',\n '&:hover': {\n backgroundColor: '#1a1a1a',\n },\n },\n },\n};\n\nexport interface SocialLoginButtonProps {\n provider: SocialProvider;\n onClick?: () => void;\n loading?: boolean;\n disabled?: boolean;\n fullWidth?: boolean;\n /**\n * The three provider labels (FUT-1263). `SOCIAL_LOGIN_COPY` ships both\n * languages, so a host passes `SOCIAL_LOGIN_COPY[\"pt-BR\"]` rather than\n * authoring a word.\n *\n * These used to be English string literals inside `providerConfig`, reachable\n * by nothing: a pt-BR storefront rendered \"Continue with Google\" on an\n * otherwise Portuguese sign-in screen and had no way to change it.\n *\n * OPTIONAL, unlike every other `copy` in this package, and defaulted to the\n * en-US pack. That is a deliberate exception so this ships as a MINOR: making\n * it required would break every existing caller on a routine update. The cost\n * is the one this package's convention exists to avoid — a host that says\n * nothing still renders English — so a consumer wanting Portuguese must pass\n * the pack, and FUT-1263 is not closed until it does.\n */\n copy?: SocialLoginCopy;\n /**\n * Per-provider test hook. Without one all three buttons render the same\n * `data-testid`, leaving their visible text as the only selector — which is\n * exactly the text a host is now expected to translate.\n */\n dataTestId?: string;\n}\n\n/**\n * Social login button using UI package Button component\n */\nexport const SocialLoginButton = React.forwardRef<HTMLButtonElement, SocialLoginButtonProps>(\n (\n {\n provider,\n onClick,\n loading = false,\n disabled = false,\n fullWidth = true,\n copy = EN_US_SOCIAL_LOGIN_COPY,\n dataTestId,\n },\n ref,\n ) => {\n const config = providerConfig[provider];\n\n return (\n <Button\n ref={ref}\n variant={config.variant}\n color={config.color}\n size=\"lg\"\n loading={loading}\n disabled={disabled}\n onClick={onClick}\n icon={<config.Icon />}\n dataTestId={dataTestId}\n fullWidth={fullWidth}\n sx={{\n minHeight: 48,\n justifyContent: 'flex-start',\n gap: 2,\n ...config.sx,\n }}\n >\n {copy[provider]}\n </Button>\n );\n }\n);\n\nSocialLoginButton.displayName = 'SocialLoginButton';\n\n/**\n * Container for social login buttons with optional divider\n */\nexport interface SocialLoginContainerProps {\n children: React.ReactNode;\n title?: string;\n subtitle?: string;\n showDivider?: boolean;\n dividerText?: string;\n /**\n * How wide the card is allowed to get. Defaults to the 400 it has always\n * intended, so nothing that does not ask for a width moves.\n *\n * Worth passing for a card holding a FORM rather than a row of provider\n * buttons: 400 was chosen for the latter, and an e-mail + password pair reads\n * cramped in it.\n */\n maxWidth?: number | string;\n}\n\nexport function SocialLoginContainer({\n children,\n title = \"Sign in to continue\",\n subtitle,\n showDivider = false,\n dividerText = \"or\",\n maxWidth = 400,\n}: SocialLoginContainerProps): React.ReactElement {\n return (\n // `width: 100%` is what makes the cap below mean anything. Every caller\n // centres this card in a flex column (`Container variant=\"centered\"` does),\n // and a flex item under `align-items: center` sizes to its CONTENT — so the\n // card sat at whatever the longest label happened to need, ~267px, at every\n // viewport from 390 to 1280. The 400 was never reached, which is why raising\n // it would have changed nothing; the card had no width to cap.\n <Card variant=\"elevated\" borderRadius=\"lg\" sx={{ width: '100%', maxWidth }}>\n <CardContent>\n <Stack spacing={3} sx={{ width: '100%' }}>\n {title && (\n <Box sx={{ textAlign: 'center' }}>\n <Heading level=\"h2\">\n {title}\n </Heading>\n {subtitle && (\n <Text color=\"secondary\" size=\"sm\">\n {subtitle}\n </Text>\n )}\n </Box>\n )}\n\n <Stack spacing={2}>\n {children}\n </Stack>\n\n {showDivider && (\n <Box sx={{ display: 'flex', alignItems: 'center', gap: 2 }}>\n <Separator />\n <Text color=\"secondary\" size=\"sm\">\n {dividerText}\n </Text>\n <Separator />\n </Box>\n )}\n </Stack>\n </CardContent>\n </Card>\n );\n}\n\nexport { GoogleIcon, FacebookIcon, AppleIcon };\n"],"mappings":"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","names":[]}
|