Skip to main content

Escape hatches

Overview

Jutro Design System UX specifications are based on the identified UX use cases and they describe the problems and requirements together with the recommended approaches and guidelines to cover them. The different Jutro components are built with the objective of being aligned with these UX specifications and all the properties and features provided are based on them.

Although the main goal of the components is the UX alignment, they also provide some custom alternatives that might allow developers to go a step beyond the default behavior, and this is where escape hatches are introduced.

What is an Escape Hatch?

"Escape Hatch" is a term adopted in software development to refer to intentional alternatives (leaks) in the model that allow users to 'escape' and get access to a lower abstraction layer. It might be even considered as a door opened to 'hack' the specific abstraction contract.

An example, relevant for Jutro developers would be the React escape hatches

Jutro Design System Escape Hatches

Warning

Please consider the possible side effects of any escape hatch used. While they provide a mechanism to extend a behavior or reduce requirements gaps, depending on the usage they might have unexpected effects. Some potential effects could be broken features, accessibility issues, and future upgrade complications.

Each Jutro component might provide different escape hatches, depending on the use case and the component type. In some cases, these are provided as part of the stable API of the component, but included as escape hatches as they provide options that allow an additional flexibility on top of the UX specifications alignment.

Below you can find descriptions of some of the most common escape hatches provided by the Jutro components. For component-specific escape hatches, check the component documentation.

Design Tokens

Although they are part of the Jutro components' API, the design tokens might be considered an escape hatch as they allow customization of the UX decision related to theming.

See the Design Tokens section for more details.

dangerouslySet properties

Some components include one or more dangerouslySet... properties. These allow the developer to completely override a whole element / aspect of the component. In most cases this option will be provided when UX specifications identify an edge case including some unknown alternatives.

The dangerouslySet property will be typed as a ReactNode and, normally, there will be a related hook to provide access to the component context.

Example: AccordionCard header will normally have just a text (title prop) but there is a known need to have other elements like icons, tags or even buttons in some specific cases, so a dangerouslySetHeader prop will be provided.



function MyCustomHeader() {
const { disabled } = useComponentState(); // provided hook for context information
return <span>{disabled ? 'I am disabled' : 'I am not disabled'}</span>;
}


<AccordionCard title="some title" dangerouslySetHeader={{<MyCustomHeader />}}/>

children property

While in general every component property will be typed to restrict the values and options provided, in some cases it might be left completely open (through children: ReactNode). The most common scenario for this case are those components that are mainly intended to be used as containers for other content (e.g. Modals).

className property

Jutro components might provide a className property. This is used to set the class attribute of the top level element of the component.

Warning

The underlying HTML structure of a component is not part of the component API, so it might be subject to modifications without them being considered a breaking change. While the top level element of the component would remain stable, the rest of the internal structure can be modified.

Allow passing default HTML attributes

Apart from the Jutro defined API, some components will allow passing an additional set of the native HTML attributes that the component might have. These additional attributes will be directly passed to the top level element or to the specific element specified in the component documentation.

An example of this use case is that some of the 'input' Jutro components might allow passing the standard HTML attributes that an HTML native input element would accept: e.g. id or name. The list of attributes might be restricted to avoid those attributes interfering with the component properties and behavior. As an example, if the component is already handling the maximum accepted length of its content, the maxLength native attribute might not be accepted.

As in other cases, side effects of the attributes used must be taken into consideration while using them.

note

When creating a new field, you should not use the ID prop. New fields generate a unique ID internally. If you want to create your own ID, you can use the useId hook from @jutro/platform to ensure the ID is unique. See the Hooks page for more information on the useId hook.

ref property and imperative handlers

ref is an escape hatch that provides access to DOM nodes or React components to allow developers to modify elements outside of the render flow. In the case of Jutro, this option might be considered in some specific components, but it will be normally implemented following the imperative handler approach: instead of just providing access to the whole element, specific methods or properties will be exposed based on the known use cases. These can evolve and increase in future library releases.

An example of this option would be the creation of a ref property that only provides access to specific features like setting the focus on a field or scrolling to the specific element.

Native event property

Jutro input components will expose some events like onChange. These events will normally include, apart from any other custom value, the native event object that triggered the event.

It is expected that, normally, the custom values that are passed to the event provide enough information for the developer, but this event will allow further control over some 'basic' features like preventDefault.

As an example, an onChange event would be defined as: (event: React.ChangeEvent<HTMLInputElement>, newValue: T) => void, so the developer can just use newValue to perform validations or actions based on the user input, but the native event is also available for any additional feature.