Files
yaru.nixg.ru/docs/design/yaru-style.md
T

9.3 KiB
Raw Blame History

Дизайн-система YARU

Фирменные элементы ya.ru

1. Красная первая буква имени

Наследие Яндекса: Первая буква имени пользователя выделяется красным цветом — фирменная фишка Яндекса.

Реализация

<span class="username">
  <span class="username__first-letter">К</span>разя
</span>
.username {
  font-family: Arial, Helvetica, sans-serif;
  font-size: 14px;
  color: #333333;
}

.username__first-letter {
  color: #CC0000; /* Фирменный красный Яндекс */
  font-weight: normal;
}

/* При наведении */
.username:hover {
  text-decoration: underline;
}

Svelte компонент

<!-- Username.svelte -->
<script lang="ts">
  export let username: string;
  export let link?: string;
</script>

{#if link}
  <a href={link} class="username">
    <span class="username__first-letter">{username.charAt(0)}</span>
    {username.slice(1)}
  </a>
{:else}
  <span class="username">
    <span class="username__first-letter">{username.charAt(0)}</span>
    {username.slice(1)}
  </span>
{/if}

<style>
  .username {
    font-family: Arial, Helvetica, sans-serif;
    font-size: 14px;
    color: #333333;
    text-decoration: none;
  }
  
  .username__first-letter {
    color: #CC0000;
  }
  
  .username:hover {
    text-decoration: underline;
  }
</style>

2. Короны пользователей

Статус и достижения: Корона показывает особый статус пользователя (модератор, администратор, активный участник).

Типы корон

Тип Значение Цвет Иконка
👑 Модератор Права модерации Золотой #FFD700 Корона с крестом
⭐ Активный Высокая активность Серебряный #C0C0C0 Звезда
🏆 Ветеран Давно в сервисе Бронзовый #CD7F32 Лавровый венок

Реализация

<div class="avatar-container">
  <img src="avatar.jpg" alt="Avatar" class="avatar" />
  <span class="crown crown--moderator" title="Модератор">
    <svg><!-- иконка короны --></svg>
  </span>
</div>
.avatar-container {
  position: relative;
  display: inline-block;
}

.avatar {
  width: 48px;
  height: 48px;
  border-radius: 4px;
}

.crown {
  position: absolute;
  top: -4px;
  right: -4px;
  width: 16px;
  height: 16px;
  display: flex;
  align-items: center;
  justify-content: center;
}

.crown--moderator {
  color: #FFD700;
}

.crown--active {
  color: #C0C0C0;
}

.crown--veteran {
  color: #CD7F32;
}

Svelte компонент

<!-- AvatarWithCrown.svelte -->
<script lang="ts">
  export let avatarUrl: string;
  export let username: string;
  export let crownType?: 'moderator' | 'active' | 'veteran';
  export let size?: 'small' | 'medium' | 'large' = 'medium';
  
  const crownTitles = {
    moderator: 'Модератор',
    active: 'Активный пользователь',
    veteran: 'Ветеран'
  };
</script>

<div class="avatar-container" class:size>
  <img src={avatarUrl} alt={username} class="avatar" />
  
  {#if crownType}
    <span class="crown" class={['crown--' + crownType]} title={crownTitles[crownType]}>
      <svg viewBox="0 0 24 24" fill="currentColor">
        <path d="M5 16L3 5L8.5 10L12 4L15.5 10L21 5L19 16H5ZM19 19C19 19.6 18.6 20 18 20H6C5.4 20 5 19.6 5 19V18H19V19Z" />
      </svg>
    </span>
  {/if}
</div>

<style>
  .avatar-container {
    position: relative;
    display: inline-block;
  }
  
  .avatar-container.small .avatar {
    width: 32px;
    height: 32px;
  }
  
  .avatar-container.medium .avatar {
    width: 48px;
    height: 48px;
  }
  
  .avatar-container.large .avatar {
    width: 96px;
    height: 96px;
  }
  
  .avatar {
    border-radius: 4px;
    object-fit: cover;
  }
  
  .crown {
    position: absolute;
    top: -4px;
    right: -4px;
    width: 16px;
    height: 16px;
    display: flex;
    align-items: center;
    justify-content: center;
  }
  
  .avatar-container.small .crown {
    width: 12px;
    height: 12px;
  }
  
  .avatar-container.large .crown {
    width: 24px;
    height: 24px;
  }
  
  .crown--moderator {
    color: #FFD700;
  }
  
  .crown--active {
    color: #C0C0C0;
  }
  
  .crown--veteran {
    color: #CD7F32;
  }
</style>

Цветовая палитра

Основные цвета

:root {
  /* Фирменные цвета YARU */
  --yar-red: #CC0000;        /* Красная буква, акценты */
  --yar-orange: #FFA500;     /* Короны, предупреждения */
  --yar-green: #A8D678;      /* Фон профиля (наследие ya.ru) */
  
  /* Нейтральные */
  --yar-white: #FFFFFF;      /* Основной фон */
  --yar-gray-light: #F5F5F5; /* Вторичный фон */
  --yar-gray: #E0E0E0;       /* Разделители */
  --yar-gray-dark: #333333;  /* Основной текст */
  
  /* Ссылки */
  --yar-link: #0066CC;       /* Обычные ссылки */
  --yar-link-hover: #FF6600; /* Ссылки при наведении */
  
  /* Статусы */
  --yar-success: #4CAF50;
  --yar-error: #F44336;
  --yar-warning: #FF9800;
}

Градиенты

/* Шапка сайта (наследие ya.ru) */
.yaru-header {
  background: linear-gradient(180deg, #E3F1F9 0%, #C4D8E8 100%);
}

/* Навигационные табы */
.yaru-tabs {
  background: #F5F5DC; /* Бежевый */
}

Типографика

Шрифты

:root {
  --font-family: Arial, Helvetica, sans-serif;
  --font-size-base: 13px;
  --line-height-base: 1.5;
}

body {
  font-family: var(--font-family);
  font-size: var(--font-size-base);
  line-height: var(--line-height-base);
  color: var(--yar-gray-dark);
}

Иерархия

/* Заголовки */
h1 { font-size: 24px; font-weight: bold; }
h2 { font-size: 20px; font-weight: bold; }
h3 { font-size: 16px; font-weight: bold; }

/* Основной текст */
p { font-size: 13px; }

/* Мелкий текст (даты, мета) */
.small { font-size: 11px; color: #999; }

/* Имена пользователей */
.username { font-size: 14px; }

Компоненты

PostCard

<!-- PostCard.svelte -->
<script lang="ts">
  import Username from './Username.svelte';
  import AvatarWithCrown from './AvatarWithCrown.svelte';
  
  export let post: {
    id: string;
    author: {
      username: string;
      avatar: string;
      crown?: 'moderator' | 'active' | 'veteran';
    };
    content: string;
    timestamp: string;
    karma: number;
  };
</script>

<article class="post-card">
  <header class="post-card__header">
    <AvatarWithCrown 
      avatarUrl={post.author.avatar} 
      username={post.author.username}
      crownType={post.author.crown}
      size="small"
    />
    <div class="post-card__meta">
      <Username username={post.author.username} link={`/u/${post.author.username}`} />
      <time class="post-card__time">{post.timestamp}</time>
    </div>
  </header>
  
  <div class="post-card__content">
    {@html post.content}
  </div>
  
  <footer class="post-card__footer">
    <button class="post-card__karma">
      ▲ {post.karma}
    </button>
  </footer>
</article>

<style>
  .post-card {
    background: var(--yar-white);
    border: 1px solid var(--yar-gray);
    border-radius: 4px;
    padding: 16px;
    margin-bottom: 16px;
  }
  
  .post-card__header {
    display: flex;
    align-items: center;
    gap: 12px;
    margin-bottom: 12px;
  }
  
  .post-card__meta {
    display: flex;
    flex-direction: column;
  }
  
  .post-card__time {
    font-size: 11px;
    color: #999;
  }
  
  .post-card__footer {
    margin-top: 12px;
    padding-top: 12px;
    border-top: 1px solid var(--yar-gray);
  }
  
  .post-card__karma {
    background: none;
    border: 1px solid var(--yar-gray);
    border-radius: 4px;
    padding: 4px 8px;
    cursor: pointer;
    color: var(--yar-link);
  }
  
  .post-card__karma:hover {
    background: var(--yar-gray-light);
  }
</style>

Адаптивность

Breakpoints

/* Mobile first */
.yaru-container {
  width: 100%;
  padding: 16px;
}

@media (min-width: 768px) {
  .yaru-container {
    max-width: 768px;
    margin: 0 auto;
  }
}

@media (min-width: 1024px) {
  .yaru-container {
    max-width: 1024px;
  }
}

Тёмная тема

[data-theme="dark"] {
  --yar-white: #1A1A1A;
  --yar-gray-light: #2A2A2A;
  --yar-gray: #404040;
  --yar-gray-dark: #E0E0E0;
  --yar-link: #64B5F6;
  --yar-link-hover: #FFA726;
}

Вопросы для обсуждения

  • Сохранить ли зелёный фон профиля (#A8D678) или обновить?
  • Нужны ли дополнительные типы корон (спонсор, эксперт)?
  • Использовать ли анимацию для красной буквы (легкое свечение)?
  • Добавить ли звуковые эффекты при получении короны?