Files
sso-portal/app/theme.ts
zhangheng 37f10118d3 chore: initial commit of sso-mock SSO login service
Next.js + Mantine mock SSO service providing account/password, phone
verify-code, and Feishu QR login. Issues a one-time sso_code that the
external app exchanges for user info.

Includes:
- Feishu callback fix: guard against duplicate/concurrent /api/login
  submissions of the same single-use authorization code (feishuLogin
  once-guard + memoized onLoginSuccess to stop effect re-fire).
- ADAPTATION_GUIDE.md: how to switch from the in-memory code store to
  the real backend auth/index + inner_get_user_info endpoints.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-06 18:09:30 +08:00

177 lines
3.9 KiB
TypeScript

'use client'
import {
createTheme,
Input,
MantineColorsTuple,
type MantineTheme,
} from '@mantine/core'
export const logoBlue = '#0080FF'
export const logoBlueHover = '#006EE6'
const brandColors: MantineColorsTuple = [
'#EAF4FF',
'#D9EBFF',
'#B6D8FF',
'#8EC2FF',
'#63AAFF',
'#3393FF',
logoBlue,
logoBlueHover,
'#005FC6',
'#004897',
]
const greyColors: MantineColorsTuple = [
'#FFFFFF',
'#F7F8F9',
'#F1F2F4',
'#DCDFE4',
'#B5BBC2',
'#8F979F',
'#5D6872',
'#47535F',
'#1B2A38',
'#0F151B',
]
const darkColors: MantineColorsTuple = [
'#FFFFFF',
'#EBEEF7',
'#D3D4D8',
'#7E858F',
'#3C4859',
'#2B3648',
'#212A39',
'#1A222D',
'#151C24',
'#0D0E12',
]
const successColors: MantineColorsTuple = [
'#E6FCF5',
'#C3FAE8',
'#96F2D7',
'#5BE7B6',
'#38D9A9',
'#20C997',
'#0EA879',
'#07815B',
'#076B3F',
'#043E22',
]
export const theme = createTheme({
primaryColor: 'brand',
cursorType: 'pointer',
colors: {
brand: brandColors,
success: successColors,
grey: greyColors,
dark: darkColors,
},
defaultRadius: 'md',
radius: {
xs: '2px',
sm: '4px',
md: '8px',
lg: '12px',
xl: '16px',
xxl: '24px',
},
fontFamily:
'-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif',
fontSizes: {
xs: '0.75rem',
sm: '0.875rem',
md: '1rem',
lg: '1.125rem',
xl: '1.25rem',
xxl: '1.5rem',
},
headings: {
fontFamily:
'-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif',
fontWeight: '700',
sizes: {
h1: { fontSize: '2.25rem', lineHeight: '1.2' },
h2: { fontSize: '1.875rem', lineHeight: '1.3' },
h3: { fontSize: '1.5rem', lineHeight: '1.35' },
h4: { fontSize: '1.25rem', lineHeight: '1.4' },
h5: { fontSize: '1.125rem', lineHeight: '1.45' },
h6: { fontSize: '1rem', lineHeight: '1.5' },
},
},
spacing: {
xs: '8px',
sm: '12px',
md: '16px',
lg: '24px',
xl: '32px',
xxl: '48px',
},
shadows: {
xs: '0 1px 2px 0 rgba(0, 0, 0, 0.05)',
sm: '0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px 0 rgba(0, 0, 0, 0.06)',
md: '0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06)',
lg: '0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05)',
xl: '0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04)',
},
breakpoints: {
xs: '36em',
sm: '48em',
md: '62em',
lg: '75em',
xl: '88em',
},
defaultGradient: {
from: 'brand',
to: 'success',
deg: 45,
},
components: {
Button: {
styles: (_theme: MantineTheme, props: Record<string, unknown>) => {
const variant = props.variant
if (variant === 'page-ghost') {
return {
root: {
outline: 'none',
height: 30,
borderRadius: 4,
border: '1px solid rgba(71, 81, 105, 0.2)',
backgroundColor: '#FFFFFF',
color: '#1D2129',
paddingInline: 16,
'&:hover': { backgroundColor: '#F7F8FA' },
},
label: { fontSize: 12, lineHeight: '18px', fontWeight: 400 },
}
}
if (variant === 'page-primary') {
return {
root: {
outline: 'none',
height: 30,
borderRadius: 4,
border: 'none',
backgroundColor: logoBlue,
color: '#FFFFFF',
paddingInline: 16,
'&:hover': { backgroundColor: logoBlueHover },
},
label: { fontSize: 12, lineHeight: '18px', fontWeight: 500 },
}
}
return { root: { outline: 'none' } }
},
},
InputWrapper: Input.Wrapper.extend({
defaultProps: {
inputWrapperOrder: ['label', 'input', 'description', 'error'],
},
}),
},
})