Skip to content

Commit

Permalink
copy m3 design to playground/m3.html
Browse files Browse the repository at this point in the history
  • Loading branch information
finphy committed Sep 14, 2023
1 parent b31b399 commit 5a1abed
Show file tree
Hide file tree
Showing 20 changed files with 2,224 additions and 0 deletions.
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
},
"dependencies": {},
"devDependencies": {
"@alpinejs/persist": "^3.13.0",
"@iconscout/unicons": "^4.0.8",
"@vimesh/style": "^1.1.0",
"@vimesh/ui": "^0.12.4",
"alpinejs": "^3.10.5",
Expand Down
199 changes: 199 additions & 0 deletions playground/components/m3/app/float-menu.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
<script>
const appFloatMenu = {
all: {
data() {
return {
selected: null,
submenu: null,
show: false,
showSubMenu: false,
init() {
this.$nextTick(() => {
this.show = true;
});
},
openMenuControl(menu) {
if (menu.children && menu.children.length > 0) {
this.selected = menu.name;
this.$nextTick(() => {
this.showSubMenu = true;
});
}
},
back() {
if (this.selected) {
this.showSubMenu = false;
this.$nextTick(() => {
setTimeout(() => this.selected = null, 300);
});
} else {
this.show = false;
setTimeout(() => this.$dispatch('close-sub-menu'), 300);
}
}
}
},
},
float: {
data() {
return {
show: false,
init() {
this.$nextTick(() => {
this.show = true;
})
}
}
},
},
menu: {
data() {
return {
selected: null,
opens: [],
openSubMenuControl(submenu) {
const index = this.opens.indexOf(submenu.path);
if (index === -1) {
this.opens = [...this.opens, submenu.path]
} else {
this.opens = [...this.opens.slice(0, index), ...this.opens.slice(index + 1)]
}
},
init() {
if (this.$route.path.startsWith('/')) {
const ps = this.$route.path.split('/');
ps.pop();
this.opens = [ps.join('/')];
}
}
}
}
},
getSubmenu(menus, name) {
if (!name) return null;
const menu = menus.find(m => m.name === name) || { name: '' };
return menu;
},
}
</script>

<template x-component:app="float-menu-all" x-data="appFloatMenu.all.data">
<div class="absolute top-0 left-0 w-full h-full bg-zinc-800/70 border" style="z-index:0;"
@click="show=false;setTimeout(() => $dispatch('close-sub-menu'), 300);"></div>
<div :class="`shadow-md grid absolute top-0 left-0 h-full bg-${$store.page.color}-100 font-medium text-${$store.page.color}-600 dark:text-white dark:bg-${$store.page.color}-700 border-l border-l-${$store.page.color}-500 overflow-hidden`"
:style="`${show ? 'width:308px;' : 'width:0px;'} transition: width 0.3s; z-index:1;grid-template-rows: 50px auto 78px;`">
<div class="px-2 py-2">
<button :class="`hover:bg-${$store.page.color}-200 dark:hover:bg-${$store.page.color}-600 rounded-full p-3`"
@click="back">
<i class="uil uil-left-indent text-2xl"></i>
</button>
</div>
<div>
<template x-if="Boolean(selected) === false">
<template x-for="(menu, index) in $prop('menus', [])">
<div :class="`${index===0 ? 'pt-0' : ''} px-2`">
<template x-if="!Boolean(menu.children) || menu.children.length === 0">
<div
:class="`px-3 flex w-full justify-between items-center hover:bg-${$store.page.color}-200 dark:hover:bg-${$store.page.color}-600 rounded-full cursor-pointer ${selected === menu.name ? 'bg-sky-200 dark:bg-sky-800' : ''}`">

<a :href="`#${menu.path}`" class="flex items-center">
<i :class="`uil uil-${menu.icon} text-2xl`"></i>
<button class="px-4 py-3 text-sm whitespace-nowrap text-2xl font-semibold"
x-text="menu.name"></button>
</a>
</div>
</template>

<template x-if="Boolean(menu.children) && menu.children.length > 0">
<div @click="openMenuControl(menu)"
:class="`px-3 flex w-full justify-between items-center hover:bg-${$store.page.color}-200 dark:hover:bg-${$store.page.color}-600 rounded-full cursor-pointer ${selected === menu.name ? 'bg-sky-200 dark:bg-sky-800' : ''}`">
<div class="flex items-center">
<i :class="`uil uil-${menu.icon} text-2xl`"></i>
<button class="px-4 py-3 text-sm whitespace-nowrap text-2xl font-semibold"
x-text="menu.name"></button>
</div>
<i class="uil uil-arrow-right text-2xl"></i>
</div>
</template>
</div>
</template>
</template>
<template x-if="Boolean(selected)">
<div x-data="{menu:appFloatMenu.getSubmenu($prop('menus', []), selected)}">
<fin-topbar-float-menu :menu="menu" :show="showSubMenu"></fin-topbar-float-menu>
</div>
</template>
</div>
<div class="flex justify-center items-center">
<template x-if="Boolean(selected) === false">
<div :class="`hover:bg-${$store.page.color}-200 dark:hover:bg-${$store.page.color}-600 rounded-full px-5 py-3 flex gap-3 cursor-pointer whitespace-nowrap border`"
x-on:click="$store.persist.changeTheme()">
<i :class="`uil uil-${$store.persist.theme==='dark'?'brightness':'moon'} text-2xl`"></i>
<div x-text="`Switch to ${$store.persist.theme === 'dark' ? 'light': 'dark'} mode`"></div>
</div>
</template>
</div>
</div>
</template>

<template x-component:app="side-float-menu" x-data="appFloatMenu.float.data">
<div :class="`shadow-md hover:shadow-lg absolute top-0 h-screen bg-${$store.page.color}-100 font-medium text-${$store.page.color}-600 dark:text-white dark:bg-${$store.page.color}-700 border-l border-l-${$store.page.color}-500 overflow-x-hidden overflow-y-auto`"
:style="`left:88px;${show ? 'width:240px;' : 'width:0px;'} transition: width 0.3s; z-index:1;`"
@mouseleave.debounce="if(!$prop('menu') || !Boolean($prop('menu').children) || $prop('menu').children.length === 0) { show=false; }setTimeout(() => $dispatch('close-sub-menu', $prop('menu')), 300);">

<div x-data="{menu:$prop('menu')}">
<fin-float-menu :menu="menu"></fin-float-menu>
</div>
</div>
</template>

<template x-component:fin="topbar-float-menu">
<div :class="`absolute top-0 h-screen bg-${$store.page.color}-100 font-medium text-${$store.page.color}-600 dark:text-white dark:bg-${$store.page.color}-700 border-l border-l-${$store.page.color}-500 overflow-x-hidden overflow-y-auto`"
:style="`left:64px;${$prop('show') ? 'width:240px;' : 'width:0px;'} transition: width 0.3s; z-index:1;`">

<div x-data="{menu:$prop('menu')}">
<fin-float-menu :menu="menu"></fin-float-menu>
</div>

</div>
</template>

<template x-component:fin="float-menu" x-data="appFloatMenu.menu.data">
<template x-for="(submenu,index) in $prop('menu',{children:[]}).children">
<div :class="`${index===0 ? 'pt-4' : ''} px-2`">

<template x-if="!Boolean(submenu.children) || submenu.children.length === 0">
<a :href="`#${submenu.path}`"
:class="`mb-1 px-2 flex w-full justify-between hover:bg-${$store.page.color}-300 dark:hover:bg-${$store.page.color}-600 rounded-full cursor-pointer ${$route.path.startsWith(submenu.path || 'abc') ? `bg-${$store.page.color}-300 dark:bg-${$store.page.color}-800` : ''}`">
<button class="flex justify-center px-4 py-3 text-sm whitespace-nowrap"
x-text="submenu.name"></button>
<template x-if="Boolean(submenu.children) && submenu.children.length > 0">
<button class="px-4"><i class="uil uil-angle-down text-2xl"></i></button>
</template>
</a>
</template>

<template x-if="Boolean(submenu.children) && submenu.children.length > 0">
<div @click="openSubMenuControl(submenu)"
:class="`mb-1 px-2 flex w-full justify-between hover:bg-${$store.page.color}-300 dark:hover:bg-${$store.page.color}-600 rounded-full cursor-pointer ${$route.path.startsWith(submenu.path || 'abc') ? `bg-${$store.page.color}-300 dark:bg-${$store.page.color}-900` : ''}`">
<button class="flex justify-center px-4 py-3 text-sm whitespace-nowrap"
x-text="submenu.name"></button>
<button class="px-4"><i class="uil uil-angle-down text-2xl"></i></button>
</div>
</template>

<template x-if="Boolean(submenu.children) && submenu.children.length > 0">
<div class="pl-4 overflow-hidden"
:style="`${opens.indexOf(submenu.path) !== -1 ? `height:${submenu.children.length * 48}px;` : 'height:0px;'} transition: height 0.6s;`">
<template x-for="childmenu in submenu.children">
<a :href="`#${childmenu.path}`"
:class="`mb-1 px-2 flex w-full justify-between hover:bg-${$store.page.color}-300 dark:hover:bg-${$store.page.color}-600 rounded-full cursor-pointer ${$route.path === childmenu.path ? `bg-${$store.page.color}-200 dark:bg-${$store.page.color}-800` : ''}`">
<button class="flex justify-center px-4 py-3 text-sm whitespace-nowrap"
x-text="childmenu.name"></button>
</a>
</template>
</div>
</template>
</div>
</template>
</template>
14 changes: 14 additions & 0 deletions playground/components/m3/app/footer.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<template x-component:app="footer">
<div class="mt-24 mb-16 w-full relative" style="height:8px;">
<svg aria-hidden="true" width="100%" height="8" fill="none" xmlns="http:https://www.w3.org/2000/svg">
<pattern id="a" width="91" height="8" patternUnits="userSpaceOnUse">
<g clip-path="url(#clip0_2426_11367)">
<path
d="M114 4c-5.067 4.667-10.133 4.667-15.2 0S88.667-.667 83.6 4 73.467 8.667 68.4 4 58.267-.667 53.2 4 43.067 8.667 38 4 27.867-.667 22.8 4 12.667 8.667 7.6 4-2.533-.667-7.6 4s-10.133 4.667-15.2 0S-32.933-.667-38 4s-10.133 4.667-15.2 0-10.133-4.667-15.2 0-10.133 4.667-15.2 0-10.133-4.667-15.2 0-10.133 4.667-15.2 0-10.133-4.667-15.2 0-10.133 4.667-15.2 0-10.133-4.667-15.2 0-10.133 4.667-15.2 0-10.133-4.667-15.2 0-10.133 4.667-15.2 0-10.133-4.667-15.2 0-10.133 4.667-15.2 0-10.133-4.667-15.2 0-10.133 4.667-15.2 0-10.133-4.667-15.2 0-10.133 4.667-15.2 0-10.133-4.667-15.2 0-10.133 4.667-15.2 0-10.133-4.667-15.2 0-10.133 4.667-15.2 0-10.133-4.667-15.2 0-10.133 4.667-15.2 0-10.133-4.667-15.2 0-10.133 4.667-15.2 0"
stroke="#E1E3E1" stroke-linecap="square"></path>
</g>
</pattern>
<rect width="100%" height="100%" fill="url(#a)"></rect>
</svg>
</div>
</template>
37 changes: 37 additions & 0 deletions playground/components/m3/app/on-this-page.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<script>
const onThisPage = {
data() {
return {
top: 500,
list: [],
init() {
this.$nextTick(() => {
this.top = this.$prop('top', 500);
this.list = this.$prop('list', []);
})
},
onSelect(index) {
if (this.list[index].hrefid) {
this.$dispatch('on-select', this.list[index].hrefid);
}
}
}
},
scroll(e) {
const onThisPage = document.getElementById('onThisPage');
const top = +onThisPage.style.top.replace('px', '');
if (e.target.scrollTop <= (top - 60)) {
onThisPage.style.marginTop = `${-1 * e.target.scrollTop}px`;
}
},
};
</script>
<template x-component:app="on-this-page" x-data="onThisPage.data">
<div id="onThisPage" class="absolute bg-gray-100 dark:bg-neutral-700 dark:text-gray-300 p-4 rounded-lg" :style="`width: 200px; right: 20px; top:${top}px;`">
<div class="px-6 font-xs font-light">On this page</div>
<template x-for="(item,index) in list">
<div :class="`px-6 py-1 font-normal rounded-full cursor-pointer ${$prop('selected',0) === index ? `font-semibold border` : ``}`"
x-text="item.text" @click="onSelect(index)"></div>
</template>
</div>
</template>
23 changes: 23 additions & 0 deletions playground/components/m3/app/page-container.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<script>
const pageContainer = {
data() {
return {
init() {
setTimeout(() => {
this.$nextTick(() => {
const mainPageContainer = document.getElementById('mainPageContainer');
this.$store.page.mainSize.width = mainPageContainer.getBoundingClientRect().width;
})
}, 600)
}
}
}
}
</script>

<template x-component:app="page-container" id="mainPageContainer"
:class="`bg-transparent w-full text-black dark:text-slate-300 dark:bg-neutral-800 p-2 overflow-y-auto ${$prop('class', '')}`"
:style="`height:${$store.page.size.height - ($store.page.showTopbar ? 60 : 0)}px; ${$prop('style', '')}`"
x-data="pageContainer.data" x-on:scroll="$prop('scroll', () => { })">
<slot></slot>
</template>
35 changes: 35 additions & 0 deletions playground/components/m3/app/side-menu.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<script>
function appSideMenuData() {
return {
selected: this.$route.path,
isSelected(menu) {
const start = menu.path.startsWith('/') ? `/${menu.path.split('/')[1]}` : 'abc';
return this.selected.startsWith(start);
}
}
};
</script>
<template x-component:app="side-menu" x-data="appSideMenuData">
<div :class="`bg-${$store.page.color}-100 font-medium text-${$store.page.color}-600 dark:text-${$store.page.color}-200 dark:bg-${$store.page.color}-700 py-4 h-full grid shadow`"
style="grid-template-rows: auto 60px;">
<div>
<template x-for="menu in $prop('menus',[])">
<div class="mb-6">
<a class="font-medium text-${$store.page.color}-600" :href="`#${menu.path}`">
<button x-on:click="selected = menu.path"
@mouseenter.debounce="$dispatch('open-sub-menu', menu)"
:class="`m-auto flex justify-center px-4 py-1 hover:bg-${$store.page.color}-200 dark:hover:bg-${$store.page.color}-600 rounded-full cursor-pointer ${isSelected(menu) ? `bg-${$store.page.color}-200 dark:bg-${$store.page.color}-800` : ''}`">
<i :class="`uil uil-${menu.icon} text-2xl`"></i>
</button>
<div :class="`flex justify-center pt-1 text-xs ${isSelected(menu) ? 'font-bold dark:text-sky-200' : ''}`"
x-text="menu.name"></div>
</a>
</div>
</template>
</div>
<button x-on:click="$store.persist.changeTheme()"
:class="`m-auto flex justify-center p-3 dark:hover:bg-${$store.page.color}-600 rounded-full cursor-pointer border`">
<i :class="`uil uil-${$store.persist.theme==='dark'?'brightness':'moon'} text-2xl`"></i>
</button>
</div>
</template>
50 changes: 50 additions & 0 deletions playground/components/m3/app/tab-list.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<script>
const appTabList = {
data() {
return {
list: [],
init() {
this.$nextTick(() => {
this.list = this.$prop('list', []);
})
},
onSelect(index) {
this.$dispatch('on-select', index);
}
}
},
scroll(e) {
const topContainer = document.getElementById('topContainer');
const tabListContainer = document.getElementById('tabListContainer');
const tabListInnerContainer = document.getElementById('tabListInnerContainer');
if (e.target.scrollTop >= topContainer.getBoundingClientRect().height) {
tabListContainer.classList.add('absolute');
tabListContainer.classList.add('top-0');
tabListContainer.classList.add('text-xl');
tabListContainer.classList.add('scale-70');

tabListInnerContainer.classList.add('shadow-md');

} else {
tabListContainer.classList.remove('absolute');
tabListContainer.classList.remove('top-0');
tabListContainer.classList.remove('text-xl');
tabListContainer.classList.remove('scale-70');

tabListInnerContainer.classList.remove('shadow-md');
}
},
};
</script>
<template x-component:app="tab-list" x-data="appTabList.data">
<div id="tabListContainer" class="h-20 flex justify-center transition-transform delay-100 ease-in-in"
:style="`width:${$store.page.mainSize.width - 32}px`">
<div id="tabListInnerContainer"
:class="`bg-gray-100 font-medium text-dark dark:text-neutral-200 dark:bg-neutral-700 flex justify-between rounded-full w-full h-full`">
<template x-for="(item,index) in list">
<div :class="`h-full rounded-full flex grow justify-center items-center cursor-pointer ${$prop('selected',0) === index ? `font-semibold bg-${$store.page.color}-200 hover:bg-${$store.page.color}-300 dark:bg-${$store.page.color}-400 dark:hover:bg-${$store.page.color}-500` : `bg-transparent hover:bg-gray-300 dark:bg-transparent dark:hover:bg-neutral-700`}`"
x-text="item" @click="onSelect(index)"></div>
</template>
</div>
</div>
</template>
Loading

0 comments on commit 5a1abed

Please sign in to comment.