mirror of
https://gitlab.com/PronounsPage/PronounsPage.git
synced 2025-08-05 12:07:22 -04:00
662 lines
26 KiB
Vue
662 lines
26 KiB
Vue
<script setup lang="ts">
|
|
import { DateTime } from 'luxon';
|
|
import type { RouteLocationRaw } from 'vue-router';
|
|
|
|
import useConfig from '../composables/useConfig.ts';
|
|
import forbidden from '../src/forbidden.ts';
|
|
import type { User } from '../src/user.ts';
|
|
import { useMainStore } from '../store/index.ts';
|
|
|
|
import type SearchDialogue from '~/components/search/SearchDialogue.vue';
|
|
import { newDate } from '~/src/helpers.ts';
|
|
|
|
type HeaderTo = { link: string; name?: never } | { name: string; link?: never };
|
|
|
|
type HeaderLink = HeaderTo & {
|
|
header?: boolean;
|
|
avatar?: User | null;
|
|
icon: string;
|
|
text: string;
|
|
textLong?: string;
|
|
extra?: (string | null)[];
|
|
desktop?: boolean;
|
|
mobile?: boolean;
|
|
};
|
|
|
|
const NounsNav = useLocaleComponent('nouns', 'NounsNav');
|
|
|
|
const { $translator: translator, $isGranted: isGranted } = useNuxtApp();
|
|
const config = useConfig();
|
|
|
|
const hoverItem = ref<HeaderLink | null>(null);
|
|
const searchDialogue = useTemplateRef<typeof SearchDialogue>('searchDialogue');
|
|
const hamburgerActive = ref(false);
|
|
const hamburgerShown = ref(false);
|
|
const censusDismissed = ref(false);
|
|
|
|
const today = newDate();
|
|
|
|
const { user } = storeToRefs(useMainStore());
|
|
const links = computed((): HeaderLink[] => {
|
|
// remember to modify ~/server/api/search.get.ts, page kind too
|
|
const links: HeaderLink[] = [];
|
|
|
|
links.push({
|
|
header: true,
|
|
name: 'index',
|
|
icon: 'home',
|
|
text: translator.translate('home.header'),
|
|
textLong: translator.translate('home.link'),
|
|
});
|
|
|
|
if (config.pronouns.enabled) {
|
|
const extra = [];
|
|
const prefixes = [...config.pronouns.sentence ? config.pronouns.sentence.prefixes : [], ''];
|
|
for (const prefix of prefixes) {
|
|
extra.push(`${prefix}/${config.pronouns.any}`);
|
|
extra.push(`${prefix}/${config.pronouns.any}:`);
|
|
if (config.pronouns.null && config.pronouns.null.routes) {
|
|
for (const route of config.pronouns.null.routes) {
|
|
extra.push(`${prefix}/${route}`);
|
|
}
|
|
}
|
|
if (config.pronouns.mirror) {
|
|
extra.push(`${prefix}/${config.pronouns.mirror.route}`);
|
|
}
|
|
if (config.pronouns.ask) {
|
|
for (const route of config.pronouns.ask.routes) {
|
|
extra.push(`pronouns-${route}`);
|
|
}
|
|
}
|
|
}
|
|
links.push({
|
|
name: 'pronouns',
|
|
icon: 'tags',
|
|
text: translator.translate('pronouns.header'),
|
|
textLong: translator.translate('pronouns.headerLong').replace(/(<([^>]+)>)/ig, ''),
|
|
extra,
|
|
});
|
|
}
|
|
|
|
if (config.nouns.enabled) {
|
|
const extras = [];
|
|
for (const subroute of config.nouns.subroutes || []) {
|
|
extras.push(`/${subroute}`);
|
|
}
|
|
links.push({
|
|
name: 'nouns',
|
|
icon: 'book',
|
|
text: translator.translate('nouns.header'),
|
|
textLong: translator.translate('nouns.headerLong'),
|
|
extra: extras,
|
|
});
|
|
}
|
|
|
|
if (config.sources.enabled) {
|
|
links.push({
|
|
name: 'sources',
|
|
icon: 'books',
|
|
text: translator.translate('sources.header'),
|
|
textLong: translator.translate('sources.headerLong'),
|
|
});
|
|
}
|
|
|
|
if (config.faq.enabled && !config.links.split) {
|
|
links.push({
|
|
name: 'faq',
|
|
icon: 'map-marker-question',
|
|
text: translator.translate('faq.header'),
|
|
textLong: translator.translate('faq.headerLong'),
|
|
});
|
|
}
|
|
|
|
if (config.links.enabled) {
|
|
links.push({
|
|
name: 'links',
|
|
icon: 'bookmark',
|
|
text: translator.translate('links.header'),
|
|
textLong: translator.translate('links.headerLong'),
|
|
extra: [
|
|
config.links.academicRoute ? `/${config.links.academicRoute}` : '',
|
|
config.links.translinguisticsRoute ? `/${config.links.translinguisticsRoute}` : '',
|
|
config.links.splitBlog ? '' : 'blog',
|
|
config.links.splitBlog ? '' : 'blogEntry',
|
|
config.links.splitBlog ? '' : 'blogEntryShortcut',
|
|
config.links.mediaRoute ? `/${config.links.mediaRoute}` : '',
|
|
config.links.split ? 'faq' : '',
|
|
config.english && config.english.enabled ? 'english' : '',
|
|
config.links.zine && config.links.zine.enabled ? `/${config.links.zine.route}` : '',
|
|
],
|
|
});
|
|
|
|
if (config.links.blog && config.links.splitBlog) {
|
|
links.push({
|
|
name: 'blog',
|
|
icon: 'pen-nib',
|
|
text: translator.translate('links.blog'),
|
|
extra: ['blogEntry', 'blogEntryShortcut'],
|
|
});
|
|
}
|
|
}
|
|
|
|
if ((config.terminology.enabled && config.terminology.published) ||
|
|
config.calendar?.enabled ||
|
|
config.census?.enabled ||
|
|
config.inclusive?.enabled ||
|
|
config.people?.enabled ||
|
|
(config.contact && config.contact.team?.enabled)
|
|
) {
|
|
const extra = [
|
|
config.terminology.enabled && config.terminology.published ? 'terminology' : '',
|
|
config.calendar?.enabled ? 'calendar' : '',
|
|
config.calendar?.enabled ? 'calendarDay' : '',
|
|
config.census.enabled ? 'census' : '',
|
|
config.inclusive.enabled ? 'inclusive' : '',
|
|
config.names.enabled && config.names.published ? 'names' : '',
|
|
config.people.enabled ? 'people' : '',
|
|
config.contact.enabled ? 'team' : '',
|
|
config.workshops?.enabled ? 'workshops' : '',
|
|
];
|
|
|
|
if (config.community) {
|
|
links.push({
|
|
link: `/${encodeURIComponent(config.community.route)}`,
|
|
icon: 'users',
|
|
text: translator.translate('community.header'),
|
|
textLong: translator.translate('community.headerLong'),
|
|
extra,
|
|
});
|
|
} else if (config.calendar && config.calendar.enabled) {
|
|
links.push({
|
|
name: 'calendar',
|
|
icon: 'calendar-star',
|
|
text: translator.translate('calendar.header'),
|
|
textLong: translator.translate('calendar.headerLong'),
|
|
extra,
|
|
});
|
|
}
|
|
}
|
|
|
|
if (config.contact.enabled) {
|
|
links.push({
|
|
name: 'contact',
|
|
icon: 'comment-alt-smile',
|
|
text: translator.translate('contact.header'),
|
|
});
|
|
}
|
|
|
|
links.push({
|
|
link: 'https://shop.pronouns.page',
|
|
icon: 'shopping-bag',
|
|
text: translator.translate('contact.groups.shop'),
|
|
desktop: false,
|
|
});
|
|
|
|
if (config.user.enabled) {
|
|
links.push({
|
|
name: 'user',
|
|
avatar: user.value,
|
|
icon: 'user',
|
|
text: user.value ? `@${user.value.username}` : translator.translate('user.header'),
|
|
textLong: user.value ? `@${user.value.username}` : translator.translate('user.headerLong'),
|
|
extra: ['/editor', user.value ? `/@${user.value.username}` : null],
|
|
});
|
|
if (isGranted('panel') || isGranted('external')) {
|
|
links.push({
|
|
name: 'admin',
|
|
icon: 'user-cog',
|
|
text: translator.translate('admin.header'),
|
|
textLong: translator.translate('admin.header'),
|
|
extra: [
|
|
'/admin/users',
|
|
'/admin/profiles',
|
|
'/admin/timesheets',
|
|
'/admin/moderation',
|
|
'/admin/abuse-reports',
|
|
'/admin/pending-bans',
|
|
'/admin/translations/missing',
|
|
'/admin/translations/awaiting',
|
|
],
|
|
});
|
|
}
|
|
}
|
|
|
|
return links;
|
|
});
|
|
|
|
const route = useRoute();
|
|
const showCensus = computed((): boolean => {
|
|
if (!import.meta.client) {
|
|
return false;
|
|
}
|
|
const finished = !!parseInt(window.localStorage.getItem(`census-${config.census.edition}-finished`) || '0');
|
|
const dismissed = !!parseInt(window.localStorage.getItem(`census-${config.census.edition}-dismissed`) || '0');
|
|
const alreadyIn = route.name === 'census';
|
|
const isHomepage = route.name === 'index';
|
|
if (!config.census.enabled || !isHomepage && (finished || dismissed) || censusDismissed.value || alreadyIn) {
|
|
return false;
|
|
}
|
|
const start = DateTime.fromISO(config.census.start).toLocal();
|
|
const end = DateTime.fromISO(config.census.end).toLocal();
|
|
const now = DateTime.utc().setZone(config.format?.timezone ?? 'utc');
|
|
return now >= start && now <= end;
|
|
});
|
|
|
|
const buildRoute = (link: HeaderLink): RouteLocationRaw => {
|
|
if (link.name !== undefined) {
|
|
return { name: link.name };
|
|
}
|
|
return link.link;
|
|
};
|
|
const isActiveRoute = (link: HeaderLink) => {
|
|
return (route.name !== undefined && route.name === link.name) ||
|
|
(route.meta.headerCategory !== undefined && route.meta.headerCategory === link.name) ||
|
|
(link.extra && route.name && link.extra.includes((route.name as string).split(':')[0])) ||
|
|
(link.extra || []).includes(decodeURIComponent(route.path)) ||
|
|
(link.extra || []).filter((x) => x && (
|
|
decodeURIComponent(route.path).startsWith(`${x}/`) ||
|
|
decodeURIComponent(route.path).startsWith(`${x}:`))).length;
|
|
};
|
|
|
|
onMounted(() => {
|
|
document.addEventListener('click', documentClicked);
|
|
updateShown();
|
|
window.addEventListener('scroll', updateShown);
|
|
});
|
|
onUnmounted(() => {
|
|
document.removeEventListener('click', documentClicked);
|
|
document.removeEventListener('scroll', updateShown);
|
|
});
|
|
|
|
const documentClicked = (): void => {
|
|
if (hamburgerActive.value) {
|
|
hamburgerActive.value = false;
|
|
}
|
|
};
|
|
const updateShown = (): void => {
|
|
const st = document.body.scrollTop || document.querySelector('html')!.scrollTop;
|
|
hamburgerShown.value = st > 300;
|
|
};
|
|
const dismissCensus = (): void => {
|
|
window.localStorage.setItem(`census-${config.census.edition}-dismissed`, '1');
|
|
censusDismissed.value = true;
|
|
};
|
|
</script>
|
|
|
|
<template>
|
|
<div v-if="config.header" class="mb-lg-4">
|
|
<header @mouseleave="hoverItem = null">
|
|
<SkipLink />
|
|
<div class="d-none d-lg-flex justify-content-between align-items-center flex-row nav-custom btn-group mb-0">
|
|
<template v-for="link in links">
|
|
<PotentiallyExternalLink
|
|
v-if="link.desktop === undefined || link.desktop === true"
|
|
:key="link.name ?? link.link"
|
|
:to="buildRoute(link)"
|
|
:class="`nav-item btn btn-sm ${link.header ? 'nav-header' : ''} ${isActiveRoute(link) ? 'active' : ''} ${link.header ? 'flex-grow-0' : ''}`"
|
|
@mouseenter="hoverItem = link"
|
|
>
|
|
<h1 v-if="link.header" class="text-nowrap">
|
|
<Logo flag />
|
|
<span class="higher"><T>title</T></span>
|
|
</h1>
|
|
<template v-else>
|
|
<Avatar v-if="link.avatar" :user="link.avatar" dsize="1.6rem" />
|
|
<Icon v-else :v="link.icon" :size="1.6" />
|
|
<br>
|
|
<Spelling class="text-nowrap" :text="link.text" />
|
|
</template>
|
|
</PotentiallyExternalLink>
|
|
</template>
|
|
<button type="button" class="nav-item nav-header btn btn-sm position-relative" @click="searchDialogue?.open()">
|
|
<span style="position: absolute; right: 0.1em; top: 0.1em; opacity: 0.7; z-index: -1">
|
|
<ClientOnly>
|
|
<kbd class="bg-light text-dark border">{{ isMac ? '⌘K' : 'Ctrl+K' }}</kbd>
|
|
</ClientOnly>
|
|
</span>
|
|
<Icon v="search" :size="1.6" />
|
|
<br>
|
|
<T>search.header</T>
|
|
</button>
|
|
<div class="nav-item flex-grow-0" @mouseenter="hoverItem = null">
|
|
<VersionDropdown end />
|
|
</div>
|
|
</div>
|
|
<div class="d-block-force d-lg-none p-4">
|
|
<div class="text-center mb-3">
|
|
<nuxt-link to="/">
|
|
<h1 class="text-nowrap">
|
|
<Logo flag class="me-2" /><span class="higher"><T>title</T></span>
|
|
</h1>
|
|
</nuxt-link>
|
|
<AdPlaceholder :phkey="[null, 'header']" />
|
|
<VersionDropdown />
|
|
</div>
|
|
<div class="btn-group-vertical d-flex nav-custom mb-2">
|
|
<template v-for="link in links">
|
|
<PotentiallyExternalLink
|
|
v-if="link.mobile === undefined || link.mobile === true"
|
|
:key="link.name ?? link.link"
|
|
:to="buildRoute(link)"
|
|
:class="`btn btn-sm ${isActiveRoute(link) ? 'active' : ''}`"
|
|
>
|
|
<Avatar v-if="link.avatar" :user="link.avatar" dsize="1rem" />
|
|
<Icon v-else :v="link.icon" />
|
|
<Spelling :text="link.textLong || link.text" />
|
|
</PotentiallyExternalLink>
|
|
</template>
|
|
<span class="btn btn-sm" @click="searchDialogue?.open()">
|
|
<Icon v="search" />
|
|
<T>search.header</T>
|
|
</span>
|
|
</div>
|
|
</div>
|
|
<div :class="['hamburger-menu']" :style="`opacity: ${hamburgerShown ? 1 : 0}`">
|
|
<button
|
|
type="button"
|
|
:class="['btn btn-outline-secondary', hamburgerActive ? 'text-bg-secondary' : 'text-bg-light']"
|
|
@click="hamburgerActive = !hamburgerActive"
|
|
>
|
|
<Icon v="bars" />
|
|
</button>
|
|
<div :class="['bg border p-3 shadow', hamburgerActive ? '' : 'd-none']">
|
|
<div class="btn-group-vertical d-flex nav-custom nav-custom-start mb-2">
|
|
<template v-for="link in links">
|
|
<PotentiallyExternalLink
|
|
v-if="link.mobile === undefined || link.mobile === true"
|
|
:key="link.name ?? link.link"
|
|
:to="buildRoute(link)"
|
|
:class="`btn btn-sm ${isActiveRoute(link) ? 'active' : ''}`"
|
|
>
|
|
<Avatar v-if="link.avatar" :user="link.avatar" dsize="1rem" />
|
|
<Icon v-else :v="link.icon" />
|
|
<Spelling :text="link.textLong || link.text" />
|
|
</PotentiallyExternalLink>
|
|
</template>
|
|
<button type="button" class="btn btn-sm" @click="searchDialogue?.open()">
|
|
<Icon v="search" />
|
|
<T>search.header</T>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<NounsNav
|
|
v-if="hoverItem?.name === 'nouns'"
|
|
class="mb-0 container py-5 hide-if-empty"
|
|
/>
|
|
<LinksNav
|
|
v-if="hoverItem?.name === 'links'"
|
|
class="mb-0 container py-5 hide-if-empty"
|
|
/>
|
|
<CommunityNav
|
|
v-if="config.community && hoverItem?.link === `/${encodeURIComponent(config.community.route)}`"
|
|
class="mb-0 container py-5 hide-if-empty"
|
|
/>
|
|
<AccountSwitch
|
|
v-if="hoverItem?.name === 'user'"
|
|
class="container py-5 hide-if-empty"
|
|
:minimum-count="1"
|
|
/>
|
|
</header>
|
|
<div
|
|
v-if="config.locale === 'zh' &&
|
|
today < new Date(2022, 0, 1, 0, 0, 0) &&
|
|
$route.path === '/'"
|
|
class="container"
|
|
>
|
|
<div class="alert alert-info my-3">
|
|
<p class="h4">
|
|
<Icon v="people-carry" />
|
|
Help needed!
|
|
</p>
|
|
<p class="mb-0">
|
|
If you speak Mandarin
|
|
(preferably traditional spelling, since simplified can be generated out of it, but not the other way around)
|
|
and you'd like to help us with translating new features of zh.pronouns.page,
|
|
please send us an email to <a href="mailto:contact@pronouns.page" target="_blank" rel="noopener">contact@pronouns.page</a>
|
|
or DM us on Twitter <a href="https://twitter.com/PronounsPage" target="_blank" rel="noopener">@PronounsPage</a>
|
|
😉
|
|
</p>
|
|
</div>
|
|
</div>
|
|
<div
|
|
v-if="config.locale === 'pl' &&
|
|
today < new Date(2022, 3, 12, 19, 0, 0) &&
|
|
$route.path === '/'"
|
|
class="container"
|
|
>
|
|
<div class="alert alert-info my-3">
|
|
<p>
|
|
<Icon v="calendar" />
|
|
We <strong>wtorek, 12 kwietnia, o 18:00</strong>
|
|
Sybil i Andrea będą gościć w Katedrze Performatyki Uniwersytetu Jagiellońskiego
|
|
w rozmowie „W stronę niebinarności. Nowe relacje w języku”.
|
|
Zapraszamy do oglądania lajwa!
|
|
</p>
|
|
<p class="mb-0 text-center">
|
|
<a href="https://www.facebook.com/events/711884409825918" target="_blank" rel="noopener" class="btn btn-primary">
|
|
<Icon v="play" />
|
|
Live/event
|
|
</a>
|
|
</p>
|
|
</div>
|
|
</div>
|
|
<div
|
|
v-if="config.locale === 'en' &&
|
|
today < new Date(2024, 8, 1, 0, 0, 0) &&
|
|
$route.path === '/'"
|
|
class="container"
|
|
>
|
|
<a href="https://discord.pronouns.page" target="_blank" rel="noopener">
|
|
<img :src="`/img/${config.locale}/blog/community-discord-banner.png`" class="w-100 shadow" alt="We've launched a community server! discord.pronouns.page">
|
|
</a>
|
|
</div>
|
|
<div v-if="$locales[config.locale].published === false" class="alert alert-warning mb-0 mx-5 text-center">
|
|
<Icon v="exclamation-triangle" />
|
|
This language version is still under construction!
|
|
</div>
|
|
<div v-if="showCensus" class="container position-relative">
|
|
<nuxt-link :to="{ name: 'census' }">
|
|
<img
|
|
:src="`/img/${config.locale}/census/census-banner-horizontal.png`"
|
|
alt="Na tle flagi osób niebinarnych (cztery poziome pasy: żółty, biały, fioletowy, czarny) tekst: Trwa trzecia edycja największego badania języka osób niebinarnych! Jakich form używamy? Jak unikamy upłciowionego języka? Jak nasz język rozwija się i zmienia? Wypełnij naszą ankietę, by pomóc nam to zbadać! Niebinarny Spis Powszechny 2023; zaimki.pl/spis"
|
|
class="w-100 shadow d-none d-md-block"
|
|
>
|
|
<img
|
|
:src="`/img/${config.locale}/census/census-banner-horizontal-mobile.png`"
|
|
alt="Na tle flagi osób niebinarnych (cztery poziome pasy: żółty, biały, fioletowy, czarny) tekst: Trwa trzecia edycja największego badania języka osób niebinarnych! Jakich form używamy? Jak unikamy upłciowionego języka? Jak nasz język rozwija się i zmienia? Wypełnij naszą ankietę, by pomóc nam to zbadać! Niebinarny Spis Powszechny 2023; zaimki.pl/spis"
|
|
class="w-100 shadow d-md-none"
|
|
>
|
|
</nuxt-link>
|
|
<a
|
|
href="#"
|
|
class="position-absolute p-2 bg-primary text-white btn-dismiss"
|
|
@click.prevent="dismissCensus"
|
|
>
|
|
<Icon v="times" />
|
|
</a>
|
|
</div>
|
|
<div
|
|
v-if="config.locale === 'pl' &&
|
|
today < new Date(2023, 4, 1, 0, 0, 0) &&
|
|
['/', '/spis'].includes($route.path)"
|
|
class="container position-relative"
|
|
>
|
|
<nuxt-link to="/blog/spis-2023">
|
|
<img
|
|
:src="`/img/${config.locale}/census/census-banner-report-horizontal.png`"
|
|
alt="Na tle flagi osób niebinarnych (cztery poziome pasy: żółty, biały, fioletowy, czarny) tekst: Przedstawiamy raport z trzeciej edycji największego badania języka osób niebinarnych! Niebinarny Spis Powszechny 2023; zaimki.pl/spis"
|
|
class="w-100 shadow d-none d-md-block"
|
|
>
|
|
<img
|
|
:src="`/img/${config.locale}/census/census-banner-report-horizontal-mobile.png`"
|
|
alt="Na tle flagi osób niebinarnych (cztery poziome pasy: żółty, biały, fioletowy, czarny) tekst: Niebinarny Spis Powszechny 2023; Przeczytaj raport z badania! zaimki.pl/spis"
|
|
class="w-100 shadow d-md-none"
|
|
>
|
|
</nuxt-link>
|
|
</div>
|
|
<!-- <div class="container">
|
|
<SafariWarning dismissable />
|
|
</div> -->
|
|
<div v-if="$user() && $user()!.bannedReason" class="alert alert-danger mb-0 container">
|
|
<p class="h4 mb-2">
|
|
<Icon v="ban" />
|
|
<T>ban.header</T>
|
|
</p>
|
|
<p>
|
|
<T>ban.reason</T><T>quotation.colon</T>
|
|
{{ $user()!.bannedReason }}
|
|
</p>
|
|
<p>
|
|
<T>ban.termsIntro</T><T>quotation.colon</T>
|
|
</p>
|
|
<blockquote class="small">
|
|
<T>terms.content.content.violations</T>
|
|
<template v-for="(violation, i) in forbidden">
|
|
<T :class="[$user()!.bannedTerms?.includes(violation) ? 'fw-bold' : '']">terms.content.content.violationsExamples.{{ violation }}</T><template v-if="i !== forbidden.length - 1">
|
|
,
|
|
</template>
|
|
</template>.
|
|
</blockquote>
|
|
</div>
|
|
</div>
|
|
<header v-else class="mb-4">
|
|
<div class="container">
|
|
<h1 class="text-nowrap p-4 mb-0">
|
|
<nuxt-link to="/">
|
|
<Logo flag class="me-2" /><span class="higher"><T>title</T></span>
|
|
</nuxt-link>
|
|
</h1>
|
|
</div>
|
|
</header>
|
|
<ClientOnly>
|
|
<Teleport to="#teleports">
|
|
<SearchDialogue ref="searchDialogue" />
|
|
</Teleport>
|
|
</ClientOnly>
|
|
</template>
|
|
|
|
<style lang="scss" scoped>
|
|
@import "assets/variables";
|
|
|
|
header {
|
|
padding: 0;
|
|
width: 100%;
|
|
}
|
|
|
|
@include media-breakpoint-down('lg', $grid-breakpoints) {
|
|
h1 {
|
|
font-size: 2rem;
|
|
}
|
|
|
|
.nav-custom {
|
|
:deep(.btn) {
|
|
border: none;
|
|
border-inline-start: 1px solid $gray-500;
|
|
border-radius: 0;
|
|
|
|
&:hover, &:focus, &.active {
|
|
border-inline-start: 3px solid $primary;
|
|
padding-inline-start: calc(#{$btn-padding-x-sm} - 2px);
|
|
color: $primary;
|
|
}
|
|
|
|
text-align: left;
|
|
}
|
|
}
|
|
|
|
.hamburger-menu {
|
|
position: fixed;
|
|
top: 0;
|
|
left: $spacer;
|
|
z-index: 1030;
|
|
transition: all .5s ease-in-out;
|
|
.bg {
|
|
background-color: rgba($white, .9)
|
|
}
|
|
}
|
|
}
|
|
|
|
.nav-custom-start {
|
|
.btn {
|
|
border: none;
|
|
border-inline-start: 1px solid $gray-500;
|
|
border-radius: 0;
|
|
|
|
&:hover, &:focus, &.active {
|
|
border-inline-start: 3px solid $primary;
|
|
padding-inline-start: calc(#{$btn-padding-x-sm} - 2px);
|
|
color: $primary;
|
|
}
|
|
|
|
text-align: left;
|
|
}
|
|
}
|
|
|
|
@include media-breakpoint-up('lg', $grid-breakpoints) {
|
|
header {
|
|
position: fixed;
|
|
z-index: 99;
|
|
top: 0;
|
|
left: 0;
|
|
background-color: rgba($white, .9);
|
|
box-shadow: $box-shadow;
|
|
}
|
|
|
|
.nav-custom:not(.nav-custom-start) {
|
|
:deep(.nav-item) {
|
|
border: none;
|
|
border-bottom: 1px solid $gray-500;
|
|
border-radius: 0;
|
|
|
|
&.btn {
|
|
&:hover, &:focus, &.active {
|
|
border-bottom: 3px solid $primary;
|
|
padding-bottom: calc(#{$btn-padding-y-sm} - 2px);
|
|
color: $primary;
|
|
}
|
|
}
|
|
|
|
height: $header-height;
|
|
padding-top: 1.2rem;
|
|
&.nav-header {
|
|
padding-top: 0.6rem;
|
|
}
|
|
margin-top: 3px;
|
|
|
|
&:first-child, &:last-child {
|
|
padding-left: 1rem;
|
|
padding-right: 1rem;
|
|
}
|
|
}
|
|
}
|
|
|
|
.hamburger-menu {
|
|
display: none;
|
|
}
|
|
}
|
|
|
|
h1 {
|
|
text-decoration: none;
|
|
margin-bottom: .5em;
|
|
.higher {
|
|
position: relative;
|
|
top: -0.1em;
|
|
}
|
|
}
|
|
|
|
.btn-dismiss {
|
|
top: 0;
|
|
right: 0;
|
|
opacity: 0.5;
|
|
transition: opacity .25s ease-in-out;
|
|
&:hover {
|
|
opacity: 1;
|
|
}
|
|
}
|
|
|
|
.hide-if-empty:empty {
|
|
display: none !important;
|
|
}
|
|
</style>
|