Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

✨ 181 stepper component #279

Open
wants to merge 8 commits into
base: beta
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 45 additions & 0 deletions src/components/Stepper/MucStepper.stories.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import MucStepper from "./MucStepper.vue";

export default {
component: MucStepper,
title: "MucStepper",
tags: ["autodocs"],
parameters: {
docs: {
description: {
component: `The MucStepper offers the functionality of a progress bar.

[🔗 Patternlab-Docs](https://patternlab.muenchen.space/?p=components-form-steps)
`,
},
},
},
};

export const Default = {
args: {
stepItems: [
{
id: "1",
label: "Order",
icon: "shopping-cart",
},
{
id: "2",
label: "Delivery",
icon: "calendar",
},
{
id: "3",
label: "Contact",
icon: "mail",
},
{
id: "4",
label: "Overview",
icon: "information",
},
],
activeItem: "2",
},
};
96 changes: 96 additions & 0 deletions src/components/Stepper/MucStepper.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
<template>
<div class="m-component m-component-form-progress">
<div class="container">
<div class="m-component__grid">
<div class="m-component__column">
<ol class="m-form-steps">
<template
v-for="item in stepItems"
:key="item.id"
>
<MucStepperItem
:item="item"
:is-active="isActive(item.id)"
:is-done="isDone(item.id)"
v-on:click="handleChange"
/>
</template>
</ol>
</div>
</div>
</div>
</div>
</template>

<script setup lang="ts">
import { ref, watch } from "vue";

import MucStepperItem from "./MucStepperItem.vue";
import { StepperItem } from "./MucStepperTypes";

const { stepItems, activeItem } = defineProps<{
/**
* List of items displayed in the stepper
*/
stepItems: StepperItem[];

/**
* Id of the current step item
*/
activeItem: string;
}>();

const emit = defineEmits<{
/**
* Triggered when an item is clicked.
* @param e Click-Event
* @param id
*/
(e: "changeStep", id: string): void;
}>();

watch(
() => activeItem,
() => {
indexOfActivItem.value = getIndexOfItem(activeItem);
}
);

/**
* Returns the index of an item in the array
* @param id id of the item
* @return index of the item
*/
const getIndexOfItem = (id: string) => {
return stepItems.findIndex((item) => item.id === id);
};

/**
* Index of activ item
*/
const indexOfActivItem = ref<number>(getIndexOfItem(activeItem));

/**
* Checks if an item is the activ item
* @param id id of the item
* @return if item is an active item
*/
const isActive = (id: string) => id === activeItem;

/**
* Checks if an item is done
* @param id id of the item
* @return if item is done
*/
const isDone = (id: string) => getIndexOfItem(id) < indexOfActivItem.value;

/**
* Handles a click on an item
* @param id id of the item
*/
const handleChange = (id: string) => {
emit("changeStep", id);
};
</script>

<style scoped></style>
93 changes: 93 additions & 0 deletions src/components/Stepper/MucStepperItem.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
<template>
<li
:class="isActiveStep"
@click="handleClick"
>
<div
class="m-form-step__icon"
:tabindex="getTabindex"
:aria-label="getAriaLabel"
>
<MucIcon :icon="getIcon" />
</div>
<div class="m-form-step__title">
<span aria-disabled="true"> {{ item.label }}</span>
</div>
</li>
</template>

<script setup lang="ts">
import { computed } from "vue";

import { MucIcon } from "../Icon";
import { StepperItem } from "./MucStepperTypes";

const { item, isActive, isDone } = defineProps<{
/**
* Individual item to display inside the MucStepper component
*/
item: StepperItem;

/**
* Show stepper as active
*/
isActive: boolean;

/**
* Show stepper as done
*/
isDone: boolean;
}>();

const emit = defineEmits<{
/**
* Triggered when an item is clicked.
* @param e Click-Event
* @param id
*/
(e: "click", id: string): void;
}>();

/**
* Computed property set active state of step
*/
const isActiveStep = computed(() =>
isActive
? "m-form-step m-form-step--current"
: "m-form-step" + clickableStep.value
);

/**
* Computed property show courser on clickable step
*/
const clickableStep = computed(() => (isDone ? " show-cursor" : ""));

/**
* Computed property set icon of step
*/
const getIcon = computed(() => (isDone ? "check" : item.icon));

/**
* Computed property set tabindex
*/
const getTabindex = computed(() => (isActive || isDone ? 0 : -1));

/**
* Computed property set aria-label
*/
const getAriaLabel = computed(() =>
isActive
? "Aktueller Schritt: " + item.label
: "Zurück zu Schritt: " + item.label
);

const handleClick = () => {
if (isDone) emit("click", item.id);
};
</script>

<style scoped>
.show-cursor {
cursor: pointer;
}
</style>
5 changes: 5 additions & 0 deletions src/components/Stepper/MucStepperTypes.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export interface StepperItem {
id: string;
label: string;
icon: string;
}
3 changes: 3 additions & 0 deletions src/components/Stepper/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import MucStepper from "./MucStepper.vue";

export { MucStepper };
4 changes: 4 additions & 0 deletions src/components/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { MucBanner } from "./Banner";
import { MucButton } from "./Button";
import { MucCalendar } from "./Calendar";
import { MucCallout } from "./Callout";
import { MucCard, MucCardContainer } from "./Card";
import { MucComment, MucCommentText } from "./Comment/";
Expand All @@ -20,6 +21,7 @@ import { MucIcon } from "./Icon";
import { MucIntro } from "./Intro";
import { MucLink } from "./Link";
import { MucPercentageSpinner } from "./PercentageSpinner";
import { MucStepper } from "./Stepper";

export {
MucButton,
Expand All @@ -44,4 +46,6 @@ export {
MucFileDropzone,
MucCounter,
MucPercentageSpinner,
MucStepper,
MucCalendar,
};