You've already forked AstralRinth
forked from didirus/AstralRinth
Make current code library + add docs
This commit is contained in:
142
lib/components/base/Button.vue
Normal file
142
lib/components/base/Button.vue
Normal file
@@ -0,0 +1,142 @@
|
||||
<script setup>
|
||||
import { IssuesIcon, ExternalIcon, UnknownIcon} from '@/components'
|
||||
|
||||
import { computed } from 'vue'
|
||||
|
||||
const props = defineProps({
|
||||
link: {
|
||||
type: String,
|
||||
default: null,
|
||||
},
|
||||
external: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
action: {
|
||||
type: Function,
|
||||
default: null,
|
||||
},
|
||||
design: {
|
||||
type: String,
|
||||
default: 'default',
|
||||
},
|
||||
color: {
|
||||
type: String,
|
||||
default: 'default',
|
||||
},
|
||||
iconOnly: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
}
|
||||
})
|
||||
|
||||
const defaultDesign = computed(() => props.design === 'default')
|
||||
const accentedButton = computed(
|
||||
() => defaultDesign.value && ['danger', 'primary'].includes(props.color)
|
||||
)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<!-- <nuxt-link-->
|
||||
<!-- v-if="link && link.startsWith('/')"-->
|
||||
<!-- class="omorphia__button button-base button-color-base padding-block-sm padding-inline-lg radius-sm"-->
|
||||
<!-- :class="{-->
|
||||
<!-- 'icon-only': props.iconOnly,-->
|
||||
<!-- 'bg-raised': raised,-->
|
||||
<!-- 'bg-red': danger,-->
|
||||
<!-- 'bg-brand': primary,-->
|
||||
<!-- 'color-accent-contrast': danger || primary,-->
|
||||
<!-- }"-->
|
||||
<!-- :to="link"-->
|
||||
<!-- :target="external ? '_blank' : '_self'"-->
|
||||
<!-- >-->
|
||||
<!-- <slot />-->
|
||||
<!-- <Icon v-if="external && !props.iconOnly" class="external-icon" icon="external" />-->
|
||||
<!-- <Icon v-if="!$slots.default" icon="unknown" />-->
|
||||
<!-- </nuxt-link>-->
|
||||
<a
|
||||
v-if="link"
|
||||
class="omorphia__button button-base padding-block-sm padding-inline-lg radius-sm"
|
||||
:class="{
|
||||
'standard-button': defaultDesign,
|
||||
'icon-only': props.iconOnly,
|
||||
'bg-raised': defaultDesign && color === 'raised',
|
||||
'bg-red': defaultDesign && color === 'danger',
|
||||
'bg-brand': defaultDesign && color === 'primary',
|
||||
'color-accent-contrast': accentedButton,
|
||||
}"
|
||||
:href="link"
|
||||
:target="external ? '_blank' : '_self'"
|
||||
>
|
||||
<slot />
|
||||
<ExternalIcon v-if="external && !iconOnly" class="external-icon" />
|
||||
<UnknownIcon v-if="!$slots.default" />
|
||||
</a>
|
||||
<button
|
||||
v-else-if="action"
|
||||
class="omorphia__button button-base padding-block-sm padding-inline-lg radius-sm"
|
||||
:class="{
|
||||
'standard-button': defaultDesign,
|
||||
'icon-only': props.iconOnly,
|
||||
'bg-raised': defaultDesign && color === 'raised',
|
||||
'bg-red': defaultDesign && color === 'danger',
|
||||
'bg-brand': defaultDesign && color === 'primary',
|
||||
'color-accent-contrast': accentedButton,
|
||||
}"
|
||||
@click="action"
|
||||
>
|
||||
<slot />
|
||||
<UnknownIcon v-if="!$slots.default" />
|
||||
</button>
|
||||
<div
|
||||
v-else
|
||||
class="omorphia__button button-base button-color-base padding-block-sm padding-inline-lg radius-sm bg-red color-accent-contrast"
|
||||
>
|
||||
<IssuesIcon />
|
||||
Missing link or action!
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
:where(button) {
|
||||
background: none;
|
||||
color: var(--color-base);
|
||||
}
|
||||
|
||||
.omorphia__button {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
width: fit-content;
|
||||
height: fit-content;
|
||||
text-decoration: none;
|
||||
|
||||
:deep(svg) {
|
||||
width: 1.1rem;
|
||||
height: 1.1rem;
|
||||
margin-right: 0.5rem;
|
||||
}
|
||||
|
||||
:deep(.external-icon) {
|
||||
width: 0.75rem;
|
||||
height: 0.75rem;
|
||||
margin-bottom: auto;
|
||||
margin-left: 0.25rem;
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
&.icon-only {
|
||||
padding: 0;
|
||||
height: 2.25rem;
|
||||
width: 2.25rem;
|
||||
|
||||
:deep(svg) {
|
||||
min-width: 1.25rem;
|
||||
max-width: 1.25rem;
|
||||
min-height: 1.25rem;
|
||||
max-height: 1.25rem;
|
||||
margin: auto;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
62
lib/components/base/Card.vue
Normal file
62
lib/components/base/Card.vue
Normal file
@@ -0,0 +1,62 @@
|
||||
<script setup>
|
||||
import { Button, DropdownIcon } from '@/components'
|
||||
|
||||
import { reactive } from 'vue'
|
||||
|
||||
const props = defineProps({
|
||||
collapsible: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
defaultCollapsed: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
noAutoBody: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
})
|
||||
|
||||
const state = reactive({
|
||||
collapsed: props.defaultCollapsed,
|
||||
})
|
||||
|
||||
function toggleCollapsed() {
|
||||
state.collapsed = !state.collapsed
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div
|
||||
class="omorphia__card standard-body padding-xl bg-raised radius-lg margin-bottom-md"
|
||||
:class="{ 'auto-body': !noAutoBody }"
|
||||
>
|
||||
<div v-if="!!$slots.header || collapsible" class="header">
|
||||
<slot name="header"></slot>
|
||||
<div v-if="collapsible" class="button-group margin-left-auto margin-right-0">
|
||||
<Button :action="toggleCollapsed">
|
||||
<DropdownIcon :style="{ transform: `rotate(${state.collapsed ? 0 : 180}deg)` }" />
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
<slot v-if="!state.collapsed" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.omorphia__card {
|
||||
}
|
||||
|
||||
.header {
|
||||
display: flex;
|
||||
|
||||
:deep(h1, h2, h3, h4) {
|
||||
margin-block: 0;
|
||||
}
|
||||
|
||||
&:not(:last-child) {
|
||||
margin-bottom: var(--gap-lg);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
121
lib/components/base/Page.vue
Normal file
121
lib/components/base/Page.vue
Normal file
@@ -0,0 +1,121 @@
|
||||
<script setup>
|
||||
defineProps({
|
||||
collapsible: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
rightSidebar: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div
|
||||
class="omorphia__page"
|
||||
:class="{
|
||||
'right-sidebar': rightSidebar,
|
||||
'has-sidebar': !!$slots.sidebar,
|
||||
'has-header': !!$slots.header,
|
||||
'has-footer': !!$slots.footer,
|
||||
}"
|
||||
>
|
||||
<div v-if="!!$slots.header" class="header">
|
||||
<slot name="header" />
|
||||
</div>
|
||||
<div v-if="!!$slots.sidebar" class="sidebar">
|
||||
<slot name="sidebar" />
|
||||
</div>
|
||||
<div class="content">
|
||||
<slot />
|
||||
</div>
|
||||
<div v-if="!!$slots.footer" class="footer">
|
||||
<slot name="footer" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.omorphia__page {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 0 0.75rem;
|
||||
|
||||
.header {
|
||||
grid-area: header;
|
||||
}
|
||||
|
||||
.sidebar {
|
||||
grid-area: sidebar;
|
||||
}
|
||||
|
||||
.footer {
|
||||
grid-area: footer;
|
||||
}
|
||||
|
||||
.content {
|
||||
grid-area: content;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 1024px) {
|
||||
.omorphia__page {
|
||||
margin: 0 auto;
|
||||
max-width: 80rem;
|
||||
column-gap: 0.75rem;
|
||||
|
||||
&.has-sidebar {
|
||||
display: grid;
|
||||
grid-template:
|
||||
'sidebar content' auto
|
||||
'footer content' auto
|
||||
'dummy content' 1fr
|
||||
/ 20rem 1fr;
|
||||
|
||||
&.has-header {
|
||||
grid-template:
|
||||
'header header' auto
|
||||
'sidebar content' auto
|
||||
'footer content' auto
|
||||
'dummy content' 1fr
|
||||
/ 20rem 1fr;
|
||||
}
|
||||
|
||||
&.right-sidebar {
|
||||
grid-template:
|
||||
'content sidebar' auto
|
||||
'content footer' auto
|
||||
'content dummy' 1fr
|
||||
/ 1fr 20rem;
|
||||
|
||||
&.has-header {
|
||||
grid-template:
|
||||
'header header' auto
|
||||
'content sidebar' auto
|
||||
'content footer' auto
|
||||
'content dummy' 1fr
|
||||
/ 1fr 20rem;
|
||||
}
|
||||
}
|
||||
|
||||
.content {
|
||||
max-width: calc(60rem - 0.75rem);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.sidebar {
|
||||
min-width: 20rem;
|
||||
width: 20rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 80rem) {
|
||||
.omorphia__page.has-sidebar {
|
||||
.content {
|
||||
width: calc(60rem - 0.75rem);
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
88
lib/components/index.js
Normal file
88
lib/components/index.js
Normal file
@@ -0,0 +1,88 @@
|
||||
export { default as Card } from './base/Card.vue'
|
||||
export { default as Page } from './base/Page.vue'
|
||||
export { default as Button } from './base/Button.vue'
|
||||
|
||||
export { default as NavItem } from './nav/NavItem.vue'
|
||||
export { default as NavRow } from './nav/NavRow.vue'
|
||||
export { default as NavStack } from './nav/NavStack.vue'
|
||||
|
||||
export { default as AlignLeftIcon } from '@/assets/icons/align-left.svg'
|
||||
export { default as ArchiveIcon } from '@/assets/icons/archive.svg'
|
||||
export { default as AsteriskIcon } from '@/assets/icons/asterisk.svg'
|
||||
export { default as BellIcon } from '@/assets/icons/bell.svg'
|
||||
export { default as BellRingIcon } from '@/assets/icons/bell-ring.svg'
|
||||
export { default as BookIcon } from '@/assets/icons/book.svg'
|
||||
export { default as BoxIcon } from '@/assets/icons/box.svg'
|
||||
export { default as CalendarIcon } from '@/assets/icons/calendar.svg'
|
||||
export { default as ChartIcon } from '@/assets/icons/chart.svg'
|
||||
export { default as CheckIcon } from '@/assets/icons/check.svg'
|
||||
export { default as CheckCircleIcon } from '@/assets/icons/check-circle.svg'
|
||||
export { default as ChevronLeftIcon } from '@/assets/icons/chevron-left.svg'
|
||||
export { default as ChevronRightIcon } from '@/assets/icons/chevron-right.svg'
|
||||
export { default as ClearIcon } from '@/assets/icons/clear.svg'
|
||||
export { default as ClientIcon } from '@/assets/icons/client.svg'
|
||||
export { default as ClipboardCopyIcon } from '@/assets/icons/clipboard-copy.svg'
|
||||
export { default as CoinsIcon } from '@/assets/icons/coins.svg'
|
||||
export { default as ContractIcon } from '@/assets/icons/contract.svg'
|
||||
export { default as copyrightIcon } from '@/assets/icons/copyright.svg'
|
||||
export { default as CurrencyIcon } from '@/assets/icons/currency.svg'
|
||||
export { default as DashboardIcon } from '@/assets/icons/dashboard.svg'
|
||||
export { default as DownloadIcon } from '@/assets/icons/download.svg'
|
||||
export { default as DropdownIcon } from '@/assets/icons/dropdown.svg'
|
||||
export { default as EditIcon } from '@/assets/icons/edit.svg'
|
||||
export { default as ExitIcon } from '@/assets/icons/exit.svg'
|
||||
export { default as ExpandIcon } from '@/assets/icons/expand.svg'
|
||||
export { default as ExternalIcon } from '@/assets/icons/external.svg'
|
||||
export { default as EyeIcon } from '@/assets/icons/eye.svg'
|
||||
export { default as EyeOffIcon } from '@/assets/icons/eye-off.svg'
|
||||
export { default as FileIcon } from '@/assets/icons/file.svg'
|
||||
export { default as FileTextIcon } from '@/assets/icons/file-text.svg'
|
||||
export { default as FilterIcon } from '@/assets/icons/filter.svg'
|
||||
export { default as GapIcon } from '@/assets/icons/gap.svg'
|
||||
export { default as GitHubIcon } from '@/assets/icons/github.svg'
|
||||
export { default as GlobeIcon } from '@/assets/icons/globe.svg'
|
||||
export { default as GridIcon } from '@/assets/icons/grid.svg'
|
||||
export { default as HamburgerIcon } from '@/assets/icons/hamburger.svg'
|
||||
export { default as HashIcon } from '@/assets/icons/hash.svg'
|
||||
export { default as HeartHandshakeIcon } from '@/assets/icons/heart-handshake.svg'
|
||||
export { default as ImageIcon } from '@/assets/icons/image.svg'
|
||||
export { default as InfoIcon } from '@/assets/icons/info.svg'
|
||||
export { default as IssuesIcon } from '@/assets/icons/issues.svg'
|
||||
export { default as LeftArrowIcon } from '@/assets/icons/left-arrow.svg'
|
||||
export { default as LightBulbIcon } from '@/assets/icons/light-bulb.svg'
|
||||
export { default as LinkIcon } from '@/assets/icons/link.svg'
|
||||
export { default as ListIcon } from '@/assets/icons/list.svg'
|
||||
export { default as LockIcon } from '@/assets/icons/lock.svg'
|
||||
export { default as LogOutIcon } from '@/assets/icons/log-out.svg'
|
||||
export { default as MoonIcon } from '@/assets/icons/moon.svg'
|
||||
export { default as OmorphiaIcon } from '@/assets/icons/omorphia.svg'
|
||||
export { default as PaintBrushIcon } from '@/assets/icons/paintbrush.svg'
|
||||
export { default as PlusIcon } from '@/assets/icons/plus.svg'
|
||||
export { default as ReportIcon } from '@/assets/icons/report.svg'
|
||||
export { default as RightArrowIcon } from '@/assets/icons/right-arrow.svg'
|
||||
export { default as SaveIcon } from '@/assets/icons/save.svg'
|
||||
export { default as SearchIcon } from '@/assets/icons/search.svg'
|
||||
export { default as SendIcon } from '@/assets/icons/send.svg'
|
||||
export { default as ServerIcon } from '@/assets/icons/server.svg'
|
||||
export { default as SettingsIcon } from '@/assets/icons/settings.svg'
|
||||
export { default as ShieldIcon } from '@/assets/icons/shield.svg'
|
||||
export { default as SlashIcon } from '@/assets/icons/slash.svg'
|
||||
export { default as StarIcon } from '@/assets/icons/star.svg'
|
||||
export { default as SunIcon } from '@/assets/icons/sun.svg'
|
||||
export { default as SunriseIcon } from '@/assets/icons/sunrise.svg'
|
||||
export { default as TagIcon } from '@/assets/icons/tag.svg'
|
||||
export { default as TagsIcon } from '@/assets/icons/tags.svg'
|
||||
export { default as TransferIcon } from '@/assets/icons/transfer.svg'
|
||||
export { default as TrashIcon } from '@/assets/icons/trash.svg'
|
||||
export { default as UndoIcon } from '@/assets/icons/undo.svg'
|
||||
export { default as UnknownIcon } from '@/assets/icons/unknown.svg'
|
||||
export { default as UnknownDonationIcon } from '@/assets/icons/unknown-donation.svg'
|
||||
export { default as UpdatedIcon } from '@/assets/icons/updated.svg'
|
||||
export { default as UploadIcon } from '@/assets/icons/upload.svg'
|
||||
export { default as UserIcon } from '@/assets/icons/user.svg'
|
||||
export { default as UserPlusIcon } from '@/assets/icons/user-plus.svg'
|
||||
export { default as UserXIcon } from '@/assets/icons/user-x.svg'
|
||||
export { default as UsersIcon } from '@/assets/icons/users.svg'
|
||||
export { default as VersionIcon } from '@/assets/icons/version.svg'
|
||||
export { default as WikiIcon } from '@/assets/icons/wiki.svg'
|
||||
export { default as XIcon } from '@/assets/icons/x.svg'
|
||||
50
lib/components/nav/NavItem.vue
Normal file
50
lib/components/nav/NavItem.vue
Normal file
@@ -0,0 +1,50 @@
|
||||
<script setup>
|
||||
import { Button } from '@/components'
|
||||
|
||||
defineProps({
|
||||
link: {
|
||||
type: String,
|
||||
default: null,
|
||||
},
|
||||
external: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
action: {
|
||||
type: Function,
|
||||
default: null,
|
||||
},
|
||||
selected: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
label: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
icon: {
|
||||
type: String,
|
||||
default: null,
|
||||
},
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Button
|
||||
:link="link"
|
||||
:external="external"
|
||||
:action="action"
|
||||
design="nav"
|
||||
class="quiet-disabled"
|
||||
:class="{
|
||||
selected: selected,
|
||||
}"
|
||||
:disabled="selected"
|
||||
:navlabel="label"
|
||||
>
|
||||
<slot />
|
||||
{{ label }}
|
||||
</Button>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
47
lib/components/nav/NavRow.vue
Normal file
47
lib/components/nav/NavRow.vue
Normal file
@@ -0,0 +1,47 @@
|
||||
<script setup>
|
||||
defineProps({})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="omorphia__navrow">
|
||||
<slot />
|
||||
<div class="margin-left-auto">
|
||||
<slot name="right" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.omorphia__navrow {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
|
||||
:deep(.omorphia__button) {
|
||||
position: relative;
|
||||
|
||||
&::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
width: calc(100% - var(--gap-lg) * 2);
|
||||
height: 4px;
|
||||
bottom: 4px;
|
||||
border-radius: var(--radius-max);
|
||||
background-color: var(--color-brand);
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
&:hover::after {
|
||||
opacity: 50%;
|
||||
}
|
||||
|
||||
&.selected {
|
||||
color: var(--color-contrast);
|
||||
font-weight: bold;
|
||||
|
||||
&::after {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
26
lib/components/nav/NavStack.vue
Normal file
26
lib/components/nav/NavStack.vue
Normal file
@@ -0,0 +1,26 @@
|
||||
<script setup>
|
||||
defineProps({})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="omorphia__navstack">
|
||||
<slot />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.omorphia__navstack {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
:deep(.omorphia__button) {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
|
||||
&.selected {
|
||||
background-color: var(--color-button-bg);
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user