Skip to content
ONIWC
iwc 0.1.0

link element

A hyperlink to a route, an anchor, an external URL, mailto: or tel:.

Renders

<a> (external links with rel="noopener noreferrer" when newTab)

Required

label (or content, bind, child elements) and target.

Native apps

Compiled native apps and server-driven apps

Syntax

link element
{ "type": "link" }

An element lives in a screen's sections, another element's elements, a layout slot or a component root.

Properties

PropertyTypeDescription
storestringstate store for action=state
mutationstringidentifiers use letters, digits and '_' and do not start with a digit
action"navigate""open""close""toggle""submit""state""api""logout""scroll""share""install""notifications""sync""pay""tracking""native"share: the system share sheet (web: Web Share, else copies the link) for target (default: this page) with value as the message; install: the browser's install prompt (pwa; hidden until the app can be installed); notifications: ask for notification permission and send the push subscription to pwa.push; sync: open the list of changes waiting to sync (offline); pay: call api for a payment, open the provider's payment sheet in a native app (hosted checkout on the web) and check it with confirm; tracking: value "start"/"stop" background location (platforms.*.background.location); native: call your own Kotlin/Swift extension named by target ("Scanner.scan") with value, and post its result to api
labelstring
targetstringroute, element id, or URL
newTabboolean
valueanyvalue passed to a state mutation; strings starting with item. or props. are bound

Plus the properties every element accepts: id, className, style, responsive, states, animation, visible, ariaLabel, attributes and more.

Events & actions

Without an action, a link navigates to target. Links to routes no screen has are warnings; javascript: URLs are compile errors.

Example

link example
{
  "type": "column",
  "elements": [
    { "type": "link", "label": "All products", "target": "/products" },
    {
      "type": "link",
      "label": "Read the docs",
      "target": "https://example.com/docs",
      "newTab": true
    },
    {
      "type": "link",
      "label": "hello@lumenoak.example",
      "target": "mailto:hello@lumenoak.example"
    }
  ]
}

A link's target can be filled from the current record: "/products/:slug". The link to the current page gets aria-current="page".

Expected output

The HTML IWC rendered for the example above (inside the page's content wrapper). Class names such as i807b63fc are generated per element for its scoped CSS.

Rendered HTML
<div class="iwc-page ipage" id="iwc-content">
  <div class="iwc-column iabf4b029">
    <a class="iwc-link i2b6b1933" href="/products">All products</a><a class="iwc-link i9e6ea336" href="https://example.com/docs" target="_blank" rel="noopener noreferrer">Read the docs</a><a class="iwc-link ie5ccfb9f" href="mailto:hello@lumenoak.example">hello@lumenoak.example</a>
  </div>
</div>

Data, conditions & styling

  • Conditional rendering: "visible": {"auth": "signed-in"}, {"roles": ["admin"]} or an expression such as "=product.stock > 0". Decided on the server: hidden elements are never sent.
  • Data binding: bind takes text from data (name, user.name, props.title, params.slug, state.cart.count); binds binds attributes. Containers become data-driven with data + item. See data binding.
  • Styling: className for your stylesheets, style for CSS in JSON, states for hover/focus/active, animation for entrance motion. See the style property reference.
  • Responsive behaviour: responsive applies CSS at or below a breakpoint ({"mobile": {"padding": "12px"}}); grids also take responsiveColumns.