From 8e1348f7e06e8956704933e8eadb097ef3a0e85e Mon Sep 17 00:00:00 2001 From: Michal Kleszcz Date: Wed, 28 Aug 2024 17:49:08 +0200 Subject: [PATCH] feat: Update Mantine --- .stylelintignore | 2 + .stylelintrc.json | 28 + apps/app/.eslintrc.json | 6 +- apps/app/.stylelintignore | 2 + apps/app/.stylelintrc.json | 3 + apps/app/next.config.js | 1 + apps/app/package.json | 12 +- apps/app/postcss.config.cjs | 3 + .../app/[lang]/app/crud/[id]/crudDetails.tsx | 18 +- apps/app/src/app/[lang]/app/crud/crudList.tsx | 2 +- .../src/app/[lang]/app/dashboard.module.css | 3 + .../src/app/[lang]/app/dashboard.styles.ts | 7 - apps/app/src/app/[lang]/app/dashboard.tsx | 3 +- apps/app/src/app/[lang]/app/layout.tsx | 22 +- apps/app/src/app/[lang]/layout.tsx | 13 +- .../crudItem/crudItem.component.tsx | 2 +- .../components/crudItem/crudItem.stories.tsx | 4 +- .../crudItemForm/crudItemForm.component.tsx | 4 +- .../crudItemForm/crudItemForm.stories.tsx | 4 +- .../header/__tests__/header.spec.tsx | 7 +- .../components/header/header.component.tsx | 39 +- .../homepage/features/feature.component.tsx | 2 +- .../homepage/features/features.component.tsx | 15 +- .../homepage/features/features.module.css | 27 + .../homepage/features/features.styles.tsx | 31 - .../homepage/footer/footer.component.tsx | 25 +- .../homepage/footer/footer.module.css | 111 +++ .../homepage/footer/footer.styles.tsx | 95 -- .../homepage/header/header.component.tsx | 25 +- .../homepage/header/header.module.css | 41 + .../homepage/header/header.styles.tsx | 73 -- .../homepage/hero/hero.component.tsx | 4 +- .../components/homepage/hero/hero.module.css | 66 ++ .../components/homepage/hero/hero.styles.tsx | 63 -- .../loginState/loginState.component.tsx | 4 +- .../components/navbar/navbar.component.tsx | 18 +- .../src/components/navbar/navbar.module.css | 43 + .../src/components/navbar/navbar.styles.tsx | 46 - .../profileForm/profileForm.component.tsx | 4 +- .../profileForm/profileForm.stories.tsx | 4 +- apps/app/src/config/auth.ts | 4 +- .../__tests__/useUserRole.spec.tsx | 2 +- apps/app/src/middleware.ts | 19 +- .../appProviders/appProviders.component.tsx | 13 +- apps/app/src/tests/factories/crudItem.ts | 14 +- apps/app/src/tests/setupTests.ts | 16 + apps/app/src/theme/index.ts | 13 + apps/app/src/theme/theme.module.css | 10 + package.json | 13 +- .../backButton/backButton.component.tsx | 2 +- .../genericError/genericError.component.tsx | 8 +- .../genericError/genericError.module.css | 32 + .../genericError/genericError.styles.ts | 45 - .../languageSwitch.component.tsx | 4 +- .../themeToggler/themeToggler.component.tsx | 10 +- .../themeToggler/themeToggler.module.css | 18 + packages/core/src/providers/index.ts | 1 - .../MantineProvider.component.tsx | 53 -- .../mantineProvider/MantineProvider.const.tsx | 1 - .../src/providers/mantineProvider/index.ts | 2 - packages/core/src/tests/utils/rendering.tsx | 2 +- pnpm-lock.yaml | 869 +++++++++++++----- postcss.config.cjs | 14 + 63 files changed, 1214 insertions(+), 833 deletions(-) create mode 100644 .stylelintignore create mode 100644 .stylelintrc.json create mode 100644 apps/app/.stylelintignore create mode 100644 apps/app/.stylelintrc.json create mode 100644 apps/app/postcss.config.cjs create mode 100644 apps/app/src/app/[lang]/app/dashboard.module.css delete mode 100644 apps/app/src/app/[lang]/app/dashboard.styles.ts create mode 100644 apps/app/src/components/homepage/features/features.module.css delete mode 100644 apps/app/src/components/homepage/features/features.styles.tsx create mode 100644 apps/app/src/components/homepage/footer/footer.module.css delete mode 100644 apps/app/src/components/homepage/footer/footer.styles.tsx create mode 100644 apps/app/src/components/homepage/header/header.module.css delete mode 100644 apps/app/src/components/homepage/header/header.styles.tsx create mode 100644 apps/app/src/components/homepage/hero/hero.module.css delete mode 100644 apps/app/src/components/homepage/hero/hero.styles.tsx create mode 100644 apps/app/src/components/navbar/navbar.module.css delete mode 100644 apps/app/src/components/navbar/navbar.styles.tsx create mode 100644 apps/app/src/theme/index.ts create mode 100644 apps/app/src/theme/theme.module.css create mode 100644 packages/core/src/components/genericError/genericError.module.css delete mode 100644 packages/core/src/components/genericError/genericError.styles.ts create mode 100644 packages/core/src/components/themeToggler/themeToggler.module.css delete mode 100644 packages/core/src/providers/mantineProvider/MantineProvider.component.tsx delete mode 100644 packages/core/src/providers/mantineProvider/MantineProvider.const.tsx delete mode 100644 packages/core/src/providers/mantineProvider/index.ts create mode 100644 postcss.config.cjs diff --git a/.stylelintignore b/.stylelintignore new file mode 100644 index 0000000..21a1365 --- /dev/null +++ b/.stylelintignore @@ -0,0 +1,2 @@ +.next +out \ No newline at end of file diff --git a/.stylelintrc.json b/.stylelintrc.json new file mode 100644 index 0000000..4ea6506 --- /dev/null +++ b/.stylelintrc.json @@ -0,0 +1,28 @@ +{ + "extends": ["stylelint-config-standard-scss"], + "rules": { + "custom-property-pattern": null, + "selector-class-pattern": null, + "scss/no-duplicate-mixins": null, + "declaration-empty-line-before": null, + "declaration-block-no-redundant-longhand-properties": null, + "alpha-value-notation": null, + "custom-property-empty-line-before": null, + "property-no-vendor-prefix": null, + "color-function-notation": null, + "length-zero-no-unit": null, + "selector-not-notation": null, + "no-descending-specificity": null, + "comment-empty-line-before": null, + "scss/at-mixin-pattern": null, + "scss/at-rule-no-unknown": null, + "value-keyword-case": null, + "media-feature-range-notation": null, + "selector-pseudo-class-no-unknown": [ + true, + { + "ignorePseudoClasses": ["global"] + } + ] + } +} diff --git a/apps/app/.eslintrc.json b/apps/app/.eslintrc.json index a5b646a..67211f0 100644 --- a/apps/app/.eslintrc.json +++ b/apps/app/.eslintrc.json @@ -1,5 +1,5 @@ { - "extends": ["plugin:react/recommended", "plugin:@next/next/recommended", "../../.eslintrc.json"], + "extends": ["mantine", "plugin:react/recommended", "plugin:@next/next/recommended", "../../.eslintrc.json"], "ignorePatterns": ["!**/*", "node_modules/**/*"], "plugins": ["react-hooks", "formatjs", "testing-library"], "rules": { @@ -29,6 +29,10 @@ }, { "files": "*.{ts,tsx}", + "parser": "@typescript-eslint/parser", + "parserOptions": { + "project": "./tsconfig.base.json" + }, "rules": { "@typescript-eslint/no-var-requires": "off", "@typescript-eslint/ban-ts-comment": "off", diff --git a/apps/app/.stylelintignore b/apps/app/.stylelintignore new file mode 100644 index 0000000..21a1365 --- /dev/null +++ b/apps/app/.stylelintignore @@ -0,0 +1,2 @@ +.next +out \ No newline at end of file diff --git a/apps/app/.stylelintrc.json b/apps/app/.stylelintrc.json new file mode 100644 index 0000000..ca4dbc2 --- /dev/null +++ b/apps/app/.stylelintrc.json @@ -0,0 +1,3 @@ +{ + "extends": ["../../.stylelintrc.json"] +} diff --git a/apps/app/next.config.js b/apps/app/next.config.js index 6ef75a9..c986380 100644 --- a/apps/app/next.config.js +++ b/apps/app/next.config.js @@ -6,6 +6,7 @@ const nextConfig = { transpilePackages: ['@alp/graphql-api', '@alp/api-client', '@alp/core', 'ramda'], experimental: { serverComponentsExternalPackages: ['typeorm'], + optimizePackageImports: ['@mantine/core', '@mantine/hooks'], }, webpack: (config, { isServer }) => { // fix for: Can't resolve 'pg-native' issue diff --git a/apps/app/package.json b/apps/app/package.json index f7269a3..bb2db1d 100644 --- a/apps/app/package.json +++ b/apps/app/package.json @@ -6,7 +6,8 @@ "dev": "pnpm nx serve:app", "build": "next build", "start": "next start", - "lint": "next lint", + "lint": "next lint && npm run lint:stylelint", + "lint:stylelint": "stylelint '**/*.css' --cache", "extract-intl": "formatjs extract 'src/**/!(*.d).(js|jsx|ts|tsx)' '../../packages/core/src/**/!(*.d).(js|jsx|ts|tsx)' --id-interpolation-pattern '[sha512:contenthash:base64:6]' --out-file ../../packages/core/src/translations/en.json --ignore src/tests/mocks/**", "test": "jest", "test:watch": "jest --watch", @@ -25,8 +26,8 @@ "@emotion/server": "^11.11.0", "@formatjs/intl-localematcher": "^0.4.2", "@heroicons/react": "^2.0.17", - "@mantine/next": "^6.0.11", - "@mantine/notifications": "^6.0.19", + "@mantine/next": "^6.0.21", + "@mantine/notifications": "^7.10.1", "negotiator": "^0.6.3", "react-hook-form": "^7.43.9", "sharp": "^0.32.6" @@ -36,6 +37,9 @@ "@next/eslint-plugin-next": "^13.4.19", "@storybook/cli": "^7.4.5", "@types/negotiator": "^0.6.1", - "eslint-config-next": "13.4.19" + "eslint-config-next": "13.4.19", + "postcss": "^8.4.38", + "postcss-preset-mantine": "^1.15.0", + "postcss-simple-vars": "^7.0.1" } } diff --git a/apps/app/postcss.config.cjs b/apps/app/postcss.config.cjs new file mode 100644 index 0000000..fa14302 --- /dev/null +++ b/apps/app/postcss.config.cjs @@ -0,0 +1,3 @@ +const main = require('../../postcss.config.cjs'); + +module.exports = main; \ No newline at end of file diff --git a/apps/app/src/app/[lang]/app/crud/[id]/crudDetails.tsx b/apps/app/src/app/[lang]/app/crud/[id]/crudDetails.tsx index 176380b..fcb717a 100644 --- a/apps/app/src/app/[lang]/app/crud/[id]/crudDetails.tsx +++ b/apps/app/src/app/[lang]/app/crud/[id]/crudDetails.tsx @@ -8,13 +8,11 @@ import { CrudItem as CrudItemType } from '@alp/api-client'; export interface CrudDetailsProps { crudItem: CrudItemType; } -export const CrudDetails = ({ crudItem }: CrudDetailsProps) => { - return ( - - - - - {crudItem.name} - - ); -}; +export const CrudDetails = ({ crudItem }: CrudDetailsProps) => ( + + + + + {crudItem.name} + +); diff --git a/apps/app/src/app/[lang]/app/crud/crudList.tsx b/apps/app/src/app/[lang]/app/crud/crudList.tsx index a3c3d77..e952574 100644 --- a/apps/app/src/app/[lang]/app/crud/crudList.tsx +++ b/apps/app/src/app/[lang]/app/crud/crudList.tsx @@ -27,7 +27,7 @@ export const CrudList = () => { return ( <> - } disabled={notAdmin}> + } disabled={notAdmin}> diff --git a/apps/app/src/app/[lang]/app/dashboard.module.css b/apps/app/src/app/[lang]/app/dashboard.module.css new file mode 100644 index 0000000..47966ec --- /dev/null +++ b/apps/app/src/app/[lang]/app/dashboard.module.css @@ -0,0 +1,3 @@ +.text { + color: var(--mantine-colors-gray-7); +} \ No newline at end of file diff --git a/apps/app/src/app/[lang]/app/dashboard.styles.ts b/apps/app/src/app/[lang]/app/dashboard.styles.ts deleted file mode 100644 index 939107e..0000000 --- a/apps/app/src/app/[lang]/app/dashboard.styles.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { createStyles } from '@mantine/core'; - -export const useStyles = createStyles((theme) => ({ - text: { - color: theme.colorScheme === 'dark' ? theme.white : theme.black, - }, -})); diff --git a/apps/app/src/app/[lang]/app/dashboard.tsx b/apps/app/src/app/[lang]/app/dashboard.tsx index 3ccfa1e..d37efb5 100644 --- a/apps/app/src/app/[lang]/app/dashboard.tsx +++ b/apps/app/src/app/[lang]/app/dashboard.tsx @@ -3,10 +3,9 @@ import { Text } from '@mantine/core'; import { FormattedMessage } from 'react-intl'; -import { useStyles } from './dashboard.styles'; +import classes from './dashboard.module.css'; export function Dashboard() { - const { classes } = useStyles(); return (
diff --git a/apps/app/src/app/[lang]/app/layout.tsx b/apps/app/src/app/[lang]/app/layout.tsx index 388a1cf..fcbce47 100644 --- a/apps/app/src/app/[lang]/app/layout.tsx +++ b/apps/app/src/app/[lang]/app/layout.tsx @@ -1,23 +1,29 @@ 'use client'; -import { AppShell } from '@mantine/core'; +import { AppShell, rem } from '@mantine/core'; import { ReactNode, useState } from 'react'; import { Header, Navbar } from '@app/components'; +const HEADER_HEIGHT = rem(60); + export default function AppLayout({ children }: { children: ReactNode }) { const [opened, setOpened] = useState(false); return ( } - navbarOffsetBreakpoint="sm" - header={
setOpened(!opened)} />} - styles={(theme) => ({ - main: { backgroundColor: theme.colorScheme === 'dark' ? theme.colors.dark[8] : theme.colors.white }, - })} + header={{ + height: HEADER_HEIGHT, + }} + navbar={{ + width: 300, + breakpoint: 'sm', + collapsed: { mobile: !opened }, + }} > - {children} +
setOpened(!opened)} /> + + {children} ); } diff --git a/apps/app/src/app/[lang]/layout.tsx b/apps/app/src/app/[lang]/layout.tsx index ad6243d..9f00c0b 100644 --- a/apps/app/src/app/[lang]/layout.tsx +++ b/apps/app/src/app/[lang]/layout.tsx @@ -1,10 +1,10 @@ -import { ColorScheme } from '@mantine/core'; +import { ColorSchemeScript } from '@mantine/core'; +import '@mantine/core/styles.css'; import { Metadata, Viewport } from 'next'; import { getServerSession } from 'next-auth'; -import { cookies, headers } from 'next/headers'; +import { headers } from 'next/headers'; import { Locale, i18n } from '@alp/core/config/i18n'; -import { COLOR_SCHEME_COOKIE_NAME } from '@alp/core/providers/mantineProvider/MantineProvider.const'; import { authOptions } from '@app/config/auth'; import { AppProviders } from '@app/providers/appProviders'; @@ -29,10 +29,12 @@ export default async function Root({ children, params }: { children: React.React const authHeaders = { COOKIE: headers().get('COOKIE') || '', }; - const cookieStore = cookies(); - const colorSchemeValue = cookieStore.get(COLOR_SCHEME_COOKIE_NAME); return ( + + + + {children} diff --git a/apps/app/src/components/crudItem/crudItem.component.tsx b/apps/app/src/components/crudItem/crudItem.component.tsx index 5d6aa6b..9461201 100644 --- a/apps/app/src/components/crudItem/crudItem.component.tsx +++ b/apps/app/src/components/crudItem/crudItem.component.tsx @@ -59,7 +59,7 @@ export const CrudItem = ({ crudItem }: CrudItemProps) => { - {crudItem.name} + {crudItem.name} diff --git a/apps/app/src/components/crudItem/crudItem.stories.tsx b/apps/app/src/components/crudItem/crudItem.stories.tsx index e206bf6..e926bab 100644 --- a/apps/app/src/components/crudItem/crudItem.stories.tsx +++ b/apps/app/src/components/crudItem/crudItem.stories.tsx @@ -15,9 +15,7 @@ const meta: Meta = { export default meta; -const Template: StoryFn = (args) => { - return ; -}; +const Template: StoryFn = (args) => ; export const Default: Story = { render: Template, diff --git a/apps/app/src/components/crudItemForm/crudItemForm.component.tsx b/apps/app/src/components/crudItemForm/crudItemForm.component.tsx index 81aae51..759ed36 100644 --- a/apps/app/src/components/crudItemForm/crudItemForm.component.tsx +++ b/apps/app/src/components/crudItemForm/crudItemForm.component.tsx @@ -16,7 +16,7 @@ export type CrudItemFormProps = { }; export const CrudItemForm = ({ loading, onSubmit, initialData }: CrudItemFormProps) => { - const initialForm = initialData ? initialData : { name: '' }; + const initialForm = initialData || { name: '' }; const form = useForm({ initialValues: initialForm, validate: { @@ -28,7 +28,7 @@ export const CrudItemForm = ({ loading, onSubmit, initialData }: CrudItemFormPro
- + diff --git a/apps/app/src/components/crudItemForm/crudItemForm.stories.tsx b/apps/app/src/components/crudItemForm/crudItemForm.stories.tsx index e3cb584..7edaf09 100644 --- a/apps/app/src/components/crudItemForm/crudItemForm.stories.tsx +++ b/apps/app/src/components/crudItemForm/crudItemForm.stories.tsx @@ -12,9 +12,7 @@ const meta: Meta = { export default meta; -const Template: StoryFn = (args) => { - return ; -}; +const Template: StoryFn = (args) => ; export const Default: Story = { render: Template, diff --git a/apps/app/src/components/header/__tests__/header.spec.tsx b/apps/app/src/components/header/__tests__/header.spec.tsx index e96718d..fc89c3f 100644 --- a/apps/app/src/components/header/__tests__/header.spec.tsx +++ b/apps/app/src/components/header/__tests__/header.spec.tsx @@ -1,3 +1,4 @@ +import { AppShell } from '@mantine/core'; import '@testing-library/jest-dom'; import { screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; @@ -8,7 +9,11 @@ import { Header } from '../header.component'; describe('App: Header', () => { it('renders `Features` button', async () => { const toggleOpen = jest.fn(); - render(
); + render( + +
+ + ); await userEvent.click(screen.getByTestId('toggle-button')); expect(toggleOpen).toHaveBeenCalled(); diff --git a/apps/app/src/components/header/header.component.tsx b/apps/app/src/components/header/header.component.tsx index 99a7ca5..14dcc19 100644 --- a/apps/app/src/components/header/header.component.tsx +++ b/apps/app/src/components/header/header.component.tsx @@ -1,12 +1,4 @@ -import { - Burger, - Flex, - Header as HeaderBase, - MediaQuery, - rem, - useMantineColorScheme, - useMantineTheme, -} from '@mantine/core'; +import { AppShell, Burger, Flex, Image as MantineImage, useMantineTheme } from '@mantine/core'; import Image from 'next/image'; import { LanguageSwitch, ThemeToggler } from '@alp/core/components'; @@ -19,32 +11,29 @@ export interface MobileHeaderProps { toggleOpen: () => void; } -export const HEADER_HEIGHT = rem(60); - export function Header({ opened, toggleOpen }: MobileHeaderProps) { const theme = useMantineTheme(); - const { colorScheme } = useMantineColorScheme(); return ( - + <> - - - - Apptension + + + - + ); } diff --git a/apps/app/src/components/homepage/features/feature.component.tsx b/apps/app/src/components/homepage/features/feature.component.tsx index 0bd5d7f..72f512c 100644 --- a/apps/app/src/components/homepage/features/feature.component.tsx +++ b/apps/app/src/components/homepage/features/feature.component.tsx @@ -17,7 +17,7 @@ export function Feature({ icon: Icon, title, description }: FeatureProps) { {title} - + {description}
diff --git a/apps/app/src/components/homepage/features/features.component.tsx b/apps/app/src/components/homepage/features/features.component.tsx index 536b2cb..96cbdb7 100644 --- a/apps/app/src/components/homepage/features/features.component.tsx +++ b/apps/app/src/components/homepage/features/features.component.tsx @@ -3,7 +3,7 @@ import { Container, SimpleGrid, Text, Title } from '@mantine/core'; import { Feature, FeatureProps } from './feature.component'; -import { useStyles } from './features.styles'; +import classes from './features.module.css'; export const FEATURES_ANCHOR_ID = 'features'; @@ -14,7 +14,6 @@ interface FeaturesGridProps { } export function Features({ title, description, data }: FeaturesGridProps) { - const { classes } = useStyles(); const features = data.map((feature, index) => ); return ( @@ -22,20 +21,12 @@ export function Features({ title, description, data }: FeaturesGridProps) { {title} - + {description} - + {features} diff --git a/apps/app/src/components/homepage/features/features.module.css b/apps/app/src/components/homepage/features/features.module.css new file mode 100644 index 0000000..f56c027 --- /dev/null +++ b/apps/app/src/components/homepage/features/features.module.css @@ -0,0 +1,27 @@ +.wrapper { + padding-top: calc(var(--mantine-spacing-xl) * 4); + padding-bottom: calc(var(--mantine-spacing-xl) * 4); +} + +.title { + font-family: "Greycliff CF", var(--mantine-font-family); + font-weight: 900; + margin-bottom: var(--mantine-spacing-md); + text-align: center; + + @media (max-width: $mantine-breakpoint-sm) { + font-size: rem(28px); + text-align: left; + } +} + + +.description { + font-family: "Greycliff CF", var(--mantine-font-family); + text-align: center; + + @media (max-width: $mantine-breakpoint-sm) { + text-align: left; + } +} + diff --git a/apps/app/src/components/homepage/features/features.styles.tsx b/apps/app/src/components/homepage/features/features.styles.tsx deleted file mode 100644 index 324f940..0000000 --- a/apps/app/src/components/homepage/features/features.styles.tsx +++ /dev/null @@ -1,31 +0,0 @@ -'use client'; - -import { createStyles, rem } from '@mantine/core'; - -export const useStyles = createStyles((theme) => ({ - wrapper: { - paddingTop: `calc(${theme.spacing.xl} * 4)`, - paddingBottom: `calc(${theme.spacing.xl} * 4)`, - }, - - title: { - fontFamily: `Greycliff CF, ${theme.fontFamily}`, - fontWeight: 900, - marginBottom: theme.spacing.md, - textAlign: 'center', - - [theme.fn.smallerThan('sm')]: { - fontSize: rem(28), - textAlign: 'left', - }, - }, - - description: { - fontFamily: `Greycliff CF, ${theme.fontFamily}`, - textAlign: 'center', - - [theme.fn.smallerThan('sm')]: { - textAlign: 'left', - }, - }, -})); diff --git a/apps/app/src/components/homepage/footer/footer.component.tsx b/apps/app/src/components/homepage/footer/footer.component.tsx index a07c547..c0a940d 100644 --- a/apps/app/src/components/homepage/footer/footer.component.tsx +++ b/apps/app/src/components/homepage/footer/footer.component.tsx @@ -6,7 +6,7 @@ import Image from 'next/image'; import LogoDark from '../../../../public/logo-dark.png'; import LogoLight from '../../../../public/logo-light.png'; -import { useStyles } from './footer.styles'; +import classes from './footer.module.css'; interface FooterLinksProps { data: { @@ -16,7 +16,6 @@ interface FooterLinksProps { } export function Footer({ data }: FooterLinksProps) { - const { classes } = useStyles(); const { colorScheme } = useMantineColorScheme(); const groups = data.map((group) => { @@ -50,17 +49,29 @@ export function Footer({ data }: FooterLinksProps) { © {new Date().getFullYear()} apptension.com. All rights reserved. - - + + - + - + - + diff --git a/apps/app/src/components/homepage/footer/footer.module.css b/apps/app/src/components/homepage/footer/footer.module.css new file mode 100644 index 0000000..4ffeb03 --- /dev/null +++ b/apps/app/src/components/homepage/footer/footer.module.css @@ -0,0 +1,111 @@ +.footer { + margin-top: rem(5); + padding-top: calc(var(--mantine-spacing-xl) * 2); + padding-bottom: calc(var(--mantine-spacing-md)); + background-color: light-dark( + var(--mantine-color-gray-0), + var(--mantine-color-dark-6) + ); + border-top: light-dark( + var(--mantine-color-gray-2), + var(--mantine-color-dark-5) + ); +} + +.logo { + max-width: rem(200); + + @media (max-width: $mantine-breakpoint-sm) { + display: flex; + flex-direction: column; + align-items: center; + } +} + + +.description { + margin-top: rem(5); + + @media (max-width: $mantine-breakpoint-sm) { + margin-top: var(--mantine-spacing-xs); + text-align: center; + } +} + + +.inner { + display: flex; + justify-content: space-between; + + @media (max-width: $mantine-breakpoint-sm) { + flex-direction: column; + align-items: center; + } +} + + +.groups { + display: flex; + flex-wrap: wrap; +} + +@media (max-width: var(--mantine-breakpoint-sm)) { + .groups { + display: none; + } +} + +.wrapper { + width: rem(160); +} + +.link { + display: block; + color: light-dark( + var(--mantine-color-gray-6), + var(--mantine-color-dark-1) + ); + font-size: var(--mantine-font-size-sm); + padding-top: rem(3); + padding-bottom: rem(3); + + &:hover { + text-decoration: underline; + } +} + +.title { + font-size: var(--mantine-font-size-lg); + font-weight: 700; + font-family: "Greycliff CF", var(--mantine-font-family); + margin-bottom: calc(var(--mantine-spacing-xs) / 2); + color: light-dark( + var(--mantine-color-black), + var(--mantine-color-white) + ); +} + +.afterFooter { + display: flex; + justify-content: space-between; + align-items: center; + margin-top: var(--mantine-spacing-xl); + padding-top: var(--mantine-spacing-xl); + padding-bottom: var(--mantine-spacing-xl); + border-top: rem(1) solid light-dark( + var(--mantine-color-gray-2), + var(--mantine-color-dark-4) + ); +} + +@media (max-width: var(--mantine-breakpoint-sm)) { + .afterFooter { + flex-direction: column; + } +} + +.social { + @media (max-width: var(--mantine-breakpoint-sm)) { + margin-top: var(--mantine-spacing-xs); + } +} \ No newline at end of file diff --git a/apps/app/src/components/homepage/footer/footer.styles.tsx b/apps/app/src/components/homepage/footer/footer.styles.tsx deleted file mode 100644 index 1e68261..0000000 --- a/apps/app/src/components/homepage/footer/footer.styles.tsx +++ /dev/null @@ -1,95 +0,0 @@ -'use client'; - -import { createStyles, rem } from '@mantine/core'; - -export const useStyles = createStyles((theme) => ({ - footer: { - marginTop: rem(120), - paddingTop: `calc(${theme.spacing.xl} * 2)`, - paddingBottom: `calc(${theme.spacing.xl} * 2)`, - backgroundColor: theme.colorScheme === 'dark' ? theme.colors.dark[6] : theme.colors.gray[0], - borderTop: `${rem(1)} solid ${theme.colorScheme === 'dark' ? theme.colors.dark[5] : theme.colors.gray[2]}`, - }, - - logo: { - maxWidth: rem(200), - - [theme.fn.smallerThan('sm')]: { - display: 'flex', - flexDirection: 'column', - alignItems: 'center', - }, - }, - - description: { - marginTop: rem(5), - - [theme.fn.smallerThan('sm')]: { - marginTop: theme.spacing.xs, - textAlign: 'center', - }, - }, - - inner: { - display: 'flex', - justifyContent: 'space-between', - - [theme.fn.smallerThan('sm')]: { - flexDirection: 'column', - alignItems: 'center', - }, - }, - - groups: { - display: 'flex', - flexWrap: 'wrap', - - [theme.fn.smallerThan('sm')]: { - display: 'none', - }, - }, - - wrapper: { - width: rem(160), - }, - - link: { - display: 'block', - color: theme.colorScheme === 'dark' ? theme.colors.dark[1] : theme.colors.gray[6], - fontSize: theme.fontSizes.sm, - paddingTop: rem(3), - paddingBottom: rem(3), - - '&:hover': { - textDecoration: 'underline', - }, - }, - - title: { - fontSize: theme.fontSizes.lg, - fontWeight: 700, - fontFamily: `Greycliff CF, ${theme.fontFamily}`, - marginBottom: `calc(${theme.spacing.xs} / 2)`, - color: theme.colorScheme === 'dark' ? theme.white : theme.black, - }, - - afterFooter: { - display: 'flex', - justifyContent: 'space-between', - alignItems: 'center', - marginTop: theme.spacing.xl, - paddingTop: theme.spacing.xl, - paddingBottom: theme.spacing.xl, - borderTop: `${rem(1)} solid ${theme.colorScheme === 'dark' ? theme.colors.dark[4] : theme.colors.gray[2]}`, - - [theme.fn.smallerThan('sm')]: { - flexDirection: 'column', - }, - }, - - social: { - [theme.fn.smallerThan('sm')]: { - marginTop: theme.spacing.xs, - }, - }, -})); diff --git a/apps/app/src/components/homepage/header/header.component.tsx b/apps/app/src/components/homepage/header/header.component.tsx index 32fa50d..66dcd44 100644 --- a/apps/app/src/components/homepage/header/header.component.tsx +++ b/apps/app/src/components/homepage/header/header.component.tsx @@ -1,23 +1,15 @@ 'use client'; -import { - Burger, - Container, - Divider, - Group, - Header as HeaderBase, - Paper, - Transition, - useMantineColorScheme, -} from '@mantine/core'; +import { Burger, Container, Divider, Group, Paper, Transition, useMantineColorScheme } from '@mantine/core'; import { useDisclosure } from '@mantine/hooks'; +import cx from 'clsx'; import Image from 'next/image'; import { useState } from 'react'; import LogoDark from '../../../../public/logo-dark.png'; import LogoLight from '../../../../public/logo-light.png'; import { LoginState } from '../loginState'; -import { HEADER_HEIGHT, useStyles } from './header.styles'; +import classes from './header.module.css'; interface HeaderResponsiveProps { links: { link: string; label: string }[]; @@ -26,7 +18,6 @@ interface HeaderResponsiveProps { export function Header({ links }: HeaderResponsiveProps) { const [opened, { toggle, close }] = useDisclosure(false); const [active, setActive] = useState(links[0].link); - const { classes, cx } = useStyles(); const { colorScheme } = useMantineColorScheme(); const items = links.map((link) => ( @@ -45,15 +36,15 @@ export function Header({ links }: HeaderResponsiveProps) { )); return ( - - +
+ Apptension - + {items} - + {(styles) => ( @@ -62,6 +53,6 @@ export function Header({ links }: HeaderResponsiveProps) { )} - +
); } diff --git a/apps/app/src/components/homepage/header/header.module.css b/apps/app/src/components/homepage/header/header.module.css new file mode 100644 index 0000000..6828235 --- /dev/null +++ b/apps/app/src/components/homepage/header/header.module.css @@ -0,0 +1,41 @@ +.dropdown { + position: absolute; + top: rem(56px); + left: 0; + right: 0; + z-index: 0; + overflow: hidden; +} + +.header { + height: rem(56px); + background-color: var(--mantine-color-body); + border-bottom: rem(1px) solid light-dark(var(--mantine-color-gray-3), var(--mantine-color-dark-4)); +} + +.inner { + height: rem(56px); + display: flex; + justify-content: space-between; + align-items: center; +} + +.link { + display: block; + line-height: 1; + padding: rem(8px) rem(12px); + border-radius: var(--mantine-radius-sm); + text-decoration: none; + color: light-dark(var(--mantine-color-gray-7), var(--mantine-color-dark-0)); + font-size: var(--mantine-font-size-sm); + font-weight: 500; + + @mixin hover { + background-color: light-dark(var(--mantine-color-gray-0), var(--mantine-color-dark-6)); + } + + [data-mantine-color-scheme] &[data-active] { + background-color: var(--mantine-color-blue-filled); + color: var(--mantine-color-white); + } +} \ No newline at end of file diff --git a/apps/app/src/components/homepage/header/header.styles.tsx b/apps/app/src/components/homepage/header/header.styles.tsx deleted file mode 100644 index 06b7ac5..0000000 --- a/apps/app/src/components/homepage/header/header.styles.tsx +++ /dev/null @@ -1,73 +0,0 @@ -'use client'; - -import { createStyles, rem } from '@mantine/core'; - -export const HEADER_HEIGHT = rem(60); -export const useStyles = createStyles((theme) => ({ - root: { - position: 'relative', - zIndex: 1, - }, - - dropdown: { - position: 'absolute', - top: HEADER_HEIGHT, - left: 0, - right: 0, - zIndex: 0, - borderTopRightRadius: 0, - borderTopLeftRadius: 0, - borderTopWidth: 0, - overflow: 'hidden', - - [theme.fn.largerThan('sm')]: { - display: 'none', - }, - }, - - header: { - display: 'flex', - justifyContent: 'space-between', - alignItems: 'center', - height: '100%', - }, - - links: { - [theme.fn.smallerThan('sm')]: { - display: 'none', - }, - }, - - burger: { - [theme.fn.largerThan('sm')]: { - display: 'none', - }, - }, - - link: { - display: 'block', - lineHeight: 1, - padding: `${rem(8)} ${rem(12)}`, - borderRadius: theme.radius.sm, - textDecoration: 'none', - color: theme.colorScheme === 'dark' ? theme.colors.dark[0] : theme.colors.gray[7], - fontSize: theme.fontSizes.sm, - fontWeight: 500, - - '&:hover': { - backgroundColor: theme.colorScheme === 'dark' ? theme.colors.dark[6] : theme.colors.gray[0], - }, - - [theme.fn.smallerThan('sm')]: { - borderRadius: 0, - padding: theme.spacing.md, - }, - }, - - linkActive: { - '&, &:hover': { - backgroundColor: theme.fn.variant({ variant: 'light', color: theme.primaryColor }).background, - color: theme.fn.variant({ variant: 'light', color: theme.primaryColor }).color, - }, - }, -})); diff --git a/apps/app/src/components/homepage/hero/hero.component.tsx b/apps/app/src/components/homepage/hero/hero.component.tsx index cf52198..8f319cf 100644 --- a/apps/app/src/components/homepage/hero/hero.component.tsx +++ b/apps/app/src/components/homepage/hero/hero.component.tsx @@ -3,11 +3,9 @@ import { Container, Text, Title } from '@mantine/core'; import { Dots } from './dots.component'; -import { useStyles } from './hero.styles'; +import classes from './hero.module.css'; export function Hero() { - const { classes } = useStyles(); - return ( diff --git a/apps/app/src/components/homepage/hero/hero.module.css b/apps/app/src/components/homepage/hero/hero.module.css new file mode 100644 index 0000000..d53096e --- /dev/null +++ b/apps/app/src/components/homepage/hero/hero.module.css @@ -0,0 +1,66 @@ +.wrapper { + position: relative; + padding-top: rem(120px); + padding-bottom: rem(20px); + + @media (max-width: $mantine-breakpoint-sm) { + padding-top: rem(80px); + padding-bottom: rem(60px); + } +} + +.inner { + position: relative; + z-index: 1; +} + +.dots { + position: absolute; + color: light-dark( + var(--mantine-color-gray-1), + var(--mantine-color-dark-5) + ); + + @media (max-width: $mantine-breakpoint-sm) { + display: none; + } +} + +.dotsLeft { + top: 0; + left: 0; +} + +.title { + text-align: center; + font-weight: 800; + font-size: rem(40px); + letter-spacing: -1px; + margin-bottom: 8px; + color: light-dark( + var(--mantine-color-black), + var(--mantine-color-white) + ); + + @media (max-width: $mantine-breakpoint-xs) { + font-size: rem(28px); + text-align: left; + } +} + +.highlight { + color: light-dark( + var(--mantine-color-primary-4), + var(--mantine-color-primary-6) + ); +} + +.description { + text-align: center; + + @media (max-width: $mantine-breakpoint-xs) { + text-align: left; + font-size: 16px; + } +} + diff --git a/apps/app/src/components/homepage/hero/hero.styles.tsx b/apps/app/src/components/homepage/hero/hero.styles.tsx deleted file mode 100644 index 7d7e37a..0000000 --- a/apps/app/src/components/homepage/hero/hero.styles.tsx +++ /dev/null @@ -1,63 +0,0 @@ -'use client'; - -import { createStyles, rem } from '@mantine/core'; - -export const useStyles = createStyles((theme) => ({ - wrapper: { - position: 'relative', - paddingTop: rem(120), - paddingBottom: rem(20), - - [theme.fn.smallerThan('sm')]: { - paddingTop: rem(80), - paddingBottom: rem(60), - }, - }, - - inner: { - position: 'relative', - zIndex: 1, - }, - - dots: { - position: 'absolute', - color: theme.colorScheme === 'dark' ? theme.colors.dark[5] : theme.colors.gray[1], - - [theme.fn.smallerThan('sm')]: { - display: 'none', - }, - }, - - dotsLeft: { - left: 0, - top: 0, - }, - - title: { - textAlign: 'center', - fontWeight: 800, - fontSize: rem(40), - letterSpacing: -1, - color: theme.colorScheme === 'dark' ? theme.white : theme.black, - marginBottom: theme.spacing.xs, - fontFamily: `Greycliff CF, ${theme.fontFamily}`, - - [theme.fn.smallerThan('xs')]: { - fontSize: rem(28), - textAlign: 'left', - }, - }, - - highlight: { - color: theme.colors[theme.primaryColor][theme.colorScheme === 'dark' ? 4 : 6], - }, - - description: { - textAlign: 'center', - - [theme.fn.smallerThan('xs')]: { - textAlign: 'left', - fontSize: theme.fontSizes.md, - }, - }, -})); diff --git a/apps/app/src/components/homepage/loginState/loginState.component.tsx b/apps/app/src/components/homepage/loginState/loginState.component.tsx index ea3a2d3..a59e46d 100644 --- a/apps/app/src/components/homepage/loginState/loginState.component.tsx +++ b/apps/app/src/components/homepage/loginState/loginState.component.tsx @@ -17,7 +17,7 @@ export const LoginState = () => { } const renderUnauthorized = () => ( - ); @@ -27,7 +27,7 @@ export const LoginState = () => { {session?.user?.name?.slice(0, 2)} - + Go to app diff --git a/apps/app/src/components/navbar/navbar.component.tsx b/apps/app/src/components/navbar/navbar.component.tsx index 98f84bc..139ac3b 100644 --- a/apps/app/src/components/navbar/navbar.component.tsx +++ b/apps/app/src/components/navbar/navbar.component.tsx @@ -1,13 +1,14 @@ 'use client'; -import { Navbar as NavbarBase, ScrollArea } from '@mantine/core'; +import { AppShell, ScrollArea } from '@mantine/core'; import { IconDashboard, IconLogout, IconStar, IconUser } from '@tabler/icons-react'; +import cx from 'clsx'; import { signOut } from 'next-auth/react'; import Link from 'next/link'; import { usePathname } from 'next/navigation'; import { FormattedMessage } from 'react-intl'; -import { useStyles } from './navbar.styles'; +import classes from './navbar.module.css'; const data = [ { link: '/app', label: 'Dashboard', icon: IconDashboard }, @@ -20,7 +21,6 @@ export interface NavbarProps { } export function Navbar({ opened }: NavbarProps) { - const { classes, cx } = useStyles(); const pathname = usePathname(); const links = data.map((item) => ( @@ -35,12 +35,12 @@ export function Navbar({ opened }: NavbarProps) { )); return ( - + + ); } diff --git a/apps/app/src/components/navbar/navbar.module.css b/apps/app/src/components/navbar/navbar.module.css new file mode 100644 index 0000000..8e9ed8f --- /dev/null +++ b/apps/app/src/components/navbar/navbar.module.css @@ -0,0 +1,43 @@ +.footer { + padding-top: var(--mantine-spacing-md); + margin-top: var(--mantine-spacing-md); + border-top: 1px solid light-dark( + var(--mantine-color-gray-2), + var(--mantine-color-dark-4) + ); +} + +.link { + display: flex; + align-items: center; + text-decoration: none; + font-size: var(--mantine-font-sizes-sm); + color: light-dark( + var(--mantine-color-gray-7), + var(--mantine-color-dark-1) + ); + padding: var(--mantine-spacing-xs) var(--mantine-spacing-sm); + border-radius: var(--mantine-radius-sm); + font-weight: 500; +} + +.link:hover { + background-color: light-dark( + var(--mantine-color-gray-0), + var(--mantine-color-dark-6) + ); + color: var(--mantine-black); +} + +.linkIcon { + color: light-dark( + var(--mantine-color-gray-6), + var(--mantine-color-dark-2) + ); + margin-right: var(--mantine-spacing-sm); +} + +.linkActive { + background-color: var(--mantine-primary-color); + color: var(--mantine-primary-color); +} \ No newline at end of file diff --git a/apps/app/src/components/navbar/navbar.styles.tsx b/apps/app/src/components/navbar/navbar.styles.tsx deleted file mode 100644 index 671ec12..0000000 --- a/apps/app/src/components/navbar/navbar.styles.tsx +++ /dev/null @@ -1,46 +0,0 @@ -import { createStyles, getStylesRef, rem } from '@mantine/core'; - -export const useStyles = createStyles((theme) => ({ - footer: { - paddingTop: theme.spacing.md, - marginTop: theme.spacing.md, - borderTop: `${rem(1)} solid ${theme.colorScheme === 'dark' ? theme.colors.dark[4] : theme.colors.gray[2]}`, - }, - - link: { - ...theme.fn.focusStyles(), - display: 'flex', - alignItems: 'center', - textDecoration: 'none', - fontSize: theme.fontSizes.sm, - color: theme.colorScheme === 'dark' ? theme.colors.dark[1] : theme.colors.gray[7], - padding: `${theme.spacing.xs} ${theme.spacing.sm}`, - borderRadius: theme.radius.sm, - fontWeight: 500, - - '&:hover': { - backgroundColor: theme.colorScheme === 'dark' ? theme.colors.dark[6] : theme.colors.gray[0], - color: theme.colorScheme === 'dark' ? theme.white : theme.black, - - [`& .${getStylesRef('icon')}`]: { - color: theme.colorScheme === 'dark' ? theme.white : theme.black, - }, - }, - }, - - linkIcon: { - ref: getStylesRef('icon'), - color: theme.colorScheme === 'dark' ? theme.colors.dark[2] : theme.colors.gray[6], - marginRight: theme.spacing.sm, - }, - - linkActive: { - '&, &:hover': { - backgroundColor: theme.fn.variant({ variant: 'light', color: theme.primaryColor }).background, - color: theme.fn.variant({ variant: 'light', color: theme.primaryColor }).color, - [`& .${getStylesRef('icon')}`]: { - color: theme.fn.variant({ variant: 'light', color: theme.primaryColor }).color, - }, - }, - }, -})); diff --git a/apps/app/src/components/profileForm/profileForm.component.tsx b/apps/app/src/components/profileForm/profileForm.component.tsx index 51e984a..4a3afec 100644 --- a/apps/app/src/components/profileForm/profileForm.component.tsx +++ b/apps/app/src/components/profileForm/profileForm.component.tsx @@ -15,7 +15,7 @@ export type ProfileFormProps = { }; export const ProfileForm = ({ loading, onSubmit, initialData }: ProfileFormProps) => { - const initialForm = initialData ? initialData : { name: '' }; + const initialForm = initialData || { name: '' }; const form = useForm({ initialValues: initialForm, validate: { @@ -27,7 +27,7 @@ export const ProfileForm = ({ loading, onSubmit, initialData }: ProfileFormProps - + diff --git a/apps/app/src/components/profileForm/profileForm.stories.tsx b/apps/app/src/components/profileForm/profileForm.stories.tsx index 0557edb..0463d7a 100644 --- a/apps/app/src/components/profileForm/profileForm.stories.tsx +++ b/apps/app/src/components/profileForm/profileForm.stories.tsx @@ -12,9 +12,7 @@ const meta: Meta = { export default meta; -const Template: StoryFn = (args) => { - return ; -}; +const Template: StoryFn = (args) => ; export const Default: Story = { render: Template, diff --git a/apps/app/src/config/auth.ts b/apps/app/src/config/auth.ts index 2592117..009c018 100644 --- a/apps/app/src/config/auth.ts +++ b/apps/app/src/config/auth.ts @@ -14,8 +14,8 @@ export const authOptions: NextAuthOptions = { }), providers: [ GoogleProvider({ - clientId: process.env['OAUTH_GOOGLE_CLIENT_ID'] ?? '', - clientSecret: process.env['OAUTH_GOOGLE_SECRET'] ?? '', + clientId: process.env.OAUTH_GOOGLE_CLIENT_ID ?? '', + clientSecret: process.env.OAUTH_GOOGLE_SECRET ?? '', }), ], session: { diff --git a/apps/app/src/hooks/useUserRole/__tests__/useUserRole.spec.tsx b/apps/app/src/hooks/useUserRole/__tests__/useUserRole.spec.tsx index e8443bf..53dbc4b 100644 --- a/apps/app/src/hooks/useUserRole/__tests__/useUserRole.spec.tsx +++ b/apps/app/src/hooks/useUserRole/__tests__/useUserRole.spec.tsx @@ -1,6 +1,6 @@ import { UserRole } from '@alp/graphql-api/types'; -import { useUserRole } from '../'; +import { useUserRole } from '..'; import { sessionProviderFactory } from '../../../tests/factories/sessionProviderFactory'; import { renderHook } from '../../../tests/utils/rendering'; diff --git a/apps/app/src/middleware.ts b/apps/app/src/middleware.ts index 734c3c7..1a32ac6 100644 --- a/apps/app/src/middleware.ts +++ b/apps/app/src/middleware.ts @@ -10,7 +10,9 @@ function getLocale(request: NextRequest): string | undefined { // Negotiator expects plain object so we need to transform headers const negotiatorHeaders: Record = {}; - request.headers.forEach((value, key) => (negotiatorHeaders[key] = value)); + request.headers.forEach((value, key) => { + negotiatorHeaders[key] = value; + }); const language = request.cookies.get('NEXT_LOCALE')?.value ?? getBrowserLanguage(request) ?? i18n.defaultLocale; @@ -21,9 +23,7 @@ const authMiddleware = withAuth( // Note that this callback is only invoked if // the `authorized` callback has returned `true` // and not for pages listed in `pages`. - function onSuccess(req) { - return intlMiddleware(req); - }, + (req) => intlMiddleware(req), { callbacks: { authorized: ({ token }) => token != null, @@ -32,7 +32,7 @@ const authMiddleware = withAuth( ); export function intlMiddleware(request: NextRequest) { - const pathname = request.nextUrl.pathname; + const { pathname } = request.nextUrl; // // `/_next/` and `/api/` are ignored by the watcher, but we need to ignore files in `public` manually. // // If you have one @@ -56,6 +56,7 @@ export function intlMiddleware(request: NextRequest) { // e.g. incoming request is /products // The new URL is now /en-US/products + // eslint-disable-next-line consistent-return return NextResponse.redirect(new URL(`/${locale}${pathname.startsWith('/') ? '' : '/'}${pathname}`, request.url)); } } @@ -66,9 +67,8 @@ export default function middleware(req: NextRequest) { if (isPublicPage) { return intlMiddleware(req); - } else { - return (authMiddleware as any)(req); } + return (authMiddleware as any)(req); } export const config = { @@ -76,8 +76,8 @@ export const config = { matcher: ['/((?!api|_next/static|_next/image|favicon.ico|emails/logo.png).*)'], }; -const getBrowserLanguage = (req: NextRequest) => { - return req.headers +const getBrowserLanguage = (req: NextRequest) => + req.headers .get('accept-language') ?.split(',') .map((i) => i.split(';')) @@ -85,4 +85,3 @@ const getBrowserLanguage = (req: NextRequest) => { ?.sort((a, b) => (a.priority > b.priority ? -1 : 1)) ?.find((i) => (i18n.locales as readonly string[]).includes(i.code.substring(0, 2))) ?.code?.substring(0, 2); -}; diff --git a/apps/app/src/providers/appProviders/appProviders.component.tsx b/apps/app/src/providers/appProviders/appProviders.component.tsx index b83d6ea..055c1f2 100644 --- a/apps/app/src/providers/appProviders/appProviders.component.tsx +++ b/apps/app/src/providers/appProviders/appProviders.component.tsx @@ -1,6 +1,6 @@ 'use client'; -import { ColorScheme } from '@mantine/core'; +import { MantineProvider } from '@mantine/core'; import { Notifications } from '@mantine/notifications'; import { Session } from 'next-auth'; import { SessionProvider } from 'next-auth/react'; @@ -9,22 +9,22 @@ import { ReactNode } from 'react'; import { MakeClientOpts } from '@alp/api-client/client'; import { ApolloProvider } from '@alp/api-client/providers'; import { Locale } from '@alp/core/config/i18n'; -import { IntlProvider, LocalesProvider, MantineProvider } from '@alp/core/providers'; +import { IntlProvider, LocalesProvider } from '@alp/core/providers'; + +import { theme } from '../../theme'; interface AppProvidersProps { children: ReactNode; session?: Session | null; apolloClientOpts?: MakeClientOpts; lang: Locale; - defaultColorScheme?: ColorScheme; } -export const AppProviders = ({ children, session, apolloClientOpts, lang, defaultColorScheme }: AppProvidersProps) => { - return ( +export const AppProviders = ({ children, session, apolloClientOpts, lang }: AppProvidersProps) => ( - + {children} @@ -34,4 +34,3 @@ export const AppProviders = ({ children, session, apolloClientOpts, lang, defaul ); -}; diff --git a/apps/app/src/tests/factories/crudItem.ts b/apps/app/src/tests/factories/crudItem.ts index d91a397..7f85a81 100644 --- a/apps/app/src/tests/factories/crudItem.ts +++ b/apps/app/src/tests/factories/crudItem.ts @@ -15,27 +15,25 @@ export const crudItemFactory = createDeepFactory>((faker) => ( name: faker.string.alpha(10), })); -export const fillCrudDemoItemDetailsQuery = (data = crudItemFactory(), variables = {}) => { - return composeMockedQueryResult(detailsCrudItemQuery, { +export const fillCrudDemoItemDetailsQuery = (data = crudItemFactory(), variables = {}) => + composeMockedQueryResult(detailsCrudItemQuery, { variables, data: { crudDemoItem: data, }, }); -}; -export const fillCRUDListQuery = (data = times(() => crudItemFactory(), 3)) => { - return composeMockedListQueryResult(allCrudItemsQuery, 'allCrudItems', 'CRUDItem', { data }); -}; +export const fillCRUDListQuery = (data = times(() => crudItemFactory(), 3)) => + composeMockedListQueryResult(allCrudItemsQuery, 'allCrudItems', 'CRUDItem', { data }); export const fillAddCRUDItemQuery = (name: string, data: AddCrudItemMutation) => composeMockedQueryResult(addCRUDItemMutation, { variables: { newCrudItemData: { name } }, - data: data, + data, }); export const fillUpdateCRUDItemQuery = (id: string, name: string, data: UpdateCrudItemMutation) => composeMockedQueryResult(updateCRUDItemMutation, { variables: { updateCrudItemData: { name, id } }, - data: data, + data, }); diff --git a/apps/app/src/tests/setupTests.ts b/apps/app/src/tests/setupTests.ts index d961ac6..a518d1f 100644 --- a/apps/app/src/tests/setupTests.ts +++ b/apps/app/src/tests/setupTests.ts @@ -1,3 +1,19 @@ import '@testing-library/jest-dom'; import '@alp/api-client/tests/setupTests'; + +global.ResizeObserver = require('resize-observer-polyfill'); + +Object.defineProperty(window, 'matchMedia', { + writable: true, + value: jest.fn().mockImplementation((query) => ({ + matches: false, + media: query, + onchange: null, + addListener: jest.fn(), // Deprecated + removeListener: jest.fn(), // Deprecated + addEventListener: jest.fn(), + removeEventListener: jest.fn(), + dispatchEvent: jest.fn(), + })), +}); diff --git a/apps/app/src/theme/index.ts b/apps/app/src/theme/index.ts new file mode 100644 index 0000000..3d61a7d --- /dev/null +++ b/apps/app/src/theme/index.ts @@ -0,0 +1,13 @@ +'use client'; + +import { Button, createTheme } from '@mantine/core'; + +import classes from './theme.module.css'; + +export const theme = createTheme({ + components: { + Button: Button.extend({ + classNames: classes, + }), + }, +}); diff --git a/apps/app/src/theme/theme.module.css b/apps/app/src/theme/theme.module.css new file mode 100644 index 0000000..c228ee7 --- /dev/null +++ b/apps/app/src/theme/theme.module.css @@ -0,0 +1,10 @@ +.root { + &[data-variant='danger'] { + background-color: var(--mantine-color-red-9); + color: var(--mantine-color-red-0); + } + + &[data-variant='danger']:hover { + background-color: var(--mantine-color-red-7); + } +} \ No newline at end of file diff --git a/package.json b/package.json index 3190817..2ac1fe8 100644 --- a/package.json +++ b/package.json @@ -59,6 +59,7 @@ "lint-staged": "^13.2.2", "nx": "^16.9.1", "prettier": "^2.8.8", + "resize-observer-polyfill": "^1.5.1", "storybook": "^7.4.5", "storybook-dark-mode": "^3.0.1", "ts-jest": "^29.1.1", @@ -71,11 +72,13 @@ "@apollo/experimental-nextjs-app-support": "^0.8.0", "@apollo/server": "^4.10.0", "@emotion/react": "^11.11.1", - "@mantine/core": "^6.0.11", - "@mantine/form": "^6.0.17", - "@mantine/hooks": "^6.0.11", - "@mantine/modals": "^6.0.17", + "@mantine/core": "^7.10.1", + "@mantine/form": "^7.10.1", + "@mantine/hooks": "^7.10.1", + "@mantine/modals": "^7.10.1", "@tabler/icons-react": "^2.30.0", + "clsx": "^2.1.1", + "eslint-config-mantine": "^3.2.0", "graphql": "^16.8.1", "next": "14.1.2", "next-auth": "^4.24.6", @@ -83,6 +86,8 @@ "react": "^18.2.0", "react-dom": "^18.2.0", "react-intl": "^6.6.2", + "stylelint": "^16.9.0", + "stylelint-config-standard-scss": "^13.1.0", "typeorm": "^0.3.20", "zod": "^3.21.4" }, diff --git a/packages/core/src/components/backButton/backButton.component.tsx b/packages/core/src/components/backButton/backButton.component.tsx index b62caac..169a012 100644 --- a/packages/core/src/components/backButton/backButton.component.tsx +++ b/packages/core/src/components/backButton/backButton.component.tsx @@ -18,7 +18,7 @@ export const BackButton = ({ children }: BackButtonProps) => { }; return ( - ); diff --git a/packages/core/src/components/genericError/genericError.component.tsx b/packages/core/src/components/genericError/genericError.component.tsx index 6f1b69b..ccf5b7b 100644 --- a/packages/core/src/components/genericError/genericError.component.tsx +++ b/packages/core/src/components/genericError/genericError.component.tsx @@ -4,11 +4,9 @@ import { Container, Group, Text, Title } from '@mantine/core'; import { FormattedMessage } from 'react-intl'; import { Link } from '../link'; -import { useStyles } from './genericError.styles'; +import classes from './genericError.module.css'; export function GenericError() { - const { classes } = useStyles(); - return (
@@ -16,13 +14,13 @@ export function GenericError() { <FormattedMessage defaultMessage="Something went wrong" id="GenericError / Title" /> - + - + diff --git a/packages/core/src/components/genericError/genericError.module.css b/packages/core/src/components/genericError/genericError.module.css new file mode 100644 index 0000000..91c54a2 --- /dev/null +++ b/packages/core/src/components/genericError/genericError.module.css @@ -0,0 +1,32 @@ +.root { + padding-top: var(--mantine-spacing-xl); + padding-bottom: var(--mantine-spacing-xl); +} + +.inner { + position: relative; +} + +.image { + opacity: 0.75; +} + +.content { + padding-top: var(--mantine-spacing-xl); + position: relative; + z-index: 1; +} + +.title { + font-family: "Greycliff CF", var(--mantine-font-family); + text-align: center; + font-weight: 900; + font-size: var(--mantine-font-sizes-xl); +} + +.description { + max-width: var(--mantine-spacing-xl); + margin: auto; + margin-top: var(--mantine-spacing-xl); + margin-bottom: calc(var(--mantine-spacing-xl) * 1.5); +} \ No newline at end of file diff --git a/packages/core/src/components/genericError/genericError.styles.ts b/packages/core/src/components/genericError/genericError.styles.ts deleted file mode 100644 index 890e8ca..0000000 --- a/packages/core/src/components/genericError/genericError.styles.ts +++ /dev/null @@ -1,45 +0,0 @@ -import { createStyles, rem } from '@mantine/core'; - -export const useStyles = createStyles((theme) => ({ - root: { - paddingTop: rem(80), - paddingBottom: rem(80), - }, - - inner: { - position: 'relative', - }, - - image: { - ...theme.fn.cover(), - opacity: 0.75, - }, - - content: { - paddingTop: rem(220), - position: 'relative', - zIndex: 1, - - [theme.fn.smallerThan('sm')]: { - paddingTop: rem(120), - }, - }, - - title: { - fontFamily: `Greycliff CF, ${theme.fontFamily}`, - textAlign: 'center', - fontWeight: 900, - fontSize: rem(38), - - [theme.fn.smallerThan('sm')]: { - fontSize: rem(32), - }, - }, - - description: { - maxWidth: rem(540), - margin: 'auto', - marginTop: theme.spacing.xl, - marginBottom: `calc(${theme.spacing.xl} * 1.5)`, - }, -})); diff --git a/packages/core/src/components/languageSwitch/languageSwitch.component.tsx b/packages/core/src/components/languageSwitch/languageSwitch.component.tsx index 2dd5232..14d065a 100644 --- a/packages/core/src/components/languageSwitch/languageSwitch.component.tsx +++ b/packages/core/src/components/languageSwitch/languageSwitch.component.tsx @@ -4,7 +4,7 @@ import { Select } from '@mantine/core'; import { usePathname, useRouter } from 'next/navigation'; import { useCallback, useTransition } from 'react'; -import { Locale, i18n } from '../../config/i18n'; +import { i18n } from '../../config/i18n'; import { useLocales } from '../../hooks'; export const LanguageSwitch = () => { @@ -14,7 +14,7 @@ export const LanguageSwitch = () => { const { replace } = useRouter(); const onChange = useCallback( - (newLocales: Locale) => { + (newLocales: string | null) => { if (newLocales) { startTransition(() => { const days = 30; diff --git a/packages/core/src/components/themeToggler/themeToggler.component.tsx b/packages/core/src/components/themeToggler/themeToggler.component.tsx index 30ecb1a..be6dfa7 100644 --- a/packages/core/src/components/themeToggler/themeToggler.component.tsx +++ b/packages/core/src/components/themeToggler/themeToggler.component.tsx @@ -1,18 +1,20 @@ import { ActionIcon, useMantineColorScheme } from '@mantine/core'; import { IconMoonStars, IconSun } from '@tabler/icons-react'; +import classes from './themeToggler.module.css'; + export const ThemeToggler = () => { - const { colorScheme, toggleColorScheme } = useMantineColorScheme(); - const dark = colorScheme === 'dark'; + const { toggleColorScheme } = useMantineColorScheme(); return ( toggleColorScheme()} title="Toggle color scheme" + className={classes.root} > - {dark ? : } + + ); }; diff --git a/packages/core/src/components/themeToggler/themeToggler.module.css b/packages/core/src/components/themeToggler/themeToggler.module.css new file mode 100644 index 0000000..db302bc --- /dev/null +++ b/packages/core/src/components/themeToggler/themeToggler.module.css @@ -0,0 +1,18 @@ +.root { + color: light-dark( + var(--mantine-color-blue-5), + var(--mantine-color-yellow-5) + ); +} + +.iconDark { + @mixin light { + display: none; + } +} + +.iconLight { + @mixin dark { + display: none; + } +} \ No newline at end of file diff --git a/packages/core/src/providers/index.ts b/packages/core/src/providers/index.ts index 77e7c8e..3ce339c 100644 --- a/packages/core/src/providers/index.ts +++ b/packages/core/src/providers/index.ts @@ -1,3 +1,2 @@ -export * from './mantineProvider'; export * from './intlProvider'; export * from './localesProvider'; diff --git a/packages/core/src/providers/mantineProvider/MantineProvider.component.tsx b/packages/core/src/providers/mantineProvider/MantineProvider.component.tsx deleted file mode 100644 index 998cf38..0000000 --- a/packages/core/src/providers/mantineProvider/MantineProvider.component.tsx +++ /dev/null @@ -1,53 +0,0 @@ -import { - ColorScheme, - ColorSchemeProvider, - MantineProvider as DefaultMantineProvider, - useEmotionCache, -} from '@mantine/core'; -import { useColorScheme } from '@mantine/hooks'; -import { getCookie, setCookie } from 'cookies-next'; -import { useServerInsertedHTML } from 'next/navigation'; -import { PropsWithChildren, useCallback, useState } from 'react'; - -import { COLOR_SCHEME_COOKIE_NAME } from './MantineProvider.const'; - -export interface MantineProviderProps { - defaultColorScheme?: ColorScheme; -} - -export const MantineProvider = ({ children, defaultColorScheme }: PropsWithChildren) => { - const cache = useEmotionCache(); - cache.compat = true; - - useServerInsertedHTML(() => ( -