mirror of
https://github.com/stack-auth/stack.git
synced 2026-06-04 21:04:37 +08:00
Add an OAuth provider for Twitch (#728)
<!-- ELLIPSIS_HIDDEN -->
> [!IMPORTANT]
> Add Twitch as a new OAuth provider, updating backend logic and UI
components to support Twitch authentication.
>
> - **Behavior**:
> - Add `TwitchProvider` class in `providers/twitch.tsx` to handle OAuth
with Twitch, including user info post-processing.
> - Update `_providers` in `index.tsx` to include `TwitchProvider`.
> - Add `TWITCH` to `StandardOAuthProviderType` enum in `schema.prisma`.
> - **UI Components**:
> - Add Twitch icon and color in `brand-icons.tsx` and `BRAND_COLORS`.
> - Update `ProviderIcon`, `ProviderSettingDialog`, and `OAuthButton` to
support Twitch in `providers.tsx` and `oauth-button.tsx`.
> - **Misc**:
> - Add `twitch` to `standardProviders` in `oauth.tsx`.
>
> <sup>This description was created by </sup>[<img alt="Ellipsis"
src="https://img.shields.io/badge/Ellipsis-blue?color=175173">](https://www.ellipsis.dev?ref=stack-auth%2Fstack-auth&utm_source=github&utm_medium=referral)<sup>
for 08c0de5762. You can
[customize](https://app.ellipsis.dev/stack-auth/settings/summaries) this
summary. It will automatically update as commits are pushed.</sup>
<!-- ELLIPSIS_HIDDEN -->
---------
Co-authored-by: Zai Shi <zaishi00@outlook.com>
This commit is contained in:
parent
fc7850487c
commit
6a58bb03b0
@ -0,0 +1,2 @@
|
||||
-- AlterEnum
|
||||
ALTER TYPE "StandardOAuthProviderType" ADD VALUE 'TWITCH';
|
||||
@ -363,6 +363,7 @@ enum StandardOAuthProviderType {
|
||||
LINKEDIN
|
||||
APPLE
|
||||
X
|
||||
TWITCH
|
||||
}
|
||||
|
||||
model OAuthToken {
|
||||
|
||||
@ -17,6 +17,7 @@ import { MicrosoftProvider } from "./providers/microsoft";
|
||||
import { MockProvider } from "./providers/mock";
|
||||
import { SpotifyProvider } from "./providers/spotify";
|
||||
import { XProvider } from "./providers/x";
|
||||
import { TwitchProvider } from "./providers/twitch";
|
||||
|
||||
const _providers = {
|
||||
github: GithubProvider,
|
||||
@ -30,6 +31,7 @@ const _providers = {
|
||||
bitbucket: BitbucketProvider,
|
||||
linkedin: LinkedInProvider,
|
||||
x: XProvider,
|
||||
twitch: TwitchProvider,
|
||||
} as const;
|
||||
|
||||
const mockProvider = MockProvider;
|
||||
|
||||
56
apps/backend/src/oauth/providers/twitch.tsx
Normal file
56
apps/backend/src/oauth/providers/twitch.tsx
Normal file
@ -0,0 +1,56 @@
|
||||
import { getEnvVariable } from "@stackframe/stack-shared/dist/utils/env";
|
||||
import { OAuthUserInfo, validateUserInfo } from "../utils";
|
||||
import { OAuthBaseProvider, TokenSet } from "./base";
|
||||
|
||||
export class TwitchProvider extends OAuthBaseProvider {
|
||||
private constructor(
|
||||
...args: ConstructorParameters<typeof OAuthBaseProvider>
|
||||
) {
|
||||
super(...args);
|
||||
}
|
||||
|
||||
static async create(options: {
|
||||
clientId: string,
|
||||
clientSecret: string,
|
||||
}) {
|
||||
return new TwitchProvider(...await OAuthBaseProvider.createConstructorArgs({
|
||||
issuer: "https://id.twitch.tv",
|
||||
authorizationEndpoint: "https://id.twitch.tv/oauth2/authorize",
|
||||
tokenEndpoint: "https://id.twitch.tv/oauth2/token",
|
||||
tokenEndpointAuthMethod: "client_secret_post",
|
||||
redirectUri: getEnvVariable("NEXT_PUBLIC_STACK_API_URL") + "/api/v1/auth/oauth/callback/twitch",
|
||||
baseScope: "user:read:email",
|
||||
...options,
|
||||
}));
|
||||
}
|
||||
|
||||
async postProcessUserInfo(tokenSet: TokenSet): Promise<OAuthUserInfo> {
|
||||
const info = await fetch("https://api.twitch.tv/helix/users", {
|
||||
headers: {
|
||||
Authorization: `Bearer ${tokenSet.accessToken}`,
|
||||
"Client-Id": this.oauthClient.client_id as string,
|
||||
},
|
||||
}).then((res) => res.json());
|
||||
|
||||
|
||||
const userInfo = info.data?.[0];
|
||||
|
||||
return validateUserInfo({
|
||||
accountId: userInfo.id,
|
||||
displayName: userInfo.display_name,
|
||||
email: userInfo.email,
|
||||
profileImageUrl: userInfo.profile_image_url,
|
||||
emailVerified: true,
|
||||
});
|
||||
}
|
||||
|
||||
async checkAccessTokenValidity(accessToken: string): Promise<boolean> {
|
||||
const info = await fetch("https://api.twitch.tv/helix/users", {
|
||||
headers: {
|
||||
Authorization: `Bearer ${accessToken}`,
|
||||
"Client-Id": this.oauthClient.client_id as string,
|
||||
},
|
||||
}).then((res) => res.json());
|
||||
return info.data?.[0] !== undefined;
|
||||
}
|
||||
}
|
||||
@ -13,7 +13,7 @@ import * as yup from "yup";
|
||||
export function ProviderIcon(props: { id: string }) {
|
||||
return (
|
||||
<div
|
||||
className="flex items-center justify-center w-12 h-12 rounded-md border border-gray-800"
|
||||
className="flex items-center justify-center w-12 h-12 rounded-md border"
|
||||
style={{ backgroundColor: props.id in BrandIcons.BRAND_COLORS ? BrandIcons.BRAND_COLORS[props.id] : undefined }}
|
||||
>
|
||||
<BrandIcons.Mapping iconSize={24} provider={props.id} />
|
||||
@ -40,6 +40,7 @@ function toTitle(id: string) {
|
||||
apple: "Apple",
|
||||
bitbucket: "Bitbucket",
|
||||
linkedin: "LinkedIn",
|
||||
twitch: "Twitch",
|
||||
x: "X",
|
||||
}[id];
|
||||
}
|
||||
@ -216,7 +217,7 @@ export function ProviderSettingSwitch(props: Props) {
|
||||
return (
|
||||
<>
|
||||
<div
|
||||
className={clsx("flex flex-col items-center justify-center gap-2 py-2 border border-1 rounded-lg p-2 w-[120px] h-[120px] cursor-pointer transition-all", enabled ? "border-white" : "border-gray-800 hover:border-gray-400")}
|
||||
className={clsx("flex flex-col items-center justify-center gap-2 py-2 border border-1 rounded-lg p-2 w-[120px] h-[120px] transition-all hover:border-gray-500 cursor-pointer")}
|
||||
onClick={() => {
|
||||
if (enabled) {
|
||||
setTurnOffProviderDialogOpen(true);
|
||||
|
||||
@ -159,7 +159,7 @@ function MobileClickableCollapsibleSection({
|
||||
e.stopPropagation();
|
||||
setIsOpen(!isOpen);
|
||||
}}
|
||||
className="opacity-0 group-hover:opacity-100 transition-opacity p-0.5 rounded hover:bg-fd-muted/30"
|
||||
className="transition-opacity p-0.5 rounded hover:bg-fd-muted/30"
|
||||
>
|
||||
{isOpen ? (
|
||||
<ChevronDown className="h-3 w-3" />
|
||||
|
||||
@ -37,13 +37,13 @@ import Link from 'fumadocs-core/link';
|
||||
import type { PageTree } from 'fumadocs-core/server';
|
||||
import {
|
||||
NavProvider,
|
||||
type PageStyles,
|
||||
StylesProvider,
|
||||
type PageStyles,
|
||||
} from 'fumadocs-ui/contexts/layout';
|
||||
import { TreeContextProvider } from 'fumadocs-ui/contexts/tree';
|
||||
import { ArrowLeft, ChevronDown, ChevronRight, Languages, Sidebar as SidebarIcon } from 'lucide-react';
|
||||
import { usePathname, useRouter } from 'next/navigation';
|
||||
import { createContext, type HTMLAttributes, type ReactNode, useContext, useEffect, useMemo, useRef, useState } from 'react';
|
||||
import { createContext, useContext, useEffect, useMemo, useRef, useState, type HTMLAttributes, type ReactNode } from 'react';
|
||||
import { createPortal } from 'react-dom';
|
||||
import { usePlatformPreference } from '../../hooks/use-platform-preference';
|
||||
import { cn } from '../../lib/cn';
|
||||
@ -79,7 +79,7 @@ import {
|
||||
type IconItemType,
|
||||
type LinkItemType,
|
||||
} from './links';
|
||||
import { type BaseLayoutProps, getLinks, omit, slot, slots } from './shared';
|
||||
import { getLinks, omit, slot, slots, type BaseLayoutProps } from './shared';
|
||||
import { isInApiSection } from './shared-header';
|
||||
import { useSidebar as useCustomSidebar } from './sidebar-context';
|
||||
|
||||
@ -245,7 +245,7 @@ function ClickableCollapsibleSection({
|
||||
e.stopPropagation();
|
||||
setIsOpen(!isOpen);
|
||||
}}
|
||||
className="opacity-0 group-hover:opacity-100 transition-opacity p-0.5 rounded hover:bg-fd-muted/30"
|
||||
className="transition-opacity p-0.5 rounded hover:bg-fd-muted/30"
|
||||
>
|
||||
{isOpen ? (
|
||||
<ChevronDown className="h-3 w-3" />
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
---
|
||||
title: "Apple Authentication"
|
||||
title: "Apple"
|
||||
---
|
||||
|
||||
This guide explains how to set up Apple as an authentication provider with Stack Auth. Sign in with Apple allows users to sign in to your application using their Apple ID.
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
---
|
||||
title: "Bitbucket Authentication"
|
||||
title: "Bitbucket"
|
||||
---
|
||||
|
||||
This guide explains how to set up Bitbucket as an authentication provider with Stack Auth. Bitbucket OAuth allows users to sign in to your application using their Bitbucket account.
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
---
|
||||
title: "Discord Authentication"
|
||||
title: "Discord"
|
||||
---
|
||||
|
||||
This guide explains how to set up Discord as an authentication provider with Stack Auth. Discord OAuth2 allows users to sign in to your application using their Discord account.
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
---
|
||||
title: "Facebook Authentication"
|
||||
title: "Facebook"
|
||||
---
|
||||
|
||||
This guide explains how to set up Facebook as an authentication provider with Stack Auth. Facebook OAuth allows users to sign in to your application using their Facebook account.
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
---
|
||||
title: "GitHub Authentication"
|
||||
title: "GitHub"
|
||||
---
|
||||
|
||||
This guide explains how to set up GitHub as an authentication provider with Stack Auth. GitHub OAuth allows users to sign in to your application using their GitHub account.
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
---
|
||||
title: "GitLab Authentication"
|
||||
title: "GitLab"
|
||||
---
|
||||
|
||||
This guide explains how to set up GitLab as an authentication provider with Stack Auth. GitLab OAuth allows users to sign in to your application using their GitLab account.
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
---
|
||||
title: "Google Authentication"
|
||||
title: "Google"
|
||||
---
|
||||
|
||||
This guide explains how to set up Google as an authentication provider with Stack Auth. Google OAuth2 allows users to sign in to your application using their Google account.
|
||||
|
||||
21
docs/templates/concepts/auth-providers/index.mdx
vendored
21
docs/templates/concepts/auth-providers/index.mdx
vendored
@ -107,6 +107,27 @@ Stack Auth supports a wide range of authentication providers to help you add sec
|
||||
<svg viewBox="0 0 24 24" width="40" height="40"><path fill="currentColor" d="M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z"/></svg>
|
||||
</div>
|
||||
</Card>
|
||||
|
||||
<Card
|
||||
title="Twitch"
|
||||
href="./auth-providers/twitch"
|
||||
>
|
||||
<div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', marginTop: '0.5rem' }}>
|
||||
<svg aria-label="Twitch" viewBox="0 0 2400 2800" width="40" height="40">
|
||||
<g>
|
||||
<polygon fill={"#FFFFFF"}
|
||||
points="2200,1300 1800,1700 1400,1700 1050,2050 1050,1700 600,1700 600,200 2200,200"/>
|
||||
<g>
|
||||
<g id="Layer_1-2">
|
||||
<path fill={"#9146FF"} d="M500,0L0,500v1800h600v500l500-500h400l900-900V0H500z M2200,1300l-400,400h-400l-350,350v-350H600V200h1600 V1300z"/>
|
||||
<rect x="1700" y="550" fill={"#9146FF"} width="200" height="600"/>
|
||||
<rect x="1150" y="550" fill={"#9146FF"} width="200" height="600"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
</div>
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
## Other Authentication Methods
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
---
|
||||
title: "LinkedIn Authentication"
|
||||
title: "LinkedIn"
|
||||
---
|
||||
|
||||
This guide explains how to set up LinkedIn as an authentication provider with Stack Auth. LinkedIn OAuth2 allows users to sign in to your application using their LinkedIn account.
|
||||
|
||||
@ -13,6 +13,7 @@
|
||||
"bitbucket",
|
||||
"linkedin",
|
||||
"x-twitter",
|
||||
"twitch",
|
||||
"passkey",
|
||||
"two-factor-auth"
|
||||
]
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
---
|
||||
title: "Microsoft Authentication"
|
||||
title: "Microsoft"
|
||||
---
|
||||
|
||||
This guide explains how to set up Microsoft as an authentication provider with Stack Auth. Microsoft OAuth allows users to sign in to your application using their Microsoft account.
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
---
|
||||
title: "Passkey Authentication"
|
||||
title: "Passkey"
|
||||
---
|
||||
|
||||
This guide explains how to set up Passkey authentication with Stack Auth. Passkeys allow users to sign in to your application securely using biometrics, mobile devices, or security keys.
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
---
|
||||
title: "Spotify Authentication"
|
||||
title: "Spotify"
|
||||
---
|
||||
|
||||
This guide explains how to set up Spotify as an authentication provider with Stack Auth. Spotify OAuth allows users to sign in to your application using their Spotify account.
|
||||
|
||||
36
docs/templates/concepts/auth-providers/twitch.mdx
vendored
Normal file
36
docs/templates/concepts/auth-providers/twitch.mdx
vendored
Normal file
@ -0,0 +1,36 @@
|
||||
---
|
||||
title: "Twitch"
|
||||
---
|
||||
|
||||
This guide explains how to set up Twitch as an authentication provider with Stack Auth. Twitch OAuth allows users to sign in to your application using their Twitch account.
|
||||
|
||||
## Integration Steps
|
||||
|
||||
<Steps>
|
||||
<Step>
|
||||
### Create a Twitch OAuth App
|
||||
|
||||
1. Navigate to the [Twitch Developer Console](https://dev.twitch.tv/console).
|
||||
2. Log in with your Twitch account.
|
||||
3. Navigate to **Applications** and click **Register New Application**.
|
||||
4. Enter a **Name** and select a **Category**.
|
||||
5. Under **OAuth Redirect URLs**, add `https://api.stack-auth.com/api/v1/auth/oauth/callback/twitch`
|
||||
6. Click **Create**.
|
||||
7. You'll be redirected to your app's dashboard.
|
||||
8. Click **Manage** of the app you just created to view more details about your app.
|
||||
9. Click "New Secret" to generate a new secret.
|
||||
10. Copy and save the **Client ID** and **Client Secret**.
|
||||
</Step>
|
||||
<Step>
|
||||
### Enable Twitch OAuth in Stack Auth
|
||||
|
||||
1. On the Stack Auth dashboard, select **Auth Methods** in the left sidebar.
|
||||
2. Click **Add SSO Providers** and select **Twitch** as the provider.
|
||||
3. Set the **Client ID** and **Client Secret** you obtained from the Twitch Developer Console earlier.
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
### Need More Help?
|
||||
|
||||
- Check the [Twitch OAuth Documentation](https://dev.twitch.tv/docs/authentication/getting-tokens-oauth/)
|
||||
- Join our [Discord](https://discord.stack-auth.com)
|
||||
@ -1,5 +1,5 @@
|
||||
---
|
||||
title: "X (Twitter) Authentication"
|
||||
title: "X (Twitter)"
|
||||
---
|
||||
|
||||
This guide explains how to set up X (formerly Twitter) as an authentication provider with Stack Auth. X OAuth 2.0 allows users to sign in to your application using their X account.
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
export const standardProviders = ["google", "github", "microsoft", "spotify", "facebook", "discord", "gitlab", "bitbucket", "linkedin", "apple", "x"] as const;
|
||||
export const standardProviders = ["google", "github", "microsoft", "spotify", "facebook", "discord", "gitlab", "bitbucket", "linkedin", "apple", "x", "twitch"] as const;
|
||||
// No more shared providers should be added except for special cases
|
||||
export const sharedProviders = ["google", "github", "microsoft", "spotify"] as const;
|
||||
export const allProviders = standardProviders;
|
||||
|
||||
@ -1,62 +1,70 @@
|
||||
import { StackAssertionError, throwErr } from "@stackframe/stack-shared/dist/utils/errors";
|
||||
|
||||
export function Google({ iconSize } : { iconSize: number} ) {
|
||||
export function Google({ iconSize }: { iconSize: number }) {
|
||||
return (
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width={iconSize} height={iconSize} viewBox="0 0 24 24">
|
||||
<path fill="#4285F4" 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"/>
|
||||
<path fill="#34A853" 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"/>
|
||||
<path fill="#FBBC05" 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"/>
|
||||
<path fill="#EA4335" 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"/>
|
||||
<path fill="none" d="M1 1h22v22H1z" />
|
||||
<path fill="#4285F4"
|
||||
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"/>
|
||||
<path fill="#34A853"
|
||||
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"/>
|
||||
<path fill="#FBBC05"
|
||||
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"/>
|
||||
<path fill="#EA4335"
|
||||
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"/>
|
||||
<path fill="none" d="M1 1h22v22H1z"/>
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
|
||||
export function Facebook({ iconSize } : { iconSize: number} ) {
|
||||
export function Facebook({ iconSize }: { iconSize: number }) {
|
||||
return (
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width={iconSize} height={iconSize} viewBox="0 0 512 512">
|
||||
<path fill='#FFFFFF' d="M512 256C512 114.6 397.4 0 256 0S0 114.6 0 256C0 376 82.7 476.8 194.2 504.5V334.2H141.4V256h52.8V222.3c0-87.1 39.4-127.5 125-127.5c16.2 0 44.2 3.2 55.7 6.4V172c-6-.6-16.5-1-29.6-1c-42 0-58.2 15.9-58.2 57.2V256h83.6l-14.4 78.2H287V510.1C413.8 494.8 512 386.9 512 256h0z"/>
|
||||
<path fill='#FFFFFF'
|
||||
d="M512 256C512 114.6 397.4 0 256 0S0 114.6 0 256C0 376 82.7 476.8 194.2 504.5V334.2H141.4V256h52.8V222.3c0-87.1 39.4-127.5 125-127.5c16.2 0 44.2 3.2 55.7 6.4V172c-6-.6-16.5-1-29.6-1c-42 0-58.2 15.9-58.2 57.2V256h83.6l-14.4 78.2H287V510.1C413.8 494.8 512 386.9 512 256h0z"/>
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
|
||||
export function GitHub({ iconSize } : { iconSize: number} ) {
|
||||
export function GitHub({ iconSize }: { iconSize: number }) {
|
||||
return (
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width={iconSize} height={iconSize} viewBox="0 0 496 512">
|
||||
<path fill='#FFFFFF' d="M165.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3 .3-5.6-1.3-5.6-3.6 0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6zm-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6 0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5 .3-6.2 2.3zm44.2-1.7c-2.9 .7-4.9 2.6-4.6 4.9 .3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9zM244.8 8C106.1 8 0 113.3 0 252c0 110.9 69.8 205.8 169.5 239.2 12.8 2.3 17.3-5.6 17.3-12.1 0-6.2-.3-40.4-.3-61.4 0 0-70 15-84.7-29.8 0 0-11.4-29.1-27.8-36.6 0 0-22.9-15.7 1.6-15.4 0 0 24.9 2 38.6 25.8 21.9 38.6 58.6 27.5 72.9 20.9 2.3-16 8.8-27.1 16-33.7-55.9-6.2-112.3-14.3-112.3-110.5 0-27.5 7.6-41.3 23.6-58.9-2.6-6.5-11.1-33.3 2.6-67.9 20.9-6.5 69 27 69 27 20-5.6 41.5-8.5 62.8-8.5s42.8 2.9 62.8 8.5c0 0 48.1-33.6 69-27 13.7 34.7 5.2 61.4 2.6 67.9 16 17.7 25.8 31.5 25.8 58.9 0 96.5-58.9 104.2-114.8 110.5 9.2 7.9 17 22.9 17 46.4 0 33.7-.3 75.4-.3 83.6 0 6.5 4.6 14.4 17.3 12.1C428.2 457.8 496 362.9 496 252 496 113.3 383.5 8 244.8 8zM97.2 352.9c-1.3 1-1 3.3 .7 5.2 1.6 1.6 3.9 2.3 5.2 1 1.3-1 1-3.3-.7-5.2-1.6-1.6-3.9-2.3-5.2-1zm-10.8-8.1c-.7 1.3 .3 2.9 2.3 3.9 1.6 1 3.6 .7 4.3-.7 .7-1.3-.3-2.9-2.3-3.9-2-.6-3.6-.3-4.3 .7zm32.4 35.6c-1.6 1.3-1 4.3 1.3 6.2 2.3 2.3 5.2 2.6 6.5 1 1.3-1.3 .7-4.3-1.3-6.2-2.2-2.3-5.2-2.6-6.5-1zm-11.4-14.7c-1.6 1-1.6 3.6 0 5.9 1.6 2.3 4.3 3.3 5.6 2.3 1.6-1.3 1.6-3.9 0-6.2-1.4-2.3-4-3.3-5.6-2z"/>
|
||||
<path fill='#FFFFFF'
|
||||
d="M165.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3 .3-5.6-1.3-5.6-3.6 0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6zm-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6 0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5 .3-6.2 2.3zm44.2-1.7c-2.9 .7-4.9 2.6-4.6 4.9 .3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9zM244.8 8C106.1 8 0 113.3 0 252c0 110.9 69.8 205.8 169.5 239.2 12.8 2.3 17.3-5.6 17.3-12.1 0-6.2-.3-40.4-.3-61.4 0 0-70 15-84.7-29.8 0 0-11.4-29.1-27.8-36.6 0 0-22.9-15.7 1.6-15.4 0 0 24.9 2 38.6 25.8 21.9 38.6 58.6 27.5 72.9 20.9 2.3-16 8.8-27.1 16-33.7-55.9-6.2-112.3-14.3-112.3-110.5 0-27.5 7.6-41.3 23.6-58.9-2.6-6.5-11.1-33.3 2.6-67.9 20.9-6.5 69 27 69 27 20-5.6 41.5-8.5 62.8-8.5s42.8 2.9 62.8 8.5c0 0 48.1-33.6 69-27 13.7 34.7 5.2 61.4 2.6 67.9 16 17.7 25.8 31.5 25.8 58.9 0 96.5-58.9 104.2-114.8 110.5 9.2 7.9 17 22.9 17 46.4 0 33.7-.3 75.4-.3 83.6 0 6.5 4.6 14.4 17.3 12.1C428.2 457.8 496 362.9 496 252 496 113.3 383.5 8 244.8 8zM97.2 352.9c-1.3 1-1 3.3 .7 5.2 1.6 1.6 3.9 2.3 5.2 1 1.3-1 1-3.3-.7-5.2-1.6-1.6-3.9-2.3-5.2-1zm-10.8-8.1c-.7 1.3 .3 2.9 2.3 3.9 1.6 1 3.6 .7 4.3-.7 .7-1.3-.3-2.9-2.3-3.9-2-.6-3.6-.3-4.3 .7zm32.4 35.6c-1.6 1.3-1 4.3 1.3 6.2 2.3 2.3 5.2 2.6 6.5 1 1.3-1.3 .7-4.3-1.3-6.2-2.2-2.3-5.2-2.6-6.5-1zm-11.4-14.7c-1.6 1-1.6 3.6 0 5.9 1.6 2.3 4.3 3.3 5.6 2.3 1.6-1.3 1.6-3.9 0-6.2-1.4-2.3-4-3.3-5.6-2z"/>
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
|
||||
export function Microsoft({ iconSize } : { iconSize: number} ) {
|
||||
export function Microsoft({ iconSize }: { iconSize: number }) {
|
||||
return (
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width={iconSize} height={iconSize} viewBox="0 0 21 21">
|
||||
<title>{"MS-SymbolLockup"}</title>
|
||||
<path fill="#f25022" d="M1 1h9v9H1z" />
|
||||
<path fill="#00a4ef" d="M1 11h9v9H1z" />
|
||||
<path fill="#7fba00" d="M11 1h9v9h-9z" />
|
||||
<path fill="#ffb900" d="M11 11h9v9h-9z" />
|
||||
<path fill="#f25022" d="M1 1h9v9H1z"/>
|
||||
<path fill="#00a4ef" d="M1 11h9v9H1z"/>
|
||||
<path fill="#7fba00" d="M11 1h9v9h-9z"/>
|
||||
<path fill="#ffb900" d="M11 11h9v9h-9z"/>
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
|
||||
export function Spotify({ iconSize } : { iconSize: number} ) {
|
||||
export function Spotify({ iconSize }: { iconSize: number }) {
|
||||
return (
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width={iconSize} height={iconSize} viewBox="0 0 496 512">
|
||||
<path fill='#ffffff' d="M248 8C111.1 8 0 119.1 0 256s111.1 248 248 248 248-111.1 248-248S384.9 8 248 8zm100.7 364.9c-4.2 0-6.8-1.3-10.7-3.6-62.4-37.6-135-39.2-206.7-24.5-3.9 1-9 2.6-11.9 2.6-9.7 0-15.8-7.7-15.8-15.8 0-10.3 6.1-15.2 13.6-16.8 81.9-18.1 165.6-16.5 237 26.2 6.1 3.9 9.7 7.4 9.7 16.5s-7.1 15.4-15.2 15.4zm26.9-65.6c-5.2 0-8.7-2.3-12.3-4.2-62.5-37-155.7-51.9-238.6-29.4-4.8 1.3-7.4 2.6-11.9 2.6-10.7 0-19.4-8.7-19.4-19.4s5.2-17.8 15.5-20.7c27.8-7.8 56.2-13.6 97.8-13.6 64.9 0 127.6 16.1 177 45.5 8.1 4.8 11.3 11 11.3 19.7-.1 10.8-8.5 19.5-19.4 19.5zm31-76.2c-5.2 0-8.4-1.3-12.9-3.9-71.2-42.5-198.5-52.7-280.9-29.7-3.6 1-8.1 2.6-12.9 2.6-13.2 0-23.3-10.3-23.3-23.6 0-13.6 8.4-21.3 17.4-23.9 35.2-10.3 74.6-15.2 117.5-15.2 73 0 149.5 15.2 205.4 47.8 7.8 4.5 12.9 10.7 12.9 22.6 0 13.6-11 23.3-23.2 23.3z"/>
|
||||
<path fill='#ffffff'
|
||||
d="M248 8C111.1 8 0 119.1 0 256s111.1 248 248 248 248-111.1 248-248S384.9 8 248 8zm100.7 364.9c-4.2 0-6.8-1.3-10.7-3.6-62.4-37.6-135-39.2-206.7-24.5-3.9 1-9 2.6-11.9 2.6-9.7 0-15.8-7.7-15.8-15.8 0-10.3 6.1-15.2 13.6-16.8 81.9-18.1 165.6-16.5 237 26.2 6.1 3.9 9.7 7.4 9.7 16.5s-7.1 15.4-15.2 15.4zm26.9-65.6c-5.2 0-8.7-2.3-12.3-4.2-62.5-37-155.7-51.9-238.6-29.4-4.8 1.3-7.4 2.6-11.9 2.6-10.7 0-19.4-8.7-19.4-19.4s5.2-17.8 15.5-20.7c27.8-7.8 56.2-13.6 97.8-13.6 64.9 0 127.6 16.1 177 45.5 8.1 4.8 11.3 11 11.3 19.7-.1 10.8-8.5 19.5-19.4 19.5zm31-76.2c-5.2 0-8.4-1.3-12.9-3.9-71.2-42.5-198.5-52.7-280.9-29.7-3.6 1-8.1 2.6-12.9 2.6-13.2 0-23.3-10.3-23.3-23.6 0-13.6 8.4-21.3 17.4-23.9 35.2-10.3 74.6-15.2 117.5-15.2 73 0 149.5 15.2 205.4 47.8 7.8 4.5 12.9 10.7 12.9 22.6 0 13.6-11 23.3-23.2 23.3z"/>
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
|
||||
export function Discord({ iconSize } : { iconSize: number} ) {
|
||||
export function Discord({ iconSize }: { iconSize: number }) {
|
||||
return (
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width={iconSize} height={iconSize} viewBox="0 0 127.14 96.36">
|
||||
<path fill="#fff" d="M107.7,8.07A105.15,105.15,0,0,0,81.47,0a72.06,72.06,0,0,0-3.36,6.83A97.68,97.68,0,0,0,49,6.83,72.37,72.37,0,0,0,45.64,0,105.89,105.89,0,0,0,19.39,8.09C2.79,32.65-1.71,56.6.54,80.21h0A105.73,105.73,0,0,0,32.71,96.36,77.7,77.7,0,0,0,39.6,85.25a68.42,68.42,0,0,1-10.85-5.18c.91-.66,1.8-1.34,2.66-2a75.57,75.57,0,0,0,64.32,0c.87.71,1.76,1.39,2.66,2a68.68,68.68,0,0,1-10.87,5.19,77,77,0,0,0,6.89,11.1A105.25,105.25,0,0,0,126.6,80.22h0C129.24,52.84,122.09,29.11,107.7,8.07ZM42.45,65.69C36.18,65.69,31,60,31,53s5-12.74,11.43-12.74S54,46,53.89,53,48.84,65.69,42.45,65.69Zm42.24,0C78.41,65.69,73.25,60,73.25,53s5-12.74,11.44-12.74S96.23,46,96.12,53,91.08,65.69,84.69,65.69Z"/>
|
||||
<path fill="#fff"
|
||||
d="M107.7,8.07A105.15,105.15,0,0,0,81.47,0a72.06,72.06,0,0,0-3.36,6.83A97.68,97.68,0,0,0,49,6.83,72.37,72.37,0,0,0,45.64,0,105.89,105.89,0,0,0,19.39,8.09C2.79,32.65-1.71,56.6.54,80.21h0A105.73,105.73,0,0,0,32.71,96.36,77.7,77.7,0,0,0,39.6,85.25a68.42,68.42,0,0,1-10.85-5.18c.91-.66,1.8-1.34,2.66-2a75.57,75.57,0,0,0,64.32,0c.87.71,1.76,1.39,2.66,2a68.68,68.68,0,0,1-10.87,5.19,77,77,0,0,0,6.89,11.1A105.25,105.25,0,0,0,126.6,80.22h0C129.24,52.84,122.09,29.11,107.7,8.07ZM42.45,65.69C36.18,65.69,31,60,31,53s5-12.74,11.43-12.74S54,46,53.89,53,48.84,65.69,42.45,65.69Zm42.24,0C78.41,65.69,73.25,60,73.25,53s5-12.74,11.44-12.74S96.23,46,96.12,53,91.08,65.69,84.69,65.69Z"/>
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
|
||||
export function Gitlab({ iconSize } : { iconSize: number} ) {
|
||||
export function Gitlab({ iconSize }: { iconSize: number }) {
|
||||
return (
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
@ -67,13 +75,27 @@ export function Gitlab({ iconSize } : { iconSize: number} ) {
|
||||
preserveAspectRatio="xMidYMid"
|
||||
>
|
||||
<g>
|
||||
<path d="M128.07485,236.074667 L128.07485,236.074667 L175.17885,91.1043048 L80.9708495,91.1043048 L128.07485,236.074667 L128.07485,236.074667 Z" fill="#E24329"></path>
|
||||
<path d="M128.07485,236.074423 L80.9708495,91.104061 L14.9557638,91.104061 L128.07485,236.074423 L128.07485,236.074423 Z" fill="#FC6D26"></path>
|
||||
<path d="M14.9558857,91.1044267 L14.9558857,91.1044267 L0.641828571,135.159589 C-0.663771429,139.17757 0.766171429,143.57955 4.18438095,146.06275 L128.074971,236.074789 L14.9558857,91.1044267 L14.9558857,91.1044267 Z" fill="#FCA326"></path>
|
||||
<path d="M14.9558857,91.1045486 L80.9709714,91.1045486 L52.6000762,3.79026286 C51.1408762,-0.703146667 44.7847619,-0.701927619 43.3255619,3.79026286 L14.9558857,91.1045486 L14.9558857,91.1045486 Z" fill="#E24329"></path>
|
||||
<path d="M128.07485,236.074423 L175.17885,91.104061 L241.193935,91.104061 L128.07485,236.074423 L128.07485,236.074423 Z" fill="#FC6D26"></path>
|
||||
<path d="M241.193935,91.1044267 L241.193935,91.1044267 L255.507992,135.159589 C256.813592,139.17757 255.38365,143.57955 251.96544,146.06275 L128.07485,236.074789 L241.193935,91.1044267 L241.193935,91.1044267 Z" fill="#FCA326"></path>
|
||||
<path d="M241.193935,91.1045486 L175.17885,91.1045486 L203.549745,3.79026286 C205.008945,-0.703146667 211.365059,-0.701927619 212.824259,3.79026286 L241.193935,91.1045486 L241.193935,91.1045486 Z" fill="#E24329"></path>
|
||||
<path
|
||||
d="M128.07485,236.074667 L128.07485,236.074667 L175.17885,91.1043048 L80.9708495,91.1043048 L128.07485,236.074667 L128.07485,236.074667 Z"
|
||||
fill="#E24329"></path>
|
||||
<path
|
||||
d="M128.07485,236.074423 L80.9708495,91.104061 L14.9557638,91.104061 L128.07485,236.074423 L128.07485,236.074423 Z"
|
||||
fill="#FC6D26"></path>
|
||||
<path
|
||||
d="M14.9558857,91.1044267 L14.9558857,91.1044267 L0.641828571,135.159589 C-0.663771429,139.17757 0.766171429,143.57955 4.18438095,146.06275 L128.074971,236.074789 L14.9558857,91.1044267 L14.9558857,91.1044267 Z"
|
||||
fill="#FCA326"></path>
|
||||
<path
|
||||
d="M14.9558857,91.1045486 L80.9709714,91.1045486 L52.6000762,3.79026286 C51.1408762,-0.703146667 44.7847619,-0.701927619 43.3255619,3.79026286 L14.9558857,91.1045486 L14.9558857,91.1045486 Z"
|
||||
fill="#E24329"></path>
|
||||
<path
|
||||
d="M128.07485,236.074423 L175.17885,91.104061 L241.193935,91.104061 L128.07485,236.074423 L128.07485,236.074423 Z"
|
||||
fill="#FC6D26"></path>
|
||||
<path
|
||||
d="M241.193935,91.1044267 L241.193935,91.1044267 L255.507992,135.159589 C256.813592,139.17757 255.38365,143.57955 251.96544,146.06275 L128.07485,236.074789 L241.193935,91.1044267 L241.193935,91.1044267 Z"
|
||||
fill="#FCA326"></path>
|
||||
<path
|
||||
d="M241.193935,91.1045486 L175.17885,91.1045486 L203.549745,3.79026286 C205.008945,-0.703146667 211.365059,-0.701927619 212.824259,3.79026286 L241.193935,91.1045486 L241.193935,91.1045486 Z"
|
||||
fill="#E24329"></path>
|
||||
</g>
|
||||
</svg>
|
||||
);
|
||||
@ -95,19 +117,23 @@ export function Bitbucket({ iconSize }: { iconSize: number }) {
|
||||
y1="13.818%"
|
||||
y2="78.776%"
|
||||
>
|
||||
<stop offset=".18" stopColor="#0052cc" />
|
||||
<stop offset="1" stopColor="#2684ff" />
|
||||
<stop offset=".18" stopColor="#0052cc"/>
|
||||
<stop offset="1" stopColor="#2684ff"/>
|
||||
</linearGradient>
|
||||
<g fill="none">
|
||||
<path d="M101.272 152.561h53.449l12.901-75.32H87.06z" />
|
||||
<path d="M8.308 0A8.202 8.202 0 0 0 .106 9.516l34.819 211.373a11.155 11.155 0 0 0 10.909 9.31h167.04a8.202 8.202 0 0 0 8.201-6.89l34.82-213.752a8.202 8.202 0 0 0-8.203-9.514zm146.616 152.768h-53.315l-14.436-75.42h80.67z" fill="#2684ff"/>
|
||||
<path d="M244.61 77.242h-76.916l-12.909 75.36h-53.272l-62.902 74.663a11.105 11.105 0 0 0 7.171 2.704H212.73a8.196 8.196 0 0 0 8.196-6.884z" fill="url(#a)"/>
|
||||
<path d="M101.272 152.561h53.449l12.901-75.32H87.06z"/>
|
||||
<path
|
||||
d="M8.308 0A8.202 8.202 0 0 0 .106 9.516l34.819 211.373a11.155 11.155 0 0 0 10.909 9.31h167.04a8.202 8.202 0 0 0 8.201-6.89l34.82-213.752a8.202 8.202 0 0 0-8.203-9.514zm146.616 152.768h-53.315l-14.436-75.42h80.67z"
|
||||
fill="#2684ff"/>
|
||||
<path
|
||||
d="M244.61 77.242h-76.916l-12.909 75.36h-53.272l-62.902 74.663a11.105 11.105 0 0 0 7.171 2.704H212.73a8.196 8.196 0 0 0 8.196-6.884z"
|
||||
fill="url(#a)"/>
|
||||
</g>
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
|
||||
export function LinkedIn({ iconSize } : { iconSize: number} ) {
|
||||
export function LinkedIn({ iconSize }: { iconSize: number }) {
|
||||
return (
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
@ -117,27 +143,54 @@ export function LinkedIn({ iconSize } : { iconSize: number} ) {
|
||||
viewBox="0 0 310 310"
|
||||
>
|
||||
<g id="XMLID_801_">
|
||||
<path id="XMLID_802_" d="M72.16,99.73H9.927c-2.762,0-5,2.239-5,5v199.928c0,2.762,2.238,5,5,5H72.16c2.762,0,5-2.238,5-5V104.73 C77.16,101.969,74.922,99.73,72.16,99.73z" />
|
||||
<path id="XMLID_803_" d="M41.066,0.341C18.422,0.341,0,18.743,0,41.362C0,63.991,18.422,82.4,41.066,82.4 c22.626,0,41.033-18.41,41.033-41.038C82.1,18.743,63.692,0.341,41.066,0.341z" />
|
||||
<path id="XMLID_804_" d="M230.454,94.761c-24.995,0-43.472,10.745-54.679,22.954V104.73c0-2.761-2.238-5-5-5h-59.599 c-2.762,0-5,2.239-5,5v199.928c0,2.762,2.238,5,5,5h62.097c2.762,0,5-2.238,5-5v-98.918c0-33.333,9.054-46.319,32.29-46.319 c25.306,0,27.317,20.818,27.317,48.034v97.204c0,2.762,2.238,5,5,5H305c2.762,0,5-2.238,5-5V194.995 C310,145.43,300.549,94.761,230.454,94.761z" />
|
||||
<path id="XMLID_802_"
|
||||
d="M72.16,99.73H9.927c-2.762,0-5,2.239-5,5v199.928c0,2.762,2.238,5,5,5H72.16c2.762,0,5-2.238,5-5V104.73 C77.16,101.969,74.922,99.73,72.16,99.73z"/>
|
||||
<path id="XMLID_803_"
|
||||
d="M41.066,0.341C18.422,0.341,0,18.743,0,41.362C0,63.991,18.422,82.4,41.066,82.4 c22.626,0,41.033-18.41,41.033-41.038C82.1,18.743,63.692,0.341,41.066,0.341z"/>
|
||||
<path id="XMLID_804_"
|
||||
d="M230.454,94.761c-24.995,0-43.472,10.745-54.679,22.954V104.73c0-2.761-2.238-5-5-5h-59.599 c-2.762,0-5,2.239-5,5v199.928c0,2.762,2.238,5,5,5h62.097c2.762,0,5-2.238,5-5v-98.918c0-33.333,9.054-46.319,32.29-46.319 c25.306,0,27.317,20.818,27.317,48.034v97.204c0,2.762,2.238,5,5,5H305c2.762,0,5-2.238,5-5V194.995 C310,145.43,300.549,94.761,230.454,94.761z"/>
|
||||
</g>
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
|
||||
export function Apple({ iconSize } : { iconSize: number} ) {
|
||||
export function Apple({ iconSize }: { iconSize: number }) {
|
||||
return (
|
||||
<svg fill="#fff" height={iconSize} width={iconSize} version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 22.773 22.773">
|
||||
<path d="M15.769,0c0.053,0,0.106,0,0.162,0c0.13,1.606-0.483,2.806-1.228,3.675c-0.731,0.863-1.732,1.7-3.351,1.573c-0.108-1.583,0.506-2.694,1.25-3.561C13.292,0.879,14.557,0.16,15.769,0z"/>
|
||||
<path d="M20.67,16.716c0,0.016,0,0.03,0,0.045c-0.455,1.378-1.104,2.559-1.896,3.655c-0.723,0.995-1.609,2.334-3.191,2.334c-1.367,0-2.275-0.879-3.676-0.903c-1.482-0.024-2.297,0.735-3.652,0.926c-0.155,0-0.31,0-0.462,0c-0.995-0.144-1.798-0.932-2.383-1.642c-1.725-2.098-3.058-4.808-3.306-8.276c0-0.34,0-0.679,0-1.019c0.105-2.482,1.311-4.5,2.914-5.478c0.846-0.52,2.009-0.963,3.304-0.765c0.555,0.086,1.122,0.276,1.619,0.464c0.471,0.181,1.06,0.502,1.618,0.485c0.378-0.011,0.754-0.208,1.135-0.347c1.116-0.403,2.21-0.865,3.652-0.648c1.733,0.262,2.963,1.032,3.723,2.22c-1.466,0.933-2.625,2.339-2.427,4.74C17.818,14.688,19.086,15.964,20.67,16.716z"/>
|
||||
<svg fill="#fff" height={iconSize} width={iconSize} version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 22.773 22.773">
|
||||
<path
|
||||
d="M15.769,0c0.053,0,0.106,0,0.162,0c0.13,1.606-0.483,2.806-1.228,3.675c-0.731,0.863-1.732,1.7-3.351,1.573c-0.108-1.583,0.506-2.694,1.25-3.561C13.292,0.879,14.557,0.16,15.769,0z"/>
|
||||
<path
|
||||
d="M20.67,16.716c0,0.016,0,0.03,0,0.045c-0.455,1.378-1.104,2.559-1.896,3.655c-0.723,0.995-1.609,2.334-3.191,2.334c-1.367,0-2.275-0.879-3.676-0.903c-1.482-0.024-2.297,0.735-3.652,0.926c-0.155,0-0.31,0-0.462,0c-0.995-0.144-1.798-0.932-2.383-1.642c-1.725-2.098-3.058-4.808-3.306-8.276c0-0.34,0-0.679,0-1.019c0.105-2.482,1.311-4.5,2.914-5.478c0.846-0.52,2.009-0.963,3.304-0.765c0.555,0.086,1.122,0.276,1.619,0.464c0.471,0.181,1.06,0.502,1.618,0.485c0.378-0.011,0.754-0.208,1.135-0.347c1.116-0.403,2.21-0.865,3.652-0.648c1.733,0.262,2.963,1.032,3.723,2.22c-1.466,0.933-2.625,2.339-2.427,4.74C17.818,14.688,19.086,15.964,20.67,16.716z"/>
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
|
||||
export function X({ iconSize } : { iconSize: number} ) {
|
||||
export function X({ iconSize }: { iconSize: number }) {
|
||||
return (
|
||||
<svg aria-label="X" viewBox="0 0 1200 1227" width={iconSize} height={iconSize} xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill="#FFFFFF" d="M714.163 519.284L1160.89 0H1055.03L667.137 450.887L357.328 0H0L468.492 681.821L0 1226.37H105.866L515.491 750.218L842.672 1226.37H1200L714.137 519.284H714.163ZM569.165 687.828L521.697 619.934L144.011 79.6944H306.615L611.412 515.685L658.88 583.579L1055.08 1150.3H892.476L569.165 687.854V687.828Z"/>
|
||||
<svg aria-label="X" viewBox="0 0 1200 1227" width={iconSize} height={iconSize}
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill="#FFFFFF"
|
||||
d="M714.163 519.284L1160.89 0H1055.03L667.137 450.887L357.328 0H0L468.492 681.821L0 1226.37H105.866L515.491 750.218L842.672 1226.37H1200L714.137 519.284H714.163ZM569.165 687.828L521.697 619.934L144.011 79.6944H306.615L611.412 515.685L658.88 583.579L1055.08 1150.3H892.476L569.165 687.854V687.828Z"/>
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
|
||||
export function Twitch({ iconSize }: { iconSize: number }) {
|
||||
return (
|
||||
<svg aria-label="Twitch" viewBox="0 0 2400 2800" width={iconSize} height={iconSize}
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<g>
|
||||
<polygon fill={"#FFFFFF"}
|
||||
points="2200,1300 1800,1700 1400,1700 1050,2050 1050,1700 600,1700 600,200 2200,200"/>
|
||||
<g>
|
||||
<g id="Layer_1-2">
|
||||
<path fill={"#9146FF"} d="M500,0L0,500v1800h600v500l500-500h400l900-900V0H500z M2200,1300l-400,400h-400l-350,350v-350H600V200h1600 V1300z"/>
|
||||
<rect x="1700" y="550" fill={"#9146FF"} width="200" height="600"/>
|
||||
<rect x="1150" y="550" fill={"#9146FF"} width="200" height="600"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
@ -146,42 +199,45 @@ export function Mapping({
|
||||
provider,
|
||||
iconSize,
|
||||
}: {
|
||||
provider: string,
|
||||
iconSize: number,
|
||||
provider: string,
|
||||
iconSize: number,
|
||||
}) {
|
||||
switch (provider) {
|
||||
case "google": {
|
||||
return <Google iconSize={iconSize} />;
|
||||
return <Google iconSize={iconSize}/>;
|
||||
}
|
||||
case "github": {
|
||||
return <GitHub iconSize={iconSize} />;
|
||||
return <GitHub iconSize={iconSize}/>;
|
||||
}
|
||||
case "facebook": {
|
||||
return <Facebook iconSize={iconSize} />;
|
||||
return <Facebook iconSize={iconSize}/>;
|
||||
}
|
||||
case "microsoft": {
|
||||
return <Microsoft iconSize={iconSize} />;
|
||||
return <Microsoft iconSize={iconSize}/>;
|
||||
}
|
||||
case "spotify": {
|
||||
return <Spotify iconSize={iconSize} />;
|
||||
return <Spotify iconSize={iconSize}/>;
|
||||
}
|
||||
case "discord": {
|
||||
return <Discord iconSize={iconSize} />;
|
||||
return <Discord iconSize={iconSize}/>;
|
||||
}
|
||||
case "gitlab": {
|
||||
return <Gitlab iconSize={iconSize} />;
|
||||
return <Gitlab iconSize={iconSize}/>;
|
||||
}
|
||||
case "bitbucket": {
|
||||
return <Bitbucket iconSize={iconSize} />;
|
||||
return <Bitbucket iconSize={iconSize}/>;
|
||||
}
|
||||
case "linkedin": {
|
||||
return <LinkedIn iconSize={iconSize} />;
|
||||
return <LinkedIn iconSize={iconSize}/>;
|
||||
}
|
||||
case "apple": {
|
||||
return <Apple iconSize={iconSize} />;
|
||||
return <Apple iconSize={iconSize}/>;
|
||||
}
|
||||
case "x": {
|
||||
return <X iconSize={iconSize} />;
|
||||
return <X iconSize={iconSize}/>;
|
||||
}
|
||||
case "twitch": {
|
||||
return <Twitch iconSize={iconSize}/>;
|
||||
}
|
||||
default: {
|
||||
throw new StackAssertionError(`Icon not found for provider: ${provider}`);
|
||||
@ -202,6 +258,7 @@ export function toTitle(id: string) {
|
||||
bitbucket: "Bitbucket",
|
||||
linkedin: "LinkedIn",
|
||||
x: "X",
|
||||
twitch: "Twitch"
|
||||
}[id] || throwErr(`Unknown provider: ${id}`);
|
||||
}
|
||||
|
||||
@ -215,4 +272,5 @@ export const BRAND_COLORS: Record<string, string> = {
|
||||
linkedin: '#0A66C2',
|
||||
x: '#000000',
|
||||
apple: '#000000',
|
||||
twitch: '#ffffff'
|
||||
};
|
||||
|
||||
@ -147,6 +147,15 @@ export function OAuthButton({
|
||||
};
|
||||
break;
|
||||
}
|
||||
case 'twitch': {
|
||||
style = {
|
||||
backgroundColor: "#6441a5",
|
||||
textColor: "#fff",
|
||||
name: "Twitch",
|
||||
icon: <BrandIcons.Twitch iconSize={iconSize} />,
|
||||
};
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
style = {
|
||||
name: provider,
|
||||
|
||||
Loading…
Reference in New Issue
Block a user