@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.
@@ -5,7 +5,7 @@ import {
5
5
  GoogleIcon,
6
6
  SocialLoginButton,
7
7
  SocialLoginContainer
8
- } from "../../chunk-2WSU6OGE.js";
8
+ } from "../../chunk-T7WU7JGC.js";
9
9
  import "../../chunk-INGPH3YQ.js";
10
10
  import "../../chunk-6GP2DOOO.js";
11
11
  import "../../chunk-SLMA4UQS.js";
@@ -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: copy[provider]
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-2WSU6OGE.js.map
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":[]}
@@ -4,7 +4,7 @@ import {
4
4
  GoogleIcon,
5
5
  SocialLoginButton,
6
6
  SocialLoginContainer
7
- } from "./chunk-2WSU6OGE.js";
7
+ } from "./chunk-T7WU7JGC.js";
8
8
  import "./chunk-INGPH3YQ.js";
9
9
  import "./chunk-6GP2DOOO.js";
10
10
  import "./chunk-SLMA4UQS.js";
@@ -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;AAQ/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;AAkDF,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;CACrB;AAED;;GAEG;AACH,eAAO,MAAM,iBAAiB,kGAsC7B,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"}
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@12-apps/ui",
3
- "version": "6.28.0",
3
+ "version": "6.29.1",
4
4
  "license": "MIT",
5
5
  "packageManager": "pnpm@10.34.5",
6
6
  "type": "module",
@@ -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
- {copy[provider]}
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":[]}