Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 | 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 2x 2x 1x 1x 4x 4x 4x 4x | <template>
<div class="calendar-list-toggle-container">
<h2 id="viewToggleLabel">
{{ t("time") }}
</h2>
<div
class="m-toggle-switch"
role="switch"
:aria-checked="localIsListView"
:aria-labelledby="'viewToggleLabel'"
tabindex="0"
@click="toggleView"
@keydown.enter.prevent="toggleView"
@keydown.space.prevent="toggleView"
>
<span
class="m-toggle-switch__label"
:class="{ disabled: localIsListView }"
>{{ t("calendarView") }}</span
>
<span class="m-toggle-switch__indicator"><span></span></span>
<span
class="m-toggle-switch__label"
:class="{ disabled: !localIsListView }"
>{{ t("listView") }}</span
>
</div>
</div>
</template>
<script setup lang="ts">
import { ref, watch, withDefaults } from "vue";
const props = withDefaults(
defineProps<{
t: (key: string) => string;
isListView: boolean;
}>(),
{ isListView: false }
);
const emit = defineEmits<{
(e: "update:isListView", value: boolean): void;
}>();
const localIsListView = ref<boolean>(props.isListView);
watch(
() => props.isListView,
(v) => {
localIsListView.value = v;
}
);
const toggleView = () => {
const next = !localIsListView.value;
localIsListView.value = next;
emit("update:isListView", next);
};
</script>
<style lang="scss" scoped>
@use "@/styles/breakpoints.scss" as *;
.calendar-list-toggle-container {
display: flex;
flex-direction: column;
gap: 16px;
margin-bottom: 20px;
padding: 16px 0;
}
/* Responsive layout: on larger screens, display toggle to the right of heading */
@include xs-up {
.calendar-list-toggle-container {
flex-direction: row;
justify-content: space-between;
align-items: flex-start;
}
}
.m-toggle-switch {
display: flex;
align-items: center;
gap: 8px;
cursor: pointer;
user-select: none;
}
.m-toggle-switch__label {
color: #005a9f; /* BDE Blue */
transition: color 0.2s ease;
}
.m-toggle-switch__label.disabled {
opacity: 1;
color: #617586; /* Grey Light */
transition: color 0.2s ease;
}
.m-toggle-switch:focus {
outline: 2px solid var(--color-primary);
outline-offset: 2px;
}
</style>
|