Skip to content

Instantly share code, notes, and snippets.

@jouni
Last active August 6, 2020 14:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jouni/fd105cf7316e629a1d44929f99b9e2b5 to your computer and use it in GitHub Desktop.
Save jouni/fd105cf7316e629a1d44929f99b9e2b5 to your computer and use it in GitHub Desktop.
Prototype documentation how custom design systems might work in Vaadin

How to create a reusable design system

Create a new project with the following folder structure:

src/main
  java/org/your/name/components
    MyButton.java
  resources/META-INF/resource/frontend
    my-design-system
      assets
        mds-font.woff2
      components
        my-button
          my-button.ts
          my-button.css
      shared-styles.css
      [color.css]
      ...
pom.xml
pom.xml

Add any components you wish as dependencies to this project in pom.xml. Use the @NpmPackage annotation in a component’s Java API class to include an existing npm packaged web component (meaning, do not use package.json to include pure web components).

src/main/java

Contains component Java API classes, and any other Java helpers.

src/main/resources/META-INF/resource/frontend/my-design-system

Contains the frontend resources of your design system, including static assets (fonts, icons, etc), style sheets, and web component implementations (including their style sheets). You are free to define the folder structure as you wish, but the above is the recommended structure.

src/main/resources/META-INF/resource/frontend/my-design-system/shared-styles.css

The shared-styles.css file is a style sheet which should be included in all style scopes, including global and view specific scopes (though, it is not recommended to use shadow DOM for application views). Commonly, it defines utility CSS classes and/or overrides the default styling of standard HTML elements (like paragraphs, headings, and links).

If your design system is light-weight, you can use this file to override component specific styles as well (using @media, see "Styling Components").

Examples of the file contents

shared-styles.css

@import "./color.css";

@font-face {
  font-family: "MDS";
  src: url("my-design-system/assets/mds-font.woff2") format("WOFF2");
}

h1 {
  font-weight: 300;
  color: var(--mds-color-heading);
}

@media vaadin-checkbox {
  [part="label"] {
    ...
  }
}

color.css

html {
  --mds-color-primary: rgb(8,180,195);
  --lumo-primary-color: var(--mds-color-primary);
  ...
}

my-button.css

/* Make sure the required color properties are defined */
@import "../../color.css";

/* I’m not sure this is the correct approach,
or whether component style sheets should write
the selectors without wrapping them with @media.
That would require the component to include the
CSS in its template. Then, the @import above
would duplicate those styles inside the shadow
root */
@media my-button {
  :host {
    color: var(--mds-color-primary);
  }
}

my-button.ts

import {ButtonElement} from '@vaadin/vaadin-button/src/vaadin-button';

import './my-button.css';

export class MyButton extends ButtonElement {
  ...
}
Note
There are many ways to improve the modularity of the CSS code. The above is only scratching the surface.

How to test the design system locally in another project

  1. Deploy the design system project to your local Maven repository by running mvn install.

  2. Add the design system as a dependency to your project’s pom.xml:

    <dependency>
        <groupId>org.your.name</groupId>
        <artifactId>my-design-system</artifactId>
        <version>1.0-SNAPSHOT</version>
    </dependency>
  3. Import the theme style sheet:

    In server-side views:

    @CssImport("./my-design-system/shared-styles.css")

    In client-side views (without shadow DOM):

    import '@vaadin/flow-frontend/my-design-system/shared-styles.css':

    Or, for views with shadow DOM:

    import css from '@vaadin/flow-frontend/my-design-system/shared-styles.css':
    
    // Include the css string in your view template
  4. Use the components

    import org.your.name.components.MyButton;
    import '@vaadin/flow-frontend/my-design-system/components/my-button/my-button';
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment