components / Library version 5.5.0
Components Overview
Browse our available UI components to understand the functionality and purpose of each component, and review installation and usage instructions to understand how to integrate them into your projects.
Basic Controls
Essential interactive components that can be implemented for various use cases.
Communication
Components used to communication system status or information to users.
Data Visualization
Visualize data to help users understand key insights and important information.
Form Inputs
Build forms and collect data using these form input components.
Datepicker
Datepicker enters a single date by input or calendar selection
Date Range
Date Range picker enters a range of dates by input or calendar selection
File List
File List displays a list of uploaded files with meta data and actions
Input
Input is a text field that can be used to collect data
Search
Search filters data based on inputted text
Tag Input
Tag Input enables the selection of tags from a searchable list
Textarea
Textarea is a multi-line text input field that has an adjustable height
Timepicker
Timepicker enters a time by input or dropdown selection
Uploader
Uploader can upload multiple files and display them in a list
Layout Containers
Components that serve to contain content.
Navigation
Components used to navigate the user to a new view or page.
Navigation
Navigation navigates users through the primary menu pages of a product
Navigator
Navigator navigates users between Watermark products and provides a logout option
Pagination
Pagination navigates through a collection of items split between pages
Tabs
Tabs navigate between related views in the same context or page
Installation
The component library is distributed as javascript modules (CommonJS and ES modules) to use with a bundler, as well as standalone javascript files that can be loaded directly (e.g. via a script tag). It also includes an ES5 build for older browsers, and we release a separate react-specific package (see instructions at the bottom of this page). The core distribution includes the following builds:
-
dist/cjs
CommonJS, for bundlers -
dist/esm
ES modules, for bundlers -
dist/esm-es5
ES modules, compatible with older browsers -
dist/collection
for lazy loading in other Stencil applications -
dist/ripple
for loading directly, e.g. via a script tag
We recommend that you let Stencil's loader determine which build to use. For this, simply import and execute the
defineCustomElements
function in
dist/loader
.
The components use the Material Design Icons, an icon set which is probably already being pulled in your codebase (unless your product has not adopted the Ripple design system yet). If it is not available, make sure to load it before using the components, for instance by adding a link tag in the page head:
<link href="https://cdn.materialdesignicons.com/3.6.95/css/materialdesignicons.min.css" rel="stylesheet">
The components also use Ripple's color tokens, which are loaded separately so you can use them in your projects:
<link href="https://cdn.watermarkinsights.com/css/1.4.0/tokens.css" rel="stylesheet">
Installing in a NodeJS application
-
Add the package:
npm i @watermarkinsights/ripple@5.5.0
-
Import the loader and polyfill functions:
import { applyPolyfills, defineCustomElements } from '@watermarkinsights/ripple/dist/loader';
-
Call them to load the components:
applyPolyfills().then(() => { defineCustomElements(); });
You can now use the components as you would any other html element:
<wm-button>Click me</wm-button>
To update, simply run the install command again, specifying the desired version.
Loading as a script
Alternatively, you can simply load this script to use the library:
<script type="module" src="https://cdn.watermarkinsights.com/ripple/5.5.0/ripple/ripple.js"></script>
To update, replace
5.5.0
by the desired version.
Installing React Wrappers
If your project uses React, install this package instead of the core library to use the Ripple component the React
way. The components' names and props will be CamelCased rather than hyphenated, and you will be able to hook to events
directly on the component (e.g.
onWmEventTriggered=...
), rather than
.addEventListener("wmEventTriggered", ...)
.
-
Add the package:
npm i @watermarkinsights/ripple-react@5.5.0
-
Import the components at the top of your file:
import { WmButton, WmSelect, WmOption } from '@watermarkinsights/ripple-react';
As for the core library, the Material Design Icons and Ripple's color tokens need to be loaded before.
To update, simply run the install command again, specifying the desired version.
Usage
Issue reporting
Please follow the instructons in the Components Issues Checklist when reporting an issue.
Basic usage
The components API (properties and events) is documented on this site. Please do not use undocumented props or events. Some of them are for the components' internal use and may change at any time, breaking functionality. Please contact the Design System Team if you think the current API doesn't allow a particular scenario. We'll either adapt the component or show you a different way to handle your case.
Components width
Many components have a width of 100%, meaning they will take the entire width of their parent. You can control the width by setting the width of the parent element.
Font size
The font size of the components is inherited from the page. If they display at a wrong size, check if a font size was set on the body. For accessibility reasons, you should not set a fixed global size. Browers default this value to 16px, and users have the ability to change this value in the settings. Setting a fixed value on the body can interfere with this, since the page won't respond to the user's preference.
Re-rendering
Front-end frameworks like React or Elm take care of re-rendering elements when they change. You can dynamically change a component the way you would any other element and expect the changes to be reflected.
But things are a bit different with compound components (when components have a parent-child relationship). If you dynamically change a property on a child component, there may not be a visible change to its parent or vice versa. For instance changing the selected
property of an Option will not update the Select component, which will keep displaying the previously displayed item. Similarly, changing the selected-tab
property on wm-tab-list
will not re-render its children wm-tab-item
.
A common solution to this problem is to use keyed nodes, which will cause a change in one component to trigger a re-render in the other.
The Shadow DOM
The components are rendered in the
shadow DOM, which isolates them from the rest of the DOM.
A few things to note:
- Styles don't bleed in.
The shadow host element can be selected, but nothing in the shadow DOM will be affected by external styles.
Targeting the host element can be useful for positioning the component on the page.
Components rendered as children of other components (e.g., a wm-option in a wm-action-menu) can also be selected.In other words, you can style what you write the markup for, but not what is built into the component.
-
Inheritable styles
continue to inherit.
body { color: purple; /* will apply inside the components */ }
-
Elements in the shadow root can be queried via the
Element.shadowRoot
property.You shouldn't have to reach in a component's shadow DOM. If you do, please let us know your use case so we can adapt the component, or show you the intended use in your case.
Flash of Unstyled Content
Unstyled component content can sometimes appear on the page before the component is loaded,
because the browser doesn't know the custom element yet and treats it as a div. You can add
a rule to your app's styles to ensure content is hidden before the component is loaded. Here's
an example for wm-button
:
wm-button:not(.hydrated) { visibility: hidden }
Add a rule per component, as needed.
Accessibility
The components are already fully accessible. Accessibility doesn't need to be implemented.
Usage in React
The library can be used as React components. The web components are simply wrapped in a React component,
allowing usage of the library as any other React component. In particular, events become available the React way (e.g. onWmEventTriggered
).
Please refer to the installation tab for instructions.
Usage in Elm
We recommend creating helper functions to simplify the use of components. In Phoenix-based projects, you should find some in assets/elm/Common/Components.elm
. Feel free to use and update this file. This file is not maintained by the Ripple team.
Simple helper
To render a Ripple component in an Elm app, you need to use the node
function, passing it the name of the node to render, e.g. node "wm-button"
, followed by the list of attributes and the list of children, like any other HTML element. In its simplest form, a helper can simply abstract away this node "wm-componentname"
part. Here's an example:
-- imports for all the examples on this page
import Html exposing (Html, div, text, button, node)
import Html.Events as Events
import Html.Attributes as Attrs
import Json.Decode as JD
wmButton : List (Html.Attribute msg) -> List (Html msg) -> Html msg
wmButton buttonAttrs buttonText = node "wm-button" buttonAttrs buttonText
Presets
But there is much more to it. Components are often reused almost identically, most attributes being always set to the same values. You can create a "preset" to abstract away the repeated parts. For instance here's a function that renders a primary button. It takes the button text and the onclick function as arguments and does the rest for you:
primaryButton : String -> msg -> Html msg
primaryButton buttonText onclickFunc =
node "wm-button"
[ Attrs.attribute "button-type" "primary", Events.onClick onclickFunc ]
[ text buttonText ]
If you often reach for an icononly
button with the "close" icon, you could create a helper with all attributes already set. Please note that the string "close" is not internationalized in this example:
closeButton : msg -> Html msg
closeButton onClickFunc =
node "wm-button"
[ Attrs.attribute "button-type" "icononly"
, Attrs.attribute "icon" "f156"
, Attrs.attribute "tooltip" "close"
, Events.onClick onClickFunc
]
[ text "Close" ]
Using types
To pass many attributes, you may want to represent the attributes as a record and declare a type alias:
type alias WmInputAttributes =
{ id : String
, label : String
, labelPosition : String
, requiredField : Bool
, placeholder : String
, info : String
, value : String
, characterLimit : Int
, disabled : Bool
, errorMessage : String
}
stringFromBool : Bool -> String
stringFromBool b =
case b of
True ->
"true"
False ->
"false"
wmInputWithEvents : WmInputAttributes -> (String -> msg) -> msg -> Html msg
wmInputWithEvents a inputMsg blurMsg =
node "wm-input"
[ Attrs.attribute "id" a.id
, Attrs.attribute "label" a.label
, Attrs.attribute "label-position" a.labelPosition
, Attrs.attribute "required-field" (stringFromBool a.requiredField)
, Attrs.attribute "placeholder" a.placeholder
, Attrs.attribute "info" a.info
, Attrs.value a.value
, Attrs.attribute "character-limit" (String.fromInt a.characterLimit)
, Attrs.attribute "error-message" a.errorMessage
, Attrs.attribute "disabled" (stringFromBool a.disabled)
, Events.onInput inputMsg
, Events.onBlur blurMsg
]
[]
Using custom events
Here is a way to hook up a custom event:
onPageClicked : (Int -> msg) -> Html.Attribute msg
onPageClicked message = Events.on "wmPaginationPageClicked" (JD.map message valDecoder)
valDecoder : JD.Decoder Int
valDecoder = JD.field "target" (JD.field "value" JD.int)
wmPagination : Int -> Int -> Int -> (Int -> msg) -> Html msg
wmPagination currentPage totalItems itemsPerPage updatePage =
node "wm-pagination"
[ Attrs.attribute "current-page" (String.fromInt currentPage)
, Attrs.attribute "total-items" (String.fromInt totalItems)
, Attrs.attribute "items-per-page" (String.fromInt itemsPerPage)
, onPageClicked updatePage
]
[]
The valDecoder
function above is needed to extract a string, but sometimes all we need is to know whether the event has fired. For instance whether a button was clicked. Here's a simpler event handler for these cases. Note: Modal emits the event wmModalCloseTriggered
when the close button is pressed:
onWmModalCloseTriggered : msg -> Html.Attribute msg
onWmModalCloseTriggered message = Events.on "wmModalCloseTriggered" (JD.succeed message)
Don't hesitate to reach out to the Ripple team if you need help writing helpers!
Neutral Theme
For Faculty Success we provide an alternate "Neutral" theme for our component library. To enable this theme, include the following attribute on your <html>
element: wm-theme="neutral"