mirror of
https://github.com/IT4Change/Ocelot-Social.git
synced 2026-03-01 12:44:28 +00:00
108 lines
2.4 KiB
Vue
108 lines
2.4 KiB
Vue
<template>
|
|
<client-only>
|
|
<div
|
|
class="layout-toggle"
|
|
:class="{ 'layout-toggle--hidden': isMobile }"
|
|
role="radiogroup"
|
|
:aria-label="$t('layout.toggle.label')"
|
|
@keydown.left.prevent="setLayout(true)"
|
|
@keydown.right.prevent="setLayout(false)"
|
|
>
|
|
<os-button
|
|
ref="singleBtn"
|
|
circle
|
|
size="sm"
|
|
:appearance="value ? 'filled' : 'ghost'"
|
|
variant="primary"
|
|
role="radio"
|
|
:aria-checked="String(value)"
|
|
:aria-label="$t('layout.toggle.singleColumn')"
|
|
:tabindex="value ? '0' : '-1'"
|
|
@click="setLayout(true)"
|
|
>
|
|
<template #icon>
|
|
<os-icon :icon="icons.list" />
|
|
</template>
|
|
</os-button>
|
|
<os-button
|
|
ref="multiBtn"
|
|
circle
|
|
size="sm"
|
|
:appearance="!value ? 'filled' : 'ghost'"
|
|
variant="primary"
|
|
role="radio"
|
|
:aria-checked="String(!value)"
|
|
:aria-label="$t('layout.toggle.multiColumn')"
|
|
:tabindex="!value ? '0' : '-1'"
|
|
@click="setLayout(false)"
|
|
>
|
|
<template #icon>
|
|
<os-icon :icon="icons.columns" />
|
|
</template>
|
|
</os-button>
|
|
</div>
|
|
</client-only>
|
|
</template>
|
|
|
|
<script>
|
|
import { OsButton, OsIcon } from '@ocelot-social/ui'
|
|
import { iconRegistry } from '~/utils/iconRegistry'
|
|
import mobile from '~/mixins/mobile'
|
|
|
|
const STORAGE_KEY = 'ocelot-layout-single-column'
|
|
|
|
export default {
|
|
components: {
|
|
OsButton,
|
|
OsIcon,
|
|
},
|
|
mixins: [mobile(639)],
|
|
props: {
|
|
value: {
|
|
type: Boolean,
|
|
default: false,
|
|
},
|
|
},
|
|
created() {
|
|
this.icons = iconRegistry
|
|
},
|
|
mounted() {
|
|
try {
|
|
const stored = localStorage.getItem(STORAGE_KEY)
|
|
if (stored !== null) {
|
|
this.$emit('input', stored === 'true')
|
|
}
|
|
} catch (e) {
|
|
// localStorage not available
|
|
}
|
|
},
|
|
methods: {
|
|
setLayout(val) {
|
|
try {
|
|
localStorage.setItem(STORAGE_KEY, String(val))
|
|
} catch (e) {
|
|
// localStorage not available
|
|
}
|
|
this.$emit('input', val)
|
|
this.$nextTick(() => {
|
|
const ref = val ? this.$refs.singleBtn : this.$refs.multiBtn
|
|
const el = ref?.$el || ref
|
|
if (el) el.focus()
|
|
})
|
|
},
|
|
},
|
|
}
|
|
</script>
|
|
|
|
<style lang="scss">
|
|
.layout-toggle {
|
|
display: inline-flex;
|
|
gap: 4px;
|
|
align-items: center;
|
|
}
|
|
|
|
.layout-toggle--hidden {
|
|
display: none;
|
|
}
|
|
</style>
|