Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Breadcrumb customization options #6953

Open
6 of 7 tasks
ben-qnimble opened this issue Mar 21, 2022 · 17 comments
Open
6 of 7 tasks

Add Breadcrumb customization options #6953

ben-qnimble opened this issue Mar 21, 2022 · 17 comments
Labels
feature This is not a bug or issue with Docusausus, per se. It is a feature request for the future.

Comments

@ben-qnimble
Copy link
Contributor

Have you read the Contributing Guidelines on issues?

Prerequisites

  • I'm using the latest version of Docusaurus.
  • I have tried the npm run clear or yarn clear command.
  • I have tried rm -rf node_modules yarn.lock package-lock.json and re-installing packages.
  • I have tried creating a repro with https://new.docusaurus.io.
  • I have read the console error message carefully (if applicable).

Description

If you have the docs module configured where the structure matches the category index convention as mentioned for autogenerated sidebars, for example you have the following pages and URLs:

/docs/docs.md -> /docs/
/docs/item1.md -> /docs/item1
/docs/cat1/cat1.md -> /docs/cat1
/docs/cat1/sub1.md -> /docs/cat1/sub1
/docs/cat1/sub2.md -> /docs/cat1/sub2

it seems like in this usage, the breadcrumbs should match the URL structure and show all the links contained in the full URL. However, if you are on the sub2.md page, the bread crumbs goes from "/" to "/docs/cat1" and skip over the "/docs" url link:

"/" -> "/docs/cat1" -> "/docs/cat1/sub2"

I think the breadcrumb should either be

"/docs" -> "/docs/cat1" -> "/docs/cat1/sub2"
or
"/" -> "/docs" -> "/docs/cat1" -> "/docs/cat1/sub2"

Basically, the first idea would be to have the breadcrumbs "home" to go to "/docs" instead of "/" (when /docs is a valid URL). I think this makes sense since the breadcrumbs are specific to the docs module, so it isn't clear that "home" should go to the website home instead of the docs home. Maybe the way to implement this is for a parameter to set the breadcrumb home URL.

Another option would to (maybe optionally) add the "/docs" to the breadcrumb structure.

Reproducible demo

https://docusaurus.io/docs/sidebar/autogenerated

Steps to reproduce

Create structure like shown in https://docusaurus.io/docs/sidebar/autogenerated and enable breadcrumbs.

Expected behavior

breakcrumbs would look like

"/docs" -> "/docs/cat1" -> "/docs/cat1/sub2"

or

"/" -> "/docs" -> "/docs/cat1" -> "/docs/cat1/sub2"

Actual behavior

breadcrumbs are

"/" -> "/docs/cat1" -> "/docs/cat1/sub2"

Your environment

Tested on beta17

Self-service

  • I'd be willing to fix this bug myself.
@ben-qnimble ben-qnimble added bug An error in the Docusaurus core causing instability or issues with its execution status: needs triage This issue has not been triaged by maintainers labels Mar 21, 2022
@Josh-Cena
Copy link
Collaborator

Josh-Cena commented Mar 21, 2022

Hi, in a perfect world, this would be the case; however, this is virtually not achievable.

Routes are very arbitrary. Because you can use slug to customize a page's route, the existence of /docs/cat1/sub2 doesn't imply the existence of /docs or /docs/cat1 at all. And even if those routes exist, there's no implication that they are logically connected to /docs/cat1/sub2. Therefore, we would generate breadcrumbs based on the sidebar structure.

Now, maybe the issue is just a misconception of how breadcrumbs work, but being maximally charitable, this is actually what we plan to do: including more segments in the breadcrumbs. However, the problem is that the /docs path means the root path of a plugin, but plugins don't have human-readable labels yet. Moreover, we'd also like to include the sidebar in that, so that the breadcrumbs would be like plugin name > sidebar name > position of this doc in the sidebar. See #6786.

@Josh-Cena Josh-Cena added feature This is not a bug or issue with Docusausus, per se. It is a feature request for the future. and removed bug An error in the Docusaurus core causing instability or issues with its execution status: needs triage This issue has not been triaged by maintainers labels Mar 21, 2022
@Josh-Cena Josh-Cena changed the title Breadcrumbs match URL structure Include plugin route base path and sidebar path in breadcrumbs Mar 21, 2022
@ben-qnimble
Copy link
Contributor Author

Thanks for the info, this is more complex than I appreciated. It seems like the discussions in #6786 may include changes that would address my issue. I've posted a comment there.

@slorber
Copy link
Collaborator

slorber commented Mar 23, 2022

As commented in the other issue, it looks like a plugin option such as:

breadcrumbPrefix: [
  { to: "/", label: "🏠" },
  { to: "/docs", label: "Docs home" }
];

could work for you?

Eventually, we could also add "breadcrumb item types", to cover more dynamic cases like showing a human-readable sidebar label?

breadcrumbPrefix: [
  { to: "/", label: "🏠" },
  { to: "/docs", label: "Docs home" },
  { type: "sidebarName" }
];

Does it make sense?

(note we don't have any human-readable docs-plugin label or sidebar label yet)


Some related questions:

  • Do we want to allow computing a custom breadcrumb on a per-doc basis, using a callback to create or modify the default breadcrumb?
  • Do we only want a prefix, or also a prefix? Should we have a { type: "sidebarBreadcrumb" } type for maximum flexibility?

@slorber slorber changed the title Include plugin route base path and sidebar path in breadcrumbs Add Breadcrumb customization options Mar 23, 2022
@ben-qnimble
Copy link
Contributor Author

I don't think I fully appreciate what can be done if we have the option type: "sidebarName", but I like the breadcrumbPrefix idea in general.

I think having an individual doc override the breadcrumb makes sense. Something like:

---
id: MainDoc
slug: /
breadcrumbPrefix: [ { to: "/", label: "🏠" }]
---

I think this might be useful when the default breadcrumbPrefix is ["/", "/docs"] for the doc that has a slug of "/" (full url is "/docs") so the breadcrumb isn't "

/ -> /docs -> /docs

where the last item is the current page, which is also the last item in the breadcrumbPrefix. (Although maybe this could be address in other logic.)

@slorber
Copy link
Collaborator

slorber commented Mar 23, 2022

I don't think I fully appreciate what can be done if we have the option type: "sidebarName",

Docusaurus site has 2 sidebars: Docs and API

This means that one of those labels could eventually appear in the breadcrumb.

For example: Home > API > CLI instead of

image


adding frontMatter can be convenient yes.

Maybe for maximum flexibility you should be able to provide the full breadcrumb too?

breadcrumb: [ { to: "/", label: "🏠" } , {to:  "/docs/xyz", label :"XYZ" }]

breadcrumb:
  prefix: [ { to: "/", label: "🏠" }]

🤷‍♂️


I don't understand the last part 😅

@ben-qnimble
Copy link
Contributor Author

Thanks for the explanation. Having { type: "sidebarName" } as an option makes sense now. I think sites with multiple sidebars could use that functionality.

My point about an individual doc overriding the default breadcrumb prefix is that when on a page that is included in the default breadcrumb prefix, that might generate a breadcrumb that lists the page twice: once as part of the prefix, and once as the current page. Having the means to change the breadcrumb prefix for just that page might be a useful way to avoid that issue. (But again, there are other solutions).

I think having a breadcrumb prefix and a full breadcrumb override makes sense. One use case could be shortening the breadcrumbs (skipping some entries) for sites that have lots of structure. Or localizing it so you can't go 'too far' back in one shot.

@chernodub
Copy link
Contributor

Hi guys, firstly, thanks for your contribution to the community, I really appreciate what you're doing and my team enjoys using Docusaurus.

Preface/context

We're currently using it to build an internal wiki website that would have several tech-stack scopes. Basically, the structure is similar like in @slorber's example. At the same time, we'd like to preserve the consistency within the docs/ directory. Docs structure would be similar to the following (example, similar to ours, in a way):

docs/
  frontend/
    frameworks/
      angular/
        best-practices.md
        whatever.md
  backend/
    python/
      best-practices.md
      whatever.md

We're using several autogenerated sidebars (each one represents a directory within docs/ folder). By using autogenerated + dirName in sidebars.js. I've also provided an example on stackblitz, consider checking it out.

It's all working fine except the breadcrumbs, it basically ignores the starting directory in docs/, since sidebar considers a directory from dirName to be a root. (e.g. for /docs/backend/python/best-practices/ we would get 🏠 > Python > Best Practices). This is not what we really need, and I'd like to propose a solution too.

As the guys suggested, we could use the breadcrumb prefix like: [{ to: "/", label: "🏠" } , {to: "/docs/xyz", label :"XYZ" }]. But, when leveraging autogenerated sidebar, it's going to be a pain to add this meta-header for each file within a directory (also, this would break the auto-generation purpose, in a way, since each child document would know where it lies).

So, my idea would be to also be able to use _category_.json (or some other meta file) for providing a prefix for all of its descendants. Here's an example:

docs/
  frontend/
    _category_.json <!-- { breadcrumbPrefix: [ { to: "/", label: "🏠" } , {to:  "/frontend", label :"Frontend" }] } -->
    frameworks/
      angular/
        best-practices.md
        whatever.md
  backend/
    _category_.json <!-- { breadcrumbPrefix: [ { to: "/", label: "🏠" } , {to:  "/backend", label :"Backend" }] } -->
    python/
      best-practices.md
      whatever.md

This way, a breacrumb prefix could be auto-generated for all of the pages within these directories. For /docs/frameworks/angular/best-practices it would be 🏠 > Frontend > Framework > Angular > Best Practices. Please note that best-practices.md doesn't have any information regarding the breadcrumb, it's inherited by one of the parent's _category_.json.

Also, so as not to duplicate the original root prefix, and to avoid the possible conflicts with it (in case it's changed in future), we could use some string constant, like "default_root" instead of { to: "/", label: "🏠" }. As a result, we would get something like breadcrumbsPrefix: ["default_root", {to: "/backend", label :"Backend" }]. Or, in case this is not going to work, we could also use some other header that would implicitly append our prefix to the root. Example: additionalBreadcrumbPrefix: [{to: "/backend", label :"Backend" }]

I'm interested to hear your opinion on this, guys. And thanks again!

@ben-qnimble
Copy link
Contributor Author

Hi chernodub,

I think I'm understanding what you want, and it seems to me, unless I'm missing something, that as currently structured the breadcrumbs will do what you want (except for the link to /docs). If you use the category index convention, and have:

docs/
  frontend/
    index.md   -- this is the page for the url "docs/frontend/"
    frameworks/
      index.md   -- this is the page for the url "docs/frontend/frameworks/"
      angular/
        index.md   -- this is the page for the url "docs/frontend/frameworks/angular/"
        best-practices.md
        whatever.md
  backend/
   index.md   -- this is the page for the url "docs/backend/"
    python/
      index.md   -- this is the page for the url "docs/backend/python/"
      best-practices.md
      whatever.md

then you will get an auto-generated breadcrumbs for /docs/backend/python/whatever of "Home" -> "Backend" -> "Python" -> "Whatever"
and for /docs/frontend/frameworks/angular/whatever of "Home" -> "Frontend" -> "Frameworks" -> "Angular" -> "Whatever"

I think the only part that is missing is if you want "Home" -> "Docs" -> "Frontend" and/or to "Docs/" -> "Frontend" without the "Home"

Am I misunderstanding anything?

@chernodub
Copy link
Contributor

chernodub commented Mar 29, 2022

Yes, you're right, that was my mistake, since I didn't know (at the time of writing my previous comment) that a root folder (specified in sidebars.js) is not considered to be a category in Docusaurus.
So, _category_.json/index.md doesn't really fit here. Consider this example, root folders are not present in breadcrumb. What I need is to set a breadcrumbPrefix for each descendant of frontend/backend roots.
I think it is only achievable either by providing some kind of root metadata, or by passing an additional property to autogenerated sidebar, like the following:

sidebars.js

const sidebars = {
  frontend: [{type: 'autogenerated', dirName: 'frontend', breadcrumb: 'Frontend'}],
  dotnet: [{type: 'autogenerated', dirName: 'dotnet', breadcrumb: 'Backend'}],
};

I still may miss something, so feel free to lead me to a right direction

@Josh-Cena
Copy link
Collaborator

Autogenerated will be eventually unwrapped to regular sidebar items, so the idea is that we need to set metadata for each sidebar, like frontend: { breakdcrumb: "Frontend", items: [{ type: "autogenerated", dirName: "frontend"] } }, which is currently not possible (each sidebar is only an array of items; no place for metadata).

@chernodub
Copy link
Contributor

Sounds reasonable, this will definitely fit a use-case I described before

@kolos450
Copy link

kolos450 commented May 8, 2022

It would be great to have an option to provide some arbitrary breadcrumbs to Docusaurus.

Previously I used a custom breadcrumbs component for some pages of a Docusaurus website with a complex structure. But now there's a cute out-of-the-box component and I would like to enable it for the rest of the website. The point is that I cannot use a single template currently and have to copy it to ensure the components look indistinguishable.

Perhaps it would be acceptable to introduce something like sidebarItemsGenerator docs plugin option but for breadcrumbs?

@ezbeazy
Copy link

ezbeazy commented Sep 4, 2022

just a breadcrumb_label option in doc front matter would be great

@slorber
Copy link
Collaborator

slorber commented Sep 7, 2022

frontMatter.breadcrumb_label + sidebarCategoryItem.breadcrumbLabel 👍 we can easily add this today until we figure more advanced customization cases.

Does anyone want to send a PR?

@3v0k4
Copy link
Contributor

3v0k4 commented Dec 12, 2022

I was trying to have the home breadcrumb link go to a custom URL (not /) and landed on this issue.

Solution

Eject

npm run swizzle @docusaurus/theme-classic DocBreadcrumbs -- --eject

Customize the URL

/src/theme/DocBreadcrumbs/index.js:

-  const homeHref = useBaseUrl('/');
+  const homeHref = useBaseUrl('/overview');

You should also update the aria labels in HomeBreadcrumbItem.


@slorber What if we extracted HomeBreadcrumbItem into a separate component that can be ejected without ejecting all the DocBreadcrumbs? I'd be happy to look into it and open a PR if it's useful 🙂

@slorber
Copy link
Collaborator

slorber commented Dec 14, 2022

I'm not against extracting a few breadcrumbs components if that can simplify things on the short term until we figure out a good api/options.

We can keep the components as unsafe to swizzle until we find the best structure

@octogonz
Copy link

octogonz commented May 24, 2024

I was trying to have the home breadcrumb link go to a custom URL (not /) and landed on this issue.

For what it's worth, I encountered the same requirement.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature This is not a bug or issue with Docusausus, per se. It is a feature request for the future.
Projects
None yet
Development

No branches or pull requests

8 participants