Подпись StackWorks: вариант «штамп» со знаком и анимацией полос

Claude-Session: https://claude.ai/code/session_01BFaqS6mH9sa99RWghq2j46
Этот коммит содержится в:
2026-10-06 02:14:24 +09:00
родитель 61ff14915b
Коммит 0134f36ce6
4 изменённых файлов: 55 добавлений и 1 удалений
+30
Просмотреть файл
@@ -0,0 +1,30 @@
/*
* Подпись студии StackWorks («штамп»): знак и две строки - «разработка и поддержка» / StackWorks.
* В остальных проектах она ставится скриптом https://stackworks.ru/sign/sw-sign.js,
* здесь - компонентом, чтобы React не спорил с чужими изменениями страницы.
* Оформление в src/index.css, классы swsig*.
*/
export default function SwSignature({ dark = false }: { dark?: boolean }) {
const bg = dark ? '#F3F1EB' : '#16171C';
const fg = dark ? '#16171C' : '#F3F1EB';
return (
<a
className={'swsig' + (dark ? ' swsig-dark' : '')}
href="https://stackworks.ru/?utm_source=mail.stackworks.ru&utm_medium=signature"
target="_blank"
rel="noopener"
aria-label="Разработка и поддержка - StackWorks"
>
<svg viewBox="0 0 100 100" aria-hidden="true">
<rect x="2" y="2" width="96" height="96" rx="25" fill={bg} />
<rect className="b b1" x="20" y="29" width="44" height="12" rx="6" fill={fg} />
<rect className="b b2" x="30" y="45" width="50" height="12" rx="6" fill="#FF4A1C" />
<rect className="b b3" x="40" y="61" width="34" height="12" rx="6" fill={fg} />
</svg>
<span className="swsig-txt">
<span className="swsig-cap">разработка и поддержка</span>
<span className="swsig-word">Stack<i>Works</i></span>
</span>
</a>
);
}
+5
Просмотреть файл
@@ -4,6 +4,7 @@
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL
*/ */
import SwSignature from '@/components/common/SwSignature';
import { useCallback, useEffect, useMemo, useRef, useState } from 'react'; import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { useLocation, useNavigate } from 'react-router-dom'; import { useLocation, useNavigate } from 'react-router-dom';
import * as LucideIcons from 'lucide-react'; import * as LucideIcons from 'lucide-react';
@@ -365,6 +366,10 @@ export function Sidebar() {
</nav> </nav>
</div> </div>
<div className="flex justify-center px-3 py-3">
<SwSignature dark />
</div>
{layouts.length > 1 && ( {layouts.length > 1 && (
<TooltipProvider> <TooltipProvider>
<div className="sw-aside-foot flex items-center justify-around border-t bg-background px-2 py-2"> <div className="sw-aside-foot flex items-center justify-around border-t bg-background px-2 py-2">
+17
Просмотреть файл
@@ -165,3 +165,20 @@ aside.sw-aside .text-muted-foreground { color: #8d8f96 !important; }
@media (max-width: 640px) { @media (max-width: 640px) {
main h1 { font-size: 1.6rem; } main h1 { font-size: 1.6rem; }
} }
/* подпись студии (компонент SwSignature, повторяет https://stackworks.ru/sign/sw-sign.js) */
.swsig { --ink: #16171c; --cap: #6a6c75; --acc: #ff4a1c; display: inline-flex; align-items: center; gap: 10px;
min-height: 44px; text-decoration: none; color: var(--ink); border-radius: 8px; }
.swsig-dark { --ink: #f3f1eb; --cap: #9a9ca3; }
.swsig svg { width: 30px; height: 30px; flex: 0 0 auto; display: block; }
.swsig-txt { display: flex; flex-direction: column; gap: 4px; }
.swsig-cap { font: 400 11.5px/1 'SW Inter', system-ui, sans-serif; color: var(--cap); white-space: nowrap; }
.swsig-word { font: 700 16px/1 'SW Rubik', sans-serif; letter-spacing: -.01em; color: var(--ink); white-space: nowrap; }
.swsig-word i { font-style: normal; color: var(--acc); }
@keyframes swsig-shuffle { 0%, 100% { transform: translateX(0); } 45% { transform: translateX(9px); } }
.swsig .b { transform-box: fill-box; }
.swsig:hover .b, .swsig:focus-visible .b { animation: swsig-shuffle .38s ease-in-out both; }
.swsig:hover .b2, .swsig:focus-visible .b2 { animation-delay: .07s; }
.swsig:hover .b3, .swsig:focus-visible .b3 { animation-delay: .14s; }
.swsig:focus-visible { outline: 2px solid var(--acc); outline-offset: 4px; }
@media (prefers-reduced-motion: reduce) { .swsig .b { animation: none !important; } }
+3 -1
Просмотреть файл
@@ -10,6 +10,7 @@ import { useTranslation } from 'react-i18next';
import { ArrowRight, Loader2 } from 'lucide-react'; import { ArrowRight, Loader2 } from 'lucide-react';
import Logo from '@/components/common/Logo'; import Logo from '@/components/common/Logo';
import SwSignature from '@/components/common/SwSignature';
import { useDocumentTitle } from '@/hooks/useDocumentTitle'; import { useDocumentTitle } from '@/hooks/useDocumentTitle';
import { Button } from '@/components/ui/button'; import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input'; import { Input } from '@/components/ui/input';
@@ -43,7 +44,7 @@ export default function LoginPage() {
} }
return ( return (
<div className="flex min-h-screen items-center justify-center bg-content-background px-4"> <div className="flex min-h-screen flex-col items-center justify-center gap-6 bg-content-background px-4">
<Card className="w-full max-w-sm shadow-sm"> <Card className="w-full max-w-sm shadow-sm">
<CardHeader className="items-center text-center"> <CardHeader className="items-center text-center">
<Logo /> <Logo />
@@ -87,6 +88,7 @@ export default function LoginPage() {
</form> </form>
</CardContent> </CardContent>
</Card> </Card>
<SwSignature />
</div> </div>
); );
} }