Skip to content

Commit

Permalink
Merge pull request #11 from MarkMelior/feature/VEES-17-themes
Browse files Browse the repository at this point in the history
VEES-17 | Сделать переключение тем
  • Loading branch information
MarkMelior authored Jan 10, 2025
2 parents 118f9b8 + 456806a commit 9c75256
Showing 52 changed files with 534 additions and 306 deletions.
10 changes: 1 addition & 9 deletions .stylelintrc.mjs
Original file line number Diff line number Diff line change
@@ -7,14 +7,7 @@ const config = {
],
plugins: ['stylelint-order', './config/stylelint/restrict-apply.js'],
rules: {
'custom-rules/restrict-apply': [
true, {
allowedPatterns: [
'^text-(sm|base|lg|xl|\\d+)$',
'^border',
],
},
],
'custom-rules/restrict-apply': [true, { allowedPatterns: [] }],
'declaration-empty-line-before': null,
'function-no-unknown': [
true,
@@ -104,7 +97,6 @@ const config = {
{
ignoreAtRules: [
'tailwind',
'apply',
'include',
'variants',
'responsive',
16 changes: 11 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -2,6 +2,8 @@

> Самое удобное приложение для записи результатов тренировок (:

- ✨🎨 Разработан [дизайн в Figma](https://www.figma.com/design/l7WmZZ7WKEr3YnVNdibxGD/Mobile-App?node-id=250-793&t=7fycS0Obh0DIcwXF-1)
- Собственный [UI Kit](/src/shared/ui/)
- Серверный рендеринг и [AppRouter](https://nextjs.org/docs/app)
@@ -17,6 +19,7 @@
![React 19](https://img.shields.io/badge/React_19-20232A?style=for-the-badge&logo=react&logoColor=61DAFB)
![TypeScript 5](https://img.shields.io/badge/TypeScript_5-007ACC?style=for-the-badge&logo=typescript&logoColor=white)
![Module SCSS](https://img.shields.io/badge/module_scss-CC6699?style=for-the-badge&logo=sass&logoColor=white)
![Feature-Sliced Design](https://img.shields.io/badge/FSD-3481FE?style=for-the-badge&logo=flat&logoColor=white)
![GIT](https://img.shields.io/badge/CI_/_CD-000000?style=for-the-badge&logo=github&logoColor=white)
![ESLint](https://img.shields.io/badge/ESLint-4B32C3?style=for-the-badge&logo=ESLint&logoColor=white)
![stylelint](https://img.shields.io/badge/stylelint-263238?style=for-the-badge&logo=stylelint&logoColor=white)
@@ -27,7 +30,7 @@

> Продемонстрировать свои навыки, это не про «усложнить проект»...
> *(всевозможные самописные утилиты, хуки, размазывание не переиспользуемого функционала по всей архитектуре, тесты на всё подряд)*.
>
> ~
> Настоящее мастерство находится в простоте `^-^`
@@ -55,10 +58,13 @@
##### SCSS

- [[custom-rules/restrict-apply](./config/stylelint/restrict-apply.js)] `@apply` можно использовать только для:
- размера текста: `text-sm` | `text-base` и т.п.
- border: `border...` и т.п.
- [[custom-rules/scss-import-name](./config/eslint/scss-import-name.js)] Импорт стилей из `.module.scss` нужно называть `styles`
- [[custom-rules/restrict-apply](./config/stylelint/restrict-apply.js)] `@apply` запрещено использовать;
- [[custom-rules/scss-import-name](./config/eslint/scss-import-name.js)] Импорт стилей из `.module.scss` нужно называть `styles`.

##### Tailwind

- Добавлять пользовательские цвета нужно в `/shared/theme.scss` формата RGB! Далее нужно добавить этот цвет в `/tailwind.config.ts`.
- Использовать переменную цвета нужно строго через `theme('colors.base.{50-950}')`. Через `var(--color-base-{50-950})` использовать запрещено!

---

4 changes: 2 additions & 2 deletions config/stylelint/restrict-apply.js
Original file line number Diff line number Diff line change
@@ -3,7 +3,7 @@ const stylelint = require('stylelint');
const ruleName = 'custom-rules/restrict-apply';

const messages = stylelint.utils.ruleMessages(ruleName, {
invalid: value => `The class "${value}" is not allowed in @apply.`,
invalid: (value) => `The class "${value}" is not allowed in @apply.`,
});

module.exports = stylelint.createPlugin(
@@ -21,7 +21,7 @@ module.exports = stylelint.createPlugin(

classes.forEach((className) => {
const isAllowed = allowedPatterns.some(
pattern => new RegExp(pattern).test(className),
(pattern) => new RegExp(pattern).test(className),
);

if (!isAllowed) {
9 changes: 9 additions & 0 deletions config/tailwind/colors.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
export const withOpacity = (variable: string): string =>
// @ts-ignore
(test) => {
if (test.opacityValue === undefined) {
return `rgb(var(--color-${variable}))`;
}

return `rgba(var(--color-${variable}), ${test.opacityValue})`;
};
7 changes: 5 additions & 2 deletions eslint.config.mjs
Original file line number Diff line number Diff line change
@@ -222,8 +222,11 @@ const eslintConfig = [
rules: { 'max-len': 'off' },
},
{
files: ['**/config/**/*.js'],
rules: { '@typescript-eslint/no-require-imports': 'off' },
files: ['**/config/**/*.{js,ts}'],
rules: {
'@typescript-eslint/ban-ts-comment': 'off',
'@typescript-eslint/no-require-imports': 'off',
},
},
];

159 changes: 86 additions & 73 deletions src/app/(with-navbar)/settings/ui/SettingsContent.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
'use client';

import { useTheme } from 'next-themes';

import {
ExportOutlineIcon,
FlashOutlineIcon,
@@ -11,78 +13,89 @@ import {
} from '@/shared/icons';
import { Button, Section } from '@/shared/ui';

import { ThemesModal } from '@/features/ThemesModal';

import styles from './settingsContent.module.scss';

export const SettingsContent = () => (
<>
<Section
items={[
{
color: '#1A80E5',
icon: <VeesIcon height={26} width={26} />,
onClick: () => { /* void */ },
title: 'Тренировки',
},
{
color: '#FFB21A',
icon: <FolderOutlineIcon />,
onClick: () => { /* void */ },
title: 'Настроить группы',
},
{
color: '#FA4838',
icon: <FlashOutlineIcon />,
onClick: () => { /* void */ },
title: 'Упражнения',
},
]}
/>
<Section
items={[
{
color: '#553FA6',
icon: <LangIcon />,
onClick: () => { /* void */ },
rightText: 'Русский',
title: 'Язык',
},
{
color: '#5AADF2',
icon: <ThemeIcon />,
onClick: () => { /* void */ },
rightText: 'Как в системе',
title: 'Оформление',
},
]}
/>
<Section
items={[
{
color: '#39C680',
description: 'Загрузить файл',
icon: <ImportOutlineIcon />,
onClick: () => { /* void */ },
title: 'Импорт настроек',
},
{
color: '#D15347',
description: 'Сохранить файл',
icon: <ExportOutlineIcon />,
onClick: () => { /* void */ },
title: 'Экспорт настроек',
},
]}
/>
<Button
className={styles.logout}
color="red"
disabled={true}
full={true}
radius="large"
size="large"
variant="bordered"
>
Выйти с аккаунта
</Button>
</>
);
const getThemeName = (theme: string | undefined) => {
switch (theme) {
case 'system':
return 'Как в системе';
case 'dark':
return 'Темная тема';
case 'light':
return 'Светлая тема';
default:
return 'Тема не выбрана';
}
};

export const SettingsContent = () => {
const { theme } = useTheme();

return (
<>
<Section>
<Section.Item
color="#1A80E5"
icon={<VeesIcon height={26} width={26} />}
title="Тренировки"
/>
<Section.Item
color="#FFB21A"
icon={<FolderOutlineIcon />}
title="Настроить группы"
/>
<Section.Item
color="#FA4838"
icon={<FlashOutlineIcon />}
showDivider={false}
title="Упражнения"
/>
</Section>
<Section>
<Section.Item
color="#553FA6"
icon={<LangIcon />}
rightText="Русский"
title="Язык"
/>
<ThemesModal>
<Section.Item
color="#5AADF2"
icon={<ThemeIcon />}
rightText={getThemeName(theme)}
showDivider={false}
title="Оформление"
/>
</ThemesModal>
</Section>
<Section>
<Section.Item
color="#39C680"
description="Загрузить файл"
icon={<ImportOutlineIcon />}
title="Импорт настроек"
/>
<Section.Item
color="#D15347"
description="Сохранить файл"
icon={<ExportOutlineIcon />}
showDivider={false}
title="Экспорт настроек"
/>
</Section>
<Button
className={styles.logout}
color="red"
disabled={true}
full={true}
radius="large"
size="large"
variant="bordered"
>
Выйти с аккаунта
</Button>
</>
);
};
5 changes: 0 additions & 5 deletions src/app/globals.scss
Original file line number Diff line number Diff line change
@@ -7,11 +7,6 @@ body {

background: linear-gradient(90deg, theme('colors.base.950') 15px, transparent 1%) 50%, linear-gradient(theme('colors.base.950') 15px, theme('colors.base.800') 1%) 0, hsl(0deg 0% 100% / 16%);
background-size: 16px 16px;

[data-mode="light"] & {
background: linear-gradient(90deg, theme('colors.base.100') 15px, transparent 1%) 50%, linear-gradient(theme('colors.base.100') 15px, theme('colors.base.300') 1%) 0, hsl(0deg 0% 100% / 16%);
background-size: 16px 16px;
}
}

::-webkit-scrollbar {
3 changes: 2 additions & 1 deletion src/app/layout.tsx
Original file line number Diff line number Diff line change
@@ -7,6 +7,7 @@ import type { Metadata } from 'next';

import './globals.scss';
import '@/shared/styles/custom.scss';
import '@/shared/styles/theme.scss';

const inter = Inter({
subsets: ['cyrillic', 'latin'],
@@ -26,7 +27,7 @@ const RootLayout = ({ children }: IRootLayout) => (
(
<html lang="ru" suppressHydrationWarning={true}>
<body className={inter.className}>
<ThemeProvider attribute="data-mode">
<ThemeProvider attribute="data-mode" defaultTheme="dark">
{children}
<Light />
<div id="modal-root" />
File renamed without changes.
38 changes: 38 additions & 0 deletions src/features/AddExerciseModal/model/mock.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import type { IGroupExercises } from '../ui/AddExerciseModal';

export const mockAddExerciseModal: IGroupExercises[] = [
{
color: '#FAC938',
exercises: ['Горизонтальная тяга', 'Подтягивания с доп. весом', 'Трансформер'],
name: 'Спина',
},
{
color: '#FA4838',
exercises: ['Разведения в кроссовере на одну руку', 'Разведение гантелей в стороны'],
name: 'Средние дельты',
},
{
color: '#00FF80',
exercises: [
'Французский жим лёжа',
'Жим лёжа узким хватом',
'Брусья с доп. весом', // TODO: Синхронизировать по ID
],
name: 'Трицепс',
},
{
color: '#1A80E5',
exercises: [
'Жим штанги',
'Жим гантелей в наклоне',
'Жим штанги в наклоне',
'Брусья с доп. весом', // TODO: Синхронизировать по ID
],
name: 'Грудь',
},
{
color: '#9B693B',
exercises: [],
name: 'Квадрицепсы',
},
];
Original file line number Diff line number Diff line change
@@ -35,15 +35,18 @@ export const AddExerciseModal = ({ items }: IAddExerciseModal) => {

return (
<ModalBase
action={{
icon: <SettingsOutlineIcon />,
onClick: () => { /* Redirect в настройки */ },
text: 'Настроить',
}}
button={(
<Button iconOnly={true}>
<AddOutlineIcon />
</Button>
)}
closeOnClickOverlay={!selectedGroup}
iconAction={<SettingsOutlineIcon />}
onClickOverlay={() => setSelectedGroup(null)}
textAction="Настроить"
title={(
<>
<div className={selectedGroup ? styles.visible : styles.hidden}>
Original file line number Diff line number Diff line change
@@ -10,10 +10,9 @@

background: theme('colors.base.900 / 75%');
border-radius: 1.25rem;
border: 1px solid theme('colors.base.400 / 15%');
overflow: clip;

@apply border border-base-400/15;

&:hover {
background: theme('colors.base.900 / 50%');
}
@@ -80,10 +79,9 @@
padding: 10px;

transition: background 0.3s ease;
border-bottom: 1px solid theme('colors.base.800');
cursor: pointer;

@apply border-b border-base-800;

&:hover {
background: theme('colors.base.800 / 50%');
}
Loading

0 comments on commit 9c75256

Please sign in to comment.