GrLink
Берут, когда нужен переход.
Обзор
Когда брать
- нужен переход — ссылка меняет адрес, и открытие в новой вкладке обязано работать;
- роутер свой —
asподменяет корневой тег наRouterLinkилиNuxtLinkбез обёртки; - ссылка ведёт наружу —
externalдобавляет значок и подпись «в новой вкладке» для скринридера; - ссылка живёт в тексте —
underlineиtoneдержат её узнаваемой внутри абзаца.
Когда взять другое
| Нужно | Берите |
|---|---|
| Действие меняет состояние, а не адрес | GrButton |
| Ссылка выглядит кнопкой | GrButton с as/href |
| Список переходов | GrSidebar / GrDropdownMenu |
| Путь до текущей страницы | GrBreadcrumbs |
Кнопка меняет состояние, ссылка меняет адрес. Подменять одно другим ради внешности нельзя: у ссылки работают средняя кнопка мыши, контекстное меню и «открыть в новой вкладке», у кнопки — нет, и пользователь замечает это первым.
Варианты все тона и виды — настоящим компонентом
tone \ variant | default | muted |
|---|---|---|
primary | ||
neutral | ||
success | ||
warning | ||
danger | ||
info | ||
slate | ||
azure |
Размеры
xssmmdlg
Состояния
обычнаяdisabled
Матрица живая: наводите и нажимайте. Состояний наведения, фокуса и нажатия здесь нет — они за браузером, а не за пропом.
Playground контролы выводятся из API, а не пишутся руками
Загружается…
0 изменено· состояние — в адресе
<GrLink>Текст</GrLink>Примеры 3 у каждого — живое демо и его код
Ссылки в тексте о биллинге
Внутри текста ссылки держат ритм абзаца, а
underline="always"делает их узнаваемыми и без цвета. «Скачать чек»disabled, пока платёж не прошёл: она становится текстом и уходит из порядка табуляции. Ссылка на налоговые правила —external: значок, безопасныйrelи скрытое «откроется в новой вкладке».Team plan · 23 seats Your next invoice of €1,284.50 is issued on 1 November. Change the plan or add a purchase order number before then — invoices already issued keep their details.
The October payment is processing. Download the receipt once it clears, usually within a day. VAT is charged under the Irish reverse-charge rules(откроется в новой вкладке).
Действия в строках активных сессий
В списке ссылки действуют на строки:
underline="none"оставляет колонку спокойной,tone="danger"отмечает то, что завершает сессию, аsize="sm"совпадает с текстом строки. «Выйти везде, кроме этого» ведёт на страницу подтверждения, поэтому остаётся ссылкой — средняя кнопка и «открыть в новой вкладке» работают.Where you are signed inSign out everywhere elseMacBook Pro · SafariDublin, IE · This deviceCurrentiPhone 15 · Granularity appDublin, IE · 2 hours agoSign outWindows · EdgeLisbon, PT · 6 days agoSign out
API порождается из пакета · разойтись не может
Props
| Prop | Type | по умолчанию | Описание |
|---|---|---|---|
disabled | boolean | undefined | false | Ссылка недоступна: корень — `<span>` без `href`, вне порядка `Tab`, с `aria-disabled`. |
tone |
| "primary" | Семантический цвет ссылки из палитры `GrTone`. |
variant | GrLinkVariant | undefined | "default" | Уровень акцента: `default` (окрашен) или `muted` (приглушён, акцент на hover). |
size | "xs" | "sm" | "md" | "lg" | undefined | undefined | Кегль ссылки и её иконки. По умолчанию `md`; берётся из `GrConfigProvider`. |
ariaLabel | string | undefined | undefined | Доступное имя вместо текста; подсказка о новой вкладке дописывается к нему сама. |
as | string | Component | undefined | undefined | Кастомный корневой тег/компонент. Если передан и компонент не `disabled` — рендерится через `<component :is="as">`. Игнорируется при `disabled`. |
href | string | undefined | undefined | Адрес ссылки: без `as` корень становится `<a>`. При `disabled` не выводится. |
target | string | undefined | undefined | `target` ссылки, сильнее `external`. С `_blank` добавляются защитный `rel` и подсказка. |
rel | string | undefined | undefined | `rel` ссылки. Без него при `target="_blank"` ставится `noopener noreferrer`. |
external | boolean | undefined | false | Открыть в новой вкладке: `target="_blank"`, `rel="noopener noreferrer"` и иконка. |
underline | GrLinkUnderline | undefined | "auto" | Подчёркивание: `auto` — при наведении, `always` — всегда, для ссылки посреди текста, `none` — никогда. По умолчанию `auto`. |
externalIcon | boolean | undefined | undefined | Иконка внешней ссылки. По умолчанию показывается у любой ссылки, которая открывается в новой вкладке, — не только при `external`. |
newTabLabel | string | undefined | undefined | i18n: скрытая подсказка «откроется в новой вкладке». |
Слоты
| Slot | Type | Описание |
|---|---|---|
default | any | Текст ссылки. |
Типы
Все экспортируемые типы подпути, по файлам, где они объявлены. Имена, дженерики и тела читаются из файлов деклараций пакета и разойтись не могут.
import type { GrLinkTone, GrLinkVariant, GrLinkUnderline } from '@feugene/granularity/components/GrLink'Файлdist/types/components/GrLink/config.d.ts
dynamicTokens — имена, которые собираются в рантайме: цвет тона читается как
var(--gr-${tone}-text), и статический анализ видит от имени только префикс
--gr-. Объявление снимает находку token-undefined на этом префиксе и
сообщает обрезке токенов, что весь набор -text компоненту нужен.
const grLinkConfig: import("@feugene/granum/contract").GranumComponentDescriptor<"GrLink">;Файлdist/types/components/GrLink/grLinkStyles.d.ts
Архитектура цвета GrLink (согласована с остальной GR, ср. GrButton):
- tone — семантический ЦВЕТ из общей палитры GrTone
(primary | neutral | success | warning | danger | info | slate | azure).
- variant — уровень акцента (СТРУКТУРА), независимый от цвета:
- default — текст окрашен в tone в покое, tone-hover/tone-active при
наведении/нажатии (обычная акцентная ссылка);
- muted — приглушённый текст (--gr-muted-fg) в покое, окрашивается в tone
при наведении (вторичные/inline-ссылки в плотных областях).
Оси ортогональны намеренно: «красная ссылка» и «приглушённая ссылка» —
независимые решения, и любая их комбинация осмысленна.
type GrLinkTone = GrTone;type GrLinkVariant = 'default' | 'muted';type GrLinkUnderline = 'auto' | 'always' | 'none';type GrLinkSize = GrComponentSize;Файлdist/types/components/GrLink/safelist.d.ts
const grLinkSafelist: string[];Файлdist/types/components/GrLink/defaults.d.ts
Пропы GrLink, настраиваемые глобально через
<GrConfigProvider :component-defaults="{ GrLink: { … } }">.
Только оформление — см. GrButton/defaults.ts.
interface GrLinkConfigurableProps {
size: GrLinkSize;
}Файлdist/types/components/GrLink/GrLink.vue.d.ts
interface GrLinkProps {
/**
* Кастомный корневой тег/компонент. Если передан и компонент не `disabled` —
* рендерится через `<component :is="as">`. Игнорируется при `disabled`.
*/
as?: string | Component;
/** Адрес ссылки: без `as` корень становится `<a>`. При `disabled` не выводится. */
href?: string;
/** Открыть в новой вкладке: `target="_blank"`, `rel="noopener noreferrer"` и иконка. */
external?: boolean;
/** `target` ссылки, сильнее `external`. С `_blank` добавляются защитный `rel` и подсказка. */
target?: string;
/** `rel` ссылки. Без него при `target="_blank"` ставится `noopener noreferrer`. */
rel?: string;
/** Ссылка недоступна: корень — `<span>` без `href`, вне порядка `Tab`, с `aria-disabled`. */
disabled?: boolean;
/** Доступное имя вместо текста; подсказка о новой вкладке дописывается к нему сама. */
ariaLabel?: string;
/** Семантический цвет ссылки из палитры `GrTone`. */
tone?: GrLinkTone;
/** Уровень акцента: `default` (окрашен) или `muted` (приглушён, акцент на hover). */
variant?: GrLinkVariant;
/**
* Подчёркивание: `auto` — при наведении, `always` — всегда, для ссылки посреди текста, `none` —
* никогда. По умолчанию `auto`.
*/
underline?: GrLinkUnderline;
/** Кегль ссылки и её иконки. По умолчанию `md`; берётся из `GrConfigProvider`. */
size?: GrLinkSize;
/**
* Иконка внешней ссылки. По умолчанию показывается у любой ссылки, которая
* открывается в новой вкладке, — не только при `external`.
*/
externalIcon?: boolean;
/** i18n: скрытая подсказка «откроется в новой вкладке». */
newTabLabel?: string;
}Использование из прозы библиотеки
Корневой тег
| Условие | Что рендерится |
|---|---|
задан as и не disabled | <component :is="as"> — RouterLink, Link от Inertia, любой свой |
задан href и не disabled | <a> |
остальное, включая disabled | <span> |
Отключённая ссылка намеренно перестаёт быть <a>: так она не кликабельна и не
участвует в порядке табуляции. Внешние CSS-селекторы это должны учитывать.
Атрибуты роутера (method, replace, preserve-scroll) проходят через
fallthrough — компонент их не перечисляет.
Новая вкладка объявляется
Ссылка, открывающаяся в новой вкладке, получает две вещи:
- иконку внешней ссылки — видимый признак;
- скрытый суффикс «(откроется в новой вкладке)» — предупреждение о смене контекста (WCAG 3.2.5), без него переход в новую вкладку для незрячего пользователя происходит без предупреждения.
Условие — фактическое поведение ссылки (target="_blank"), а не проп
external: target снаружи даёт ровно тот же сюрприз. По той же причине
компонент выставляет rel="noopener noreferrer" любой ссылке с _blank, а не
только external.
<GrLink href="https://example.com" external>
Документация
</GrLink>
<GrLink href="https://example.com" target="_blank">
То же самое
</GrLink>
<!-- Иконку можно выключить или, наоборот, включить внутренней ссылке. -->
<GrLink href="https://example.com" external :external-icon="false">
Без иконки
</GrLink>
<GrLink href="/inner" external-icon>
С иконкой
</GrLink>newTabLabel перекрывает текст подсказки, ключ локали — gr.link.opensInNewTab.
ariaLabel и подсказка
aria-label перекрывает содержимое элемента целиком — вместе со скрытым
суффиксом. Поэтому, если имя задано вручную, подсказка дописывается к нему:
aria-label="Документация" у внешней ссылки превращается в
«Документация, откроется в новой вкладке», а отдельный sr-only-суффикс не
рендерится, чтобы диктор не прочитал его дважды.
Цвет: tone × variant
Оси ортогональны. tone — цвет из общей палитры (primary, neutral,
success, warning, danger, info, slate, azure), variant — уровень
акцента: default (окрашен в покое) или muted (приглушён, окрашивается при
наведении).
Цвет прокидывается CSS-переменными (--gr-link-color, -hover, -active), а
не классами на каждую комбинацию: 8 тонов × 3 состояния дали бы class-эксплозию,
а safelist остаётся крошечным.
Тона берутся из ролей -text, а не из насыщенных --gr-{tone}: ссылка — это
текст на фоне страницы, а --gr-success на --gr-bg даёт 2.2:1.
Подчёркивание и disabled
underline: auto (появляется на hover), always, none.
Отключённая ссылка гасится цветом --gr-muted-fg, а не opacity: прозрачность
разбавляет выверенный на AA токен и роняет контраст ниже нормы.
Пропы этого примера