Skip to content

Module

If our Box is an atom, the Module component is an extension of a Box which you might consider a molecule. Module standardizes common patterns used across the platform to ensure consistency. If the design calls for a Box with a header, actions, content, and/or footer, you can use a Module to provide that structure easily and consistently.

Why this approach?

Composability. Breaking up what might seem like a single concept of a Module into multiple components like this helps us to maintain AND test them more easily.

Module, ModuleHeader, ModuleContent, ModuleFooter can be separate components. Not every Module implemented needs to use all of them. Some modules don't have headers or footers, etc. This is a very powerful composability pattern used by popular UI component libraries to improve testability and maintainability while giving end users the a lot of flexibility in the cleanest possible way. The resulting usage becomes much clearer, as opposed to a single component with many props, slots and/or schemas, you've got a very declarative composition of components.

It also provides the consumer developers & applications the flexibility they need to build out screens the way they want to without having a single massive component made up of many components, which we need to control through schemas, or passing nested props, or having tons of slots. All of which creates complexities in testing and maintaining a component without breaking things.

Detailed notes & conceptual designs: https://whimsical.com/module-component-Azer1UzmQPSXZowztyt1bn

When to use Module components

Don't use Module's as a replacement for Card's! Card's are containers for content representing a single entity. e.g. a product, credit profile, or licence, etc. Modules are meant to be used to give a typical Box some structure, allowing us to have consistent designs with minimal code, making it easier for FE devs to build screens rapidly.

When a design calls for a simple Box but also has a header title & actions and some footer links, that's a good indication that you should using a Module. The actual content is not particularly important for Modules.

Basic Usage

Order Details

Render anything you want in a ModuleContent!

Order no
#123123
Quantity
3
Category
Flower
template
<Module>
  <ModuleHeader>Order Details</ModuleHeader>

  <ModuleContent>
    <p>Render anything you want in a ModuleContent!</p>

    <DescriptionList>
      <DescriptionListGroup>
        <DescriptionListTerm>Order no</DescriptionListTerm>
        <DescriptionListDetail>#123123</DescriptionListDetail>
      </DescriptionListGroup>
      <DescriptionListGroup>
        <DescriptionListTerm>Quantity</DescriptionListTerm>
        <DescriptionListDetail>3</DescriptionListDetail>
      </DescriptionListGroup>
      <DescriptionListGroup>
        <DescriptionListTerm>Category</DescriptionListTerm>
        <DescriptionListDetail>Flower</DescriptionListDetail>
      </DescriptionListGroup>
    </DescriptionList>
  </ModuleContent>
</Module>

Header actions slot

You can add whatever you'd like in the actions slot. The primary use case is have user CTA's like context menus, icons or icon buttons.

User Permissions

Select companies the user

Render anything you want in a ModuleContent!

Order no
#123123
Quantity
3
Category
Flower
template
<Module>
  <ModuleHeader title="User Permissions" description="Select companies the user should have access to and select their role.">
    <template #actions>
      <Button primary>Add Companies</Button>
    </template>
  </ModuleHeader>

  <ModuleContent>
    <p>Render anything you want in a ModuleContent!</p>

    <DescriptionList>
      <DescriptionListGroup>
        <DescriptionListTerm>Order no</DescriptionListTerm>
        <DescriptionListDetail>#123123</DescriptionListDetail>
      </DescriptionListGroup>
      <DescriptionListGroup>
        <DescriptionListTerm>Quantity</DescriptionListTerm>
        <DescriptionListDetail>3</DescriptionListDetail>
      </DescriptionListGroup>
      <DescriptionListGroup>
        <DescriptionListTerm>Category</DescriptionListTerm>
        <DescriptionListDetail>Flower</DescriptionListDetail>
      </DescriptionListGroup>
    </DescriptionList>
  </ModuleContent>
</Module>

Buyer

The Green Store

15308 E 8 Mile Rd
Detroit, MI 48205

Phone: (555) 555-5555

Email: thegreenstore@gmail.com

Reference ID: 03948487

Seller

The Blue Store

97548 E 8 Mile Rd
Detroit, MI 48205

Phone: (123) 555-9876

Email: thebluestore@gmail.com

Reference ID: 87654338

template
<section class="tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-gutter">
  <Module>
    <ModuleHeader title="Buyer" size="large">
      <template #actions>
        <Icon name="edit" @click="alert('Edit!')" />
      </template>
    </ModuleHeader>
    <ModuleContent>
      <h3 class="tw-mb-6">The Green Store</h3>
      <address class="tw-mb-2">
        15308 E 8 Mile Rd<br>
        Detroit, MI 48205
      </address>
      <p class="tw-mb-2"><strong>Phone:</strong> (555) 555-5555</p>
      <p class="tw-mb-3"><strong>Email:</strong> thegreenstore@gmail.com</p>
      <p><strong>Reference ID:</strong> 03948487</p>
    </ModuleContent>
    <ModuleFooter>
      <a href="#" @click.prevent="">View Licenses</a>
    </ModuleFooter>
  </Module>
  <Module>
    <ModuleHeader title="Seller" size="large">
      <template #actions>
        <Icon name="edit" @click="alert('Edit!')" />
      </template>
    </ModuleHeader>
    <ModuleContent>
      <h3 class="tw-mb-6">The Blue Store</h3>
      <address class="tw-mb-2">
        97548 E 8 Mile Rd<br>
        Detroit, MI 48205
      </address>
      <p class="tw-mb-2"><strong>Phone:</strong> (123) 555-9876</p>
      <p class="tw-mb-3"><strong>Email:</strong> thebluestore@gmail.com</p>
      <p><strong>Reference ID:</strong> 87654338</p>
    </ModuleContent>
    <ModuleFooter>
      <a href="#" @click.prevent="">View Licenses</a>
    </ModuleFooter>
  </Module>
</section>

Header underline option

User Permissions

Select companies the user should have access to and select their role.

Render anything you want in a ModuleContent!

Order no
#123123
Quantity
3
Category
Flower
template
<Module>
  <ModuleHeader title="User Permissions" description="Select companies the user should have access to and select their role." underline>
    <template #actions>
      <Button primary>Add Companies</Button>
    </template>
  </ModuleHeader>

  <ModuleContent>
    <p>Render anything you want in a ModuleContent!</p>

    <DescriptionList>
      <DescriptionListGroup>
        <DescriptionListTerm>Order no</DescriptionListTerm>
        <DescriptionListDetail>#123123</DescriptionListDetail>
      </DescriptionListGroup>
      <DescriptionListGroup>
        <DescriptionListTerm>Quantity</DescriptionListTerm>
        <DescriptionListDetail>3</DescriptionListDetail>
      </DescriptionListGroup>
      <DescriptionListGroup>
        <DescriptionListTerm>Category</DescriptionListTerm>
        <DescriptionListDetail>Flower</DescriptionListDetail>
      </DescriptionListGroup>
    </DescriptionList>
  </ModuleContent>
</Module>

Buyer

The Green Store

15308 E 8 Mile Rd
Detroit, MI 48205

Phone: (555) 555-5555

Email: thegreenstore@gmail.com

Reference ID: 03948487

Seller

The Blue Store

97548 E 8 Mile Rd
Detroit, MI 48205

Phone: (123) 555-9876

Email: thebluestore@gmail.com

Reference ID: 87654338

template
<section class="tw-grid tw-grid-cols-1 md:tw-grid-cols-2 tw-gap-gutter">
  <Module>
    <ModuleHeader title="Buyer" size="large" underline>
      <template #actions>
        <Icon name="edit" @click="alert('Edit!')" />
      </template>
    </ModuleHeader>
    <ModuleContent>
      <h3 class="tw-mb-6">The Green Store</h3>
      <address class="tw-mb-2">
        15308 E 8 Mile Rd<br>
        Detroit, MI 48205
      </address>
      <p class="tw-mb-2"><strong>Phone:</strong> (555) 555-5555</p>
      <p class="tw-mb-3"><strong>Email:</strong> thegreenstore@gmail.com</p>
      <p><strong>Reference ID:</strong> 03948487</p>
    </ModuleContent>
    <ModuleFooter>
      <a href="#" @click.prevent="">View Licenses</a>
    </ModuleFooter>
  </Module>
  <Module>
    <ModuleHeader title="Seller" size="large" underline>
      <template #actions>
        <Icon name="edit" @click="alert('Edit!')" />
      </template>
    </ModuleHeader>
    <ModuleContent>
      <h3 class="tw-mb-6">The Blue Store</h3>
      <address class="tw-mb-2">
        97548 E 8 Mile Rd<br>
        Detroit, MI 48205
      </address>
      <p class="tw-mb-2"><strong>Phone:</strong> (123) 555-9876</p>
      <p class="tw-mb-3"><strong>Email:</strong> thebluestore@gmail.com</p>
      <p><strong>Reference ID:</strong> 87654338</p>
    </ModuleContent>
    <ModuleFooter>
      <a href="#" @click.prevent="">View Licenses</a>
    </ModuleFooter>
  </Module>
</section>

Header Media

Use the media slot for rendering an Illustration alongside the title.

Payment preferences

View and manage your company's payment preferences

Render anything you want in a ModuleContent!

Order no
#123123
Quantity
3
Category
Flower
template
<Module>
  <ModuleHeader
    title="Payment preferences"
    description="View and manage your company's payment preferences"
    size="large"
  >
    <template #media>
      <Illustration name="money" :size="65" />
    </template>
  </ModuleHeader>
  <ModuleContent>
    <p>Render anything you want in a ModuleContent!</p>
    <DescriptionList>
      <DescriptionListGroup>
        <DescriptionListTerm>Order no</DescriptionListTerm>
        <DescriptionListDetail>#123123</DescriptionListDetail>
      </DescriptionListGroup>
      <DescriptionListGroup>
        <DescriptionListTerm>Quantity</DescriptionListTerm>
        <DescriptionListDetail>3</DescriptionListDetail>
      </DescriptionListGroup>
      <DescriptionListGroup>
        <DescriptionListTerm>Category</DescriptionListTerm>
        <DescriptionListDetail>Flower</DescriptionListDetail>
      </DescriptionListGroup>
    </DescriptionList>
  </ModuleContent>
</Module>

Content "top" slots

Inactive

Render anything you want in a ModuleContent!

Order no
#123123
Quantity
3
Category
Flower
template
<Module>
  <ModuleContent>
    <template #top-left><IconLabel color="ice" icon="circle-status">Inactive</IconLabel></template>

    <template #top-right>
      <RadioGroup v-model="someRadio" name="someRadio" variant="button">
        <Radio id="active" label="Active" value="1" />
        <Radio id="inactive" label="Inactive" value="2" />
      </RadioGroup>
    </template>

    <p>Render anything you want in a ModuleContent!</p>

    <DescriptionList>
      <DescriptionListGroup>
        <DescriptionListTerm>Order no</DescriptionListTerm>
        <DescriptionListDetail>#123123</DescriptionListDetail>
      </DescriptionListGroup>
      <DescriptionListGroup>
        <DescriptionListTerm>Quantity</DescriptionListTerm>
        <DescriptionListDetail>3</DescriptionListDetail>
      </DescriptionListGroup>
      <DescriptionListGroup>
        <DescriptionListTerm>Category</DescriptionListTerm>
        <DescriptionListDetail>Flower</DescriptionListDetail>
      </DescriptionListGroup>
    </DescriptionList>
  </ModuleContent>
</Module>

Having a lot of content will cause the top slots to wrap:

Left Slot! A lot of content here will cause the slots to wrap! Try shrinking the canvas.

Render anything you want in a ModuleContent!

Order no
#123123
Quantity
3
Category
Flower
template
<Module>
  <ModuleContent>
    <template #top-left>
      Left Slot! A lot of content here will cause the slots to wrap! Try shrinking the canvas.
    </template>
    <template #top-right>
      <Button class="tw-mr-6" secondary>Right Slot Secondary button</Button>
      <Button>Right Slot!</Button>
    </template>

    <p>Render anything you want in a ModuleContent!</p>

    <DescriptionList>
      <DescriptionListGroup>
        <DescriptionListTerm>Order no</DescriptionListTerm>
        <DescriptionListDetail>#123123</DescriptionListDetail>
      </DescriptionListGroup>
      <DescriptionListGroup>
        <DescriptionListTerm>Quantity</DescriptionListTerm>
        <DescriptionListDetail>3</DescriptionListDetail>
      </DescriptionListGroup>
      <DescriptionListGroup>
        <DescriptionListTerm>Category</DescriptionListTerm>
        <DescriptionListDetail>Flower</DescriptionListDetail>
      </DescriptionListGroup>
    </DescriptionList>
  </ModuleContent>
</Module>

Disable gutters

Order Details

You can render anything you want in a Module, but they are typically meant to be used with ModuleContent or other sibling components.

If all you need is the elevated surface styling, use Box instead.

template
<Module disable-gutters>
  <ModuleHeader>Order Details</ModuleHeader>

  <ModuleContent>
    <p>You can render anything you want in a <code>Module</code>, but they are typically meant to be used with <code>ModuleContent</code> or other sibling components.</p>
    <p>If all you need is the elevated surface styling, use <code>Box</code> instead.</p>
  </ModuleContent>
</Module>

Disable padding

Order Details

You can render anything you want in a Module, but they are typically meant to be used with ModuleContent or other sibling components.

If all you need is the elevated surface styling, use Box instead.

template
<Module disable-padding>
  <ModuleHeader>Order Details</ModuleHeader>

  <ModuleContent>
    <p>You can render anything you want in a <code>Module</code>, but they are typically meant to be used with <code>ModuleContent</code> or other sibling components.</p>
    <p>If all you need is the elevated surface styling, use <code>Box</code> instead.</p>
  </ModuleContent>
</Module>

Grid display

When displaying modules in a grid they will automatically match heights and the content areas will flex so that the footers all line up with each other.

Module header

Module content will fill the remaining space of a module. We've added a border to illustrate this.

Module header

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

Module header

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.

template
<section class="tw-grid tw-grid-cols-12 tw-gap-gutter">
  <Module class="tw-col-span-12 md:tw-col-span-4">
    <ModuleHeader class="tw-border tw-border-orange-500">Module header</ModuleHeader>
    <ModuleContent class="tw-border tw-border-blue-500">
      <p>Module content will fill the remaining space of a module. We've added a border to illustrate this.</p>
    </ModuleContent>
    <ModuleFooter class="tw-border tw-border-orange-500">Module Footer</ModuleFooter>
  </Module>
  <Module class="tw-col-span-12 md:tw-col-span-4">
    <ModuleHeader class="tw-border tw-border-orange-500">Module header</ModuleHeader>
    <ModuleContent class="tw-border tw-border-blue-500">
      <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. </p>
    </ModuleContent>
    <ModuleFooter class="tw-border tw-border-orange-500">Module Footer</ModuleFooter>
  </Module>
  <Module class="tw-col-span-12 md:tw-col-span-4">
    <ModuleHeader class="tw-border tw-border-orange-500">Module header</ModuleHeader>
    <ModuleContent class="tw-border tw-border-blue-500">
      <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.</p>
    </ModuleContent>
    <ModuleFooter class="tw-border tw-border-orange-500">Module Footer</ModuleFooter>
  </Module>
</section>

Table Variant

Module Table Design Examples: TODO @tyler

We have the capability to compose a Table component within a Module right now by leveraging the existing Module and Table components. However, there's a lot of custom style overrides and specific combination of props necessary to achieve the design.

This variant helps avoid repeating all that style customization and allows us to easily render a Table within the child ModuleContent component to achieve the design pattern.

The Table can be rendered within a DataView as well if your use case calls for that.

Table inside a Module

We're rendering a Table within a Module

Product Name
Brand
Category
Price per unit
Strain
Citrus Splash 2x50mg THC Gummies
True North CollectiveEdibles & Ingestibles$2.50
Rabbit Hole 1 lb bag
MJ VerdantFlower$2,800.00Hybrid
THC-A Crystalline Rings | GMO
Kola FarmsConcentrates$10.00
Seed Junky Purple Push Pop 3.5g
Seed JunkyFlower$20.00Hybrid
GUSH-MINTS 19-23% 1.4% TERPENES
AgronomosFlower$1,400.00Indica Hybrid
template
<Module variant="table">
    <ModuleHeader title="Table inside a Module" description="We're rendering a Table within a Module" />
    <ModuleContent>
      <Table>
       ...
      </Table>
    </ModuleContent>
  </Module>

API

See the documentation below for a complete reference to all the props and classes available to the components mentioned here.