Site Content
- Content Folder
- Project Structure
- Page Hierarchy
- Page Metadata (Front Matter)
- Page Partials
- Main Landing Page & Site Name
- AsciiDoc Syntax
- Section Outline
- Code Examples
- Code Examples from Source Files
- Rendered UI Examples
- Writing Examples to be Rendered
Content Folder
Documentation pages are located in the articles
folder by default. This content root path can be configured with the ARTICLES_PATH
property.
Project Structure
The most important files in the documentation project are shown here with their directory tree placement:
my-docs (1)
├── articles/ (2)
├── dspublisher/
│ └──docs-theme
│ └──global.css (3)
├── frontend/ (4)
├── src/main/java/ (5)
└── pom.xml (6)
-
The root folder name is the short name provided to the initialization script.
-
Page content in AsciiDoc files.
-
Website style customizations.
-
TypeScript component examples.
-
Java component examples.
-
Maven Project Object Model (POM) for theme and component dependencies.
Page Hierarchy
The file and folder hierarchy defines the website URL and navigation structure directly. Each AsciiDoc file (.adoc
or .asciidoc
) inside the content folder corresponds to a page on the website.
For example:
Path | URL | Navigation hierarchy |
---|---|---|
|
|
Each folder should have an index.adoc
file, which defines the title and description of that section, and perhaps some content for the index page. An empty index page displays an automatically generated section outline (i.e., a listing of the sub-pages and sub-sections in that section).
Page Metadata (Front Matter)
Each AsciiDoc file starts with a YAML formatted metadata block called the "front matter", defined between lines with three dashes. The following front matter attributes can be defined in this block. Only the title
attribute is required.
title
string-
Required. The page’s title as shown in the navigation menus/trees, breadcrumbs, search results, and social media share previews. This title can be different from the main page heading (i.e., the largest heading on the page), which is defined using AsciiDoc. For tabbed pages, this title attribute defines the main page heading, as well.
description
string-
Page description. Shown under the main page heading and in section outlines. Also used in social media share previews.
layout
string-
Only useful for
index.adoc
pages. Set totabbed-page
to display the pages in this section as tabs on the index page instead of as child items in the navigation tree. tab-title
string-
The title displayed for this page when it is displayed as a tab. Useful if you want to show a shorter title in the tab and a longer one in the breadcrumb or search results.
page-links
list of string-
Links which are displayed in the page header. Can be used for linking, for example, to the component repository, Figma file, or other resources. The links are defined using AsciiDoc syntax, and they can also contain simple formatting.
order
number-
Overrides the placement of the page in the navigation tree among the sibling pages in the same section. By default, pages are ordered alphabetically based on the title. Pages without an order are placed after ordered pages. It’s a good practice to make them spaced by 10 or 100, so you can add pages between existing ones without changing the number in other pages.
banner
string-
Define a banner which is shown directly under the site header. A banner defined in the root
index.adoc
file is shown on all documentation pages, but it can be overridden with a page level banner. banner-style
string-
Define the banner style. Possible values are
tip
,important
,warning
, andcaution
. banner-id
string-
Define the banner ID. If defined, the user can dismiss the banner permanently on their device. A banner without an ID is displayed again after a page reload.
section-nav
string-
Allows you to control the page navigation item. Possible values are:
-
expanded
: Expand this section in the navigation tree by default. Only applicable forindex.adoc
pages, which are not using tabbed page layout. -
hidden
: Hide this page from the navigation tree, section outlines, and page navigation at the bottom of each page. If you set this on anindex.adoc
page, all sub-pages are also hidden from the navigation tree, but they are not hidden from section outlines or page navigation. -
A custom value, or a combination of values (e.g.,
expanded custom-value
). The complete value is used as a class name on the corresponding HTML element in the navigation tree and section outlines, which allows you to add custom CSS styles for that item.
-
url
string-
Define an external URL to link to. This causes the page to not be created on the documentation website (i.e., all content in that file is ignored). The navigation item is instead a link to this external URL.
The following is a comprehensive example of the page metadata attributes:
---
title: Accordion
description: Accordion is a vertically stacked set of expandable panels. It reduces clutter and helps maintain the user's focus by showing only the relevant content at any time.
layout: tabbed-page
tab-title: Usage
page-links:
- https://github.com/vaadin/vaadin-flow-components/releases/tag/24.6.0.beta3[Flow 24.6.0.beta3]
- https://github.com/vaadin/web-components/tree/v24.6.0-rc1/packages/accordion[Web Component 24.6.0-rc1]
order: 10
banner: See the new https://example.org/blog[blog post]!
banner-style: tip
banner-id: my-new-blog-post
section-nav: expanded beta-component
---
// This is the main page heading...
= Accordion
// ...and the rest of the page content goes here
Page Partials
Files whose names start with an underscore (e.g., _shared.adoc
) and which don’t define any page metadata, don’t appear as pages in the website. Those files can be used to share content using AsciiDoc’s include directive.
Main Landing Page & Site Name
The main landing page of the documentation website is defined with the articles/flow/index.adoc
file. The title
front matter attribute defines the visible name in the website header.
AsciiDoc Syntax
The content of each page is written in the AsciiDoc syntax, which has some similarities with Markdown. See the AsciiDoc Syntax Quick Reference for a comprehensive list of AsciiDoc features.
Section Outline
Using the section outline macro, section index pages (i.e., all index.adoc
files) can include an automatically generated outline of its sub-pages and sub-sections. The outline lists each sub-page or sub-section name and description.
For example:
---
title: Section Name
description: This section contains multiple sub-pages and sub-sections.
---
= Section Name
Here's a brief overview of the contents in this section.
You can learn more from the following pages:
section_outline::[]
This macro is not part of the standard AsciiDoc syntax, but an extension Design System Publisher provides.
Code Examples
To display monospace text within regular text, wrap words in backticks (i.e., the `
character). For example:
A paragraph with monospace
text.
A paragraph with `monospace` text.
Use source code blocks to display code or command-line examples. Syntax highlighting for various languages is supported. The most commonly used ones are java
, typescript
, html
, and css
. For example:
Button button = new Button("My Button");
[source,java]
----
Button button = new Button("My Button");
----
Source Code Block Title
By default, the source code language is used as the title of the block. You can define a custom title, as well. For example, you could define a file name to illustrate the location of the code like so:
Button button = new Button("My Button");
.MyButtonExample.java
[source,java]
----
Button button = new Button("My Button");
----
Combine Related Code Examples Together
You can combine multiple code examples together if you specify them inside an .example
style open block. This is a good practice for showing a UI source code example, while having a data model or resource files available.
List<Person> people = DataService.getPeople(); // See Person.java
VirtualList<Person> list = new VirtualList<>();
list.setItems(people);
[.example]
--
.VirtualListExample.java
[source,java]
----
List<Person> people = DataService.getPeople(); // See Person.java
VirtualList<Person> list = new VirtualList<>();
list.setItems(people);
----
.Person.java
[source,java]
----
public class Person {
// The source of the Person object
}
----
.Address.java
[source,java]
----
public class Address {
// The source of the Address object
}
----
--
Code Examples from Source Files
You can include code examples from any file in the documentation project, by using the AsciiDoc include directive — primarily from files in the frontend
and src/main/java
source code folders, but practically from any folder in the project. The benefit of including them from the source code folders is that those files are compiled during the build. This ensures that any compilation errors in the code examples are detected early.
Use the AsciiDoc include directive to include them in code blocks as follows:
[source,java]
----
include::{root}/src/main/java/path/to/MyExample.java[]
----
Use the {root}
attribute reference at the start of the path, if you want to use an absolute reference — starting from the project root. Otherwise the path is relative to the AsciiDoc file where the include directive is used.
By default, the name of the file included is used as the title for the source code block. You can customize the title if needed.
Include Parameters
You can pass various parameters to the include directive, between the trailing square brackets, to affect how the code example is included.
render
-
Renders a interactive example, as described in Rendered UI Examples.
tags=<name>
-
Specifies tags for extracting a source code snippets. See Snippets for more information.
indent=<spaces>
-
Specifies the indentation of the code inside the listing. Without the parameter, the indentation in the source listing is used. You should use
indent=0
. group=<name>
-
Groups the file under a group tab. You can use this for language groups, such as
group=Java
andgroup=TypeScript
in corresponding include statements. You shouldn’t use it if you only have a single group, as it would show an unnecessary tab. See Group Source Code Blocks for more information. hidden
-
Hides the example. This is necessary for TypeScript counterparts of Java examples, which are only included to load component styles, as described in Client-Side Dependencies of Java Examples.
Snippets
Snippets — known as Tagged Regions in AsciiDoc — are segments of code examples. They’re displayed by default, instead of the entire source code of an included file.
The Expand code button in the example reveals all the lines of the source code. This can be useful for making it easier for readers to see the most relevant part.
For example:
Button button = new Button("Button");
Paragraph info = new Paragraph(infoText());
button.addClickListener(clickEvent -> {
counter += 1;
info.setText(infoText());
});
[source,java]
----
include::{root}/src/main/java/com/vaadin/demo/component/button/ButtonBasic.java[tags=snippet]
----
Use snippets by adding the tags
attribute in the brackets following the path, indicating which named snippet to include (i.e., include::path/to/example[tags=snippet]
).
Defining Snippets
Snippets are defined in the source code as comments: tag::snippet[]
marks the start of the snippet; and end::snippet[]
marks the end of the snippet.
The snippet name between the colons and square brackets can be any string. You don’t need to name it "snippet", but you need to use the string for both the starting and the ending comment.
Write the comment in the format defined for the example’s syntax highlighting. For TypeScript examples, this means that code tagged with [source,html]
must use HTML comments within an HTML literal in the code. Here are examples for commonly used languages in the documentation:
public MyComponentExample() {
// tag::snippet[]
MyComponent myc = new MyComponent("My component");
// end::snippet[]
add(myc);
}
Excluding Source Code Lines
Part of the source code can be entirely omitted from the rendered code examples by appending a specific comment after the line (i.e., hidden-source-line
). For example, here’s how you would hide an annotation in a Java example:
// The following line isn't shown
// if this file is added using the include directive
public MyComponentExample() {
MyComponent myc = new MyComponent("My component");
add(myc);
}
// The following line isn't shown
// if this file is added using the include directive
@SomeAnnotation // hidden-source-line
public MyComponentExample() {
MyComponent myc = new MyComponent("My component");
add(myc);
}
This is useful for excluding code that’s only needed for a rendered UI example, but not relevant for normal use of a component.
This isn’t a standard AsciiDoc feature, but an extension that Design System Publisher provides.
Group Source Code Blocks
When you combine related code examples together, they can be grouped to create collections of related source files by including the group
attribute in the include directive. Each group can include a description for its contents written before each source code block.
A common use case for the grouping is to show alternative approaches for achieving the same end result. For example, how to implement a certain user interface in either Java or TypeScript:
Here’s some text to describe the TypeScript example. You could mention things like the Person.ts
file.
<vaadin-virtual-list
.items="${this.people}"
${virtualListRenderer(this.personCardRenderer, [])}
></vaadin-virtual-list>
[.example]
--
Here's some text to describe the TypeScript example.
You could mention things like the `Person.ts` file.
[source,html]
----
include::{root}/frontend/demo/component/virtuallist/virtual-list-basic.ts[group=TypeScript,tags=snippet,indent=0]
----
[source,typescript]
----
include::{root}/frontend/generated/com/vaadin/demo/domain/Person.ts[group=TypeScript]
----
[source,typescript]
----
include::{root}/frontend/generated/com/vaadin/demo/domain/Address.ts[group=TypeScript]
----
Here's some text to describe the Java example.
You could mention things like the `setRenderer()` method.
[source,java]
----
include::{root}/src/main/java/com/vaadin/demo/component/virtuallist/VirtualListBasic.java[group=Java,tags=snippet,indent=0]
----
[source,java]
----
include::{root}/src/main/java/com/vaadin/demo/domain/Person.java[group=Java]
----
[source,java]
----
include::{root}/src/main/java/com/vaadin/demo/domain/Address.java[group=Java]
----
--
Rendered UI Examples
You can render a code example as an interactive UI example by including the render
attribute in the include directive. Only Java and TypeScript examples can be rendered. The following is an example of a rendered Java example:
new tab
package com.vaadin.demo.component.button;
import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.html.Div;
import com.vaadin.flow.component.html.Paragraph;
import com.vaadin.flow.component.orderedlayout.FlexComponent;
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
import com.vaadin.flow.router.Route;
@Route("button-basic")
public class ButtonBasic extends Div {
private int counter = 0;
public ButtonBasic() {
Button button = new Button("Button");
Paragraph info = new Paragraph(infoText());
button.addClickListener(clickEvent -> {
counter += 1;
info.setText(infoText());
});
HorizontalLayout horizontalLayout = new HorizontalLayout(button, info);
horizontalLayout.setAlignItems(FlexComponent.Alignment.BASELINE);
add(horizontalLayout);
}
private String infoText() {
return String.format("Clicked %d times", counter);
}
}
[source,java]
----
include::{root}/src/main/java/com/vaadin/demo/component/button/ButtonBasic.java[render]
----
Client-Side Dependencies of Java Examples
Styles for components that are used in an example are only loaded for TypeScript examples. You therefore always need a TypeScript counterpart for any Java example. Otherwise, the components aren’t styled and the example appears broken. The TypeScript example doesn’t need to be functional, it only needs to import the needed components.
The TypeScript include
shouldn’t have a group
parameter, and it should have the hidden
parameter instead of render
.
For example, the AsciiDoc source for the previous example is actually the following:
[.example]
--
[source,java]
----
include::{root}/src/main/java/com/vaadin/demo/component/button/ButtonBasic.java[render]
----
[source,typescript]
----
include::{root}/frontend/demo/component/button/button-basic.ts[hidden]
----
--
Alternatively, you can use the DOCS_IMPORT_EXAMPLE_RESOURCES="true"
configuration option to load all frontend resources up front. Then it’s sufficient to include the Java code example without an additional, or hidden TypeScript example. Add it as before the start-up or build command:
DOCS_IMPORT_EXAMPLE_RESOURCES="true" npm run dspublisher:start
Use code example groups to show both a TypeScript and Java implementation for the same UI. For example, here’s the same example as before, now with a corresponding TypeScript version included.
new tab
package com.vaadin.demo.component.button;
import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.html.Div;
import com.vaadin.flow.component.html.Paragraph;
import com.vaadin.flow.component.orderedlayout.FlexComponent;
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;
import com.vaadin.flow.router.Route;
@Route("button-basic")
public class ButtonBasic extends Div {
private int counter = 0;
public ButtonBasic() {
Button button = new Button("Button");
Paragraph info = new Paragraph(infoText());
button.addClickListener(clickEvent -> {
counter += 1;
info.setText(infoText());
});
HorizontalLayout horizontalLayout = new HorizontalLayout(button, info);
horizontalLayout.setAlignItems(FlexComponent.Alignment.BASELINE);
add(horizontalLayout);
}
private String infoText() {
return String.format("Clicked %d times", counter);
}
}
[source,java]
----
include::{root}/src/main/java/com/vaadin/demo/component/button/ButtonBasic.java[render,group=Java]
----
[source,typescript]
----
include::{root}/frontend/demo/component/button/button-basic.ts[render,group=TypeScript]
----
Always Show Source Code
Use the show-code
style to show the source code immediately, so that the user doesn’t need to click the Show code button to reveal it. You can apply the style on a standalone source code block, or an .example
style open block.
new tab
Button button = new Button("Button");
Paragraph info = new Paragraph(infoText());
button.addClickListener(clickEvent -> {
counter += 1;
info.setText(infoText());
});
// Source code block
[source,java,role="show-code"]
----
...
----
// Example open block
[.example.show-code]
--
...
--
Always Hide Source Code
Use the render-only
style to hide the source code. This doesn’t disable the example group tabs, which can still be used to choose which rendered example is shown.
new tab
Button button = new Button("Button");
Paragraph info = new Paragraph(infoText());
button.addClickListener(clickEvent -> {
counter += 1;
info.setText(infoText());
});
// Source code block
[source,java,role="render-only"]
----
...
----
// Example open block
[.example.render-only]
--
...
--
Writing Examples to be Rendered
Before you can add a rendered UI example on a page, you need to create the example itself.
Add dependencies for custom components to the pom.xml
file the same way as a custom theme JAR. Components and themes can be included in the same dependency.
Java Examples
Place Java-based examples in sub-folders inside the src/main/java/
folder. Each example needs to be in its own file. To add examples for a new component, create a new folder inside the component
folder with a Java file inside it. For example, see the MyComponentExample.java
file:
my-docs
└── src/main
└── java/com/vaadin
└── demo
└── component
├── accordion
⋮ ├── AccordionBasic.java
⋮ ├── AccordionDisabledPanels.java
⋮ ⋮
├── mycomponent
⋮ ├── MyComponentExample.java
⋮ ⋮
package com.vaadin.demo.component.mycomponent;
import com.vaadin.flow.component.html.Div;
import com.vaadin.flow.router.Route;
import com.vaadin.demo.DemoExporter; // hidden-source-line
import com.example.MyComponent;
@Route("my-component-example") 2
public class MyComponentExample extends Div { 1
public MyComponentExample() {
MyComponent myc = new MyComponent("My component");
add(myc); 3
}
4
public static class Exporter extends // hidden-source-line
DemoExporter<MyComponentExample> {} // hidden-source-line
}
-
A class that extends
Div
or some other container likeVerticalLayout
. -
with an optional
@Route
annotation with a route name that’s unique within the entire website. -
and a constructor that adds the desired UI as a child to the class.
-
A static inner class that extends the
DemoExporter
class with a type parameter matching the example class.
Design System Publisher uses spring-boot-devtools
to rebuild automatically the Java examples when you modify and save them — assuming you configured your editor or IDE to do so. Rebuilding the Java examples typically takes about thirty seconds, after which the page must be reloaded manually.
TypeScript Examples
Place TypeScript-based examples in sub-folders within the frontend/
folder. Each example needs to be in its own file.
my-docs
└── frontend
└── demo
└── component
├── accordion
⋮ ├── accordion-basic.ts
⋮ ├── accordion-disabled-panels.ts
⋮ ⋮
├── my-component
⋮ ├── my-component-example.ts
⋮ ⋮
To add examples for a new component, create a folder with a TypeScript file inside it. For example:
import '../../init'; // hidden-source-line
import { applyTheme } from 'generated/theme';
import { html, LitElement, customElement } from 'lit-element';
import '@my-org/my-component/my-component';
@customElement('my-component-example') 1
export class Example extends LitElement { 2
protected createRenderRoot() { 3
const root = super.createRenderRoot();
applyTheme(root);
return root;
}
render() { 4
return html`
<my-component>My component</my-component>
`;
}
}
-
A
@customElement
annotation with a name that’s unique within the entire website. -
A class that extends
LitElement
. -
A
createRenderRoot()
method that calls theapplyTheme(root)
method. This applies your custom theme to the example. -
A render method that returns the HTML for the example.
TypeScript code examples don’t refresh automatically. The code example displayed below a rendered example isn’t refreshed when you edit the source AsciiDoc file in your text editor. To refresh the code example, the page’s text content needs to be re-saved for Design System Publisher to rebuild the page, and you need to reload the page.
6DF51E1C-15BB-4E15-A3C7-5C616B7BFC35