Эта страница переведена машинным способом и может содержать ошибки. Читать оригинал на английском

Элементы

Link

Ссылка ведет пользователя куда-либо: на веб-страницу, в другое приложение (mailto:, tel:) или на экран самого приложения. Она отвечает за поведение: нажатия, Return и Space, пока у нее есть фокус клавиатуры, отключенное состояние и роль ссылки для скринридеров. Внешний вид определяет приложение: у Link нет собственного цвета, подчеркивания или подписи, виден только его дочерний контент. href указывает, куда ведет ссылка; это данные для открытия, а не текст на экране.

el-link.tsx
use nsh_base::{link, theme};
use nsh_core::prelude::*;

fn docs() -> impl IntoElement {
    link()
        .href("https://example.com/docs")
        .text_color(move || theme().primary)
        .underline()
        .hover(|s| s.opacity(0.8))
        .focus(|s| s.rounded_sm().outline(px(2.0)).outline_color(move || theme().ring))
        .child(text("Read the docs"))
}

Link берется из nsh/base, крейта nsh-base в Rust. В Rust link() создает ссылку с сеттером для каждого свойства (.href(..), .open_with(..)), слушателем для каждого события (.on_open(..), .on_press(..)), типизированными методами стиля для самой ссылки и .child(..) для ее содержимого.

#Открытие

Нажатие, клик или Return либо Space на ссылке в фокусе открывает ее href:

  1. onOpen({ href }) сообщает, куда ведет ссылка.
  2. При openWith="system" (по умолчанию) URL другого приложения или сайта, то есть URL со схемой (https:, mailto:, tel:, схема, зарегистрированная другим приложением), открывается за пределами приложения так же, как его открывает openUrl: сначала его обрабатывает маршрутизатор встраивающего приложения, затем система. Любой другой href, путь самого приложения (/orders/42) или #anchor, передается в событии и остается за приложением.
  3. onPress() сообщает о нажатии.

При openWith="app" ссылку открывает обработчик onOpen приложения: собственный маршрут, страница во встроенном веб-представлении или сначала подтверждение.

import { Link } from "nsh/base";

<Link href={`/orders/${order.id}`} openWith="app" onOpen={({ href }) => router.push(href)} class="text-primary">
  <Text>Order #{order.id}</Text>
</Link>

Открытие URL за пределами приложения требует разрешения openUrl, если приложение объявляет разрешения в nsh.json ("openUrl": true или { "schemes": ["https", "mailto"] }).

#Свойства

СвойствоRustТипПо умолчаниюОписание
href.href(..)stringнетКуда ведет ссылка: URL или путь приложения. Передается в onOpen, никогда не отображается.
openWith.open_with(LinkOpenWith::App)"system" | "app" (LinkOpenWith)"system"Кто открывает href: система открывает URL другого приложения или сайта; "app" оставляет это на усмотрение onOpen.
disabled.disabled(..)booleanfalseНет нажатий, отклика на нажатие и фокуса клавиатуры; стили disabled: применяются, а скринридеры сообщают, что элемент неактивен.
current.current(..)booleanfalseСсылка на страницу, на которой находится пользователь, в навигации или хлебных крошках: скринридеры сообщают, что это текущая страница.
accessibilityLabel.accessibility_label(..)stringнетЧто произносят скринридеры, когда содержимое говорит слишком мало (иконка).
hitSlop.hit_slop(..)number | Partial<Edges>нетНа сколько за пределами границ нажатия все еще засчитываются, в пунктах: одно число для всех сторон или отдельно по сторонам. Как hitSlop у view.
children.child(..)JSX.ElementнетСодержимое: подпись, иконка, всё, что показывает приложение.
class, styleметоды стиляstring, StyleProp<ViewStyle>нетВнешний вид ссылки: цвет, подчеркивание, отступы; свойства текста передаются вложенным в нее текстам.
activeStyle, hoverStyle, focusStyle, disabledStyle.active(|s| ..), .hover(..), .focus(..), .disabled_style(..)StyleProp<ViewStyle>нетСтиль ссылки при нажатии, наведении, фокусе или в отключенном состоянии, как классы <state>:.

#События

СобытиеRustОписание
onOpen.on_open(|href: &SharedString| ..)Ссылка открывает href: при openWith="app" ее открывает обработчик, при "system" он узнает, что именно система попросила открыть. Происходит до onPress.
onPress.on_press(|| ..)Ссылку нажали: тап, клик или Return либо Space, пока у нее есть фокус клавиатуры.

Отключенная ссылка ничего не сообщает, а нажатие на нее не доходит до нажимаемых view вокруг.

#Состояния

Приложение стилизует каждое состояние с помощью классов или свойств стиля:

<Link
  href="https://example.com/changelog"
  class="self-start text-primary underline decoration-primary/40 transition-colors hover:decoration-primary active:opacity-70 focus:outline-2 focus:outline-ring disabled:text-muted-foreground disabled:no-underline"
>
  <Text>Changelog</Text>
</Link>

Посещенные ссылки запоминает приложение: оно хранит открытые href и стилизует такие ссылки по собственному состоянию.

const visited = signal(new Set<string>());

<Link
  href={href}
  onOpen={({ href }) => visited.set(new Set(visited()).add(href))}
  class={visited().has(href) ? "text-violet-600 underline" : "text-primary underline"}
>
  <Text>{label}</Text>
</Link>

#Внутри текста

Link внутри <Text> является строчным блоком абзаца, как и любое view внутри текста: он находится в строке, сохраняет собственные состояния, фокус и роль и остается на одной строке. align-text-bottom размещает ссылку с одной строкой текста на базовой линии абзаца:

<Text class="text-[15px] text-foreground">
  By continuing you accept the{" "}
  <Link href="https://example.com/terms" class="align-text-bottom">
    <Text class="text-[15px] text-primary underline">terms of service</Text>
  </Link>
  .
</Text>

Ссылка, которая переносится вместе со строками абзаца, является вложенным <Text> с role="link" и onPress (см. Text); так TextView отображает ссылки документа.

#Маленькая цель и hitSlop

Ссылка может быть меньше пальца: иконка, короткое слово. hitSlop заставляет засчитываться нажатия, попавшие рядом с ней, в пунктах за каждой из сторон, не меняя ее раскладку и внешний вид: одно число для всех сторон или отдельно по сторонам ({ top: 8, bottom: 8 }), как их принимает hitSlop у view.

<Link href="https://example.com/help" hitSlop={12} accessibilityLabel="Help" class="size-5 items-center justify-center">
  <Text>?</Text>
</Link>

#Доступность

  • Ссылка для скринридеров является одним элементом с ролью "link"; ее подпись — это текст дочерних элементов или accessibilityLabel. href остается данными: скринридеры произносят подпись.
  • current произносится как текущая страница (aria-current="page" из ARIA), а disabled — так, как платформа произносит неактивный элемент.
  • В macOS и вебе ссылка является остановкой фокуса клавиатуры: Tab переходит на нее, Return и Space ее открывают, а стили focus: показывают, где находится фокус.

Общие сведения о подписях, ролях и объявлениях см. в разделе Доступность.

#Примечания по платформам

  • iOS, Android и Mac Catalyst: нажатие — это тап, который заканчивается на ссылке.
  • Десктопы (macOS, Windows, Linux, GPUI) и веб: нажатие — это клик. В macOS и вебе Return и Space также открывают ссылку, у которой есть фокус клавиатуры.
  • В вебе ссылка отображается как элемент с role="link".
  • На каждой платформе отображается то, что задает стиль приложения.