4 Commits
Author SHA1 Message Date
Joe_Peach 9ec5e852c6 Merge pull request 'Feat/main page' (#2) from feat/main-page into dev
Reviewed-on: #2
2026-09-25 16:56:27 +00:00
Joe_Peach 2048c17eee made main page 2026-09-25 12:33:07 +03:00
Joe_Peach b98b531162 fixed colors and added assets 2026-09-25 12:32:46 +03:00
Joe_Peach 6770eba5b6 create navigation card-button 2026-09-25 12:32:15 +03:00
10 changed files with 237 additions and 37 deletions

No files matched your search

Binary file not shown.

After

Width:  |  Height:  |  Size: 193 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 450 KiB

@@ -0,0 +1,100 @@
.card {
position: relative;
display: grid;
min-height: 220px;
gap: var(--space-4);
align-content: start;
padding: var(--space-8);
overflow: hidden;
text-align: left;
color: var(--color-text);
cursor: pointer;
background:
linear-gradient(135deg, rgba(255, 255, 255, 0.08), rgba(255, 255, 255, 0)),
var(--color-surface);
border: 1px solid var(--color-border);
border-radius: var(--radius-md);
box-shadow: var(--shadow-sm);
transition:
border-color var(--duration-fast) var(--ease-standard),
box-shadow var(--duration-fast) var(--ease-standard),
transform var(--duration-fast) var(--ease-standard);
}
.card::before {
position: absolute;
inset: auto -28px -58px auto;
width: 180px;
height: 180px;
content: "";
background: radial-gradient(circle, var(--card-accent), transparent 66%);
opacity: 0.24;
}
.card:hover {
border-color: var(--card-accent);
box-shadow: var(--shadow-lg);
transform: translateY(-4px);
}
.card:focus-visible {
outline: 3px solid var(--card-focus);
outline-offset: 3px;
}
.cyan {
--card-accent: var(--color-primary);
--card-focus: var(--color-primary-soft);
}
.violet {
--card-accent: var(--color-accent);
--card-focus: rgba(143, 84, 255, 0.24);
}
.kicker {
width: fit-content;
padding: var(--space-2) var(--space-3);
font-size: 12px;
font-weight: 800;
line-height: 1;
color: var(--color-black);
text-transform: uppercase;
letter-spacing: 0;
background: var(--card-accent);
border-radius: var(--radius-sm);
}
.title {
max-width: 12ch;
font-size: clamp(28px, 5vw, 48px);
font-weight: 900;
line-height: 1;
}
.description {
max-width: 34ch;
color: var(--color-text-muted);
}
.action {
display: inline-flex;
width: fit-content;
align-items: center;
padding-block: var(--space-2);
margin-top: auto;
font-weight: 800;
color: var(--card-accent);
}
.action::after {
margin-left: var(--space-2);
content: "->";
}
@media (max-width: 640px) {
.card {
min-height: 190px;
padding: var(--space-6);
}
}
@@ -0,0 +1,31 @@
import styles from "./GeneratorCard.module.css";
interface GeneratorCardProps{
title: string;
description: string;
label: string;
accent: "cyan" | "violet";
onClick: () => void;
};
export default function GeneratorCard({
title,
description,
label,
accent,
onClick,
}: GeneratorCardProps) {
return (
<button
className={`${styles.card} ${styles[accent]}`}
type="button"
onClick={onClick}
aria-label={label}
>
<span className={styles.kicker}>{label}</span>
<span className={styles.title}>{title}</span>
<span className={styles.description}>{description}</span>
<span className={styles.action}>Открыть</span>
</button>
);
}
+1 -1
View File
@@ -1,4 +1,4 @@
.layout {
min-height: 100vh;
padding-block: var(--space-8);
/*padding-block: var(--space-8);*/
}
+1 -2
View File
@@ -1,5 +1,4 @@
import { Navigate, Outlet } from "react-router-dom";
import { useAppSelector } from "../../store/hooks";
import { Outlet } from "react-router-dom";
import styles from "./Layout.module.css";
export default function Layout() {
+38 -5
View File
@@ -1,15 +1,48 @@
.page {
display: grid;
gap: var(--space-12);
min-height: 100vh;
padding: var(--space-10);
align-content: center;
background: var(--color-bg);
}
.hero {
display: grid;
justify-items: center;
gap: var(--space-4);
text-align: center;
}
.logo {
width: min(540px, 86vw);
height: auto;
object-fit: contain;
filter: drop-shadow(0 24px 56px rgba(53, 216, 255, 0.2));
}
.title {
margin: 0;
font-size: 32px;
line-height: 1.15;
font-size: clamp(40px, 8vw, 88px);
font-weight: 900;
line-height: 0.95;
color: var(--color-text);
text-shadow: 0 0 32px rgba(53, 216, 255, 0.28);
}
.text {
margin: 0;
color: var(--color-text-muted);
.cards {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: var(--space-6);
}
@media (max-width: 760px) {
.page {
gap: var(--space-8);
padding-block: var(--space-8);
}
.cards {
grid-template-columns: 1fr;
}
}
+32 -5
View File
@@ -1,15 +1,42 @@
import { useNavigate } from "react-router-dom";
import GeneratorCard from "../../components/GeneratorCard/GeneratorCard";
import logo from "../../assets/common/HITGENERATOR-Logo.png";
import styles from "./Main.module.css";
import {useNavigate} from "react-router-dom";
export default function Main() {
const navigate = useNavigate();
return (
<main className={styles.page}>
<h1 className={styles.title}>Главная</h1>
<p className={styles.text}>Базовая страница приложения готова.</p>
<button onClick={() => navigate('/picture')}>Go to Picture</button>
<button onClick={() => navigate('/video')}>Go to Video</button>
<section className={styles.hero} aria-labelledby="main-title">
<img
className={styles.logo}
src={logo}
alt="ShitGenerator"
width="1080"
height="608"
/>
<h1 className={styles.title} id="main-title">
ShitGenerator
</h1>
</section>
<section className={styles.cards} aria-label="Выбор генератора">
<GeneratorCard
title="Генерация видео"
description="Собирай видеоролики из идеи, промпта и нужного визуального направления."
label="Видео"
accent="cyan"
onClick={() => navigate("/video")}
/>
<GeneratorCard
title="Генерация картинок"
description="Создавай изображения под задачу, стиль и настроение за пару кликов."
label="Картинки"
accent="violet"
onClick={() => navigate("/picture")}
/>
</section>
</main>
);
}
+5 -1
View File
@@ -1,5 +1,9 @@
body {
background: var(--color-bg);
background-image: url('../assets/common/background.jpeg');
background-size: cover;
background-position: center;
background-repeat: no-repeat;
background-attachment: fixed;
color: var(--color-text);
font-family: var(--font-family-base);
line-height: 1.5;
+29 -23
View File
@@ -6,18 +6,21 @@
sans-serif;
--color-white: #ffffff;
--color-black: #0b1220;
--color-gray-50: #f8fafc;
--color-gray-100: #f1f5f9;
--color-gray-200: #e2e8f0;
--color-gray-300: #cbd5e1;
--color-gray-500: #64748b;
--color-gray-600: #475569;
--color-gray-700: #334155;
--color-gray-900: #0f172a;
--color-teal-50: #ecfeff;
--color-teal-600: #0d9488;
--color-teal-700: #0f766e;
--color-black: #030610;
--color-gray-50: #f6f8ff;
--color-gray-100: #ecf2ff;
--color-gray-200: #d8e3fb;
--color-gray-300: #b8c7e7;
--color-gray-500: #7888aa;
--color-gray-600: #52617f;
--color-gray-700: #243452;
--color-gray-900: #07142d;
--color-cyan-50: #e9fbff;
--color-cyan-400: #35d8ff;
--color-cyan-600: #0899d8;
--color-violet-500: #8f54ff;
--color-coral-500: #ff6b79;
--color-gold-400: #ffc96b;
--color-rose-50: #fff1f2;
--color-rose-200: #fecdd3;
--color-rose-700: #be123c;
@@ -25,15 +28,18 @@
--color-green-200: #bbf7d0;
--color-green-800: #166534;
--color-bg: var(--color-gray-50);
--color-surface: var(--color-white);
--color-surface-muted: var(--color-gray-100);
--color-text: var(--color-gray-900);
--color-text-muted: var(--color-gray-600);
--color-border: var(--color-gray-200);
--color-primary: var(--color-teal-700);
--color-primary-hover: #115e59;
--color-primary-soft: rgba(13, 148, 136, 0.12);
--color-bg: #050914;
--color-surface: rgba(9, 18, 42, 0.86);
--color-surface-muted: rgba(17, 32, 67, 0.78);
--color-text: #f7fbff;
--color-text-muted: #aab8d8;
--color-border: rgba(82, 208, 255, 0.22);
--color-primary: var(--color-cyan-400);
--color-primary-hover: var(--color-gold-400);
--color-primary-soft: rgba(53, 216, 255, 0.16);
--color-accent: var(--color-violet-500);
--color-accent-warm: var(--color-coral-500);
--color-accent-gold: var(--color-gold-400);
--color-danger-bg: var(--color-rose-50);
--color-danger-border: var(--color-rose-200);
--color-danger-text: var(--color-rose-700);
@@ -55,8 +61,8 @@
--radius-md: 8px;
--radius-lg: 12px;
--shadow-sm: 0 1px 2px rgba(15, 23, 42, 0.08);
--shadow-lg: 0 24px 80px rgba(15, 23, 42, 0.14);
--shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.24);
--shadow-lg: 0 24px 80px rgba(0, 0, 0, 0.36);
--duration-fast: 160ms;
--ease-standard: ease;