diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 2ae4d21..5f197af 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -8,6 +8,8 @@ "name": "frontend", "version": "0.1.0", "dependencies": { + "@next/font": "^14.2.15", + "classnames": "^2.5.1", "next": "15.1.3", "react": "^19.0.0", "react-dom": "^19.0.0" @@ -566,6 +568,14 @@ "fast-glob": "3.3.1" } }, + "node_modules/@next/font": { + "version": "14.2.15", + "resolved": "https://registry.npmjs.org/@next/font/-/font-14.2.15.tgz", + "integrity": "sha512-QopYhBmCDDrNDynbi+ZD1hDZXmQXVFo7TmAFp4DQgO/kogz1OLbQ92hPigJbj572eZ3GaaVxNIyYVn3/eAsehg==", + "peerDependencies": { + "next": "*" + } + }, "node_modules/@next/swc-darwin-arm64": { "version": "15.1.3", "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-15.1.3.tgz", @@ -1409,6 +1419,11 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, + "node_modules/classnames": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.5.1.tgz", + "integrity": "sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==" + }, "node_modules/client-only": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", diff --git a/frontend/package.json b/frontend/package.json index f7ee440..7228696 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -9,17 +9,19 @@ "lint": "next lint" }, "dependencies": { + "@next/font": "^14.2.15", + "classnames": "^2.5.1", + "next": "15.1.3", "react": "^19.0.0", - "react-dom": "^19.0.0", - "next": "15.1.3" + "react-dom": "^19.0.0" }, "devDependencies": { - "typescript": "^5", + "@eslint/eslintrc": "^3", "@types/node": "^20", "@types/react": "^19", "@types/react-dom": "^19", "eslint": "^9", "eslint-config-next": "15.1.3", - "@eslint/eslintrc": "^3" + "typescript": "^5" } -} +} \ No newline at end of file diff --git a/frontend/public/fonts/BebasNeue-Regular.ttf b/frontend/public/fonts/BebasNeue-Regular.ttf new file mode 100644 index 0000000..130cd82 Binary files /dev/null and b/frontend/public/fonts/BebasNeue-Regular.ttf differ diff --git a/frontend/public/fonts/Raleway-Italic-VariableFont_wght.ttf b/frontend/public/fonts/Raleway-Italic-VariableFont_wght.ttf new file mode 100644 index 0000000..59d63b2 Binary files /dev/null and b/frontend/public/fonts/Raleway-Italic-VariableFont_wght.ttf differ diff --git a/frontend/public/fonts/Raleway-regular.ttf b/frontend/public/fonts/Raleway-regular.ttf new file mode 100644 index 0000000..774b382 Binary files /dev/null and b/frontend/public/fonts/Raleway-regular.ttf differ diff --git a/frontend/public/fonts/Raleway-semi-bold.ttf b/frontend/public/fonts/Raleway-semi-bold.ttf new file mode 100644 index 0000000..33969e8 Binary files /dev/null and b/frontend/public/fonts/Raleway-semi-bold.ttf differ diff --git a/frontend/src/app/components/counter.tsx b/frontend/src/app/components/counter.tsx new file mode 100644 index 0000000..69d0bdd --- /dev/null +++ b/frontend/src/app/components/counter.tsx @@ -0,0 +1,13 @@ +"use client"; + +import { useState } from "react"; + +export const Counter = () => { + + const [count, setCount] = useState(0); + + console.log('Counter component - '); + return ( + + ) +} diff --git a/frontend/src/app/components/navigation.modules.css b/frontend/src/app/components/navigation.modules.css new file mode 100644 index 0000000..e69de29 diff --git a/frontend/src/app/components/navigation.tsx b/frontend/src/app/components/navigation.tsx new file mode 100644 index 0000000..8440138 --- /dev/null +++ b/frontend/src/app/components/navigation.tsx @@ -0,0 +1,35 @@ +"use client"; +import Link from "next/link"; +import { usePathname } from "next/navigation"; + +export const Navigation = () => { + const pathname = usePathname(); + return ( + + ); +}; diff --git a/frontend/src/app/components/page.tsx b/frontend/src/app/components/page.tsx new file mode 100644 index 0000000..1e9411d --- /dev/null +++ b/frontend/src/app/components/page.tsx @@ -0,0 +1,15 @@ +"use client"; + +import { useState } from "react"; + +export const D = () => { + + const [count, setCount] = useState(0); + + console.log('Counter component - '); + return ( + + ) +} + +export default D; diff --git a/frontend/src/app/globals.css b/frontend/src/app/globals.css deleted file mode 100644 index e3734be..0000000 --- a/frontend/src/app/globals.css +++ /dev/null @@ -1,42 +0,0 @@ -:root { - --background: #ffffff; - --foreground: #171717; -} - -@media (prefers-color-scheme: dark) { - :root { - --background: #0a0a0a; - --foreground: #ededed; - } -} - -html, -body { - max-width: 100vw; - overflow-x: hidden; -} - -body { - color: var(--foreground); - background: var(--background); - font-family: Arial, Helvetica, sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; -} - -* { - box-sizing: border-box; - padding: 0; - margin: 0; -} - -a { - color: inherit; - text-decoration: none; -} - -@media (prefers-color-scheme: dark) { - html { - color-scheme: dark; - } -} diff --git a/frontend/src/app/layout.tsx b/frontend/src/app/layout.tsx index 42fc323..923562a 100644 --- a/frontend/src/app/layout.tsx +++ b/frontend/src/app/layout.tsx @@ -1,20 +1,35 @@ import type { Metadata } from "next"; -import { Geist, Geist_Mono } from "next/font/google"; -import "./globals.css"; +import localFont from 'next/font/local' -const geistSans = Geist({ - variable: "--font-geist-sans", - subsets: ["latin"], +const bebas = localFont({ + weight: '500', + variable: '--font-bebas-regular', + src: '../../public/fonts/BebasNeue-Regular.ttf', + display: 'swap', }); - -const geistMono = Geist_Mono({ - variable: "--font-geist-mono", - subsets: ["latin"], +const ralewayRegular = localFont({ + weight: '500', + variable: '--font-raleway-regular', + src: '../../public/fonts/Raleway-Regular.ttf', + display: 'swap', +}); +const ralewayItalic = localFont({ + weight: '500', + variable: '--font-raleway-italic', + src: '../../public/fonts/Raleway-Italic-VariableFont_wght.ttf', + display: 'swap', }); +const ralewaySemiBold = localFont({ + weight: '500', + variable: '--font-raleway-semobold', + src: '../../public/fonts/Raleway-semi-bold.ttf', + display: 'swap', +}); + export const metadata: Metadata = { - title: "Create Next App", - description: "Generated by create next app", + title: "Дом молитвы", + description: "Церковь Евангельских христиан-баптистов", }; export default function RootLayout({ @@ -23,9 +38,11 @@ export default function RootLayout({ children: React.ReactNode; }>) { return ( - - + + +
header
{children} + ); diff --git a/frontend/src/app/page.tsx b/frontend/src/app/page.tsx index ae80e68..c96fc7d 100644 --- a/frontend/src/app/page.tsx +++ b/frontend/src/app/page.tsx @@ -1,5 +1,17 @@ +"use client" import Image from "next/image"; +import "../styles/reset.css"; +import "../styles/colours.css"; +import "../styles/semantic.css"; +import "../styles/sizes.css"; +import "../styles/globals.css"; + +import Typography from "@/components/atoms/typography/Typography"; +import Link from "@/components/atoms/link/Link"; +import { BlockColorProvider } from "@/components/atoms/ColorBlock/ColorBlock"; + + export default function Home() { return (
+ }} + > + Добро пожаловать в Дом молитвы + Добро пожаловать в Дом молитвы + Добро пожаловать в Дом молитвы + Церковь «Дом молитвы» - это христианская протестантская церковь, миссия которой направлена на служение людям + Некая цитата из Библии + ссылка ссылка ссылка в хедера + ссылка на темном + ссылка на светлом + ссылка на светлом дефолтном + + ссылка внешняя Логотип церкви('light'); + +interface BlockColorProviderProps { + children: ReactNode; + blockColor: BlockColor; +} + +export const BlockColorProvider: React.FC = ({ children, blockColor }) => { + return ( + +
+ {children} +
+
+ ); +}; diff --git a/frontend/src/components/atoms/link/Link.module.css b/frontend/src/components/atoms/link/Link.module.css new file mode 100644 index 0000000..d654508 --- /dev/null +++ b/frontend/src/components/atoms/link/Link.module.css @@ -0,0 +1,35 @@ +/* default link styles[on light] */ +.link { + color: var(--default-components-link-fg); + text-decoration: underline; + cursor: pointer; + font-family: var(--font-raleway-regular); +} + + +.link { + display: inline-block; + position: relative; + text-decoration: none; + transition: color 0.3s ease; +} + +/* Effect one: Underline - Inside Out */ +.link::before { + content: ""; + position: absolute; + width: 100%; + height: 1px; + bottom: -1px; + left: 0; + opacity: 0.33; + background-color: var(--default-components-link-fg); + transition: width 0.3s ease, left 0.3s ease; +} + +.link:hover::before { + width: 100%; + left: 0; + opacity: 1; + background-color: var(--default-components-link-fg); +} \ No newline at end of file diff --git a/frontend/src/components/atoms/link/Link.tsx b/frontend/src/components/atoms/link/Link.tsx new file mode 100644 index 0000000..eff5e88 --- /dev/null +++ b/frontend/src/components/atoms/link/Link.tsx @@ -0,0 +1,49 @@ + +import React, { FC, PropsWithChildren } from 'react'; +import NextLink from 'next/link'; +import classNames from "classnames"; + +import styles from "./Link.module.css"; + +type LinkProps = + | { + to: string; + href?: never; + target?: string; + } + | { + to?: never; + href: string; + target?: string; + }; + +const Link: FC & { onDark?: true }> = ({ + to, + href, + target, + children, +}) => { + const classes = classNames( + styles.link, + ); + + if (to) { + // Internal link using next/link + return ( + + {children} + + ); + } + + if (href) { + // External link + return ( + + {children} + + ); + } +}; + +export default Link; \ No newline at end of file diff --git a/frontend/src/components/atoms/typography/Typography.module.css b/frontend/src/components/atoms/typography/Typography.module.css new file mode 100644 index 0000000..1b67d1e --- /dev/null +++ b/frontend/src/components/atoms/typography/Typography.module.css @@ -0,0 +1,64 @@ +.typography { + margin: 0; + padding: 0; + color: var(--default-text-onlight); +} + +.onDark { + color: var(--default-text-ondark); +} + +/* Headings */ +.typography--h1 { + font-size: var(--font-font-size-h1-font-size); + font-weight: 500; + line-height: var(--font-line-heigh-h1); + font-family: var(--font-bebas-regular); +} + +.typography--h2 { + font-size: var(--font-font-size-h2-font-size); + font-weight: 500; + line-height: var(--font-line-heigh-h2); + font-family: var(--font-bebas-regular); +} + +.typography--h3 { + font-size: var(--font-font-size-h3-font-size); + font-weight: 500; + line-height: var(--font-line-heigh-h3); + font-family: var(--font-bebas-regular); +} + +/* Body */ +.typography--body { + font-size: var(--font-font-size-body-font-size); + line-height: var(--font-line-heigh-body); + font-family: var(--font-raleway-regular); +} + +.typography--body-mini { + font-size: var(--font-font-size-body-mini-font-size); + line-height: var(--font-line-heigh-body-mini); + font-family: var(--font-raleway-regular); +} + +.typography--bold { + font-weight: 600; + font-family: var(--font-raleway-semobold); +} + + +/* Quotes */ +.typography--quote { + font-style: italic; + font-family: var(--font-raleway-italic); +} + +/* Header */ +.typography--header { + font-size: var(--font-font-size-body-font-size); + font-weight: bold; + line-height: var(--font-line-heigh-header); + font-family: var(--font-raleway-regular); +} \ No newline at end of file diff --git a/frontend/src/components/atoms/typography/Typography.tsx b/frontend/src/components/atoms/typography/Typography.tsx new file mode 100644 index 0000000..f8ebd9b --- /dev/null +++ b/frontend/src/components/atoms/typography/Typography.tsx @@ -0,0 +1,64 @@ +import React, { FC, JSX } from "react"; +import classNames from "classnames"; + +import styles from "./Typography.module.css"; + + +type TypographyTag = "H1" | "H2" | "H3" | "body" | "body-mini" | "quote" | "header"; + +interface BaseTypographyProps { + tag: TypographyTag; + children: React.ReactNode; + className?: string; + onDark?: boolean; +} + +interface BodyTypographyProps extends BaseTypographyProps { + tag: "body"; + mini?: boolean; + bold?: boolean; +} + +type TypographyProps = + | BodyTypographyProps + | (BaseTypographyProps & { tag: Exclude }); + + +const Typography: FC = ({ + ...props +}) => { + const { tag, className, children } = props; + // Map tags to HTML elements + const tagMap: Record = { + H1: "h1", + H2: "h2", + H3: "h3", + body: "div", + ["body-mini"]: "div", + quote: "blockquote", + header: "div", + }; + + const Component = tagMap[tag]; + + const classes = classNames( + styles.typography, + styles[`typography--${tag.toLowerCase()}`], + { + [styles["typography--bold"]]: tag === "body" && props?.bold, + [styles["onDark"]]: props?.onDark + }, + className + ); + + return ( + + {children} + + ); + +} + +export default Typography; diff --git a/frontend/src/styles/colours.css b/frontend/src/styles/colours.css new file mode 100644 index 0000000..6c85bd6 --- /dev/null +++ b/frontend/src/styles/colours.css @@ -0,0 +1,43 @@ +:root { + --brand-100: #e6eaec; + --brand-200: #c7d1d1; + --common-light-100: #f8f6f7; + --brand-300: #abb5b8; + --brand-400: #949fa1; + --brand-500: #849193; + --brand-600: #7a8a8d; + --brand-700: #67787a; + --brand-800: #586a6e; + --brand-900: #445e60; + --accent-100: #e1eae6; + --accent-200: #c8d1ce; + --accent-300: #acb8b2; + --accent-400: #93a29b; + --accent-500: #83958c; + --accent-600: #7a8e85; + --accent-700: #687a72; + --accent-800: #5a6e64; + --accent-900: #486054; + --common-transparent-0: #ffffff; + --common-light-0: #ffffff; + --brand-0: #eeeeee; + --common-transparent-100: #ffffff; + --common-transparent-200: #ffffff; + --common-transparent-300: #ffffff; + --common-transparent-400: #ffffff; + --common-transparent-500: #ffffff; + --common-transparent-600: #ffffff; + --common-transparent-700: #ffffff; + --common-transparent-800: #ffffff; + --common-transparent-900: #ffffff; + --common-dark-900: #3d444a; + --common-dark-800: #5f646a; + --common-dark-700: #6d7175; + --common-dark-600: #7f8488; + --common-dark-500: #888b8d; + --common-dark-400: #999a9a; + --common-dark-300: #d7d7d7; + --common-dark-200: #e0e0e0; + --common-dark-100: #e7e7e7; + --common-dark-0: #ffffff; +} \ No newline at end of file diff --git a/frontend/src/styles/globals.css b/frontend/src/styles/globals.css new file mode 100644 index 0000000..a27a085 --- /dev/null +++ b/frontend/src/styles/globals.css @@ -0,0 +1,13 @@ +html, +body { + max-width: 100vw; + overflow-x: hidden; +} + +body { + color: var(--default-text-onlight); + background: var(--default-surface-light); + font-family: Arial, Helvetica, sans-serif; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} \ No newline at end of file diff --git a/frontend/src/styles/reset.css b/frontend/src/styles/reset.css new file mode 100644 index 0000000..83676e3 --- /dev/null +++ b/frontend/src/styles/reset.css @@ -0,0 +1,138 @@ +* { + box-sizing: border-box; + margin: 0; + padding: 0; +} + +html, +body, +div, +span, +applet, +object, +iframe, +h1, +h2, +h3, +h4, +h5, +h6, +p, +blockquote, +pre, +a, +abbr, +acronym, +address, +big, +cite, +code, +del, +dfn, +em, +img, +ins, +kbd, +q, +s, +samp, +small, +strike, +strong, +sub, +sup, +tt, +var, +b, +u, +i, +center, +dl, +dt, +dd, +ol, +ul, +li, +fieldset, +form, +label, +legend, +table, +caption, +tbody, +tfoot, +thead, +tr, +th, +td, +article, +aside, +canvas, +details, +embed, +figure, +figcaption, +footer, +header, +hgroup, +menu, +nav, +output, +ruby, +section, +summary, +time, +mark, +audio, +video { + margin: 0; + padding: 0; + border: 0; + vertical-align: baseline; +} + +article, +aside, +details, +figcaption, +figure, +footer, +header, +hgroup, +menu, +nav, +section { + display: block; +} + + +body { + line-height: 1; +} + +ol, +ul { + list-style: none; +} + +blockquote, +q { + quotes: none; +} + +blockquote:before, +blockquote:after, +q:before, +q:after { + content: none; +} + +table { + border-collapse: collapse; + border-spacing: 0; +} + +a { + color: inherit; + text-decoration: none; +} \ No newline at end of file diff --git a/frontend/src/styles/semantic.css b/frontend/src/styles/semantic.css new file mode 100644 index 0000000..8f30a3a --- /dev/null +++ b/frontend/src/styles/semantic.css @@ -0,0 +1,50 @@ +:root { + --default-components-button-outlined-br: var(--common-light-100); + --default-components-button-outlined-bg: var(--common-transparent-0); + --default-components-button-outlined-fg: var(--common-light-100); + --default-components-button-filled-fg: var(--common-light-100); + --default-components-button-filled-bg: var(--brand-700); + --default-surface-light: var(--common-light-100); + --default-surface-dark-1: var(--accent-800); + --default-surface-dark-2: var(--brand-600); + --default-components-cart-border: var(--common-dark-800); + + --default-text-brand: var(--brand-800); + + + --hover-components-button-outlined-br: var(--common-light-100); + + --hover-components-button-outlined-bg: var(--common-light-100); + --hover-components-button-outlined-fg: var(--text-onlight); + --hover-components-button-filled-fg: var(--common-light-100); + --hover-components-button-filled-bg: var(--brand-900); + --hover-surface-light: var(--common-light-100); + --hover-surface-dark-1: var(--accent-800); + --hover-surface-dark-2: var(--brand-500); + --hover-components-cart-border: var(--common-dark-800); + + --hover-text-brand: var(--brand-800); + + + --active-components-button-outlined-br: var(--common-light-100); + + --active-components-button-outlined-bg: var(--common-light-100); + --active-components-button-outlined-fg: var(--text-onlight); + --active-components-button-filled-fg: var(--common-light-100); + --active-components-button-filled-bg: var(--brand-900); + --active-surface-light: var(--common-light-100); + --active-surface-dark-1: var(--accent-800); + --active-surface-dark-2: var(--brand-500); + --active-components-cart-border: var(--common-dark-800); + + --active-text-brand: var(--brand-800); + + + /* light block default*/ + --default-text: var(--common-dark-900); + --default-components-link-fg: #547478; + --hover-text: var(--common-dark-900); + --hover-components-link-fg: #4b5e60; + --active-text-onlight: var(--common-dark-900); + --active-components-link-fg: #596e71; +} \ No newline at end of file diff --git a/frontend/src/styles/sizes.css b/frontend/src/styles/sizes.css new file mode 100644 index 0000000..f11318c --- /dev/null +++ b/frontend/src/styles/sizes.css @@ -0,0 +1,95 @@ +/* Mobile-specific variables */ +@media (min-width: 375px) { + :root { + --button-border-radious: 4px; + --font-font-size-h1-font-size: 36px; + --font-font-size-h2-font-size: 32px; + --font-font-size-h3-font-size: 24px; + --font-line-heigh-h1: 48px; + --font-line-heigh-h2: 40px; + --font-line-heigh-h3: 30px; + --font-line-heigh-body: 22px; + --font-line-heigh-button: 20px; + --font-font-size-body-font-size: 18px; + --font-font-size-button-font-size: 16px; + --spacing-xs: 6px; + --spacing-x: 10px; + --spacing-s: 14px; + --spacing-m: 16px; + --spacing-l: 20px; + --spacing-xl: 24px; + --spacing-2xl: 32px; + --spacing-3xl: 40px; + --button-min-width: 150px; + --max-text-column-width: 300px; + --button-max-width: 350px; + --spacing-4xl: 48px; + --font-line-heigh-header: 20px; + --font-font-size-body-mini-font-size: 12px; + --font-line-heigh-body-mini: 16px; + } +} + +/* Tabler-specific variables */ +@media (min-width: 641px) { + :root { + --button-border-radious: 4px; + --font-font-size-h1-font-size: 48px; + --font-font-size-h2-font-size: 40px; + --font-font-size-h3-font-size: 28px; + --font-line-heigh-h1: 60px; + --font-line-heigh-h2: 50px; + --font-line-heigh-h3: 36px; + --font-line-heigh-body: 24px; + --font-line-heigh-button: 22px; + --font-font-size-body-font-size: 20px; + --font-font-size-button-font-size: 18px; + --spacing-xs: 8px; + --spacing-x: 12px; + --spacing-s: 16px; + --spacing-m: 20px; + --spacing-l: 24px; + --spacing-xl: 32px; + --spacing-2xl: 40px; + --spacing-3xl: 60px; + --button-min-width: 150px; + --max-text-column-width: 500px; + --button-max-width: 350px; + --spacing-4xl: 64px; + --font-line-heigh-header: 22px; + --font-font-size-body-mini-font-size: 14px; + --font-line-heigh-body-mini: 18px; + } +} + +/* Desktop-specific variables */ +@media (min-width: 1280px) { + :root { + --button-border-radious: 4px; + --font-font-size-h1-font-size: 54px; + --font-font-size-h2-font-size: 50px; + --font-font-size-h3-font-size: 32px; + --font-line-heigh-h1: 60px; + --font-line-heigh-h2: 56px; + --font-line-heigh-h3: 38px; + --font-line-heigh-body: 28px; + --font-line-heigh-button: 20px; + --font-font-size-body-font-size: 22px; + --font-font-size-button-font-size: 20px; + --spacing-xs: 8px; + --spacing-x: 12px; + --spacing-s: 16px; + --spacing-m: 20px; + --spacing-l: 24px; + --spacing-xl: 32px; + --spacing-2xl: 48px; + --spacing-3xl: 64px; + --button-min-width: 200px; + --max-text-column-width: 990px; + --button-max-width: 350px; + --spacing-4xl: 96px; + --font-line-heigh-header: 24px; + --font-font-size-body-mini-font-size: 16px; + --font-line-heigh-body-mini: 20px; + } +} \ No newline at end of file