UNPKG

alouette

Version:

A modern, customizable design system built on top of NativeWind v5 with configurable defaults

162 lines (122 loc) 5.19 kB
--- name: alouette-external-links description: > Open external URLs with ExternalLink (wraps expo-web-browser / Linking), or the two ready-made call sites: ExternalLinkButton (a Button) and ExternalLinkText (an inline text link with a leading arrow icon, size sm|md). openLinkBehavior is per platform (native: linking|webBrowser; web: targetBlank|targetSelf) — required on ExternalLink, defaulted to webBrowser/targetBlank on the two wrappers. Load when linking out to external URLs from alouette UI. type: composition library: alouette library_version: "22.6.0" requires: - alouette-actions sources: - "christophehurpeau/alouette:packages/alouette/src/expo/ExternalLink.tsx" - "christophehurpeau/alouette:packages/alouette/src/expo/ExternalLink.web.tsx" - "christophehurpeau/alouette:packages/alouette/src/expo/ExternalLink.shared.ts" - "christophehurpeau/alouette:packages/alouette/src/ui/actions/ExternalLinkText.tsx" - "christophehurpeau/alouette:packages/alouette/src/ui/actions/ExternalLinkText.stories.tsx" - "christophehurpeau/alouette:packages/alouette/src/ui/actions/Button.tsx" --- This skill builds on alouette-actions. Read it first for button props. # alouette + expo-web-browser — External links `ExternalLink` centralizes outbound-URL behavior per platform: an in-app browser sheet (expo-web-browser) or `Linking` on native, and a new tab or same tab on web. Two components apply it for you — `ExternalLinkButton` for a call to action, `ExternalLinkText` for a link inside a text flow. `ExternalOpenLinkBehavior` (exported from `alouette`): `{ native: "linking" | "webBrowser"; web: "targetBlank" | "targetSelf" }`. Both wrappers default it to `{ native: "webBrowser", web: "targetBlank" }`. ## Setup ```tsx import { ExternalLinkButton, ExternalLinkText } from "alouette"; <ExternalLinkButton href="https://example.com" text="Open docs" /> <ExternalLinkText href="https://example.com" text="the documentation" />; ``` ## Core Patterns ### Inline link vs link button `ExternalLinkButton` takes every `Button` prop (`variant`, `size`, `accent`, `icon`, `state`, ) and reads as an action. `ExternalLinkText` is the lightweight one: bold underlined text preceded by an affordance icon (the external-link arrow, overridable via `icon`), `size` `"sm" | "md"`, an `accent`, and a `disabled` state — on web the text and icon tint through hover/active from the interactive tokens, and the row carries the focus-visible outline. ```tsx <Paragraph> Read <ExternalLinkText size="sm" href={docsUrl} text="the guide" /> first. </Paragraph> ``` A disabled link drops its `href` on both platforms, because a disabled `Pressable` never sees the press that would cancel the navigation. On web both wrappers go through `ExternalLink`, which renders a real anchor with `target="_blank"` + `rel="noopener noreferrer"` (unless `web: "targetSelf"`), so middle-click and copy-link work. ### Wrap any component with explicit per-platform behavior `ExternalLink` takes the target component via `as` and forwards remaining props. ```tsx import { ExternalLink, Button } from "alouette"; <ExternalLink as={Button} href="https://example.com" openLinkBehavior={{ native: "webBrowser", web: "targetBlank" }} text="Open" />; ``` - `native: "webBrowser"` opens an in-app browser sheet themed with alouette colors. - `native: "linking"` hands off to the OS browser via `Linking.openURL`. - `web: "targetBlank"` opens a new tab; `"targetSelf"` navigates in place. ## Common Mistakes ### MEDIUM Calling Linking.openURL directly Wrong: ```tsx import { Linking } from "react-native"; <Pressable onPress={() => Linking.openURL(href)} /> ``` Correct: ```tsx <ExternalLink as={Button} href={href} openLinkBehavior={{ native: "webBrowser", web: "targetBlank" }} text="Open" /> ``` `ExternalLink` handles the in-app themed browser sheet on native and the correct target behavior on web; calling `Linking` directly loses both. Source: packages/alouette/src/expo/ExternalLink.tsx ### MEDIUM Omitting openLinkBehavior Wrong: ```tsx <ExternalLink as={Button} href={href} text="Open" /> ``` Correct: ```tsx <ExternalLink as={Button} href={href} openLinkBehavior={{ native: "linking", web: "targetSelf" }} text="Open" /> ``` `openLinkBehavior` is required on `ExternalLink` itself and selects the native and web strategies; without it the link can't decide how to open and throws on an unsupported branch. (`ExternalLinkButton` and `ExternalLinkText` default it for you — use them for the simple case.) Source: packages/alouette/src/expo/ExternalLink.tsx; expo/ExternalLink.shared.ts ### MEDIUM A pressable Text instead of ExternalLinkText Wrong: ```tsx <Pressable onPress={() => openUrl(href)}> <Text className="underline text-accent">the documentation</Text> </Pressable> ``` Correct: ```tsx <ExternalLinkText href={href} text="the documentation" /> ``` The hand-rolled version has no `role="link"`, no affordance icon, no hover/active/focus tint from the interactive tokens, and on web no real anchor — so the link cannot be middle-clicked or copied. Source: packages/alouette/src/ui/actions/ExternalLinkText.tsx