Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 32 additions & 4 deletions .vitepress/config/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,39 @@ export const en = defineConfig({
nav: [
{ text: 'Home', link: '/en' },
{ text: 'Event', link: '/en/event' },
{ text: 'Participate', link: '/en/participate/attendee' },
{ text: 'About', link: '/en/about' },
],
sidebar: {},
socialLinks: [
{ icon: 'github', link: 'https://github.com/COSCUP' },
],
sidebar: {
'/en/participate': [
{
text: 'Participate',
link: '/en/participate/attendee',
items: [
{ text: 'As Attendee', link: '/en/participate/attendee' },
{ text: 'As Community', link: '/en/participate/community' },
{ text: 'As Speaker', link: '/en/participate/speaker' },
{ text: 'As Sponsor', link: '/en/participate/sponsor' },
{ text: 'As Organizing', link: '/en/participate/organizing' },
],
},
],
},
socialLinks: [{ icon: 'github', link: 'https://github.com/COSCUP' }],
docFooter: {
prev: 'Previous page',
next: 'Next Page',
},

outline: {
label: '導覽',
},

langMenuLabel: 'Other Languages',
returnToTopLabel: '回到頂部',
sidebarMenuLabel: 'Menu',
darkModeSwitchLabel: 'Theme',
lightModeSwitchTitle: 'Light Mode',
darkModeSwitchTitle: 'Dark Mode',
},
})
9 changes: 7 additions & 2 deletions .vitepress/config/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { resolve } from 'node:path'
// @ts-expect-error - No type definitions available
import markdownItContainer from 'markdown-it-container'
import { FileSystemIconLoader } from 'unplugin-icons/loaders'
import IconsResolver from 'unplugin-icons/resolver'
Expand Down Expand Up @@ -74,7 +73,13 @@ export default defineConfig({
['meta', { property: 'og:type', content: conference.type }],
['meta', { property: 'og:site_name', content: conference.site_name }],
['meta', { property: 'og:image', content: conference.og_image }],
['script', { async: '', src: 'https://www.googletagmanager.com/gtag/js?id=G-C9EMTMDSS1' }],
[
'script',
{
async: '',
src: 'https://www.googletagmanager.com/gtag/js?id=G-C9EMTMDSS1',
},
],
[
'script',
{},
Expand Down
2 changes: 2 additions & 0 deletions .vitepress/config/vitepress.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
declare module 'vitepress/dist/client/theme-default/components/VPPage.vue';
declare module 'vitepress/dist/client/theme-default/components/VPHome.vue';
22 changes: 17 additions & 5 deletions .vitepress/config/zh_tw.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,25 @@ export const zh_tw = defineConfig({
nav: [
{ text: '首頁', link: '/' },
{ text: '年會資訊', link: '/event' },
{ text: '參與指南', link: '/participate/attendee' },
{ text: '關於我們', link: '/about' },
],
sidebar: {},
socialLinks: [
{ icon: 'github', link: 'https://github.com/COSCUP' },
],

sidebar: {
'/participate': [
{
text: '參與指南',
link: '/participate/attendee',
items: [
{ text: '身為「會眾」', link: '/participate/attendee' },
{ text: '身為「社群」', link: '/participate/community' },
{ text: '身為「講者」', link: '/participate/speaker' },
{ text: '身為「贊助夥伴」', link: '/participate/sponsor' },
{ text: '身為」籌備團隊」', link: '/participate/organizing' },
],
},
],
},
socialLinks: [{ icon: 'github', link: 'https://github.com/COSCUP' }],
docFooter: {
prev: '上一頁',
next: '下一頁',
Expand Down
12 changes: 5 additions & 7 deletions .vitepress/theme/Layout.vue
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
<script setup lang="ts">
import Banner from '#components/Banner.vue'
import { inBrowser, useData } from 'vitepress'
import DefaultTheme from 'vitepress/theme'
import { watchEffect } from 'vue'

const { lang } = useData()

watchEffect(() => {
if (inBrowser) {
document.cookie = `lang=${lang.value};path=/`
Expand All @@ -13,10 +13,8 @@ watchEffect(() => {
</script>

<template>
<DefaultTheme.Layout>
<template #home-hero-before>
<Banner />
</template>
</DefaultTheme.Layout>
<Footer />
<DefaultTheme.Layout />
</template>

<style scoped>
</style>
12 changes: 9 additions & 3 deletions .vitepress/theme/index.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
// https://vitepress.dev/guide/custom-theme
import type { Theme } from 'vitepress'
import Banner from '#components/Banner.vue'
import Footer from '#components/Footer.vue'
import DefaultTheme from 'vitepress/theme'
import Layout from './Layout.vue'
import { h } from 'vue'
import './style.css'

export default {
extends: DefaultTheme,
Layout,
Layout() {
return h(DefaultTheme.Layout, null, {
'home-hero-before': () => h(Banner),
'layout-bottom': () => h(Footer),
})
},
} satisfies Theme
11 changes: 11 additions & 0 deletions .vitepress/theme/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -138,3 +138,14 @@
padding-top: 0 !important;
top: calc(var(--vp-nav-height) + var(--vp-layout-top-height, 0px) + var(--vp-doc-top-height, 0px) + 48px) !important;
}

/**
* Figure in page
* -------------------------------------------------------------------------- */
figure {
display: inline-block;
text-align: center;
}
figure img {
vertical-align: top;
}
41 changes: 32 additions & 9 deletions components/Footer.vue
Original file line number Diff line number Diff line change
@@ -1,9 +1,20 @@
<script setup lang="ts">
import { conference } from '#data/conference.js'
import { useSidebar } from 'vitepress/theme'
import { computed } from 'vue'

const { hasSidebar } = useSidebar()

const footerId = computed(() => {
return hasSidebar.value ? 'hasSidebar' : ''
})
</script>

<template>
<footer id="footer">
<footer
:id="footerId"
class="footer"
>
<section class="title">
<h1>COSCUP x RubyConf Taiwan 2025</h1>
<h2>Conference for Open Source Coders, Users, and Promoters</h2>
Expand Down Expand Up @@ -72,31 +83,31 @@ import { conference } from '#data/conference.js'
</template>

<style scoped>
#footer {
.footer {
border-top: 1px solid var(--vp-c-gutter);
padding: 32px 64px;
}

#footer section {
.footer section {
margin: 50px 0;
}

#footer h1 {
.footer h1 {
font-size: 28px;
font-weight: bold;
text-align: center;

margin: 20px;
}

#footer h2 {
.footer h2 {
font-size: 20px;
text-align: center;

margin: 20px;
}

#footer .contact {
.footer .contact {
display: flex;
justify-content: space-evenly;
flex-wrap: wrap;
Expand All @@ -106,21 +117,33 @@ import { conference } from '#data/conference.js'
row-gap: 25px;
}

#footer :where(.history, .social) :is(p, a) {
.footer :where(.history, .social) :is(p, a) {
display: flex;
justify-content: center;
flex-wrap: wrap;
row-gap: 25px;
}

#footer :where(.history, .social) :is(span, a) {
.footer :where(.history, .social) :is(span, a) {
display: inline-block;
width: 65px;

text-align: center;
}

#footer .social {
.footer .social {
font-size: 24px;
}

.footer#hasSidebar {
width: auto;
margin-left: calc((100% - (var(--vp-layout-max-width) - 64px)) / 2 + var(--vp-sidebar-width) - 32px);
}

@media (max-width: 960px) {
.footer {
margin-left: 0 !important;
width: 100% !important;
}
}
</style>
89 changes: 89 additions & 0 deletions components/Tab.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
<script setup lang='ts'>
import { onMounted, provide, ref, useSlots } from 'vue'

const slots = useSlots()
const tabs = ref<string[]>([])
const activeTab = ref<string>('')

onMounted(() => {
tabs.value = Object.keys(slots).filter((name) => name.startsWith('title-')).map((name) => name.slice(6))
if (tabs.value.length > 0) {
activeTab.value = tabs.value[0]
}
})

function selectTab(tab: string) {
activeTab.value = tab
}

provide('activeTab', activeTab)
</script>

<template>
<div class="tabs">
<ul class="tab-list">
<li
v-for="tab in tabs"
:key="tab"
:class="{ active: tab === activeTab }"
@click="selectTab(tab)"
>
<slot
:is-active="tab === activeTab"
:name="`title-${tab}`"
>
{{ tab }}
</slot>
</li>
</ul>
<div class="tab-content">
<template
v-for="tab in tabs"
:key="tab"
>
<div v-if="tab === activeTab">
<slot :name="`content-${tab}`" />
</div>
</template>
</div>
</div>
</template>

<style scoped>
.tab-list {
display: flex;
list-style-type: none;
border-bottom: 1px solid #ccc;
padding: 0px;
margin: 0px;
align-items: center;
justify-content: start;
}

.vp-doc li + li {
margin-top: 0px;
}

li {
padding: 0.7rem 1rem;
margin: 0px;
cursor: pointer;
border: 1px solid transparent;
border-top-left-radius: 1rem;
border-top-right-radius: 1rem;
}

li.active {
color: #000;
background-color: #fff;
border-color: #ccc;
border-bottom-color: #fff;
}

.tab-content {
padding: 20px;
border: 1px solid white;
border-bottom-right-radius: 1rem;
border-bottom-left-radius: 1rem;
}
</style>
Loading