diff --git a/src/components/Hero.tsx b/src/components/Hero.tsx index fdd8573..22448ed 100644 --- a/src/components/Hero.tsx +++ b/src/components/Hero.tsx @@ -1,8 +1,8 @@ -import { Box, Typography, Grid, useMediaQuery, Link } from '@mui/material'; +import { Box, Typography, Grid, useMediaQuery } from '@mui/material'; import Image from 'next/image'; import React from 'react'; -import { GradientBorderDivider } from '@components'; +import { GradientBorderDivider, LinkButton } from '@components'; import theme from '../theme'; import { LandingPageResponse } from '../utils/types'; @@ -60,21 +60,12 @@ export const Hero: React.FC = ({ title, subtitle, images }) => { > {subtitle} - Join our Slack - + diff --git a/src/components/LinkButton.tsx b/src/components/LinkButton.tsx index e50d6c5..aa2a256 100644 --- a/src/components/LinkButton.tsx +++ b/src/components/LinkButton.tsx @@ -1,22 +1,71 @@ -import { Button } from '@mui/material'; +import { Button, type SxProps, type Theme } from '@mui/material'; import Link from 'next/link'; import React from 'react'; type LinkButtonProps = { href: string; reversed?: boolean; + outlined?: boolean; small?: boolean; children: React.ReactNode; }; +const pillRadius = '100px'; + export const LinkButton = ({ href, reversed, + outlined, small, children, }: LinkButtonProps) => { const isExternal = href.startsWith('https'); + const padding = small ? '7px 16px' : '10px 32px'; + + if (outlined) { + const outlinedPadding = small ? '7px 16px' : '10px 24px'; + const outlinedSx: SxProps = (theme) => ({ + ...(small + ? theme.typography.outlineButtonSmall + : theme.typography.outlineButton), + borderRadius: pillRadius, + padding: outlinedPadding, + minHeight: small ? undefined : '40px', + borderColor: theme.palette.custom.outline, + color: 'primary.main', + boxShadow: 'none', + '&:hover': { + borderColor: theme.palette.custom.outline, + backgroundColor: 'primary.light', + boxShadow: 'none', + }, + }); + + if (isExternal) { + return ( + + ); + } + + return ( + + + + ); + } + if (isExternal) { return ( @@ -45,16 +94,15 @@ export const LinkButton = ({ diff --git a/src/components/__tests__/LinkButton.test.tsx b/src/components/__tests__/LinkButton.test.tsx index b7970ad..7d97d66 100644 --- a/src/components/__tests__/LinkButton.test.tsx +++ b/src/components/__tests__/LinkButton.test.tsx @@ -1,11 +1,17 @@ +import { ThemeProvider } from '@mui/material'; import { render, screen } from '@testing-library/react'; import React from 'react'; +import theme from 'theme'; + import { LinkButton } from '../LinkButton'; +const renderWithTheme = (ui: React.ReactElement) => + render({ui}); + describe('LinkButton', () => { it('renders an internal link using Next.js Link', () => { - render(Internal Link); + renderWithTheme(Internal Link); const button = screen.getByRole('link', { name: /internal link/i }); expect(button).toBeInTheDocument(); expect(button.closest('a')).toHaveAttribute('href', '/internal'); @@ -22,4 +28,15 @@ describe('LinkButton', () => { expect(button.closest('a')).toHaveAttribute('target', '_blank'); expect(button.closest('a')).toHaveAttribute('rel', 'noopener noreferrer'); }); + + it('renders an outlined external link', () => { + renderWithTheme( + + Outlined External + , + ); + const link = screen.getByRole('link', { name: /outlined external/i }); + expect(link).toBeInTheDocument(); + expect(link.closest('a')).toHaveAttribute('href', 'https://external.com'); + }); }); diff --git a/src/pages/mentorship/index.tsx b/src/pages/mentorship/index.tsx index 7a9f211..0488e71 100644 --- a/src/pages/mentorship/index.tsx +++ b/src/pages/mentorship/index.tsx @@ -165,11 +165,11 @@ const FeedbackSection: React.FC = ({ } variant="outlined" data-testid="feedback-show-more" - sx={{ + sx={(t) => ({ borderRadius: '20px', - border: '1px solid #71787E', - color: '#1A4B66', - }} + border: `1px solid ${t.palette.custom.outline}`, + color: t.palette.custom.linkBlue, + })} > {feedbacksDisplayed >= feedbacks.length ? '- Show less' diff --git a/src/theme.ts b/src/theme.ts index 9265786..857046d 100644 --- a/src/theme.ts +++ b/src/theme.ts @@ -2,6 +2,7 @@ /* eslint-disable unused-imports/no-unused-vars */ import { createTheme } from '@mui/material/styles'; +import type { CSSProperties } from 'react'; const COLORS = { lightBlue: '#C7E7FF', @@ -9,6 +10,7 @@ const COLORS = { lightPink: '#FFDBD0', softGray: '#F4F0EF', linkBlue: '#1A4B66', + outline: '#71787E', } as const; declare module '@mui/material/styles' { @@ -84,6 +86,7 @@ declare module '@mui/material/styles' { lightOrange: string; studyGroupCardColors: string[]; linkBlue: string; + outline: string; }; } interface PaletteOptions { @@ -93,8 +96,32 @@ declare module '@mui/material/styles' { lightOrange?: string; studyGroupCardColors?: string[]; linkBlue?: string; + outline?: string; }; } + + interface TypographyVariants { + outlineButton: CSSProperties; + outlineButtonSmall: CSSProperties; + linkButtonContained: CSSProperties; + linkButtonContainedSmall: CSSProperties; + } + + interface TypographyVariantsOptions { + outlineButton?: CSSProperties; + outlineButtonSmall?: CSSProperties; + linkButtonContained?: CSSProperties; + linkButtonContainedSmall?: CSSProperties; + } +} + +declare module '@mui/material/Typography' { + interface TypographyPropsVariantOverrides { + outlineButton: true; + outlineButtonSmall: true; + linkButtonContained: true; + linkButtonContainedSmall: true; + } } const theme = createTheme({ @@ -204,6 +231,33 @@ const theme = createTheme({ lineHeight: 1.2, }, + outlineButton: { + fontFamily: '"Roboto", "Helvetica", "Arial", sans-serif', + fontWeight: 500, + fontSize: '0.875rem', + lineHeight: '20px', + letterSpacing: '0.1px', + textTransform: 'none', + }, + outlineButtonSmall: { + fontFamily: '"Roboto", "Helvetica", "Arial", sans-serif', + fontWeight: 500, + fontSize: '0.8rem', + lineHeight: '20px', + letterSpacing: '0.1px', + textTransform: 'none', + }, + linkButtonContained: { + fontWeight: 600, + fontSize: '1rem', + textTransform: 'none', + }, + linkButtonContainedSmall: { + fontWeight: 600, + fontSize: '0.8rem', + textTransform: 'none', + }, + fontWeightBold: 600, fontWeightMedium: 400, }, @@ -228,6 +282,7 @@ const theme = createTheme({ COLORS.softGray, ], linkBlue: COLORS.linkBlue, + outline: COLORS.outline, }, text: { primary: '#1b1919',