feat: компонент фильтр-чипов в дизайн-систему + фильтр проектов на /ai-dev/

This commit is contained in:
Nikolay Mamadaev committed 2026-10-07 13:05:10 +02:00
1 parent 52485a17c4
commit ee0dca11a2
9 files changed
+761 -527

No files matched your search

+196 -262
View File
@@ -5,12 +5,16 @@
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" />
<meta
name="description"
content="Николай Мамадаев, AI-разработчик. Делаю целые продукты: Telegram-боты, MCP-серверы, плагины для Figma и Obsidian, desktop-утилиты."
content="Николай Мамадаев, AI-разработник. Делаю целые продукты: Telegram-боты, MCP-серверы, плагины для Figma и Obsidian, desktop-утилиты."
/>
<title>AI-разработка · Николай Мамадаев</title>
{{> head-links}}
{{> head-plyr}}
<style>
/* Локальные правила страницы. Всё остальное — компоненты дизайн-системы:
.contact-grid (сетка), .mp-card (карточка), .filter-chips (переключатель),
.mp-card__tags/.mp-card__tag (метаданные), .case-links-grid (ссылки),
.hero__tags/.hero__tag (список навыков). */
.ai-page {
max-width: 52rem;
margin: 0 auto;
@@ -28,24 +32,19 @@
.ai-page a:not(.btn) {
color: var(--accent);
}
/* Сетка карточек проектов: 2 колонки, схлопывается в одну на мобильном */
/* Сетка проектов: контракт .contact-grid, но 2 колонки и шире минимальная
колонка — карточкам нужен воздух. Сама сетка и её адаптив из системы. */
.ai-projects {
list-style: none;
margin: 1.25rem 0 0;
padding: 0;
display: grid;
grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
gap: 1rem;
}
.ai-projects > li {
margin: 0;
margin-bottom: 0;
}
/* Обложка- заглушка внутри карточки. */
.ai-projects__media {
border-radius: var(--radius-md);
border-radius: var(--radius-sm);
overflow: hidden;
border: 1px solid var(--line);
margin-bottom: 0.7rem;
background: var(--surface);
background: var(--bg-elevated);
}
.ai-projects__media img {
display: block;
@@ -54,56 +53,19 @@
aspect-ratio: 16 / 10;
object-fit: cover;
}
.ai-projects__head {
display: flex;
align-items: baseline;
justify-content: space-between;
gap: 0.75rem;
}
.ai-projects__title {
margin: 0;
font-size: 1.05rem;
font-weight: 600;
color: var(--text);
}
/* Стек проекта — моноширинный, как .filter-chip__count в системе. */
.ai-projects__stack {
margin: 0.3rem 0 0;
font-family: var(--font-mono, ui-monospace, monospace);
font-size: 0.78rem;
color: var(--text-muted);
}
.ai-projects__desc {
margin: 0.45rem 0 0;
font-size: 0.95rem;
color: var(--text);
}
.ai-projects__links {
list-style: none;
margin: 0.6rem 0 0;
padding: 0;
display: flex;
flex-wrap: wrap;
gap: 0.4rem 0.9rem;
font-size: 0.85rem;
}
/* Навыки — компактные чипы переиспользуют стили тегов карточек активности */
.ai-stack-list {
list-style: none;
margin: 1rem 0 0;
padding: 0;
display: flex;
flex-wrap: wrap;
gap: 0.45rem;
}
.ai-stack-list li {
margin: 0;
padding: 0.3rem 0.7rem;
border: 1px solid var(--line);
border-radius: 999px;
font-family: var(--font-mono, ui-monospace, monospace);
font-size: 0.8rem;
font-size: 0.76rem;
line-height: 1.4;
color: var(--text-muted);
}
/* У mp-card--compact теги уходят вниз карточки (order 2) — оставляем
стек под заголовком, поэтому поднимаем его наравне с описанием. */
.mp-card--compact .ai-projects__stack {
order: 1;
}
</style>
</head>
<body>
@@ -123,228 +85,200 @@
</p>
<h2 id="roles">Что я делаю</h2>
<ul class="section__prose ai-stack-list">
<li>Продуктовая логика и API</li>
<li>Telegram-боты на aiogram 3</li>
<li>MCP-серверы</li>
<li>Плагины Figma и Obsidian</li>
<li>Автоматизация и агентные пайплайны</li>
<ul class="section__prose hero__tags" aria-label="Что я делаю">
<li class="hero__tag">Продуктовая логика и API</li>
<li class="hero__tag">Telegram-боты на aiogram 3</li>
<li class="hero__tag">MCP-серверы</li>
<li class="hero__tag">Плагины Figma и Obsidian</li>
<li class="hero__tag">Автоматизация и агентные пайплайны</li>
</ul>
<h2 id="projects">Проекты</h2>
<ol class="ai-projects">
<li>
<div class="ai-projects__media">
<img
src="{{assetPrefix}}assets/ai-dev/placeholder-01.webp"
alt=""
width="640"
height="400"
loading="lazy"
decoding="async"
/>
</div>
<div class="ai-projects__head">
<h3 class="ai-projects__title">Personal Assistant</h3>
</div>
<p class="ai-projects__stack">Python · aiogram 3 · PostgreSQL</p>
<p class="ai-projects__desc">
Личный ассистент в Telegram: напоминания, планирование дел и работа с LLM
в одном диалоге.
</p>
<ul class="ai-projects__links">
<li><a href="{{casesPrefix}}ai-platform-primo-rpa/" target="_blank" rel="noopener noreferrer">Кейс</a></li>
</ul>
<ul class="filter-chips" data-filter-chips data-filter-scope="#ai-projects" aria-label="Фильтр проектов по типу">
<li><button type="button" class="filter-chip" data-filter-value="all" aria-pressed="true">Все</button></li>
<li><button type="button" class="filter-chip" data-filter-value="bots" aria-pressed="false">Бots</button></li>
<li><button type="button" class="filter-chip" data-filter-value="mcp" aria-pressed="false">MCP</button></li>
<li><button type="button" class="filter-chip" data-filter-value="plugins" aria-pressed="false">Плагины</button></li>
<li><button type="button" class="filter-chip" data-filter-value="web" aria-pressed="false">Веб</button></li>
</ul>
<ol class="contact-grid ai-projects" id="ai-projects">
<li data-filter-item data-filter-tag="bots">
<article class="mp-card mp-card--compact" data-glass="false">
<div class="mp-card__media ai-projects__media" aria-hidden="true">
<img class="mp-card__image" src="{{assetPrefix}}assets/ai-dev/placeholder-01.webp" alt="" width="640" height="400" loading="lazy" decoding="async" />
</div>
<div class="mp-card__body">
<h3 class="mp-card__title">Personal Assistant</h3>
<p class="ai-projects__stack">Python · aiogram 3 · PostgreSQL</p>
<p class="mp-card__desc">Личный ассистент в Telegram: напоминания, планирование дел и работа с LLM в одном диалоге.</p>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">Боты</li>
</ul>
</div>
</article>
</li>
<li>
<div class="ai-projects__media">
<img
src="{{assetPrefix}}assets/ai-dev/placeholder-02.webp"
alt=""
width="640"
height="400"
loading="lazy"
decoding="async"
/>
</div>
<div class="ai-projects__head">
<h3 class="ai-projects__title">Image Gen Bot</h3>
</div>
<p class="ai-projects__stack">Python · aiogram 3 · Redis · PostgreSQL</p>
<p class="ai-projects__desc">
Бот для генерации изображений: баланс, реферальная программа, админ-логи
в отдельные топики супергруппы.
</p>
<ul class="ai-projects__links">
<li><a href="{{casesPrefix}}ai-platform-primo-rpa/" target="_blank" rel="noopener noreferrer">Кейс</a></li>
</ul>
<li data-filter-item data-filter-tag="bots">
<article class="mp-card mp-card--compact" data-glass="false">
<div class="mp-card__media ai-projects__media" aria-hidden="true">
<img class="mp-card__image" src="{{assetPrefix}}assets/ai-dev/placeholder-02.webp" alt="" width="640" height="400" loading="lazy" decoding="async" />
</div>
<div class="mp-card__body">
<h3 class="mp-card__title">Image Gen Bot</h3>
<p class="ai-projects__stack">Python · aiogram 3 · Redis · PostgreSQL</p>
<p class="mp-card__desc">Бот для генерации изображений: баланс, реферальная программа, админ-логи в отдельные топики супергруппы.</p>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">Боты</li>
</ul>
</div>
</article>
</li>
<li>
<div class="ai-projects__media">
<img
src="{{assetPrefix}}assets/ai-dev/placeholder-03.webp"
alt=""
width="640"
height="400"
loading="lazy"
decoding="async"
/>
</div>
<div class="ai-projects__head">
<h3 class="ai-projects__title">MCP Image Server</h3>
</div>
<p class="ai-projects__stack">JavaScript · MCP · OpenRouter</p>
<p class="ai-projects__desc">
Собственный MCP-сервер для генерации картинок. Подключается к агентам
как инструмент.
</p>
<ul class="ai-projects__links">
<li><a href="http://x1qnvk08zec2u5cx6yh5iexh.155.212.186.39.sslip.io/admin/mcp-img-gen" target="_blank" rel="noopener noreferrer">Код</a></li>
</ul>
<li data-filter-item data-filter-tag="mcp bots">
<article class="mp-card mp-card--compact" data-glass="false">
<div class="mp-card__media ai-projects__media" aria-hidden="true">
<img class="mp-card__image" src="{{assetPrefix}}assets/ai-dev/placeholder-03.webp" alt="" width="640" height="400" loading="lazy" decoding="async" />
</div>
<div class="mp-card__body">
<h3 class="mp-card__title">MCP Image Server</h3>
<p class="ai-projects__stack">JavaScript · MCP · OpenRouter</p>
<p class="mp-card__desc">Собственный MCP-сервер для генерации картинок. Подключается к агентам как инструмент.</p>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">MCP</li>
</ul>
</div>
</article>
</li>
<li>
<div class="ai-projects__media">
<img
src="{{assetPrefix}}assets/ai-dev/placeholder-01.webp"
alt=""
width="640"
height="400"
loading="lazy"
decoding="async"
/>
</div>
<div class="ai-projects__head">
<h3 class="ai-projects__title">AI assistant</h3>
</div>
<p class="ai-projects__stack">TypeScript · Figma Plugin API</p>
<p class="ai-projects__desc">
Плагин для Figma, который исполняет скрипты прямо в редакторе.
ИИ-ассистент для любого тарифа.
</p>
<ul class="ai-projects__links">
<li><a href="{{casesPrefix}}ai-assistant-figma/" target="_blank" rel="noopener noreferrer">Кейс</a></li>
</ul>
<li data-filter-item data-filter-tag="plugins">
<article class="mp-card mp-card--compact" data-glass="false">
<div class="mp-card__media ai-projects__media" aria-hidden="true">
<img class="mp-card__image" src="{{assetPrefix}}assets/ai-dev/placeholder-01.webp" alt="" width="640" height="400" loading="lazy" decoding="async" />
</div>
<div class="mp-card__body">
<h3 class="mp-card__title">AI assistant</h3>
<p class="ai-projects__stack">TypeScript · Figma Plugin API</p>
<p class="mp-card__desc">Плагин для Figma, который исполняет скрипты прямо в редакторе. ИИ-ассистент для любого тарифа.</p>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">Плагины</li>
</ul>
</div>
</article>
</li>
<li>
<div class="ai-projects__media">
<img
src="{{assetPrefix}}assets/ai-dev/placeholder-02.webp"
alt=""
width="640"
height="400"
loading="lazy"
decoding="async"
/>
</div>
<div class="ai-projects__head">
<h3 class="ai-projects__title">Card Columns</h3>
</div>
<p class="ai-projects__stack">TypeScript · Obsidian API</p>
<p class="ai-projects__desc">
Вью для заметок в стиле канбан-доски: группировка по колонкам с фильтрами
по тегам.
</p>
<ul class="ai-projects__links">
<li><a href="{{casesPrefix}}card-columns-obsidian/" target="_blank" rel="noopener noreferrer">Кейс</a></li>
</ul>
<li data-filter-item data-filter-tag="plugins">
<article class="mp-card mp-card--compact" data-glass="false">
<div class="mp-card__media ai-projects__media" aria-hidden="true">
<img class="mp-card__image" src="{{assetPrefix}}assets/ai-dev/placeholder-02.webp" alt="" width="640" height="400" loading="lazy" decoding="async" />
</div>
<div class="mp-card__body">
<h3 class="mp-card__title">Card Columns</h3>
<p class="ai-projects__stack">TypeScript · Obsidian API</p>
<p class="mp-card__desc">Вью для заметок в стиле канбан-доски: группировка по колонкам с фильтрами по тегам.</p>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">Плагины</li>
</ul>
</div>
</article>
</li>
<li>
<div class="ai-projects__media">
<img
src="{{assetPrefix}}assets/ai-dev/placeholder-03.webp"
alt=""
width="640"
height="400"
loading="lazy"
decoding="async"
/>
</div>
<div class="ai-projects__head">
<h3 class="ai-projects__title">Hermes Desktop Plugins</h3>
</div>
<p class="ai-projects__stack">JavaScript · TypeScript · Electron</p>
<p class="ai-projects__desc">
Плагины для рабочего стола Hermes: чип баланса API, звук завершения задачи
и контроль трат.
</p>
<ul class="ai-projects__links">
<li><a href="http://x1qnvk08zec2u5cx6yh5iexh.155.212.186.39.sslip.io/admin/unorouter-balance" target="_blank" rel="noopener noreferrer">Код</a></li>
</ul>
<li data-filter-item data-filter-tag="plugins">
<article class="mp-card mp-card--compact" data-glass="false">
<div class="mp-card__media ai-projects__media" aria-hidden="true">
<img class="mp-card__image" src="{{assetPrefix}}assets/ai-dev/placeholder-03.webp" alt="" width="640" height="400" loading="lazy" decoding="async" />
</div>
<div class="mp-card__body">
<h3 class="mp-card__title">Hermes Desktop Plugins</h3>
<p class="ai-projects__stack">JavaScript · TypeScript · Electron</p>
<p class="mp-card__desc">Плагины для рабочего стола Hermes: чип баланса API, звук завершения задачи и контроль трат.</p>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">Плагины</li>
</ul>
</div>
</article>
</li>
<li>
<div class="ai-projects__media">
<img
src="{{assetPrefix}}assets/ai-dev/placeholder-01.webp"
alt=""
width="640"
height="400"
loading="lazy"
decoding="async"
/>
</div>
<div class="ai-projects__head">
<h3 class="ai-projects__title">Social Post Writer</h3>
</div>
<p class="ai-projects__stack">Python · aiogram 3 · SQLite</p>
<p class="ai-projects__desc">
Бот, который превращает тезисы в готовый пост под нужную площадку и тон,
учитывая голос автора.
</p>
<ul class="ai-projects__links">
<li><a href="http://x1qnvk08zec2u5cx6yh5iexh.155.212.186.39.sslip.io/admin/social-post-writer-bot" rel="noopener noreferrer">Код</a></li>
</ul>
<li data-filter-item data-filter-tag="bots">
<article class="mp-card mp-card--compact" data-glass="false">
<div class="mp-card__media ai-projects__media" aria-hidden="true">
<img class="mp-card__image" src="{{assetPrefix}}assets/ai-dev/placeholder-01.webp" alt="" width="640" height="400" loading="lazy" decoding="async" />
</div>
<div class="mp-card__body">
<h3 class="mp-card__title">Social Post Writer</h3>
<p class="ai-projects__stack">Python · aiogram 3 · SQLite</p>
<p class="mp-card__desc">Бот, который превращает тезисы в готовый пост под нужную площадку и тон, учитывая голос автора.</p>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">Боты</li>
</ul>
</div>
</article>
</li>
<li>
<div class="ai-projects__media">
<img
src="{{assetPrefix}}assets/ai-dev/placeholder-02.webp"
alt=""
width="640"
height="400"
loading="lazy"
decoding="async"
/>
</div>
<div class="ai-projects__head">
<h3 class="ai-projects__title">AI Design Assistant</h3>
</div>
<p class="ai-projects__stack">HTML · CSS · GLSL · WebGL</p>
<p class="ai-projects__desc">
Этот сайт целиком: структура, дизайн-система, шейдеры, CI/CD.
Весь цикл создания вместе с ИИ-агентом.
</p>
<ul class="ai-projects__links">
<li><a href="{{casesPrefix}}site-portfolio/" target="_blank" rel="noopener noreferrer">Кейс</a></li>
</ul>
<li data-filter-item data-filter-tag="web">
<article class="mp-card mp-card--compact" data-glass="false">
<div class="mp-card__media ai-projects__media" aria-hidden="true">
<img class="mp-card__image" src="{{assetPrefix}}assets/ai-dev/placeholder-02.webp" alt="" width="640" height="400" loading="lazy" decoding="async" />
</div>
<div class="mp-card__body">
<h3 class="mp-card__title">AI Design Assistant</h3>
<p class="ai-projects__stack">HTML · CSS · GLSL · WebGL</p>
<p class="mp-card__desc">Этот сайт целиком: структура, дизайн-система, шейдеры, CI/CD. Весь цикл создания вместе с ИИ-агентом.</p>
<ul class="mp-card__tags" aria-label="Тип проекта">
<li class="mp-card__tag">Веб</li>
</ul>
</div>
</article>
</li>
</ol>
<h2 id="stack">Стек</h2>
<ul class="section__prose ai-stack-list">
<li>Python</li>
<li>TypeScript</li>
<li>JavaScript</li>
<li>Go</li>
<li>HTML/CSS</li>
<li>GLSL</li>
<li>aiogram 3</li>
<li>FastAPI</li>
<li>PostgreSQL</li>
<li>Redis</li>
<li>SQLite</li>
<li>Docker</li>
<li>Coolify</li>
<li>Gitea</li>
<li>MCP</li>
<ul class="section__prose hero__tags" aria-label="Стек">
<li class="hero__tag">Python</li>
<li class="hero__tag">TypeScript</li>
<li class="hero__tag">JavaScript</li>
<li class="hero__tag">Go</li>
<li class="hero__tag">HTML/CSS</li>
<li class="hero__tag">GLSL</li>
<li class="hero__tag">aiogram 3</li>
<li class="hero__tag">FastAPI</li>
<li class="hero__tag">PostgreSQL</li>
<li class="hero__tag">Redis</li>
<li class="hero__tag">SQLite</li>
<li class="hero__tag">Docker</li>
<li class="hero__tag">Coolify</li>
<li class="hero__tag">Gitea</li>
<li class="hero__tag">MCP</li>
</ul>
<h2 id="links">Где я это выкладываю</h2>
<p class="section__prose">
Код открыт: <a href="https://github.com/mamadaevv" target="_blank" rel="noopener noreferrer">GitHub</a>
и <a href="http://x1qnvk08zec2u5cx6yh5iexh.155.212.186.39.sslip.io/admin" target="_blank" rel="noopener noreferrer">Gitea</a>.
Сервисы, которые работают прямо сейчас, живут на
<a href="https://secrets-4-me.dynv6.net" target="_blank" rel="noopener noreferrer">secrets-4-me</a>.
</p>
<ul class="case-links-grid">
<li>
<a class="case-link-card" href="https://github.com/mamadaevv" target="_blank" rel="noopener noreferrer">
<span class="case-link-card__body">
<span class="case-link-card__title">GitHub</span>
<span class="case-link-card__meta">Проекты и эксперименты с кодом</span>
</span>
</a>
</li>
<li>
<a class="case-link-card" href="http://x1qnvk08zec2u5cx6yh5iexh.155.212.186.39.sslip.io/admin" target="_blank" rel="noopener noreferrer">
<span class="case-link-card__body">
<span class="case-link-card__title">Gitea</span>
<span class="case-link-card__meta">Внутренние проекты и сервисы</span>
</span>
</a>
</li>
<li>
<a class="case-link-card" href="{{casesPrefix}}site-portfolio/" target="_blank" rel="noopener noreferrer">
<span class="case-link-card__body">
<span class="case-link-card__title">Кейс этого сайта</span>
<span class="case-link-card__meta">Как я делал сайт вместе с ИИ-агентом</span>
</span>
</a>
</li>
<li>
<a class="case-link-card" href="https://secrets-4-me.dynv6.net" target="_blank" rel="noopener noreferrer">
<span class="case-link-card__body">
<span class="case-link-card__title">secrets-4-me</span>
<span class="case-link-card__meta">Сервис, который работает сейчас</span>
</span>
</a>
</li>
</ul>
</div>
</main>
</body>
+20
View File
@@ -724,6 +724,26 @@
</ul>
<p class="sg-label">.mp-card__tags / .mp-card__tag</p>
<h3>Фильтр-чипы</h3>
<p class="section__prose">
Переключаемая группа тегов над списком карточек. Нажатый чип показывает только
те элементы, у которых этот тег есть в <code>data-filter-tag</code>. Остальные
скрываются атрибутом <code>hidden</code>, поэтому сетка не оставляет дыр.
</p>
<ul class="filter-chips" data-filter-chips data-filter-scope="#filter-demo" aria-label="Фильтр демо-карточек">
<li><button type="button" class="filter-chip" data-filter-value="all" aria-pressed="true">Все</button></li>
<li><button type="button" class="filter-chip" data-filter-value="bots" aria-pressed="false">Боты</button></li>
<li><button type="button" class="filter-chip" data-filter-value="plugins" aria-pressed="false">Плагины</button></li>
<li><button type="button" class="filter-chip" data-filter-value="web" aria-pressed="false">Веб</button></li>
</ul>
<ul class="mp-card__tags" id="filter-demo" style="display: grid; gap: 0.4rem; list-style: none; padding: 0; margin: 0.5rem 0">
<li class="filter-demo-item" data-filter-item data-filter-tag="bots web" style="padding: 0.5rem 0.7rem; border: 1px solid var(--line); border-radius: var(--radius-sm); font-size: 0.88rem">Бот на aiogram + веб-панель</li>
<li class="filter-demo-item" data-filter-item data-filter-tag="bots" style="padding: 0.5rem 0.7rem; border: 1px solid var(--line); border-radius: var(--radius-sm); font-size: 0.88rem">Telegram-бот генерации картинок</li>
<li class="filter-demo-item" data-filter-item data-filter-tag="plugins" style="padding: 0.5rem 0.7rem; border: 1px solid var(--line); border-radius: var(--radius-sm); font-size: 0.88rem">Плагин для Figma</li>
<li class="filter-demo-item" data-filter-item data-filter-tag="plugins web" style="padding: 0.5rem 0.7rem; border: 1px solid var(--line); border-radius: var(--radius-sm); font-size: 0.88rem">Плагин для Obsidian</li>
</ul>
<p class="sg-label">.filter-chips / .filter-chip[aria-pressed] + [data-filter-item][data-filter-tag]</p>
<h3>Карточка портфолио</h3>
<div class="sg-portfolio-wrap">
<a class="mp-card mp-card--link mp-card--stack-bottom" href="#components" tabindex="-1" aria-hidden="true">