Component documentation
bottomSheet
Import code
{% from "components/bottomSheet.njk" import bottomSheet %}Arguments
{% call bottomSheet(
props={
triggerProps: {
toggleValue: "",
label: {off: "", on: ""},
icon: {off: "", on: ""},
tooltip: "",
type: "button | link",
size: "base | lg | sm | inherit",
variant: "",
iconPosition: "start | end"
}
},
attrs={}
{% call container({size:"base", type: "cols-1", alignment: "center"}) %}
{% endcall %}
) %}
{% endcall %}Implementation notes
- A wrapper for
dialogthat's designed specifically to be a bottom sheet / table of contents type component. Can't be visualized because it'sfixedposition. But resize this page to a narrow width to see the one integrated in the page! props.triggerPropsis for the open/close button.
button
Import code
{% from "components/button.njk" import button %}Arguments
{{ button(
props={
label: "",
icon: "",
tooltip: "",
type: "button | link",
size: "base | lg | sm | inherit",
variant: "",
toggleValue: "",
iconPosition: "start | end"
},
attrs={}
) }}Implementation notes
- Tag defaults to
buttonunless you provide anattrs.href, then it'll be anatag. - Optionally you can use
{% call %}to give custom inner HTML. props.toggleValueis thex-datavalue that the button looks for to determine its on/off state. If you use this property, thebuttonexpects theprops.iconandprops.labelvalues to be objects withonandoffkeys.
carousel



Import code
{% from "components/carousel.njk" import carousel %}Arguments
{{ carousel(
props={
macro: figure,
slides: [{}],
indicators: true,
ariaLabel: "",
},
attrs={}
) }}Implementation notes
props.macroshould be the template each slide uses. In a basic carousel it should probably befigure.- Expects
props.slidesis an array of thepropsobjects for the macro defined inprops.macro. props.indicatorsshows or hides the indicator dots.
checkbox
output: []
Import code
{% from "components/checkbox.njk" import checkbox %}Arguments
{{ checkbox(
props={
name: "",
label: "",
description: "",
options: [{label: "", value: ""}],
fieldAttrs: {}
},
attrs={}
) }}Implementation notes
- If you want access to an array of the selected checkboxes, define a
x-datavalue in a parent element with the key as theprops.nameof this component.
container
Import code
{% from "components/container.njk" import container %}Arguments
{% call container(
props={
size: "narrow | base | content | full",
type: "flex | cols-1 | cols-2 | sidebar"
},
attrs={class:""}
) %}
{% endcall %}Implementation notes
- Wrapper for most page content sections.
props.sizeto set max-widthprops.typeto define columns or sidebar layouts.
copyToClipboard
Import code
{% from "components/copyToClipboard.njk" import copyToClipboard %}Arguments
{{ copyToClipboard(
props={
input: "" | copyRef: "",
trigger: { macro:button, props:{}, attrs:{"@click":"copy"} },
toastMessage: "",
toasterId: ""
},
attrs={}
) }}Implementation notes
- Use
inputorcopyRef, not both.copyRefis thex-refvalue of an element inside the caller() that you want to copy theinnerTextvalue of. - Use
props.triggerto define the trigger element, or give an element inside the caller() the attribute@click: 'copy'to trigger the copy event. - Must have the
toastercomponent somewhere on the page for this component to work.
dialog
Import code
{% from "components/dialog.njk" import dialog %}Arguments
{% call dialog(
props={
alignment: "top | bottom | left | right",
ariaLabel: "",
teleportedStyles: "",
triggerProps: {
toggleValue: "",
label: {off: "", on: ""},
icon: {off: "", on: ""},
tooltip: "",
type: "button | link",
size: "base | lg | sm | inherit",
variant: "",
iconPosition: "start | end"
}
%}
{% endcall %},
attrs={}
) }}Implementation notes
props.alignmentdefines which direction the dialog comes from.props.triggerPropsis for the open/close button
dropdown
Import code
{% from "components/dropdown.njk" import dropdown %}Arguments
{{ dropdown(
props={
position: ["top", "bottom", "left", "right"],
dropdownItems:[
{ macro:button, props:{}, attrs:{} }
],
triggerProps: {}
},
attrs={}
) }}Implementation notes
- Defaults to displaying buttons in a list
- Can use `{% caller() %} instead for more complex inner components
positionis an array where you can set the relative positions to the trigger element.
figure

Import code
{% from "components/figure.njk" import figure %}Arguments
{{ figure(
props={
image: "/assets/uploads/" | iframe: "https://www.youtube.com/embed/",
widths: { mobile: {# below bp-sm #}, tablet: {# below bp-lg #}, desktop: {# above bg-lg #} },
unstyled: boolean,
alt: "",
lazy: boolean,
caption: "",
focus: "object-",
aspect: "aspect-"
},
attrs={}
) }}Implementation notes
props.lazymust be set to false if you want the loading to not be lazy.- The component is designed to be flexible so the image is set to
object-cover. props.focusdesignates the area to prioritize keeping in view as the image resizes. Default is center.props.aspectdesignates the preferred aspect ratio for the image. Default is auto.props.aspectandprops.focustake the TailwindCSS class name for that property.props.widthsis an object of pixel values for the @2x display size of the image at various screen sizes. Estimating is okay.
icon
Import code
{% from "components/icon.njk" import icon %}Arguments
{{ icon(props={glyph: ""} ,attrs={}) }}Implementation notes
props.glyphshould be the name of a glyph from the Material Symbols library. Must include the glyph name in the_data/icons.jsonfile array so the font is loaded properly.- The size of the icon is determined by its nearest ancestor's font size. The mutliplier is set in
theme.css. - The icon color is set by using
text-*utility classes, or inherited from an ancestor.
incrementer
Optional description
output:
Import code
{% from "components/incrementer.njk" import incrementer %}Arguments
{{ incrementer(
props={
name: "",
label: "",
description: "",
fieldAttrs={
placeholder: "",
required: boolean,
min: "",
max: ""
},
direction: "column | row"
},
attrs={}
) }}Implementation notes
props.fieldAttrs.typecan be most of the types listed here.- If you want access to the value, define a
x-datavalue in a parent element with the key as theprops.nameof this component.
input
Optional description
output: ""
Import code
{% from "components/input.njk" import input %}Arguments
{{ input(
props={
name: "",
label: "",
description: "",
fieldAttrs: {
type: "",
placeholder: "",
required: boolean,
min: "",
max: "",
autocomplete: "on | off"
},
direction: "column | row"
},
attrs={}
) }}Implementation notes
props.fieldAttrs.typecan be most of the types listed here.- If you want access to the value, define a
x-datavalue in a parent element with the key as theprops.nameof this component. - If you set
props.directiontorow, you must define the grid columns too using theattrsobject.
markdown
Import code
{% from "components/markdown.njk" import markdown %}Arguments
{{ markdown(
props={
content: "",
transform: true | false,
overrides: {
bodySize: "",
primaryColor: "",
linkColor: "",
radius: "",
headingFont: "",
headingFontWeight: "",
scale: ""
},
customStyles: ""
},
attrs={}
) }}Implementation notes
- Use
props.contentto inject markdown from a data source. Use{{ caller() }}when you want to write the content directly inside the component. props.transformcan be turned off when the content will already be transformed by Eleventy, as is the case with .md filecontent, or when the content you're injecting is already written in HTML.props.overridescan set instance-specific overrides to the styles, such as using a smaller base font size or a different color.customStylestakes in CSS to set instance-specific styles, such as making bolded text appear as a different color instead of bold, but note that you'll need to give the instance anidfor it to work.
modal
Import code
{% from "components/modal.njk" import modal %}Arguments
{% call modal(
props={
triggerProps: {
toggleValue: "",
label: {off: "", on: ""},
icon: {off: "", on: ""},
tooltip: "",
type: "button | link",
size: "base | lg | sm | inherit",
variant: "",
iconPosition: "start | end"
}
},
attrs={}
{% call container({size:"base", type: "cols-1", alignment: "center"}) %}
{% endcall %}
) %}
{% endcall %}Implementation notes
- A wrapper for
dialogthat's designed specifically to be a centered modal type component. props.triggerPropsis for the open/close button.
radio
output: {}
Import code
{% from "components/radio.njk" import radio %}Arguments
{{ radio(
props={
name: "",
label: "",
description: "",
options: [{label: "", value: ""}],
fieldAttrs: {}
},
attrs={}
) }}Implementation notes
- If you want access to the selected radio, define a
x-datavalue in a parent element with the key as theprops.nameof this component.{{ props.name }}.indexwill give you the index of the selected radio{{ props.name }}.valuewill give you the value of the selected radio (what will show up in the form submission.)
section
Import code
{% from "components/section.njk" import section %}Arguments
{% call section(
props={
padding: "base | none",
},
attrs={}
) %}
{% call container({size:"base", type: "cols-1", alignment: "center"}) %}
{% endcall %}
{% endcall %}Implementation notes
- Children just most likely by
containerordivider props.paddingsets whether or not there should be padding inline. Set to false for full-width sections.
select
This area describes the field above!
output: {}
Import code
{% from "components/select.njk" import select %}Arguments
{{ select(
props={
name: "",
label: "",
description: "",
options: [{label:"", value: ""}],
direction: "column | row",
fieldAttrs: {
placeholder: "",
required: boolean
}
},
attrs={}
) }}Implementation notes
- If you want access to the selected option, define a
x-datavalue in a parent element with the key as theprops.nameof this component.
textarea
Optional description
output: ""
Import code
{% from "components/textarea.njk" import textarea %}Arguments
{{ textarea(
props={
name: "",
label: "",
description: "",
fieldAttrs: {
value: "",
placeholder: "",
required: boolean,
rows: ""
},
direction: "column | row"
},
attrs={}
) }}Implementation notes
- If you want access to the value, define a
x-datavalue in a parent element with the key as theprops.nameof this component.
textLockup
Eyebrow
Large size
Large elaboration
Small size
Small elaboration
Import code
{% from "components/textLockup.njk" import textLockup %}Arguments
{% call textLockup(
props={
size: "xl | lg | base | sm",
textAlignment: "left | center | right",
titleTag: "h2",
eyebrow: "",
title: "",
elaboration: ""
},
attrs={}
) %}
{% endcall %}Implementation notes
- Useful most times there is a combination of title, paragraph, and button.
- Optionally, can insert custom content using
{% call %}. props.titleTagdefaults to h2, but can be changed.
toaster
Import code
{% from "components/toaster.njk" import toaster %}Arguments
{{ toaster(
props={id:""}
) }}Implementation notes
- Put this component somewhere in your base layout. In the SBS Starter site, the id defaults to
siteToaster. - Trigger a new toast with the
$dispatch('notify', { content:'{{ message }}' })function on an element.
toTopFab
Import code
{% from "components/toTopFab.njk" import toTopFab %}Arguments
{{ toTopFab() }}Implementation notes
- Can not be visualized since it's a fixed position element, but it's used on this page! Peep the bottom right corner.
- No
propsneeded! It does what it says.