Skip to content
This repository has been archived by the owner on Apr 28, 2023. It is now read-only.
/ marble Public archive

Marble is the design system of The Metropolitan Museum of Art πŸ›

Notifications You must be signed in to change notification settings

metmuseum/marble

Repository files navigation

metmuseum GitHub release (latest SemVer)

Marble

marbling paper by MarbleJournals.com

Table Of Contents

What is Marble?

Marble is the design system of the Metropolitan Museum of Art's Digital Deptartment. Marble is currently only an innersource project.

Component Explorer

Our component explorer, powered by Storybook, lives on Chromatic at:

Design Documentation and Homepage:

Marble's design docs and homepage are at:

🎨 https://marble.metmuseum.org/ 🏑

Using Marble In Your Project

Installing Marble

Marble installs from GitHub, not the NPM registry.

It's recommended that your CI/CD process use npm ci instead of npm install so that:

There are multiple ways to install Marble:

Lock to one version:

npm install metmuseum/marble#0.11.15

Lock to a specific commit:

npm install metmuseum/marble#9e68bab

Use any npm-compatible semantic versioning syntax:

npm install metmuseum/marble#semver:^0.11.15

Just get whatever's on main: npm install metmuseum/marble

Upgrading Marble

Remember, if you're using npm ci in production (recommended), then you'll need to periodically run npm install ... or npm upgrade ... and check in the updated package-lock.json.

Importing Marble

Marble can be imported a few different ways, depending on how your project preprocesses and bundles things. If you're unsure, please reach out in our #app-dev Slack channel.

Import Javascript:

  • If your project only uses CommonJS syntax (vanilla Node.js environments):

    const marble = require("@metmuseum/marble");
  • ESM syntax (Webpack, etc):

    import marble from "@metmuseum/marble";
  • Reference the files directly (not recommended):

    • Path/To/Your/Project/node_modules/@metmuseum/marble/dist/marble.js
      • This exposes a variable called marble.
    • Path/To/Your/Project/node_modules/@metmuseum/marble/dist/marble.js.map
      • Source maps (recommended)
  • TODO: Consider CDN-hosted file for <script> tag? (easy with CI, but like, version control?)

Import SCSS:

This should work, please let us know if it does not:

@import "~@metmuseum/marble/src/marble.scss";

Import Precompiled, Minified CSS:

  • If your project supports the ~ syntax:
    import "~@metmuseum/marble";
  • If not, production-ready assets are available to reference directly (not recommended):
    • Path/To/Your/Project/node_modules/@metmuseum/marble/dist/marble.css
  • TODO: Consider CDN-hosted file for stylesheet <link> tag? (easy with CI, but like, version control?)

SCSS

We recommend just using all of Marble's styles, for now. See above. ☝️

TODO: investigate Sass @import vs new @use syntax:

  • https://sass-lang.com/documentation/at-rules/import#import-only-files
  • will inform if we need our file structure to have module.import.scss naming.
  • TODO: Probably we should move away from: @import "marble/src/base/base"; (kinda bad/leaky abstraction because what if we change file structure?)
  • Depending on SCSS preprocesssor, namely scss-loader+postcss (webpack) vs gulp sass, there is totally different behave regarding scope and iikjf it follows dependencies :(

Using Marble's Components

Marble does not currently export component html or templates, only styles and javascript. Think of it a little bit like Twitter's Bootstrap Framework, or like a meal kit, but not dish you serve.

It's up to your project to implement the proper markup, based on examples you can find in /src and on our Storybook.

Example:

Take the structure and classes from Marble:

// in src/components/section-heading/section-heading.html.js

html`<div
	class="section-heading section-heading--text-${textAlignment} ${inSitu
		? "productive-component"
		: ""}"
>
	<h2 class="section-heading__heading ${context}">${header}</h2>
	<div>${he.decode(bodyCopy)}</div>
	<a
		class="button tertiary-button section-heading__text-link"
		role="button"
		tabindex="0"
		href="#"
	>
		${CTA1}</a
	>
</div>`;

And interpret them for your project's framework and data models:

<div class="section-heading section-heading--text-center productive-component section-header-@Model.Name">
	<h2 class="section-heading__heading expressive">@Html.Raw(Model.Header)</h2>
	<div>@Html.Raw(@Model.Description)</div>
	<a
		class="button tertiary-button section-heading__text-link"
		role="button"
		tabindex="0"
		href="@Model.UrlLink"
	>@Html.Raw(Model.CTA)</a>
</div>
Javascript

By design, Marble's Javascript should only cause one side-effect: exposing a variable called marble. It's up to your project to tell Marble what to do and when.

At the bare minimum, you probably want to run Marble's global code:

import marble from "@metmuseum/marble";

marble.global();

If you use a specific component, say the jumpLinkBanner, you need to call that somewhere, as well:

import marble from "@metmuseum/marble";
marble.jumpLinkBanner();

TODO: a marble.everything(); option?

Deployment and Continuous Integration

You can expect that Marble's default branch, main, is always stable and releaseable. If you installed as above, npm install and npm update should always be safe.

Make sure you always check in your your package-lock.json.

Recommended CI

Use npm ci instead of npm install. This will ensure the project only builds with the exact commit (and dependencies) that were specified earlier in the package-lock.json.

Example:

"marble": {
    "version": "github:metmuseum/marble#d765ab8a340e1e989953207115414469307da93c",
    "from": "github:metmuseum/marble#main",
    "requires": {
        "he": "^1.2.0",
        "smoothscroll-polyfill": "^0.4.4",
        "vanilla-lazyload": "^12.5.1"
    }
}

More info: https://docs.npmjs.com/cli/ci.html

It is not recommended to point your installation of Marble to an environment-specific branch on staging or production. Please always use main.

Contributing To Marble

WIP

Conventions

  • mock your data separately
  • use component story format
  • use controls
  • try to provide in-situ examples?
  • make sure a11y passes!
  • file organization

    • stories
    • scss
    • javascript
    • text casing (kebab-case?)
  • linting

    • JS: pnpm run lint
    • S/CSS: pnpm run stylelint

Marble Development As A Local Package

You may want to see your changes to Marble locally and in the context of another project you're working on. We can do this easily with pnpm link based on npm's link.

Steps:

  1. Tell your pnpm that this is the local folder where Marble lives.

    • Navigate to your local Marble repo (ie, where this README lives) and just run:

      		pnpm link
      
  1. Next, tell whatever project you're working on to use that local, linked version of Marble.

    • Navigate to a local project folder and find the directory that contains the package.json that originally specified Marble. * For example, in Ghidorah, this wouldn't be the project root, it would be: ghidorah/MMA.Ghidorah/

    • From that directory, run:

      		pnpm link @metmuseum/marble
      
    • Now, instead of what's installed in node_modules, pnpm knows to pull our Marble package files from the directory in Step 1. We can make our changes in our Marble repo (more on that below), and our other project will show them to us.

Storybook Development

Storybook is the preferred way of developing components for Marble.

With Docker:

Recommended: install Docker Desktop and run it.

Always build the latest changes if you pull, etc:

docker-compose build

Run the container:

docker-compose up

Storybook will now be available at: http://localhost:54525

Natively / Without Docker:

To start Storybook locally, launch the app with: pnpm run storybook

To publish the Storybook to its web homepage (via GitHub pages), please commit your changes, then run: pnpm run deploy-storybook. Be mindful that this overwites the current Storybook with your local version.

We use the html preset for Storybook. There are many good exmaples of html stories and add-ons at the official "kitchen sink" example directory:

Webpack Build for Release And Production

TODO: update this to have CI build dist on merge

  • For releases of Marble, we'll want to compile everything into a production-ready .css and .js file.

  • We use Webpack to build and bundle these files to /dist

  • Our build step is aliased in package.json as:

    		pnpm run build
    
  • Make sure you commit this production-ready build of Marble and not the development version that would also be generated to /dist anytime you run webpack-dev-server.

Browsers We Support

We target the latest 2 major versions of most browsers, via our .browesrslistrc file.

To see what those currently are, run:

pnpm dlx browserslist

To update the list of current browsers, it's important to frequently use:

pnpm dlx browserslist@latest --update-db

...because of reasons.


License

Currently for internal use only. Β© Copyright 2021 The Metropolitan Museum of Art. All rights are reserved.