M3 Svelte

M3 Svelte implements the Material 3 design system in Svelte, from the components to the animations to the theming.

Now with 256 stars and ripples

Fast

M3 Svelte uses minimal CSS, JS, and elements to keep your sites running smooth.

Robust

Even in some edge cases like being printed, used in high contrast mode, or with JS off, most of M3 Svelte is still usable.

Button

Elevated
No icon
Enabled

Source code

<Button {type} disabled={!enabled} {iconType}>
  Hello
</Button>

Segmented button

Single-select

Source code

<SegmentedButtonContainer>
  <input type="checkbox" id="segmented-0" />
  <SegmentedButtonItem input="segmented-0">Tab A</SegmentedButtonItem>
  <input type="checkbox" id="segmented-1" />
  <SegmentedButtonItem input="segmented-1">Tab B</SegmentedButtonItem>
</SegmentedButtonContainer>
<SegmentedButtonContainer>
  <input type="radio" id="segmented-0" />
  <SegmentedButtonItem input="segmented-0">Tab A</SegmentedButtonItem>
  <input type="radio" id="segmented-1" />
  <SegmentedButtonItem input="segmented-1">Tab B</SegmentedButtonItem>
</SegmentedButtonContainer>

FAB

Primary
Normal

Source code

<FAB
  {color}
  {size}
  {icon}
  text="Hello"
/>

Card

Elevated
Not clickable
Hello

Source code

<CardClickable {type}>Hello</CardClickable>
<Card {type}>Hello</Card>

Dialog

Permanently delete?

Deleting the selected messages will also remove them from all synced devices.

Source code

<Dialog icon={iconTrash} headline="Permanently delete?" bind:open>
  Deleting the selected messages will also remove them
  from all synced devices.
  <svelte:fragment slot="buttons">
    <Button type="text" on:click={() => (open = false)}>
      Cancel
    </Button>
    <Button type="tonal" on:click={() => (open = false)}>
      Delete
    </Button>
  </svelte:fragment>
</Dialog>

Snackbar

#if animated

Source code

<script lang="ts">
  let snackbar: (data: SnackbarIn) => void;
</script>
<Button
  type="tonal"
  on:click={() => snackbar({ message: "Hello", actions: { Undo: () => {} }, closable: true })}
>
  Show
</Button>
<Snackbar bind:show={snackbar} />

Bottom sheet

Source code

<BottomSheet on:close={() => (open = false)}>
  <div>
    <div>
      <div>
        <input type="date" id="d-start" />
        <label for="d-start">Start</label>
      </div>
      <div>
        <input type="date" id="d-end" />
        <label for="d-end">End</label>
      </div>
    </div>
    <Button type="filled">Add event</Button>
  </div>
</BottomSheet>

List

1 line
<div>

This is a headline


This is a headline

Source code

<ListItem headline="This is a headline" supporting={supportingText} {lines}>
  <svelte:fragment slot="leading">
    <Icon {icon} />
  </svelte:fragment>
</ListItem>
<Divider />
<ListItemButton headline="This is a headline" supporting={supportingText} {lines}>
  <svelte:fragment slot="leading">
    <Icon {icon} />
  </svelte:fragment>
</ListItemButton>
<Divider />
<ListItemLabel headline="This is a headline" supporting={supportingText} {lines}>
  <svelte:fragment slot="leading">
    <div class="box-wrapper">
      <Checkbox><input type="checkbox" /></Checkbox>
    </div>
  </svelte:fragment>
</ListItemLabel>

Progress

Linear
Fixed progress

Source code

<LinearProgressIndeterminate />
<LinearProgress percent={60} />
<CircularProgressIndeterminate />
<CircularProgress percent={60} />

Menu

No icons

Source code

<Menu>
  <MenuItem icon={iconUndo}>Undo</MenuItem>
  <MenuItem icon={iconRedo} disabled>Redo</MenuItem>
  <MenuItem icon={iconCut} disabled>Cut</MenuItem>
</Menu>

Radio

Animation 1
Enabled

Source code

<RadioAnim1><input type="radio" name="radio" disabled={!enabled} /></RadioAnim1>
<RadioAnim2><input type="radio" name="radio" disabled={!enabled} /></RadioAnim2>
<RadioAnim3><input type="radio" name="radio" disabled={!enabled} /></RadioAnim3>

Checkbox

Animated
Enabled

Source code

<CheckboxAnim>
  <input type="checkbox" checked disabled={!enabled} />
</CheckboxAnim>
<Checkbox>
  <input type="checkbox" checked disabled={!enabled} />
</Checkbox>

Switch

Enabled

Source code

<Switch disabled={!enabled} />

Slider

Continuous
Enabled
0

Source code

<SliderTicks step={1} max={6} disabled={!enabled} bind:value />
<Slider step={precision == "continuous" ? "any" : 10} disabled={!enabled} bind:value />

Date field

Source code

<DateField bind:date />

Text field

Filled
Text
No leading icon
Not errored
Enabled

Source code

<TextField
  bind:value
  name="Field"
  leadingIcon={leadingIcon ? iconEdit : undefined}
  error={{errored}
  {disabled}
  {extraOptions}
/>
<TextFieldOutlined
  bind:value
  name="Field"
  leadingIcon={leadingIcon ? iconEdit : undefined}
  error={{errored}
  {disabled}
  {extraOptions}
/>
<TextFieldMultiline
  bind:value
  name="Field"
  {leadingIcon}
  {error}
  disabled={!enabled}
/>
<TextFieldOutlinedMultiline
  bind:value
  name="Field"
  {leadingIcon}
  {error}
  disabled={!enabled}
/>

Chip

Input
No icon
Enabled

Source code

<Chip
  {type}
  {elevated}
  {selected}
  disabled={!enabled}
  {icon}
  {trailingIcon}
  on:click={() => (selected = !selected)}
>
  Hello
</Chip>

Tabs

Primary
No icons
Fixed

Source code

<VariableTabs bind:tab {secondary} {items} />
<Tabs bind:tab {secondary} {items} />
  • Wow! You made it all the way down here!
  • Next steps:
  • Join the M3 Svelte community on Discord.
  • Make a theme on the Theme page, and come back here to try it out.
  • Maybe even be one of my sponsors.