Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

docs: Oryx components #2187

Merged
merged 65 commits into from
Oct 13, 2023
Merged
Show file tree
Hide file tree
Changes from 46 commits
Commits
Show all changes
65 commits
Select commit Hold shift + click to select a range
f01e5c9
Oryx component definition
tobi-or-not-tobi Sep 19, 2023
ed513d2
review and moved to 2023 release
tobi-or-not-tobi Sep 20, 2023
a217910
Merge branch 'master' into docs/building-components
tobi-or-not-tobi Sep 20, 2023
7956a3b
small fixes
tobi-or-not-tobi Sep 21, 2023
bdc4800
decrease the alignment with atomic design
tobi-or-not-tobi Sep 23, 2023
e408c34
Merge branch 'master' into docs/building-components
tobi-or-not-tobi Sep 23, 2023
4711625
add missing component options by attributes
tobi-or-not-tobi Sep 25, 2023
d4c1316
drop duplicate message about lit vs non-lit
tobi-or-not-tobi Sep 25, 2023
d0d05f0
Update component-introduction.md
andriitserkovnyi Oct 4, 2023
77d1b96
Update component-types.md
andriitserkovnyi Oct 4, 2023
a7b348f
Merge branch 'master' into docs/building-components
andriitserkovnyi Oct 4, 2023
02e8956
Merge branch 'master' into docs/building-components
andriitserkovnyi Oct 4, 2023
d6c5ec1
Update component-types.md
andriitserkovnyi Oct 4, 2023
3afb81e
Update component-implementation.md
andriitserkovnyi Oct 4, 2023
610bc90
Update component-implementation.md
andriitserkovnyi Oct 4, 2023
94c2b0f
Update component-implementation.md
andriitserkovnyi Oct 4, 2023
05a9c8e
Update component-implementation.md
andriitserkovnyi Oct 5, 2023
9847b35
Update component-implementation.md
andriitserkovnyi Oct 5, 2023
28de75d
Merge branch 'master' into docs/building-components
andriitserkovnyi Oct 5, 2023
e5cb0ff
Update component-implementation.md
andriitserkovnyi Oct 5, 2023
d365029
Update component-definition.md
andriitserkovnyi Oct 5, 2023
7e6168e
Update component-definition.md
andriitserkovnyi Oct 5, 2023
1977aa9
Update component-options.md
andriitserkovnyi Oct 6, 2023
ee7424e
Update component-options.md
andriitserkovnyi Oct 6, 2023
ef1e523
fix link
tobi-or-not-tobi Oct 7, 2023
ad983b6
rephrased
tobi-or-not-tobi Oct 7, 2023
73f70f8
rephrased
tobi-or-not-tobi Oct 7, 2023
dddf848
rephrased
tobi-or-not-tobi Oct 7, 2023
420a61a
rephrased
tobi-or-not-tobi Oct 7, 2023
47497b7
added typescript enum
tobi-or-not-tobi Oct 7, 2023
ef669bc
rephrases
tobi-or-not-tobi Oct 7, 2023
b6dd8dc
Update component-options.md
andriitserkovnyi Oct 9, 2023
76b69c4
Merge branch 'docs/building-components' of https://github.com/spryker…
andriitserkovnyi Oct 9, 2023
2de7778
comments
andriitserkovnyi Oct 9, 2023
b6d0cd0
Merge branch 'master' into docs/building-components
andriitserkovnyi Oct 9, 2023
dbdb666
Update component-integration.md
andriitserkovnyi Oct 9, 2023
c8af0a7
review
andriitserkovnyi Oct 9, 2023
cb97230
review
andriitserkovnyi Oct 9, 2023
8c1d408
rename
andriitserkovnyi Oct 10, 2023
bc49bef
Update oryx-implementing-components.md
andriitserkovnyi Oct 10, 2023
d5e4cf1
Merge branch 'master' into docs/building-components
andriitserkovnyi Oct 10, 2023
3151872
Update oryx-implementing-components.md
andriitserkovnyi Oct 10, 2023
cfa0893
Update oryx-implementing-components.md
andriitserkovnyi Oct 10, 2023
14f497c
Update oryx-implementing-components.md
andriitserkovnyi Oct 10, 2023
3effd32
Update oryx-implementing-components.md
andriitserkovnyi Oct 11, 2023
6d821f2
Merge branch 'master' into docs/building-components
andriitserkovnyi Oct 11, 2023
d2701dd
Update component-definition.md
andriitserkovnyi Oct 11, 2023
52a15cf
review
andriitserkovnyi Oct 11, 2023
185afdd
Update oryx-managing-component-options.md
andriitserkovnyi Oct 11, 2023
1a6fb71
Merge branch 'master' into docs/building-components
andriitserkovnyi Oct 11, 2023
67a9927
Update oryx-integration-of-components.md
andriitserkovnyi Oct 11, 2023
fa77cda
Merge branch 'master' into docs/building-components
andriitserkovnyi Oct 11, 2023
34a1bdc
rename
andriitserkovnyi Oct 11, 2023
368f6dc
fixes
tobi-or-not-tobi Oct 11, 2023
55ca04b
Update docs/scos/dev/front-end-development/202307.0/oryx/building-com…
tobi-or-not-tobi Oct 11, 2023
885206f
Update docs/scos/dev/front-end-development/202307.0/oryx/building-com…
tobi-or-not-tobi Oct 11, 2023
430ed6c
fixes
tobi-or-not-tobi Oct 12, 2023
bc2c2b6
Merge branch 'docs/building-components' of https://github.com/spryker…
tobi-or-not-tobi Oct 12, 2023
3961d69
Merge branch 'master' into docs/building-components
andriitserkovnyi Oct 12, 2023
e8429e7
final
andriitserkovnyi Oct 12, 2023
655c9fb
after-comments
andriitserkovnyi Oct 12, 2023
80e5fe8
Merge branch 'master' into docs/building-components
andriitserkovnyi Oct 12, 2023
90b29c4
Update scos_dev_sidebar.yml
andriitserkovnyi Oct 12, 2023
d5c914b
rephrased
tobi-or-not-tobi Oct 12, 2023
5419829
links
andriitserkovnyi Oct 13, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions _data/sidebars/scos_dev_sidebar.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3391,6 +3391,35 @@ entries:
- title: Routing
url: /docs/scos/dev/front-end-development/oryx/building-pages/oryx-routing.html

- title: Building Components
include_versions:
- "202307.0"
nested:
- title: Component Introduction
include_versions:
- "202307.0"
url: /docs/scos/dev/front-end-development/{{page.version}}/oryx/building-components/component-introduction.html
- title: Component Types
include_versions:
- "202307.0"
url: /docs/scos/dev/front-end-development/{{page.version}}/oryx/building-components/component-types.html
- title: Component Implementation
include_versions:
- "202307.0"
url: /docs/scos/dev/front-end-development/{{page.version}}/oryx/building-components/component-implementation.html
- title: Component Definition
include_versions:
- "202307.0"
url: /docs/scos/dev/front-end-development/{{page.version}}/oryx/building-components/component-definition.html
- title: Component Options
include_versions:
- "202307.0"
url: /docs/scos/dev/front-end-development/{{page.version}}/oryx/building-components/component-options.html
- title: Component Integration
include_versions:
- "202307.0"
url: /docs/scos/dev/front-end-development/{{page.version}}/oryx/building-components/components-integration.html

- title: Architecture
nested:
- title: Dependency injection
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
---
title: "Oryx components definition"
description: Components are registered in an Oryx application by a definition file
last_updated: Sept 19, 2023
template: concept-topic-template
---

Oryx components can be used in different ways. They can be configured in [pages](/docs/scos/dev/front-end-development/{{page.version}}/oryx/building-pages/oryx-pages.html) and [compositions](/docs/scos/dev/front-end-development/{{page.version}}/oryx/building-pages/oryx-compositions.html), used in components or integrated in the content from a CMS of choice.

When a component is rendered for the first time, Oryx resolves the component definition from the registry and loads the associated implementation. With this, components are lazily loaded.

## Creating a component definition

To register a [component implementation](/docs/scos/dev/front-end-development/{{page.version}}/oryx/building-components/component-implementation.html), you need to provide a component definition. The component definition requires a name and an implementation. The name is used as the web component element name and consists of two or more words separated by a dash. It is a good practice to prefix components with a project, brand, or company name. For example, Oryx components are prefixed with `oryx-`.

{% info_block infoBox "Update definitions" %}
You can also update an existing component definition. To match an existing definition, you still need to provide a name.
{% endinfo_block %}

The following example shows where a component is registered, providing both the name and implementation.
andriitserkovnyi marked this conversation as resolved.
Show resolved Hide resolved

```ts
import { componentDef } from "@spryker-oryx/utilities";

export const productIdComponent = componentDef({
name: "oryx-product-id",
impl: () => import("./id.component").then((m) => m.ProductIdComponent),
});
```

The implementation is imported using the [static import declaration](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import). This import binding is used by build systems such as [Vite](https://vitejs.dev/) to create a separate JavaScript chunk during the build. This allows to load the JavaScript chunk upon demand.

## Register a component definition

After you've created a component definition, you need to configure it in the application. The [application orchestrator](/docs/scos/dev/front-end-development/{{page.version}}/oryx/building-applications/oryx-application-orchestration/oryx-application-orchestration.html) provides the `withComponents()` API that can be used to register an array of components.

```ts
import { appBuilder } from "@spryker-oryx/application";

export const app = appBuilder().withComponents([
{
name: "oryx-product-id",
impl: () => import("./components/product/id.component"),
},
]);
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
---
title: "Oryx Components options"
description: Components Options provide reusable components cross business models
last_updated: Sept 19, 2023
template: concept-topic-template
---

Oryx components support configurable options to make the components reusable in different business contexts. Component options are JavaScript objects that can be configured as part of the application configuration or added by providing an attribute. To ensure a good developer experience, each component type can provide an interface for the options.

To show the usage of component options, we use the tax message ("incl. vat") that is rendered on `ProductPriceComponent`. The tax message might not be useful for all businesses. For example, in a b2c context, the message might not be required. You can conditionally render the message based on a configuration.

## Set up component options

Component options are provided by a TypeScript interface. This ensures a good developer experience when implementing a component and configuring the application. The component option interface is defined in a separate `*.model.ts` file in Oryx components, but there's no strict rule to follow.

```ts
export interface ProductPriceOptions {
/**
* Indicates whether to show tax message for the price.
*/
enableTaxMessage?: boolean;
}
```

To resolve component options in your new components, you can use `ContentMixin`. `ContentMixin` provides a type safe `$option` [signal](/docs/scos/dev/front-end-development/{{page.version}}/oryx/architecture/reactivity/signals.html) that guarantees efficient usage of the options.

Oryx provides the `ContentMixin` mixin to work with component options. You can use the mixin to hand in the option interface. The following example shows how mixin is used to define the options.

```ts
export class ProductPriceComponent extends ContentMixin<ProductPriceOptions>(
LitElement
) {
// use the $options() signal in your code
}
```

## Configure component options

There are different ways to configure component options. Components can set up default values for the options that are used as a fallback in case no values are provided. [Feature sets](/docs/scos/dev/front-end-development/{{page.version}}/oryx/building-applications/oryx-feature-sets.html) can provide values for a specific business context. As an application developer, you can provide customized values, either for all component instances in the application configuration or by providing options per instance in the experience data.

You can also override the options when using components in your code.

The approaches to set up the values are detailed in the following sections.

### Default component option values

Components can set up default values for the component options. The default values are used as a fallback in case there are no specific values provided.

Oryx provides the `@defaultOptions` class decorator that can be used to add default values.

```ts
@defaultOptions({
enableTaxMessage: true,
})
export class ProductPriceComponent extends ContentMixin<ProductPriceOptions>(
LitElement
) {
// ...
}
```

### Feature set component options

Default component options can be overridden in feature sets. [Feature sets](/docs/scos/dev/front-end-development/{{page.version}}/oryx/building-applications/oryx-feature-sets.html) simplify the setup of a standard for a specific business model, such as B2B or B2C. Besides providing the features, a feature set can also provide component configurations. The feature set configurations override the default option values provided by the components.

### Application-driven component options

You can customize default component values and feature set values in the application configuration. The configuration is used every time the component is used in the application.

The following example shows how to configure an application using `appBuilder`.

```ts
export const app = appBuilder()
// ...
.withOptions({
"oryx-product-price": {
enableTaxMessage: false,
},
})
.create();
```

For more information, see [Application orchestration](/docs/scos/dev/front-end-development/{{page.version}}/oryx/oryx-application-orchestration/oryx-application-orchestration.html).

### Component option values in experience data

The default options, feature set configurations, and application configurations are applied to the Component type. The options provided in the experience data are applied to a specific instance in the experience data structure.

In the following configuration, you see a part of the experience data that sets the `enableSalesLabel` option to `false`. This configuration is only applied to the instance. This configuration does not affect the component when it's used elsewhere.

```ts
{
type: 'oryx-composition',
components: [
{
type: 'oryx-product-price',
options: { enableSalesLabel: false },
},
]
}
```

For more information about creating and customizing experience data, see [Oryx: Pages](/docs/scos/dev/front-end-development/{{page.version}}/oryx/building-pages/oryx-pages.html).

### Hardcoded component options

When using components in code, options can be provided using the `options` attribute. The options attribute is resolved automatically by `ContentMixin` that most domain components use.

The following example shows how component options are written in the component `options` attribute. When options are added by an attribute, the web component specs require stringified JSON. [Lit](https://lit.dev) provides a convenient property mapping shown in the example below.

```ts
protected override render(): TemplateResult {

const options: ProductPriceOptions = {
enableSalesLabel: false;
}
return html`<oryx-product-price .options=${options}></oryx-product-price>`;
}
```

## Use component options

To use component options asynchronously, it is important to observe the options and react to updates in the component UI. Oryx provides a [reactive](/docs/scos/dev/front-end-development/{{page.version}}/oryx/architecture/reactivity/reactivity.html) framework with observable data streams that can update the UI using [signals](/docs/scos/dev/front-end-development/{{page.version}}/oryx/reactivity/signals.html). To simplify the integration in component logic, `ContentMixin` provides the `$options` signal that can be called in the render logic or other signals.

The following code shows how to use the `$options` signal. Due to the component option interface, the usage of the signal is type safe.

```ts
@defaultOptions({
enableTaxMessage: true,
})
export class ProductPriceComponent extends ContentMixin<ProductPriceOptions>(
LitElement
) {
protected override render(): TemplateResult {
return html` ... ${this.renderTaxMessage()} ... `;
}

protected renderTaxMessage(): TemplateResult | void {
if (!this.$options().enableTaxMessage) return;

return html`...`;
}
}
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
---
title: "Oryx: Component types"
description: Oryx components compared to Atomic Design
last_updated: Sept 23, 2023
template: concept-topic-template
---

Oryx applications are built completely out of components. Whether it's a page or a section of the page or a button, they're all components.

Oryx supports three types of components:
andriitserkovnyi marked this conversation as resolved.
Show resolved Hide resolved

- Design system components
Highly reusable components that are used to build consistent user interfaces (UIs).
- Domain components
Functional components that are concerned with a specific _domain_, like the product or cart domains. Domain Components use
andriitserkovnyi marked this conversation as resolved.
Show resolved Hide resolved
- Composition components
Containers that are used to render pages or sections by providing a list of components and their layout.

Even though Oryx does not implement [Atomic Design](https://bradfrost.com/blog/post/atomic-web-design/), the component types can be roughly mapped to the Atomic Design levels:

| Atomic Design level | Oryx Component | Examples |
| ------------------- | ------------------------ | ------------------------------ |
| Atoms | Design system components | Button, form element |
| Molecules | Domain components | Product images, cart entry |
| Organisms | Compositions | Product carousel, product list |
| Templates | Composition references | Header, footer |
| Pages | Compositions | Product page, Cart page |

## Design system components

The Oryx design system offers a collection of highly reusable components that are essential for building a consistent and visually appealing UI. These components are agnostic of the application's context and serve as the building blocks for domain components.

Design system components ensure a consistent and cohesive visual language across the application. The components do not interact with application logic directly. Because they don't know anything about their surroundings, they're considered fairly "dumb". They are used by domain components, which provide them with properties and dispatch events that can be used by the outer components.

You can configure and customize design system components or replace them with your own. This enables you to build the required visual language throughout the application. Any reference to a design system component, like `<oryx-button>`, is resolved by your custom version regardless of where it's used.

Design system components are available in the `ui` package: `@spryker-oryx/ui`. They do not depend on any application logic, except for the integration of localized messages.

## Domain components

Oryx functionality is organized in domains. Domain packages contain functional components, also know as _domain components_. For example, all product-related components are organized in the product package.

Domain components leverage the design system components to ensure a consistent UI/UX. The design system components are integrated with inputs (properties), and all of their events are handled by domain components.

Domain components integrate with domain services to obtain and update the application state. The services handle the integration with backend APIs and application state management. In a single page application experience, domain components need to support [reactivity](/docs/scos/dev/front-end-development/{{page.version}}/oryx/reactivity/reactivity.html) to ensure the application state is reflected immediately after it is changed. The complexity of reactivity is avoided as much as possible in components by using [signals](/docs/scos/dev/front-end-development/{{page.version}}/oryx/reactivity/signals.html). To avoid repeating the boilerplate code that is required for each domain component, domains often provide a mixin. The mixin provides the required properties and signals that can be used by the components.

Each domain package contains associated domain components. Product components, for example, are part of the `@spryker-oryx/ui` package. The components use a consistent naming convention for class and element names. For example, the Product Title component, is named `ProductTitleComponent` and can be used with the `<oryx-product-title>` element. To avoid clashes with other frameworks, the elements are prefixed with `oryx-`.

## Composition components

Compositions are simple containers of components that are used to organize components on a page or a page section. The list of components and their options is configurable. The configurable approach allows for dynamic experiences that can be used to personalize or split-test experiences.

Because of this generic approach, all pages and their compositions are rendered as a single component only: `CompositionComponent` (`<oryx-composition>`). The composition component iterates over a list of components and applies layout and options to it.

To better understand the concepts of pages and compositions, see [Pages](/docs/scos/dev/front-end-development/{{page.version}}/oryx/building-pages/oryx-pages.html) and [Compositions](/docs/scos/dev/front-end-development/{{page.version}}/oryx/building-pages/oryx-compositions.html).

If you want to customize the application with your own pages, there's no need to follow the concept of compositions. You can create page-specific components, like `ProductDetailPageComponent`, and use them instead of using experience data.
Loading
Loading