mirror of
https://github.com/snachodog/just-the-docs.git
synced 2025-09-12 21:03:32 -06:00
refactor: modularize site components (#1058)
Hi everyone, this is a large refactoring PR that looks to **modularize site components** following the discussion in #959. At the top-level, it: - moves icons, the sidebar, header (navbar, search, aux links), footer, and mermaid components of the `default` layout into their own `_includes` - creates a new `minimal` layout that does not render the header or sidebar as a proof-of-concept for the composability of components - documents all existing and new layouts (including vendor code) in the "Customization" section An important goal of this PR is for it to be **just code motion and flexibility**: there should be **zero impact** on the average end user that only consumes the `default` theme. The next few sections go in-depth on each of the listed changes. ### new components The `default` layout contains a "list" of all relevant components. Importantly, some of these components have sub-components: - the header is split into the search bar, custom code, and aux links - the icons include imports different icon components, some of which are conditionally imported by feature guards There are also candidates for future splits and joins: - the sidebar could be split into navigation, collections, external link, and header/footer code - the "search footer" could be joined with other search code, which would make it easier to "include search" in one go; *however, this is a markup change* - @kevinlin1 has pointed out that there is some leakage between the sidebar (which computes parents/grandparents) and the breadcrumbs (which needs them to render). He's graciously added a bandaid fix to `minimal` (which does not render the sidebar). However, in the long term, we should either: - calculate this in a parent and pass the information to both components - change how this works entirely (which may happen with multi-level navigation) @pdmosses has done a great job outlining this and more in his [Modular Layouts test site](https://pdmosses.github.io/modular-layouts/docs/main/). ### minimal layout Based on @kevinlin1's use-case in just-the-class (see: his [Winter 2023 CSE 373 site](https://courses.cs.washington.edu/courses/cse373/23wi/)), we've created a first-class `minimal` layout that does not render the sidebar or header. In a [comment](https://github.com/just-the-docs/just-the-docs/pull/1058#discussion_r1057015039), Kevin has indicated that we can re-add the search bar in the minimal layout; however, it seems like this would be a code change. I think we should punt this to a future issue/PR. @pdmosses has also discussed the confusion of `minimal` as a layout and its meaning in inheritance. I've added a note in documentation to clarify the (lack of) inheritance relationship. ### documentation I've written documentation in the "Customization" page / [Custom layouts and includes](https://deploy-preview-1058--just-the-docs.netlify.app/docs/customization/#custom-layouts-and-includes) section explaining: - generally, that we use includes/layouts (and pointing to docs) - the `default` layout and its constituent components (with a warning about name collisions) - creating alternative layouts with `minimal` as an example - the inheritance chain of layouts and the vendor layouts that we consume I've also created (and linked to) a [minimal layout test](https://deploy-preview-1058--just-the-docs.netlify.app/docs/minimal-test/) that is currently a copy of the markdown kitchen sink but with the minimal layout. I think there's room to improve this in the future. ### future work I think there's a lot we can do. Let me break this into various sections. Potential follow-ups before `v0.4.0`: - re-including search in `minimal` (anticipating a minor code change) - fixing the leakage of parent/grandparent information between the sidebar and breadcrumbs (anticipating no end-user code change, but good to evaluate separately and discuss) - heavily document this in the migration guide (#1059) and in our RC4 release docs - improve semantic markup for components (ex `main`, `nav`) Related work in later minor versions: - split up components into smaller components - allow users to easily customize new layouts using frontmatter (see @kevinlin1's [comment in #959](https://github.com/just-the-docs/just-the-docs/issues/959#issuecomment-1249755249)) Related work for `v1.0` (i.e. a major breaking change): - rename and better categorize existing includes - standardizing the "custom" includes - moving other components to the `components/` folder (ex `head`, `nav`) - potentially: less confusing naming for various components - potentially separate the search and header as components, so that they are completely independent Tangentially related work: - more flexible grid (see @JPrevost's [comment in this PR thread](https://github.com/just-the-docs/just-the-docs/pull/1058#issuecomment-1363314610)) - a formal [feature model](https://en.wikipedia.org/wiki/Feature_model) of JTD, documenting feature dependence (see @pdmosses's [comment in this PR thread](https://github.com/just-the-docs/just-the-docs/pull/1058#issuecomment-1365414023)) - better annotate new features (motivated by writing these docs) - we should add "New" to new features :) - we should note when a feature was introduced (I think this is a core part of most software documentation) - we should annotate things that are "Advanced" in so far as the average Just the Docs user will not use them / they require significant Jekyll knowledge --- Closes #959.
This commit is contained in:
@@ -8,161 +8,12 @@ layout: table_wrappers
|
||||
{% include head.html %}
|
||||
<body>
|
||||
<a class="skip-to-main" href="#main-content">Skip to main content</a>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="d-none" >
|
||||
<symbol id="svg-link" viewBox="0 0 24 24">
|
||||
<title>Link</title>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-link">
|
||||
<path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"></path><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"></path>
|
||||
</svg>
|
||||
</symbol>
|
||||
<symbol id="svg-search" viewBox="0 0 24 24">
|
||||
<title>Search</title>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-search">
|
||||
<circle cx="11" cy="11" r="8"></circle><line x1="21" y1="21" x2="16.65" y2="16.65"></line>
|
||||
</svg>
|
||||
</symbol>
|
||||
<symbol id="svg-menu" viewBox="0 0 24 24">
|
||||
<title>Menu</title>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-menu">
|
||||
<line x1="3" y1="12" x2="21" y2="12"></line><line x1="3" y1="6" x2="21" y2="6"></line><line x1="3" y1="18" x2="21" y2="18"></line>
|
||||
</svg>
|
||||
</symbol>
|
||||
<symbol id="svg-arrow-right" viewBox="0 0 24 24">
|
||||
<title>Expand</title>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-chevron-right">
|
||||
<polyline points="9 18 15 12 9 6"></polyline>
|
||||
</svg>
|
||||
</symbol>
|
||||
<symbol id="svg-doc" viewBox="0 0 24 24">
|
||||
<title>Document</title>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-file">
|
||||
<path d="M13 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V9z"></path><polyline points="13 2 13 9 20 9"></polyline>
|
||||
</svg>
|
||||
</symbol>
|
||||
{% include icons/external_link.html %}
|
||||
{% include icons/code_copy.html %}
|
||||
</svg>
|
||||
|
||||
<div class="side-bar">
|
||||
<div class="site-header">
|
||||
<a href="{{ '/' | relative_url }}" class="site-title lh-tight">{% include title.html %}</a>
|
||||
<a href="#" id="menu-button" class="site-button">
|
||||
<svg viewBox="0 0 24 24" class="icon"><use xlink:href="#svg-menu"></use></svg>
|
||||
</a>
|
||||
</div>
|
||||
<nav aria-label="Main" id="site-nav" class="site-nav">
|
||||
{% assign pages_top_size = site.html_pages
|
||||
| where_exp:"item", "item.title != nil"
|
||||
| where_exp:"item", "item.parent == nil"
|
||||
| where_exp:"item", "item.nav_exclude != true"
|
||||
| size %}
|
||||
{% if pages_top_size > 0 %}
|
||||
{% include nav.html pages=site.html_pages key=nil %}
|
||||
{% endif %}
|
||||
{%- if site.nav_external_links -%}
|
||||
<ul class="nav-list">
|
||||
{%- for node in site.nav_external_links -%}
|
||||
<li class="nav-list-item external">
|
||||
<a href="{{ node.url | absolute_url }}" class="nav-list-link external">
|
||||
{{ node.title }}
|
||||
{% unless node.hide_icon %}<svg viewBox="0 0 24 24" aria-labelledby="svg-external-link-title"><use xlink:href="#svg-external-link"></use></svg>{% endunless %}
|
||||
</a>
|
||||
</li>
|
||||
{%- endfor -%}
|
||||
</ul>
|
||||
{%- endif -%}
|
||||
{% if site.just_the_docs.collections %}
|
||||
{% assign collections_size = site.just_the_docs.collections | size %}
|
||||
{% for collection_entry in site.just_the_docs.collections %}
|
||||
{% assign collection_key = collection_entry[0] %}
|
||||
{% assign collection_value = collection_entry[1] %}
|
||||
{% assign collection = site[collection_key] %}
|
||||
{% if collection_value.nav_exclude != true %}
|
||||
{% if collections_size > 1 or pages_top_size > 0 %}
|
||||
{% if collection_value.nav_fold == true %}
|
||||
<ul class="nav-list nav-category-list">
|
||||
<li class="nav-list-item{% if page.collection == collection_key %} active{% endif %}">
|
||||
{%- if collection.size > 0 -%}
|
||||
<a href="#" class="nav-list-expander"><svg viewBox="0 0 24 24"><use xlink:href="#svg-arrow-right"></use></svg></a>
|
||||
{%- endif -%}
|
||||
<div class="nav-category">{{ collection_value.name }}</div>
|
||||
{% include nav.html pages=collection key=collection_key %}
|
||||
</li>
|
||||
</ul>
|
||||
{% else %}
|
||||
<div class="nav-category">{{ collection_value.name }}</div>
|
||||
{% include nav.html pages=collection key=collection_key %}
|
||||
{% endif %}
|
||||
{% else %}
|
||||
{% include nav.html pages=collection key=collection_key %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</nav>
|
||||
|
||||
{% capture nav_footer_custom %}
|
||||
{%- include nav_footer_custom.html -%}
|
||||
{% endcapture %}
|
||||
{% if nav_footer_custom != "" %}
|
||||
{{ nav_footer_custom }}
|
||||
{% else %}
|
||||
<footer class="site-footer">
|
||||
This site uses <a href="https://github.com/just-the-docs/just-the-docs">Just the Docs</a>, a documentation theme for Jekyll.
|
||||
</footer>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% include icons/icons.html %}
|
||||
{% include components/sidebar.html %}
|
||||
<div class="main" id="top">
|
||||
<div id="main-header" class="main-header">
|
||||
{% if site.search_enabled != false %}
|
||||
|
||||
{% capture search_placeholder %}{% include search_placeholder_custom.html %}{% endcapture %}
|
||||
|
||||
<div class="search">
|
||||
<div class="search-input-wrap">
|
||||
<input type="text" id="search-input" class="search-input" tabindex="0" placeholder="{{ search_placeholder | strip_html | strip }}" aria-label="{{ search_placeholder | strip_html| strip }}" autocomplete="off">
|
||||
<label for="search-input" class="search-label"><svg viewBox="0 0 24 24" class="search-icon"><use xlink:href="#svg-search"></use></svg></label>
|
||||
</div>
|
||||
<div id="search-results" class="search-results"></div>
|
||||
</div>
|
||||
{% else %}
|
||||
<div></div>
|
||||
{% endif %}
|
||||
{% include header_custom.html %}
|
||||
{% if site.aux_links %}
|
||||
<nav aria-label="Auxiliary" class="aux-nav">
|
||||
<ul class="aux-nav-list">
|
||||
{% for link in site.aux_links %}
|
||||
<li class="aux-nav-list-item">
|
||||
<a href="{{ link.last }}" class="site-button"
|
||||
{% if site.aux_links_new_tab %}
|
||||
target="_blank" rel="noopener noreferrer"
|
||||
{% endif %}
|
||||
>
|
||||
{{ link.first }}
|
||||
</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</nav>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% include components/header.html %}
|
||||
<div id="main-content-wrap" class="main-content-wrap">
|
||||
{% unless page.url == "/" %}
|
||||
{% if page.parent %}
|
||||
<nav aria-label="Breadcrumb" class="breadcrumb-nav">
|
||||
<ol class="breadcrumb-nav-list">
|
||||
{% if page.grand_parent %}
|
||||
<li class="breadcrumb-nav-list-item"><a href="{{ first_level_url }}">{{ page.grand_parent }}</a></li>
|
||||
<li class="breadcrumb-nav-list-item"><a href="{{ second_level_url }}">{{ page.parent }}</a></li>
|
||||
{% else %}
|
||||
<li class="breadcrumb-nav-list-item"><a href="{{ first_level_url }}">{{ page.parent }}</a></li>
|
||||
{% endif %}
|
||||
<li class="breadcrumb-nav-list-item"><span>{{ page.title }}</span></li>
|
||||
</ol>
|
||||
</nav>
|
||||
{% endif %}
|
||||
{% endunless %}
|
||||
{% include components/breadcrumbs.html %}
|
||||
<div id="main-content" class="main-content" role="main">
|
||||
{% if site.heading_anchors != false %}
|
||||
{% include vendor/anchor_headings.html html=content beforeHeading="true" anchorBody="<svg viewBox=\"0 0 16 16\" aria-hidden=\"true\"><use xlink:href=\"#svg-link\"></use></svg>" anchorClass="anchor-heading" anchorAttrs="aria-labelledby=\"%html_id%\"" %}
|
||||
@@ -171,72 +22,20 @@ layout: table_wrappers
|
||||
{% endif %}
|
||||
|
||||
{% if page.has_children == true and page.has_toc != false %}
|
||||
<hr>
|
||||
{% include toc_heading_custom.html %}
|
||||
<ul>
|
||||
{% for child in toc_list %}
|
||||
<li>
|
||||
<a href="{{ child.url | relative_url }}">{{ child.title }}</a>{% if child.summary %} - {{ child.summary }}{% endif %}
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% include components/children_nav.html toc_list=toc_list %}
|
||||
{% endif %}
|
||||
|
||||
{% capture footer_custom %}
|
||||
{%- include footer_custom.html -%}
|
||||
{% endcapture %}
|
||||
{% if footer_custom != "" or site.last_edit_timestamp or site.gh_edit_link %}
|
||||
<hr>
|
||||
<footer>
|
||||
{% if site.back_to_top %}
|
||||
<p><a href="#top" id="back-to-top">{{ site.back_to_top_text }}</a></p>
|
||||
{% endif %}
|
||||
|
||||
{{ footer_custom }}
|
||||
|
||||
{% if site.last_edit_timestamp or site.gh_edit_link %}
|
||||
<div class="d-flex mt-2">
|
||||
{% if site.last_edit_timestamp and site.last_edit_time_format and page.last_modified_date %}
|
||||
<p class="text-small text-grey-dk-000 mb-0 mr-2">
|
||||
Page last modified: <span class="d-inline-block">{{ page.last_modified_date | date: site.last_edit_time_format }}</span>.
|
||||
</p>
|
||||
{% endif %}
|
||||
{% if
|
||||
site.gh_edit_link and
|
||||
site.gh_edit_link_text and
|
||||
site.gh_edit_repository and
|
||||
site.gh_edit_branch and
|
||||
site.gh_edit_view_mode
|
||||
%}
|
||||
<p class="text-small text-grey-dk-000 mb-0">
|
||||
<a href="{{ site.gh_edit_repository }}/{{ site.gh_edit_view_mode }}/{{ site.gh_edit_branch }}{% if site.gh_edit_source %}/{{ site.gh_edit_source }}{% endif %}{% if page.collection and site.collections_dir %}/{{ site.collections_dir }}{% endif %}/{{ page.path }}" id="edit-this-page">{{ site.gh_edit_link_text }}</a>
|
||||
</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
</footer>
|
||||
{% endif %}
|
||||
{% include components/footer.html %}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% if site.search_enabled != false %}
|
||||
{% if site.search.button %}
|
||||
<a href="#" id="search-button" class="search-button">
|
||||
<svg viewBox="0 0 24 24" class="icon"><use xlink:href="#svg-search"></use></svg>
|
||||
</a>
|
||||
{% endif %}
|
||||
|
||||
<div class="search-overlay"></div>
|
||||
{% include components/search_footer.html %}
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
{% if site.mermaid %}
|
||||
<script>
|
||||
var config = {% include mermaid_config.js %};
|
||||
mermaid.initialize(config);
|
||||
window.mermaid.init(undefined, document.querySelectorAll('.language-mermaid'));
|
||||
</script>
|
||||
{% include components/mermaid.html %}
|
||||
{% endif %}
|
||||
</body>
|
||||
</html>
|
||||
|
Reference in New Issue
Block a user