mirror of
https://github.com/ash-project/ash_hq.git
synced 2024-09-19 12:53:49 +12:00
WIP
This commit is contained in:
parent
32d3eb770a
commit
c0112737dc
5 changed files with 119 additions and 39 deletions
|
@ -48,6 +48,77 @@ Hooks.Docs = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function onScrollChange() {
|
||||||
|
const docs = document.getElementById("docs-window");
|
||||||
|
if(docs) {
|
||||||
|
const scrollTop = docs.scrollTop;
|
||||||
|
const topEl = Array.from(document.getElementsByClassName("nav-anchor")).filter((el) => {
|
||||||
|
return (el.offsetTop + el.clientHeight) >= scrollTop;
|
||||||
|
})[0];
|
||||||
|
let hash;
|
||||||
|
if(window.location.hash){
|
||||||
|
hash = window.location.hash.substring(1);
|
||||||
|
}
|
||||||
|
if(topEl && topEl.id !== hash){
|
||||||
|
history.replaceState(null, null, `#${topEl.id}`)
|
||||||
|
window.location.hash = topEl.id;
|
||||||
|
const newTarget = document.getElementById(`right-nav-${topEl.id}`);
|
||||||
|
Array.from(document.getElementsByClassName("currently-active-nav")).forEach((el) => {
|
||||||
|
el.classList.remove("currently-active-nav");
|
||||||
|
el.classList.remove("text-orange-600");
|
||||||
|
el.classList.remove("dark:text-orange-400");
|
||||||
|
})
|
||||||
|
if(newTarget) {
|
||||||
|
newTarget.classList.add("dark:text-orange-400");
|
||||||
|
newTarget.classList.add("text-orange-600");
|
||||||
|
newTarget.classList.add("currently-active-nav")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleHashChange(clear) {
|
||||||
|
if (window.location.hash) {
|
||||||
|
const el = document.getElementById("right-nav-" + window.location.hash.substring(1))
|
||||||
|
if(el) {
|
||||||
|
if (clear) {
|
||||||
|
Array.from(document.getElementsByClassName("currently-active-nav")).forEach((el) => {
|
||||||
|
el.classList.remove("currently-active-nav");
|
||||||
|
el.classList.remove("text-orange-600");
|
||||||
|
el.classList.remove("dark:text-orange-400");
|
||||||
|
})
|
||||||
|
}
|
||||||
|
el.classList.add("dark:text-orange-400");
|
||||||
|
el.classList.add("text-orange-600");
|
||||||
|
el.classList.add("currently-active-nav")
|
||||||
|
scrollIntoView(el, {
|
||||||
|
behavior: 'smooth',
|
||||||
|
block: 'center'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Hooks.RightNav = {
|
||||||
|
mounted() {
|
||||||
|
handleHashChange(false);
|
||||||
|
const docs = document.getElementById("docs-window");
|
||||||
|
if (docs) {
|
||||||
|
docs.addEventListener("scroll", () => onScrollChange())
|
||||||
|
if(this.interval) {
|
||||||
|
clearInterval(this.interval)
|
||||||
|
};
|
||||||
|
|
||||||
|
this.interval = setInterval(() => handleHashChange(true), 100);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
destroyed() {
|
||||||
|
if(this.interval) {
|
||||||
|
clearInterval(this.interval)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let csrfToken = document.querySelector("meta[name='csrf-token']").getAttribute("content")
|
let csrfToken = document.querySelector("meta[name='csrf-token']").getAttribute("content")
|
||||||
let liveSocket = new LiveSocket("/live", Socket, {
|
let liveSocket = new LiveSocket("/live", Socket, {
|
||||||
params: {_csrf_token: csrfToken},
|
params: {_csrf_token: csrfToken},
|
||||||
|
@ -94,9 +165,14 @@ window.addEventListener("phx:js:scroll-to", (e) => {
|
||||||
|
|
||||||
let scrolled = false;
|
let scrolled = false;
|
||||||
|
|
||||||
|
window.addEventListener("phx:page-loading-start", () => {
|
||||||
|
scrolled = false;
|
||||||
|
})
|
||||||
|
|
||||||
window.addEventListener("phx:page-loading-stop", ({detail}) => {
|
window.addEventListener("phx:page-loading-stop", ({detail}) => {
|
||||||
if(detail.kind === "initial" && window.location.hash && !scrolled){
|
if(detail.kind === "initial" && window.location.hash && !scrolled){
|
||||||
let hashEl = document.getElementById(window.location.hash.substring(1));
|
let hashEl = document.getElementById(window.location.hash.substring(1));
|
||||||
|
console.log(hashEl);
|
||||||
hashEl && hashEl.scrollIntoView();
|
hashEl && hashEl.scrollIntoView();
|
||||||
scrolled = true;
|
scrolled = true;
|
||||||
}
|
}
|
||||||
|
@ -109,14 +185,12 @@ window.addEventListener("phx:selected-versions", (e) => {
|
||||||
});
|
});
|
||||||
|
|
||||||
window.addEventListener("phx:selected-types", (e) => {
|
window.addEventListener("phx:selected-types", (e) => {
|
||||||
console.log(e.detail);
|
|
||||||
const cookie = e.detail.types.join(',');
|
const cookie = e.detail.types.join(',');
|
||||||
document.cookie = 'selected_types' + '=' + cookie + ';path=/';
|
document.cookie = 'selected_types' + '=' + cookie + ';path=/';
|
||||||
});
|
});
|
||||||
|
|
||||||
window.addEventListener("keydown", (event) => {
|
window.addEventListener("keydown", (event) => {
|
||||||
if(event.metaKey && event.key === "k") {
|
if(event.metaKey && event.key === "k") {
|
||||||
console.log("here3")
|
|
||||||
document.getElementById("search-button").click()
|
document.getElementById("search-button").click()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
@ -17,7 +17,7 @@ defmodule AshHqWeb.Components.DocSidebar do
|
||||||
|
|
||||||
def render(assigns) do
|
def render(assigns) do
|
||||||
~F"""
|
~F"""
|
||||||
<aside id={@id} class={"w-64 h-full block overflow-y-scroll", @class} aria-label="Sidebar">
|
<aside id={@id} class={"grid w-64 h-full overflow-y-scroll", @class} aria-label="Sidebar">
|
||||||
<div class="py-3 px-3">
|
<div class="py-3 px-3">
|
||||||
<ul class="space-y-2">
|
<ul class="space-y-2">
|
||||||
{#for library <- @libraries}
|
{#for library <- @libraries}
|
||||||
|
@ -48,7 +48,7 @@ defmodule AshHqWeb.Components.DocSidebar do
|
||||||
guide.url_safe_name
|
guide.url_safe_name
|
||||||
)}
|
)}
|
||||||
class={
|
class={
|
||||||
"flex items-center pt-1 text-base font-normal text-gray-900 rounded-lg dark:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-700",
|
"flex items-center p-1 text-base font-normal text-gray-900 rounded-lg dark:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-700",
|
||||||
"dark:bg-gray-600": @guide && @guide.id == guide.id
|
"dark:bg-gray-600": @guide && @guide.id == guide.id
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
|
@ -68,7 +68,7 @@ defmodule AshHqWeb.Components.DocSidebar do
|
||||||
<LivePatch
|
<LivePatch
|
||||||
to={Routes.extension_link(library, selected_version_name(library, @selected_versions), extension.name)}
|
to={Routes.extension_link(library, selected_version_name(library, @selected_versions), extension.name)}
|
||||||
class={
|
class={
|
||||||
"flex items-center pt-1 text-base font-normal text-gray-900 rounded-lg dark:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-700",
|
"flex items-center p-1 text-base font-normal text-gray-900 rounded-lg dark:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-700",
|
||||||
"dark:bg-gray-600": @extension && @extension.id == extension.id
|
"dark:bg-gray-600": @extension && @extension.id == extension.id
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
|
@ -116,13 +116,15 @@ defmodule AshHqWeb.Components.DocSidebar do
|
||||||
<LivePatch
|
<LivePatch
|
||||||
to={Routes.dsl_link(@library, @library_version.version, @extension.name, dsl)}
|
to={Routes.dsl_link(@library, @library_version.version, @extension.name, dsl)}
|
||||||
class={
|
class={
|
||||||
"flex items-center pt-1 text-base font-normal rounded-lg hover:text-orange-300",
|
"flex items-center p-1 text-base font-normal rounded-lg hover:text-orange-300",
|
||||||
"text-orange-600 dark:text-orange-400 font-bold": @dsl && @dsl.id == dsl.id
|
"text-orange-600 dark:text-orange-400 font-bold": @dsl && @dsl.id == dsl.id
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
{dsl.name}
|
{dsl.name}
|
||||||
</LivePatch>
|
</LivePatch>
|
||||||
{render_dsls(assigns, dsls, path ++ [dsl.name])}
|
{#if @dsl && List.starts_with?(@dsl.path ++ [@dsl.name], path ++ [dsl.name])}
|
||||||
|
{render_dsls(assigns, dsls, path ++ [dsl.name])}
|
||||||
|
{/if}
|
||||||
</li>
|
</li>
|
||||||
{/for}
|
{/for}
|
||||||
</ul>
|
</ul>
|
||||||
|
|
|
@ -2,15 +2,18 @@ defmodule AshHqWeb.Components.RightNav do
|
||||||
use Surface.Component
|
use Surface.Component
|
||||||
|
|
||||||
alias AshHqWeb.Routes
|
alias AshHqWeb.Routes
|
||||||
alias Surface.Components.LivePatch
|
|
||||||
|
|
||||||
prop functions, :list
|
prop functions, :list, default: []
|
||||||
|
prop module, :string, required: true
|
||||||
|
|
||||||
def render(assigns) do
|
def render(assigns) do
|
||||||
~F"""
|
~F"""
|
||||||
<div class="w-min flex flex-col overflow-y-scroll">
|
<div id="right-nav" class="w-min hidden xl:flex flex-col overflow-y-scroll" phx-hook="RightNav">
|
||||||
|
<a id="right-nav-module-docs" class="hover:text-orange-300 right-nav" href="#module-docs">
|
||||||
|
{@module}
|
||||||
|
</a>
|
||||||
{#for function <- @functions}
|
{#for function <- @functions}
|
||||||
<a class="hover:text-orange-300" href={"##{Routes.sanitize_name(function.name)}-#{function.arity}"}>
|
<a id={"right-nav-#{Routes.sanitize_name(function.name)}-#{function.arity}"} class="hover:text-orange-300 right-nav" href={"##{Routes.sanitize_name(function.name)}-#{function.arity}"}>
|
||||||
{"#{function.name}/#{function.arity}"}
|
{"#{function.name}/#{function.arity}"}
|
||||||
</a>
|
</a>
|
||||||
{/for}
|
{/for}
|
||||||
|
|
|
@ -25,7 +25,7 @@ defmodule AshHqWeb.Pages.Docs do
|
||||||
@spec render(any) :: Phoenix.LiveView.Rendered.t()
|
@spec render(any) :: Phoenix.LiveView.Rendered.t()
|
||||||
def render(assigns) do
|
def render(assigns) do
|
||||||
~F"""
|
~F"""
|
||||||
<div class="grow h-full w-full flex flex-col">
|
<div class="grid content-start overflow-hidden">
|
||||||
<div class="lg:hidden flex flex-row justify-start space-x-12 items-center border-b border-t border-gray-600 py-3">
|
<div class="lg:hidden flex flex-row justify-start space-x-12 items-center border-b border-t border-gray-600 py-3">
|
||||||
<button class="dark:hover:text-gray-600" phx-click={show_sidebar()}>
|
<button class="dark:hover:text-gray-600" phx-click={show_sidebar()}>
|
||||||
<Heroicons.Outline.MenuIcon class="w-8 h-8 ml-4" />
|
<Heroicons.Outline.MenuIcon class="w-8 h-8 ml-4" />
|
||||||
|
@ -51,8 +51,8 @@ defmodule AshHqWeb.Pages.Docs do
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
<span class="lg:hidden">
|
<span class="grid overflow-hidden lg:hidden ">
|
||||||
<div id="mobile-sidebar-container" class="hidden fixed w-min h-full bg-primary-black transition">
|
<div id="mobile-sidebar-container" class="overflow-hidden hidden fixed w-min h-full transition bg-primary-black">
|
||||||
<DocSidebar
|
<DocSidebar
|
||||||
id="mobile-sidebar"
|
id="mobile-sidebar"
|
||||||
libraries={@libraries}
|
libraries={@libraries}
|
||||||
|
@ -66,7 +66,7 @@ defmodule AshHqWeb.Pages.Docs do
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</span>
|
</span>
|
||||||
<div class="grow flex flex-row h-full justify-center space-x-12">
|
<div class="grow overflow-hidden flex flex-row h-full justify-center space-x-12 bg-primary-black">
|
||||||
<DocSidebar
|
<DocSidebar
|
||||||
id="sidebar"
|
id="sidebar"
|
||||||
class="hidden lg:block mt-10"
|
class="hidden lg:block mt-10"
|
||||||
|
@ -81,26 +81,30 @@ defmodule AshHqWeb.Pages.Docs do
|
||||||
/>
|
/>
|
||||||
<div
|
<div
|
||||||
id="docs-window"
|
id="docs-window"
|
||||||
class="grow w-full prose lg:max-w-3xl xl:max-w-5xl dark:prose-invert overflow-y-scroll overflow-x-visible mt-14"
|
class="w-full prose bg-primary-black md:max-w-2xl lg:max-w-3xl xl:max-w-5xl dark:prose-invert overflow-y-scroll overflow-x-visible mt-14"
|
||||||
phx-hook="Docs"
|
phx-hook="Docs"
|
||||||
>
|
>
|
||||||
{raw(@docs)}
|
<div id="module-docs" class="w-full nav-anchor">
|
||||||
|
{raw(@docs)}
|
||||||
|
</div>
|
||||||
{#if @module}
|
{#if @module}
|
||||||
{#for function <- @module.functions}
|
{#for function <- @module.functions}
|
||||||
<p>
|
<div class="rounded-lg bg-slate-700 bg-opacity-50 px-2 mb-2 pb-1">
|
||||||
<div>
|
<p class="">
|
||||||
<div class="flex flex-row items-baseline">
|
<div class="">
|
||||||
<a href={"##{Routes.sanitize_name(function.name)}-#{function.arity}"}>
|
<div class="flex flex-row items-baseline h-min">
|
||||||
<Heroicons.Outline.LinkIcon class="h-3 m-3" />
|
<a href={"##{Routes.sanitize_name(function.name)}-#{function.arity}"}>
|
||||||
</a>
|
<Heroicons.Outline.LinkIcon class="h-3 m-3" />
|
||||||
<h2 id={"#{Routes.sanitize_name(function.name)}-#{function.arity}"}>{function.name}/{function.arity}</h2>
|
</a>
|
||||||
|
<h2 class="nav-anchor" id={"#{Routes.sanitize_name(function.name)}-#{function.arity}"}>{function.name}/{function.arity}</h2>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
{#for head <- function.heads}
|
||||||
{#for head <- function.heads}
|
<code class="makeup elixir">{head}</code>
|
||||||
<code class="makeup elixir">{head}</code>
|
{/for}
|
||||||
{/for}
|
{raw(AshHq.Docs.Extensions.RenderMarkdown.render!(function, :doc))}
|
||||||
{raw(AshHq.Docs.Extensions.RenderMarkdown.render!(function, :doc))}
|
</p>
|
||||||
</p>
|
</div>
|
||||||
{/for}
|
{/for}
|
||||||
{/if}
|
{/if}
|
||||||
{#if !Enum.empty?(@options)}
|
{#if !Enum.empty?(@options)}
|
||||||
|
@ -132,11 +136,8 @@ defmodule AshHqWeb.Pages.Docs do
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
{#if @module}
|
{#if @module}
|
||||||
<div
|
<div class="w-min overflow-y-scroll overflow-x-visible mt-14 bg-primary-black bg-opacity-70" >
|
||||||
class="grow w-min overflow-y-scroll overflow-x-visible mt-14 mb-"
|
<RightNav functions={@module.functions} module={@module.name}/>
|
||||||
phx-hook="Docs"
|
|
||||||
>
|
|
||||||
<RightNav functions={@module.functions}/>
|
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -33,11 +33,11 @@ defmodule AshHqWeb.AppViewLive do
|
||||||
<button id="search-button" class="hidden" phx-click={AshHqWeb.AppViewLive.toggle_search()} />
|
<button id="search-button" class="hidden" phx-click={AshHqWeb.AppViewLive.toggle_search()} />
|
||||||
<div
|
<div
|
||||||
id="main-container"
|
id="main-container"
|
||||||
class={"h-screen flex flex-col bg-white dark:bg-primary-black dark:text-silver-phoenix overflow-x-hidden", "overflow-clip": @live_action == :docs_dsl}
|
class={"h-screen grid content-start grid-rows-[auto,1fr] w-screen bg-white dark:bg-primary-black dark:text-silver-phoenix", "overflow-scroll": @live_action == :home, "overflow-hidden": @live_action == :docs_dsl}
|
||||||
>
|
>
|
||||||
<div class={
|
<div class={
|
||||||
"flex justify-between pt-4 px-4",
|
"flex justify-between pt-4 px-4 h-min",
|
||||||
"w-full border-b bg-white dark:bg-primary-black pb-4 top-0": @live_action == :docs_dsl
|
"border-b bg-white dark:bg-primary-black": @live_action == :docs_dsl
|
||||||
}>
|
}>
|
||||||
<div class="flex flex-row align-baseline">
|
<div class="flex flex-row align-baseline">
|
||||||
<a href="/">
|
<a href="/">
|
||||||
|
@ -51,7 +51,7 @@ defmodule AshHqWeb.AppViewLive do
|
||||||
class="dark:text-gray-400 dark:hover:text-gray-200 hover:text-gray-600"
|
class="dark:text-gray-400 dark:hover:text-gray-200 hover:text-gray-600"
|
||||||
>Get Started</a>
|
>Get Started</a>
|
||||||
<div>|</div>
|
<div>|</div>
|
||||||
<a href="/docs" class="dark:text-gray-400 dark:hover:text-gray-200 hover:text-gray-600">Docs</a>
|
<a href="/docs/guides/ash/main/overview" class="dark:text-gray-400 dark:hover:text-gray-200 hover:text-gray-600">Docs</a>
|
||||||
<div>|</div>
|
<div>|</div>
|
||||||
<a href="https://github.com/ash-project">
|
<a href="https://github.com/ash-project">
|
||||||
<svg
|
<svg
|
||||||
|
|
Loading…
Reference in a new issue