feat: CultBR design system customizations

- Theme SCSS: CultBR colors (#006FEE primary, #39DDA2 secondary, #FFCF00 accent)
- Header: white minimal Fumadocs-style, 56px, logo + search
- Sidebar: white, clean nav items, retractable on mobile
- NavSidebar: removed dark mode, proper text colors for light theme
- Login: gradient background, CultBR branding
- PageHeader: clean title + description only (no icons/actions for viewers)
- Index: removed breadcrumbs, TOC, tags, share/print/history/source/actions
- WelcomeOverlay: CultBR logo and text
- MainLayout: removed footer, collapsible sidebar with breakpoint
pull/7973/head
Gabriel Mowses (Mouse) 3 weeks ago
parent 88ad926402
commit 4bdf13a29f

@ -1,89 +1,60 @@
<template lang="pug">
q-header.bg-header.text-white.site-header(
height-hint='64'
q-header.site-header(
height-hint='56'
bordered
)
.row.no-wrap
q-toolbar(
style='height: 64px;'
dark
q-toolbar(style='height: 56px; max-width: 1400px; margin: 0 auto; width: 100%;')
q-btn.q-mr-sm.lt-lg(
dense
flat
round
icon='las la-bars'
@click='$emit(`toggle-sidebar`)'
)
q-btn(
dense
flat
to='/'
)
q-avatar(
v-if='siteStore.logoText'
size='34px'
square
)
img(:src='`/_site/logo`')
img(
v-else
:src='`/_site/logo`'
style='height: 34px'
)
q-toolbar-title.text-h6(v-if='siteStore.logoText') {{siteStore.title}}
q-btn(
dense
flat
no-caps
to='/'
style='gap: 10px;'
)
img(:src='`/_site/logo`' style='height: 28px;')
span.text-weight-bold.text-body1(v-if='siteStore.logoText' style='letter-spacing: -0.3px;') {{siteStore.title}}
q-space
header-search
q-toolbar(
style='height: 64px;'
dark
q-space
q-btn.q-ml-sm(
v-if='userStore.can(`write:pages`)'
flat
dense
no-caps
icon='las la-plus'
label='New'
size='sm'
style='border-radius: 8px; padding: 4px 12px;'
)
q-space
transition(name='syncing')
q-spinner-tail(
v-show='commonStore.routerLoading'
color='accent'
size='24px'
)
q-btn.q-ml-md(
v-if='userStore.can(`write:pages`)'
flat
round
dense
icon='las la-plus-circle'
color='blue-4'
aria-label='Create New Page'
)
q-tooltip Create New Page
new-menu
q-btn.q-ml-md(
v-if='userStore.can(`browse:fileman`)'
flat
round
dense
icon='las la-folder-open'
color='positive'
aria-label='File Manager'
@click='openFileManager'
)
q-tooltip File Manager
q-btn.q-ml-md(
v-if='userStore.can(`access:admin`)'
flat
round
dense
icon='las la-tools'
color='pink'
to='/_admin'
:aria-label='t(`common.header.admin`)'
)
q-tooltip {{ t('common.header.admin') }}
//- USER BUTTON / DROPDOWN
account-menu(v-if='userStore.authenticated')
q-btn.q-ml-md(
v-else
flat
rounded
icon='las la-sign-in-alt'
color='white'
:label='$t(`common.actions.login`)'
:aria-label='$t(`common.actions.login`)'
to='/login'
padding='sm'
no-caps
new-menu
q-btn.q-ml-sm(
v-if='userStore.can(`access:admin`)'
flat
dense
round
icon='las la-cog'
size='sm'
to='/_admin'
)
account-menu.q-ml-sm(v-if='userStore.authenticated')
q-btn.q-ml-sm(
v-else
flat
dense
no-caps
icon='las la-sign-in-alt'
:label='$t(`common.actions.login`)'
to='/login'
size='sm'
style='border-radius: 8px;'
)
</template>
<script setup>
@ -100,28 +71,43 @@ import AccountMenu from '@/components/AccountMenu.vue'
import NewMenu from '@/components/PageNewMenu.vue'
import HeaderSearch from '@/components/HeaderSearch.vue'
// QUASAR
const $q = useQuasar()
// STORES
const commonStore = useCommonStore()
const siteStore = useSiteStore()
const userStore = useUserStore()
// ROUTER
const router = useRouter()
const route = useRoute()
const { t } = useI18n()
</script>
// I18N
<style lang="scss">
.site-header {
background: white !important;
border-bottom: 1px solid #E2E8F0 !important;
box-shadow: none !important;
const { t } = useI18n()
.q-toolbar {
color: #19191C;
}
// METHODS
.q-btn {
color: #4B4B53;
function openFileManager () {
siteStore.openFileManager()
&:hover {
color: #006FEE;
background: #E6F1FE;
}
}
@at-root .body--dark & {
background: $dark-5 !important;
border-bottom-color: $dark-3 !important;
.q-toolbar { color: #E2E8F0; }
.q-btn {
color: #9CA3AF;
&:hover { color: #5BA7FF; background: rgba(0,111,238,0.1); }
}
}
}
</script>
</style>

@ -6,14 +6,13 @@ q-scroll-area.sidebar-nav(
q-list.sidebar-nav-list(
clickable
dense
dark
)
template(v-for='item of siteStore.nav.items', :key='item.id')
q-item-label.sidebar-nav-header.text-caption.text-wordbreak-all(
q-item-label.sidebar-nav-header(
v-if='item.type === `header`'
header
) {{ item.label }}
q-expansion-item(
q-expansion-item.sidebar-nav-expand(
v-else-if='item.type === `link` && item.children?.length > 0'
:icon='item.icon'
:label='item.label'
@ -22,26 +21,22 @@ q-scroll-area.sidebar-nav(
q-list(
clickable
dense
dark
)
q-item(
v-for='itemChild of item.children'
:to='itemChild.target'
:key='itemChild.id'
)
q-item-section(side)
q-icon(:name='itemChild.icon', color='white')
q-item-section.text-wordbreak-all.text-white {{ itemChild.label }}
q-item-section.text-wordbreak-all {{ itemChild.label }}
q-item(
v-else-if='item.type === `link`'
:to='item.target'
)
q-item-section(side)
q-icon(:name='item.icon', color='white')
q-item-section.text-wordbreak-all.text-white {{ item.label }}
q-separator(
q-icon(:name='item.icon')
q-item-section.text-wordbreak-all {{ item.label }}
q-separator.sidebar-nav-sep(
v-else-if='item.type === `separator`'
dark
)
</template>
@ -54,41 +49,26 @@ import { useI18n } from 'vue-i18n'
import { usePageStore } from '@/stores/page'
import { useSiteStore } from '@/stores/site'
// QUASAR
const $q = useQuasar()
// STORES
const pageStore = usePageStore()
const siteStore = useSiteStore()
// ROUTER
const router = useRouter()
const route = useRoute()
// I18N
const { t } = useI18n()
// DATA
const thumbStyle = {
right: '2px',
borderRadius: '5px',
backgroundColor: '#FFF',
width: '5px',
opacity: 0.5
borderRadius: '3px',
backgroundColor: '#CBD5E1',
width: '4px',
opacity: 0.6
}
const barStyle = {
backgroundColor: '#000',
width: '9px',
backgroundColor: 'transparent',
width: '8px',
opacity: 0.1
}
// WATCHERS
watch(() => pageStore.navigationId, (newValue) => {
if (newValue && newValue !== siteStore.nav.currentId) {
siteStore.fetchNavigation(newValue)
@ -99,86 +79,87 @@ watch(() => pageStore.navigationId, (newValue) => {
<style lang="scss">
.sidebar-nav {
border-top: 1px solid rgba(255,255,255,.15);
height: calc(100% - 38px - 24px);
height: 100%;
&-list > .q-separator {
margin-top: 10px;
margin-bottom: 10px;
margin: 8px 16px;
background: #E2E8F0;
}
.q-list {
.q-separator + .q-item__label {
padding-top: 10px;
}
&-header {
color: #94A3B8 !important;
font-size: 0.7rem !important;
font-weight: 600 !important;
text-transform: uppercase;
letter-spacing: 0.8px;
padding: 16px 16px 6px !important;
}
.q-item__section--avatar {
min-width: auto;
}
&-expand {
.q-expansion-item__container > .q-item {
padding: 6px 12px;
margin: 1px 8px;
border-radius: 6px;
min-height: 34px;
color: #334155;
font-weight: 500;
font-size: 0.875rem;
.q-expansion-item > .q-expansion-item__container {
> .q-item {
&::before {
content: '';
display: block;
position: absolute;
bottom: 0;
left: 0px;
width: 10px;
height: 10px;
border-style: solid;
border-color: transparent transparent rgba(255,255,255,.25) rgba(255,255,255,.25);
transition: all .4s ease;
}
}
.q-icon { font-size: 18px; color: #94A3B8; }
&::after {
content: '';
display: block;
position: absolute;
bottom: -20px;
left: 0;
width: 10px;
height: 10px;
border-style: solid;
border-color: rgba(255,255,255,.25) transparent transparent rgba(255,255,255,.25);
transition: all .4s ease;
&:hover {
background: #F1F5F9;
}
}
.q-expansion-item--collapsed > .q-expansion-item__container {
> .q-item {
&::before {
border-width: 0 0 0 0;
.q-expansion-item__content {
border-left: none;
padding-left: 12px;
.q-item {
padding: 4px 12px 4px 36px;
margin: 1px 8px;
border-radius: 6px;
min-height: 30px;
font-size: 0.825rem;
color: #64748B;
&:hover {
background: #F1F5F9;
color: #334155;
}
}
&::after {
bottom: 0px;
border-width: 0 0 0 0;
&.q-router-link--active {
background: #E6F1FE;
color: #006FEE;
font-weight: 600;
}
}
}
}
.q-expansion-item--expanded > .q-expansion-item__container {
> .q-item {
&::before {
border-width: 0 10px 10px 0;
}
}
.q-list > .q-item {
padding: 6px 12px;
margin: 1px 8px;
border-radius: 6px;
min-height: 34px;
color: #334155;
font-size: 0.875rem;
&::after {
bottom: -20px;
border-width: 10px 10px 10px 0;
}
}
.q-icon { font-size: 18px; color: #94A3B8; }
.q-expansion-item__content {
border-left: 10px solid rgba(255,255,255,.25);
&:hover {
background: #F1F5F9;
color: #1E293B;
}
}
&-header {
color: rgba(255,255,255,.75) !important;
&.q-router-link--active {
background: #E6F1FE !important;
color: #006FEE !important;
font-weight: 600;
.q-icon { color: #006FEE; }
}
}
}
</style>

@ -1,193 +1,30 @@
<template lang="pug">
.page-header.row
//- PAGE ICON
.page-header-clean(v-if='!editorStore.isActive')
h1.page-header-title {{ pageStore.title }}
p.page-header-desc(v-if='pageStore.description') {{ pageStore.description }}
.page-header.row(v-else)
.col-auto.q-pl-md.flex.items-center
q-btn.rounded-borders(
v-if='editorStore.isActive'
padding='none'
size='37px'
:icon='pageStore.icon'
color='primary'
flat
)
q-badge(color='grey' floating rounded)
q-icon(name='las la-pen', size='xs', padding='xs xs')
q-menu(content-class='shadow-7')
.q-pa-lg: em [ TODO: Icon Picker Dialog ]
// icon-picker-dialog(v-model='pageStore.icon')
q-icon.rounded-borders(
v-else
:name='pageStore.icon'
size='64px'
color='primary'
)
//- PAGE HEADER
q-icon.rounded-borders(:name='pageStore.icon' size='64px' color='primary')
.col.q-pa-md
.text-h4.page-header-title
span {{pageStore.title}}
template(v-if='editorStore.isActive')
span.text-grey(v-if='!pageStore.title') {{ t(`editor.props.title`)}}
q-btn.acrylic-btn.q-ml-md(
icon='las la-pen'
flat
padding='xs'
size='sm'
)
q-popup-edit(
v-model='pageStore.title'
auto-save
v-slot='scope'
)
q-input(
outlined
style='width: 450px;'
v-model='scope.value'
dense
autofocus
@keyup.enter='scope.set'
:label='t(`editor.props.title`)'
)
q-btn.acrylic-btn.q-ml-md(icon='las la-pen' flat padding='xs' size='sm')
q-popup-edit(v-model='pageStore.title' auto-save v-slot='scope')
q-input(outlined style='width: 450px;' v-model='scope.value' dense autofocus @keyup.enter='scope.set' :label='t(`editor.props.title`)')
.text-subtitle2.page-header-subtitle
span {{ pageStore.description }}
template(v-if='editorStore.isActive')
span.text-grey(v-if='!pageStore.description') {{ t(`editor.props.shortDescription`)}}
q-btn.acrylic-btn.q-ml-md(
icon='las la-pen'
flat
padding='none xs'
size='xs'
)
q-popup-edit(
v-model='pageStore.description'
auto-save
v-slot='scope'
)
q-input(
outlined
style='width: 450px;'
v-model='scope.value'
dense
autofocus
@keyup.enter='scope.set'
:label='t(`editor.props.shortDescription`)'
)
//- PAGE ACTIONS
q-btn.acrylic-btn.q-ml-md(icon='las la-pen' flat padding='none xs' size='xs')
q-popup-edit(v-model='pageStore.description' auto-save v-slot='scope')
q-input(outlined style='width: 450px;' v-model='scope.value' dense autofocus @keyup.enter='scope.set' :label='t(`editor.props.shortDescription`)')
.col-auto.q-pa-md.flex.items-center.justify-end
template(v-if='!editorStore.isActive')
q-btn.q-ml-md(
v-if='userStore.authenticated'
flat
dense
icon='las la-bell'
color='grey'
aria-label='Watch Page'
@click='notImplemented'
)
q-tooltip Watch Page
q-btn.q-ml-md(
v-if='userStore.authenticated'
flat
dense
icon='las la-bookmark'
color='grey'
aria-label='Bookmark Page'
@click='notImplemented'
)
q-tooltip Bookmark Page
q-btn.q-ml-md(
v-if='siteStore.theme.showSharingMenu'
flat
dense
icon='las la-share-alt'
color='grey'
aria-label='Share'
)
q-tooltip Share
social-sharing-menu
q-btn.q-ml-md(
v-if='siteStore.theme.showPrintBtn'
flat
dense
icon='las la-print'
color='grey'
aria-label='Print'
@click='printPage'
)
q-tooltip Print
template(v-if='editorStore.isActive')
q-btn.q-ml-md.acrylic-btn(
icon='las la-question-circle'
flat
color='grey'
:href='siteStore.docsBase + `/editor/${editorStore.editor}`'
target='_blank'
type='a'
)
q-tooltip {{ t(`common.actions.viewDocs`) }}
q-btn.q-ml-sm.acrylic-btn(
icon='las la-cog'
flat
color='grey'
:aria-label='t(`editor.settings`)'
@click='openEditorSettings'
)
q-tooltip {{ t(`editor.settings`) }}
template(v-if='editorStore.isActive || editorStore.hasPendingChanges')
q-btn.acrylic-btn.q-ml-sm(
flat
icon='las la-times'
color='negative'
:label='editorStore.hasPendingChanges ? t(`common.actions.discard`) : t(`common.actions.close`)'
:aria-label='editorStore.hasPendingChanges ? t(`common.actions.discard`) : t(`common.actions.close`)'
no-caps
@click='discardChanges'
)
q-btn.acrylic-btn.q-ml-sm(
v-if='editorStore.mode === `create`'
flat
icon='las la-check'
color='positive'
:label='t(`editor.createPage`)'
:aria-label='t(`editor.createPage`)'
no-caps
@click='createPage'
)
q-btn-group.q-ml-sm(
v-else
flat
)
q-btn.acrylic-btn(
flat
icon='las la-check'
color='positive'
:label='t(`common.actions.saveChanges`)'
:aria-label='t(`common.actions.saveChanges`)'
:disabled='!editorStore.hasPendingChanges'
no-caps
@click.exact='saveChanges(false)'
@click.ctrl.exact='saveChanges(true)'
)
template(v-if='editorStore.isActive')
q-separator(vertical, dark)
q-btn.acrylic-btn(
flat
icon='las la-check-double'
color='positive'
:aria-label='t(`common.actions.saveAndClose`)'
:disabled='!editorStore.hasPendingChanges'
@click='saveChanges(true)'
)
q-tooltip {{ t(`common.actions.saveAndClose`) }}
template(v-else-if='userStore.can(`edit:pages`)')
q-btn.acrylic-btn.q-ml-md(
flat
icon='las la-edit'
color='deep-orange-9'
:label='t(`common.actions.edit`)'
:aria-label='t(`common.actions.edit`)'
no-caps
@click='editPage'
)
q-btn.acrylic-btn.q-ml-sm(flat icon='las la-question-circle' color='grey' :href='siteStore.docsBase + `/editor/${editorStore.editor}`' target='_blank' type='a')
q-btn.acrylic-btn.q-ml-sm(flat icon='las la-cog' color='grey' @click='openEditorSettings')
q-btn.acrylic-btn.q-ml-sm(flat icon='las la-times' color='negative' :label='editorStore.hasPendingChanges ? t(`common.actions.discard`) : t(`common.actions.close`)' no-caps @click='discardChanges')
q-btn-group.q-ml-sm(v-if='editorStore.mode !== `create`' flat)
q-btn.acrylic-btn(flat icon='las la-check' color='positive' :label='t(`common.actions.saveChanges`)' :disabled='!editorStore.hasPendingChanges' no-caps @click.exact='saveChanges(false)' @click.ctrl.exact='saveChanges(true)')
q-separator(vertical dark)
q-btn.acrylic-btn(flat icon='las la-check-double' color='positive' :disabled='!editorStore.hasPendingChanges' @click='saveChanges(true)')
q-btn.acrylic-btn.q-ml-sm(v-else flat icon='las la-check' color='positive' :label='t(`editor.createPage`)' no-caps @click='createPage')
</template>
<script setup>
@ -202,74 +39,34 @@ import { usePageStore } from '@/stores/page'
import { useSiteStore } from '@/stores/site'
import { useUserStore } from '@/stores/user'
import IconPickerDialog from '@/components/IconPickerDialog.vue'
import SocialSharingMenu from '@/components/SocialSharingMenu.vue'
// QUASAR
const $q = useQuasar()
// STORES
const editorStore = useEditorStore()
const flagsStore = useFlagsStore()
const pageStore = usePageStore()
const siteStore = useSiteStore()
const userStore = useUserStore()
// ROUTER
const router = useRouter()
const route = useRoute()
// I18N
const { t } = useI18n()
// METHODS
function openEditorSettings () {
EVENT_BUS.emit('openEditorSettings')
}
function openEditorSettings () { EVENT_BUS.emit('openEditorSettings') }
async function discardChanges () {
// From create mode
if (editorStore.mode === 'create') {
editorStore.$patch({
isActive: false,
editor: ''
})
// Is it the home page in create mode?
editorStore.$patch({ isActive: false, editor: '' })
if ((pageStore.path === '' || pageStore.path === 'home') && pageStore.locale === 'en') {
siteStore.overlay = 'Welcome'
}
router.replace('/')
return
}
const hadPendingChanges = editorStore.hasPendingChanges
$q.loading.show()
try {
editorStore.$patch({
isActive: false,
editor: ''
})
editorStore.$patch({ isActive: false, editor: '' })
await pageStore.cancelPageEdit()
if (hadPendingChanges) {
$q.notify({
type: 'positive',
message: 'Page has been reverted to the last saved state.'
})
}
} catch (err) {
$q.notify({
type: 'negative',
message: 'Failed to reload page state.'
})
}
if (hadPendingChanges) { $q.notify({ type: 'positive', message: 'Page reverted.' }) }
} catch (err) { $q.notify({ type: 'negative', message: 'Failed to reload.' }) }
$q.loading.hide()
}
@ -277,133 +74,76 @@ async function saveChanges (closeAfter = false) {
if (siteStore.features.reasonForChange !== 'off') {
$q.dialog({
component: defineAsyncComponent(() => import('../components/PageReasonForChangeDialog.vue')),
componentProps: {
required: siteStore.features.reasonForChange === 'required'
}
componentProps: { required: siteStore.features.reasonForChange === 'required' }
}).onOk(async ({ reason }) => {
editorStore.$patch({
reasonForChange: reason
})
editorStore.$patch({ reasonForChange: reason })
saveChangesCommit(closeAfter)
})
} else {
saveChangesCommit(closeAfter)
}
} else { saveChangesCommit(closeAfter) }
}
async function saveChangesCommit (closeAfter = false) {
await processPendingAssets()
$q.loading.show()
try {
await pageStore.pageSave()
$q.notify({
type: 'positive',
message: 'Page saved successfully.'
})
if (closeAfter) {
editorStore.$patch({
isActive: false,
editor: ''
})
}
} catch (err) {
$q.notify({
type: 'negative',
message: 'Failed to save page changes.',
caption: err.message
})
}
$q.notify({ type: 'positive', message: 'Page saved.' })
if (closeAfter) { editorStore.$patch({ isActive: false, editor: '' }) }
} catch (err) { $q.notify({ type: 'negative', message: 'Save failed.', caption: err.message }) }
$q.loading.hide()
}
async function createPage () {
// Handle home page creation flow
if (pageStore.path === 'home') {
await processPendingAssets()
$q.loading.show()
try {
await pageStore.pageSave()
$q.notify({
type: 'positive',
message: 'Homepage created successfully.'
})
editorStore.$patch({
isActive: false
})
$q.notify({ type: 'positive', message: 'Homepage created.' })
editorStore.$patch({ isActive: false })
router.replace('/')
} catch (err) {
$q.notify({
type: 'negative',
message: 'Failed to create homepage.',
caption: err.message
})
}
} catch (err) { $q.notify({ type: 'negative', message: 'Failed.', caption: err.message }) }
$q.loading.hide()
return
}
// All other pages
$q.dialog({
component: defineAsyncComponent(() => import('../components/TreeBrowserDialog.vue')),
componentProps: {
mode: 'savePage',
folderPath: '',
itemTitle: pageStore.title,
itemFileName: pageStore.path
}
componentProps: { mode: 'savePage', folderPath: '', itemTitle: pageStore.title, itemFileName: pageStore.path }
}).onOk(async ({ path, title }) => {
await processPendingAssets()
$q.loading.show()
try {
pageStore.$patch({
title,
path
})
pageStore.$patch({ title, path })
await pageStore.pageSave()
$q.notify({
type: 'positive',
message: 'Page created successfully.'
})
editorStore.$patch({
isActive: false
})
} catch (err) {
$q.notify({
type: 'negative',
message: 'Failed to create page.',
caption: err.message
})
}
$q.notify({ type: 'positive', message: 'Page created.' })
editorStore.$patch({ isActive: false })
} catch (err) { $q.notify({ type: 'negative', message: 'Failed.', caption: err.message }) }
$q.loading.hide()
})
}
async function processPendingAssets () {
if (editorStore.pendingAssets?.length > 0) {
return new Promise((resolve, reject) => {
$q.dialog({
component: defineAsyncComponent(() => import('../components/UploadPendingAssetsDialog.vue')),
persistent: true
}).onOk(resolve).onCancel(reject)
})
}
}
function printPage () { window.print() }
</script>
async function editPage () {
$q.loading.show()
await pageStore.pageEdit()
$q.loading.hide()
<style lang="scss">
.page-header-clean {
padding: 32px 32px 0;
max-width: 860px;
margin: 0 auto;
width: 100%;
}
function printPage () {
window.print()
.page-header-title {
font-size: 2rem;
font-weight: 700;
color: #0F172A;
letter-spacing: -0.5px;
margin: 0 !important;
border: none !important;
padding: 0 !important;
}
function notImplemented () {
$q.notify({
type: 'negative',
message: 'Not implemented'
})
.page-header-desc {
font-size: 0.95rem;
color: #64748B;
margin: 4px 0 0 !important;
line-height: 1.5;
}
</script>
</style>

@ -3,9 +3,9 @@
.welcome-bg
.welcome-content
.welcome-logo
img(src='/_assets/logo-wikijs.svg')
.welcome-title {{ t('welcome.title') }}
.welcome-subtitle {{ t('welcome.subtitle') }}
img(src='/_assets/cultbr.svg')
.welcome-title CultBR Wiki
.welcome-subtitle Plataforma de Gestão Cultural Base de Conhecimento
.welcome-actions
q-btn(
push

@ -1,34 +1,22 @@
// Quasar SCSS (& Sass) Variables
// --------------------------------------------------
// To customize the look and feel of this app, you can override
// the Sass/SCSS variables found in Quasar's source Sass/SCSS files.
// CultBR Design System - Quasar Theme Override
// Check documentation for full list of Quasar variables
$primary : #006FEE;
$secondary : #39DDA2;
$accent : #FFCF00;
// Your own variables (that are declared here) and Quasar's own
// ones will be available out of the box in your .vue/.scss/.sass files
$dark : #19191C;
// It's highly recommended to change the default colors
// to match your app's branding.
// Tip: Use the "Theme Builder" on Quasar's documentation website.
$positive : #39DDA2;
$negative : #FF385C;
$info : #5BA7FF;
$warning : #FFD361;
$primary : #1976D2;
$secondary : #02C39A;
$accent : #f03a47;
$header : #19191C;
$sidebar: #19191C;
$dark : #0d1117;
$positive : #02C39A;
$negative : #f03a47;
$info : #3e6990;
$warning : #f99d4d;
$header : #000;
$sidebar: $primary;
$dark-6: #070a0d;
$dark-5: #0d1117;
$dark-4: #161b22;
$dark-3: #1e232a;
$dark-2: #292f39;
$dark-1: #343b48;
$dark-6: #0D0D0E;
$dark-5: #19191C;
$dark-4: #1A2744;
$dark-3: #2A3550;
$dark-2: #3A4560;
$dark-1: #4B5570;

@ -1,108 +1,16 @@
<template lang='pug'>
q-layout(view='hHh Lpr lff')
header-nav
q-drawer.bg-sidebar(
:model-value='isSidebarShown'
header-nav(@toggle-sidebar='sidebarOpen = !sidebarOpen')
q-drawer.docs-sidebar(
v-model='sidebarOpen'
:show-if-above='siteStore.theme.sidebarPosition !== `off`'
:width='isSidebarMini ? 56 : 255'
:width='260'
:side='siteStore.theme.sidebarPosition === `right` ? `right` : `left`'
bordered
:breakpoint='1024'
)
.sidebar-mini.column.items-stretch(v-if='isSidebarMini')
q-btn.q-py-md(
flat
icon='las la-globe'
color='white'
aria-label='Switch Locale'
)
locale-selector-menu(anchor='top right' self='top left')
q-tooltip(anchor='center right' self='center left') Switch Locale
q-btn.q-py-md(
flat
icon='las la-sitemap'
color='white'
aria-label='Browse'
@click='notImplemented'
)
q-tooltip(anchor='center right' self='center left') Browse
q-separator.q-my-sm(inset, dark)
q-btn.q-py-md(
flat
icon='las la-bookmark'
color='white'
aria-label='Bookmarks'
@click='notImplemented'
)
q-tooltip(anchor='center right' self='center left') Bookmarks
q-space
q-btn.q-py-xs(
flat
icon='las la-dharmachakra'
color='white'
aria-label='Edit Nav'
size='sm'
)
q-menu(
ref='navEditMenuMini'
anchor='top right'
self='bottom left'
)
nav-edit-menu(
:menu-hide-handler='navEditMenuMini.hide'
:update-position-handler='navEditMenuMini.updatePosition'
)
q-tooltip(anchor='center right' self='center left') Edit Nav
template(v-else)
.sidebar-actions.flex.items-stretch
q-btn.q-px-sm.col(
flat
dense
icon='las la-globe'
color='blue-7'
text-color='custom-color'
:label='commonStore.locale'
:aria-label='commonStore.locale'
size='sm'
)
locale-selector-menu(:offset='[-5, 5]')
q-separator(vertical)
q-btn.q-px-sm.col(
flat
dense
icon='las la-sitemap'
color='blue-7'
text-color='custom-color'
label='Browse'
aria-label='Browse'
size='sm'
@click='notImplemented'
)
.docs-sidebar-content
nav-sidebar
q-bar.sidebar-footerbtns.text-white(
v-if='userStore.authenticated'
dense
)
q-btn.col(
icon='las la-dharmachakra'
label='Edit Nav'
flat
)
q-menu(
ref='navEditMenu'
anchor='top left'
self='bottom left'
:offset='[0, 10]'
)
nav-edit-menu(
:menu-hide-handler='navEditMenu.hide'
:update-position-handler='navEditMenu.updatePosition'
)
q-separator(vertical)
q-btn.col(
icon='las la-bookmark'
label='Bookmarks'
flat
@click='notImplemented'
)
q-page-container
router-view
q-page-scroller(
@ -114,10 +22,9 @@ q-layout(view='hHh Lpr lff')
icon='las la-arrow-up'
color='primary'
round
size='md'
size='sm'
)
main-overlay-dialog
footer-nav(v-if='!editorStore.isActive')
</template>
<script setup>
@ -133,86 +40,107 @@ import { usePageStore } from '@/stores/page'
import { useSiteStore } from '@/stores/site'
import { useUserStore } from '@/stores/user'
// COMPONENTS
import FooterNav from '@/components/FooterNav.vue'
import HeaderNav from '@/components/HeaderNav.vue'
import LocaleSelectorMenu from '@/components/LocaleSelectorMenu.vue'
import NavSidebar from '@/components/NavSidebar.vue'
import NavEditMenu from '@/components/NavEditMenu.vue'
import MainOverlayDialog from '@/components/MainOverlayDialog.vue'
// QUASAR
const $q = useQuasar()
// STORES
const commonStore = useCommonStore()
const editorStore = useEditorStore()
const flagsStore = useFlagsStore()
const pageStore = usePageStore()
const siteStore = useSiteStore()
const userStore = useUserStore()
// ROUTER
const router = useRouter()
const route = useRoute()
// I18N
const { t } = useI18n()
// META
useMeta({
titleTemplate: title => `${title} - ${siteStore.title}`
})
// REFS
const sidebarOpen = ref(true)
const navEditMenu = ref(null)
const navEditMenuMini = ref(null)
function notImplemented () {
$q.notify({ type: 'negative', message: 'Not implemented' })
}
</script>
// COMPUTED
<style lang="scss">
.docs-sidebar {
background: white !important;
border-right: 1px solid #E2E8F0 !important;
const isSidebarShown = computed(() => {
return siteStore.showSideNav && !siteStore.sideNavIsDisabled && !(editorStore.isActive && editorStore.hideSideNav)
})
@at-root .body--dark & {
background: $dark-5 !important;
border-right-color: $dark-3 !important;
}
const isSidebarMini = computed(() => {
return ['hide', 'hideExact'].includes(pageStore.navigationMode) || !pageStore.navigationId
})
&-content {
height: 100%;
overflow-y: auto;
padding: 12px 0;
}
// METHODS
.q-item {
border-radius: 6px;
margin: 1px 8px;
padding: 6px 12px;
min-height: 34px;
font-size: 0.875rem;
color: #4B4B53;
transition: all 0.15s;
&:hover {
background: #F4F7FA;
color: #19191C;
}
function notImplemented () {
$q.notify({
type: 'negative',
message: 'Not implemented'
})
}
&--active, &.router-link-active {
background: #E6F1FE !important;
color: #006FEE !important;
font-weight: 600;
}
</script>
.q-item__label {
font-size: 0.875rem;
line-height: 1.3;
}
<style lang="scss">
.sidebar-actions {
background: linear-gradient(to bottom, rgba(255,255,255,.1) 0%, rgba(0,0,0, .05) 100%);
border-bottom: 1px solid rgba(0,0,0,.2);
height: 38px;
@at-root .body--dark & {
color: #9CA3AF;
&:hover { background: $dark-4; color: #E2E8F0; }
&--active, &.router-link-active {
background: rgba(0,111,238,0.15) !important;
color: #5BA7FF !important;
}
}
}
.q-btn {
color: rgba(255,255,255,.8);
.q-expansion-item {
.q-item {
font-weight: 500;
}
}
}
.sidebar-mini {
height: 100%;
// Remove footer
.q-footer { display: none !important; }
// Clean page container
.q-page-container {
background: #FAFBFC;
@at-root .body--dark & {
background: $dark-6;
}
}
.sidebar-footerbtns {
background-color: rgba(255,255,255,.1);
// Content styling
.page-contents, .contents {
max-width: 860px;
margin: 0 auto;
padding: 32px 24px;
}
body.body--dark {
@ -226,15 +154,10 @@ body.body--dark {
}
> .q-dialog__inner {
padding: 24px 64px;
@media (max-width: $breakpoint-sm-max) {
padding: 0;
}
@media (max-width: $breakpoint-sm-max) { padding: 0; }
> .q-layout-container {
border-radius: 6px;
box-shadow: 0 0 30px 0 rgba(0,0,0,.3);
@at-root .body--light & {
background-image: linear-gradient(to bottom, $dark-5 10px, $grey-3 11px, $grey-4);
}
@ -245,31 +168,10 @@ body.body--dark {
}
}
.q-footer {
.q-bar {
@at-root .body--light & {
background-color: $grey-3;
color: $grey-7;
}
@at-root .body--dark & {
background-color: $dark-4;
color: rgba(255,255,255,.3);
}
}
}
.syncing-enter-active {
animation: syncing-anim .1s;
}
.syncing-leave-active {
animation: syncing-anim 1s reverse;
}
.syncing-enter-active { animation: syncing-anim .1s; }
.syncing-leave-active { animation: syncing-anim 1s reverse; }
@keyframes syncing-anim {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
0% { opacity: 0; }
100% { opacity: 1; }
}
</style>

@ -1,158 +1,27 @@
<template lang='pug'>
q-page.column
.page-breadcrumbs.q-py-sm.q-px-md.row(
v-if='!editorStore.isActive'
)
.col
q-breadcrumbs(
active-color='grey-7'
separator-color='grey'
)
template(v-slot:separator)
q-icon(
name='las la-angle-right'
)
q-breadcrumbs-el(icon='las la-home', to='/', aria-label='Home')
q-tooltip Home
q-breadcrumbs-el(
v-for='brd of pageStore.breadcrumbs'
:key='brd.id'
:icon='brd.icon'
:label='brd.title'
:aria-label='brd.title'
:to='brd.path'
)
.col-auto.flex.items-center.justify-end
template(v-if='!pageStore.publishState === `draft`')
.text-caption.text-accent: strong Unpublished
q-separator.q-mx-sm(vertical)
.text-caption.text-grey-6 Last modified on #[strong {{lastModified}}]
page-header
.page-container.row.no-wrap.items-stretch(style='flex: 1 1 100%;')
.col(
:style='siteStore.theme.tocPosition === `left` ? `order: 2;` : `order: 1;`'
)
q-no-ssr(
v-if='editorStore.isActive'
)
.col
q-no-ssr(v-if='editorStore.isActive')
component(:is='editorComponents[editorStore.editor]')
q-scroll-area.page-container-scrl(
v-else
:thumb-style='thumbStyle'
:bar-style='barStyle'
style='height: 100%;'
)
.q-pa-md
.page-contents(ref='pageContents', v-html='pageStore.render')
template(v-if='pageStore.relations && pageStore.relations.length > 0')
q-separator.q-my-lg
.row.align-center
.col.text-left(v-if='relationsLeft.length > 0')
q-btn.q-mr-sm.q-mb-sm(
padding='sm md'
outline
:icon='rel.icon'
no-caps
color='primary'
v-for='rel of relationsLeft'
:key='`rel-id-` + rel.id'
)
.column.text-left.q-pl-md
.text-body2: strong {{rel.label}}
.text-caption {{rel.caption}}
.col.text-center(v-if='relationsCenter.length > 0')
.column
q-btn(
:label='rel.label'
color='primary'
flat
no-caps
:icon='rel.icon'
v-for='rel of relationsCenter'
:key='`rel-id-` + rel.id'
)
.col.text-right(v-if='relationsRight.length > 0')
q-btn.q-ml-sm.q-mb-sm(
padding='sm md'
outline
:icon-right='rel.icon'
no-caps
color='primary'
v-for='rel of relationsRight'
:key='`rel-id-` + rel.id'
)
.column.text-left.q-pr-md
.text-body2: strong {{rel.label}}
.text-caption {{rel.caption}}
.page-sidebar(
v-if='showSidebar'
:style='siteStore.theme.tocPosition === `left` ? `order: 1;` : `order: 2;`'
)
template(v-if='pageStore.showToc')
//- TOC
.q-pa-md.flex.items-center
q-icon.q-mr-sm(name='las la-stream', color='grey')
.text-caption.text-grey-7 Contents
.q-px-md.q-pb-sm
q-tree.page-toc(
:nodes='pageStore.toc'
icon='las la-caret-right'
node-key='key'
dense
v-model:expanded='state.tocExpanded'
v-model:selected='state.tocSelected'
)
//- Tags
template(v-if='pageStore.showTags')
q-separator(v-if='pageStore.showToc')
.q-pa-md(
@mouseover='state.showTagsEditBtn = true'
@mouseleave='state.showTagsEditBtn = false'
)
.flex.items-center
q-icon.q-mr-sm(name='las la-tags', color='grey')
.text-caption.text-grey-7 Tags
q-space
transition(name='fade')
q-btn(
v-show='state.showTagsEditBtn'
size='sm'
padding='none xs'
icon='las la-pen'
color='deep-orange-9'
flat
label='Edit'
no-caps
@click='state.tagEditMode = !state.tagEditMode'
.page-content-wrap(v-else)
.page-contents(ref='pageContents', v-html='pageStore.render')
template(v-if='pageStore.relations && pageStore.relations.length > 0')
.page-relations
q-btn.q-mr-sm.q-mb-sm(
v-for='rel of pageStore.relations'
:key='`rel-` + rel.id'
padding='sm md'
outline
:icon='rel.icon'
:label='rel.label'
no-caps
color='primary'
size='sm'
)
page-tags.q-mt-sm(:edit='state.tagEditMode')
template(v-if='siteStore.features.ratingsMode !== `off` && pageStore.allowRatings')
q-separator(v-if='pageStore.showToc || pageStore.showTags')
//- Rating
.q-pa-md.flex.items-center
q-icon.q-mr-sm(name='las la-star-half-alt', color='grey')
.text-caption.text-grey-7 Rate this page
.q-px-md
q-rating(
v-if='siteStore.features.ratingsMode === `stars`'
v-model='state.currentRating'
icon='las la-star'
color='secondary'
size='sm'
)
.flex.items-center(v-else-if='siteStore.features.ratingsMode === `thumbs`')
q-btn.acrylic-btn(
flat
icon='las la-thumbs-down'
color='secondary'
)
q-btn.acrylic-btn.q-ml-sm(
flat
icon='las la-thumbs-up'
color='secondary'
)
page-actions-col
//- Edit actions (only in editor mode)
page-actions-col(v-if='editorStore.isActive')
side-dialog
</template>
@ -170,12 +39,9 @@ import { usePageStore } from '@/stores/page'
import { useSiteStore } from '@/stores/site'
import { useUserStore } from '@/stores/user'
// COMPONENTS
import LoadingGeneric from '@/components/LoadingGeneric.vue'
import PageActionsCol from '@/components/PageActionsCol.vue'
import PageHeader from '@/components/PageHeader.vue'
import PageTags from '@/components/PageTags.vue'
import SideDialog from '@/components/SideDialog.vue'
const editorComponents = {
@ -189,137 +55,59 @@ const editorComponents = {
})
}
// QUASAR
const $q = useQuasar()
// STORES
const commonStore = useCommonStore()
const editorStore = useEditorStore()
const flagsStore = useFlagsStore()
const pageStore = usePageStore()
const siteStore = useSiteStore()
const userStore = useUserStore()
// ROUTER
const router = useRouter()
const route = useRoute()
// I18N
const { t } = useI18n()
// META
useMeta({
title: pageStore.title
})
// DATA
const state = reactive({
showSideDialog: false,
sideDialogComponent: null,
showGlobalDialog: false,
globalDialogComponent: null,
showTagsEditBtn: false,
tagEditMode: false,
tocExpanded: ['h1-0', 'h1-1'],
tocSelected: [],
currentRating: 3
})
const thumbStyle = {
right: '2px',
borderRadius: '5px',
backgroundColor: $q.dark.isActive ? '#FFF' : '#000',
width: '5px',
opacity: 0.15
}
const barStyle = {
backgroundColor: $q.dark.isActive ? '#161b22' : '#FAFAFA',
width: '9px',
opacity: 1
}
useMeta({ title: pageStore.title })
const pageContents = ref(null)
// COMPUTED
const showSidebar = computed(() => {
return pageStore.showSidebar && siteStore.showSidebar && siteStore.theme.tocPosition !== 'off' && !editorStore.isActive
})
const relationsLeft = computed(() => {
return pageStore.relations ? pageStore.relations.filter(r => r.position === 'left') : []
})
const relationsCenter = computed(() => {
return pageStore.relations ? pageStore.relations.filter(r => r.position === 'center') : []
})
const relationsRight = computed(() => {
return pageStore.relations ? pageStore.relations.filter(r => r.position === 'right') : []
})
const lastModified = computed(() => {
return pageStore.updatedAt ? DateTime.fromISO(pageStore.updatedAt).toLocaleString(DateTime.DATETIME_MED) : 'N/A'
})
// WATCHERS
watch(() => route.path, async (newValue) => {
// -> Ignore route change (e.g. from page create route fix)
if (editorStore.ignoreRouteChange) {
editorStore.$patch({ ignoreRouteChange: false })
return
}
// -> Enter Create Mode?
if (newValue.startsWith('/_create')) {
if (!route.params.editor) {
$q.notify({
type: 'negative',
message: 'No editor specified!'
})
$q.notify({ type: 'negative', message: 'No editor specified!' })
return router.replace('/')
}
$q.loading.show()
const pageCreateArgs = { editor: route.params.editor, fromNavigate: true }
if (route.query.path) {
pageCreateArgs.path = route.query.path
}
if (route.query.locale) {
pageCreateArgs.locale = route.query.locale
}
if (route.query.path) { pageCreateArgs.path = route.query.path }
if (route.query.locale) { pageCreateArgs.locale = route.query.locale }
await pageStore.pageCreate(pageCreateArgs)
$q.loading.hide()
return
}
// -> Enter Edit Mode?
if (newValue.startsWith('/_edit')) {
if (!route.params.pagePath) {
return router.replace('/')
}
if (!route.params.pagePath) { return router.replace('/') }
$q.loading.show()
await pageStore.pageEdit({ path: route.params.pagePath, fromNavigate: true })
$q.loading.hide()
return
}
// -> Moving to a non-page path? Ignore
if (newValue.startsWith('/_')) { return }
// -> Load Page
try {
await pageStore.pageLoad({ path: newValue })
if (editorStore.isActive) {
editorStore.$patch({
isActive: false
})
}
// -> Load Blocks
if (editorStore.isActive) { editorStore.$patch({ isActive: false }) }
nextTick(() => {
for (const block of pageContents.value.querySelectorAll(':not(:defined)')) {
commonStore.loadBlocks([block.tagName.toLowerCase()])
if (pageContents.value) {
for (const block of pageContents.value.querySelectorAll(':not(:defined)')) {
commonStore.loadBlocks([block.tagName.toLowerCase()])
}
}
})
} catch (err) {
@ -333,167 +121,39 @@ watch(() => route.path, async (newValue) => {
siteStore.overlay = 'Welcome'
}
} else {
$q.notify({
type: 'negative',
message: 'This page does not exist (yet)!'
})
$q.notify({ type: 'negative', message: 'This page does not exist (yet)!' })
}
} else {
$q.notify({
type: 'negative',
message: err.message
})
$q.notify({ type: 'negative', message: err.message })
}
}
}, { immediate: true })
watch(() => pageStore.toc, () => { refreshTocExpanded() }, { immediate: true })
watch(() => pageStore.tocDepth, () => { refreshTocExpanded() })
// METHODS
function refreshTocExpanded (baseToc, lvl) {
const toExpand = []
let isRootNode = false
if (!baseToc) {
baseToc = pageStore.toc
isRootNode = true
lvl = 1
}
if (baseToc.length > 0) {
for (const node of baseToc) {
if (lvl >= pageStore.tocDepth.min && lvl < pageStore.tocDepth.max) {
toExpand.push(node.key)
}
if (node.children?.length && lvl < pageStore.tocDepth.max - 1) {
toExpand.push(...refreshTocExpanded(node.children, lvl + 1))
}
}
}
if (isRootNode) {
state.tocExpanded = toExpand
} else {
return toExpand
}
}
</script>
<style lang="scss">
.page-breadcrumbs {
@at-root .body--light & {
background: linear-gradient(to bottom, $grey-1 0%, $grey-3 100%);
border-bottom: 1px solid $grey-4;
}
@at-root .body--dark & {
background: linear-gradient(to bottom, $dark-3 0%, $dark-4 100%);
border-bottom: 1px solid $dark-3;
}
}
.page-header {
height: 95px;
@at-root .body--light & {
background: linear-gradient(to bottom, $grey-2 0%, $grey-1 100%);
border-bottom: 1px solid $grey-4;
border-top: 1px solid #FFF;
}
@at-root .body--dark & {
background: linear-gradient(to bottom, $dark-4 0%, $dark-3 100%);
// border-bottom: 1px solid $dark-5;
border-top: 1px solid $dark-6;
}
.no-height .q-field__control {
height: auto;
}
&-title {
@at-root .body--light & {
color: $grey-9;
}
@at-root .body--dark & {
color: #FFF;
}
}
&-subtitle {
@at-root .body--light & {
color: $grey-7;
}
@at-root .body--dark & {
color: rgba(255,255,255,.6);
}
}
}
.page-container {
@at-root .body--light & {
border-top: 1px solid #FFF;
}
// @at-root .body--dark & {
// border-top: 1px solid $dark-6;
// }
.page-content-wrap {
max-width: 860px;
margin: 0 auto;
padding: 0 32px 48px;
width: 100%;
.page-container-scrl > .q-scrollarea__container > .q-scrollarea__content {
width: 100%;
}
}
.page-sidebar {
flex: 0 0 300px;
@at-root .body--light & {
background-color: $grey-2;
}
@at-root .body--dark & {
background-color: $dark-5;
}
.q-separator {
background-color: rgba(0,0,0,.05);
border-bottom: 1px solid;
@at-root .body--light & {
background-color: rgba(0,0,0,.05);
border-bottom-color: #FFF;
}
@at-root .body--dark & {
background-color: rgba(255,255,255,.04);
border-bottom-color: #070a0d;
}
}
.page-relations {
margin-top: 32px;
padding-top: 24px;
border-top: 1px solid #E2E8F0;
}
.floating-syncpanel {
.q-dialog__inner {
margin-top: 14px;
right: 140px;
left: auto;
.q-card {
border-radius: 17px;
}
}
&-msg {
padding-top: 1px;
font-weight: 500;
font-size: .75rem;
padding-right: 16px;
display: flex;
align-items: center;
}
.page-container {
border-top: none;
}
.q-card {
@at-root .body--light & {
background-color: #FFF;
}
@at-root .body--dark & {
background-color: $dark-3;
}
}
.page-toc {
&.q-tree--dense .q-tree__node {
padding-bottom: 5px;
}
@at-root .body--light & { background-color: #FFF; }
@at-root .body--dark & { background-color: $dark-3; }
}
</style>

@ -3,11 +3,12 @@
.auth-content
.auth-logo
img(:src='`/_site/logo`' :alt='siteStore.title')
h2.auth-site-title(v-if='siteStore.logoText') {{ siteStore.title }}
p.text-grey-7 Login to continue
h2.auth-site-title CultBR Wiki
p.text-grey-7.auth-subtitle Plataforma de Gestão Cultural do Ministério da Cultura
auth-login-panel
.auth-footer
span.text-grey-5 Mantido por NEES/UFAL
.auth-bg(aria-hidden="true")
img(:src='`/_site/loginbg`' alt='')
</template>
<script setup>
@ -413,47 +414,57 @@ onMounted(() => {
<style lang="scss">
.auth {
background-color: #FFF;
background: linear-gradient(135deg, #19191C 0%, #1A2744 40%, #006FEE 100%);
display: flex;
@at-root .body--dark & {
background-color: $dark-6;
}
min-height: 100vh;
&-content {
flex: 1 0 100%;
width: 100%;
max-width: 500px;
padding: 3rem 4rem;
max-width: 460px;
padding: 3rem 3.5rem;
display: flex;
flex-direction: column;
justify-content: center;
align-items: stretch;
background: rgba(255,255,255,0.97);
backdrop-filter: blur(20px);
box-shadow: 20px 0 60px rgba(0,0,0,0.3);
@media (max-width: $breakpoint-xs-max) {
padding: 1rem 2rem;
padding: 2rem;
max-width: 100vw;
}
}
&-logo {
margin-bottom: 6px;
margin-bottom: 12px;
img {
height: 72px;
height: 56px;
}
}
&-site-title {
font-size: 1.875rem;
line-height: 2.25rem;
font-size: 1.6rem;
line-height: 2rem;
font-weight: 700;
margin: 0;
color: $blue-grey-9;
margin: 0 0 2px 0;
color: #19191C;
font-family: 'Poppins', sans-serif;
}
@at-root .body--dark & {
color: $blue-grey-1;
}
&-subtitle {
font-size: 0.85rem;
margin-bottom: 1.5rem;
}
&-footer {
margin-top: 2rem;
padding-top: 1.5rem;
border-top: 1px solid #ECECEC;
text-align: center;
font-size: 0.8rem;
}
&-strategies {
@ -468,18 +479,18 @@ onMounted(() => {
position: relative;
height: 100vh;
overflow: hidden;
display: flex;
align-items: center;
justify-content: center;
img {
position: relative;
width: 100%;
height: 100%;
object-fit: cover;
top: 0;
bottom: 0;
left: 0;
right: 0;
margin: 0;
padding: 0;
&::after {
content: 'CultBR';
font-family: 'Poppins', sans-serif;
font-size: 8rem;
font-weight: 800;
color: rgba(255,255,255,0.06);
position: absolute;
user-select: none;
}
}
}

Loading…
Cancel
Save