Closed aantron closed 5 years ago
I think a sidebar showing the modules of the package in a hierarchy as docre does it (though preferably foldable) would go a long way. As it is, it's too easy to get lost.
odig already generates many different kinds of index. For an example, see docs.mirage.io.
Note that odig
generates only packages indexes (from the opam
metadata). What is really missing for odoc
to finally match the features of ocamldoc
is an index page for all the identifiers of a package.
I think a sidebar showing the modules of the package in a hierarchy as docre does it (though preferably foldable) would go a long way. As it is, it's too easy to get lost.
Regarding module indexes and docre
I personally don't find the side bar very usable and rather messy (as is their typography in general, the amount of information shown on a screenful is extremely poor, the usual sin of supposedly good looking typography).
For modules indexes if you take the current odoc
navigation structure it's quite easy to get to the module list just hit the up
link one or two times (module hierarchies are and should be shallow) and you are there which seems good enough.
Personally I think that a side bar (that collapses if the page is not wide enough) with only the {1
and {2
header level should be enough (and if browsers provided ui to the html outline algorithm we wouldn't even need that...).
For modules indexes if you take the current odoc navigation structure it's quite easy to get to the module list just hit the up link one or two times (module hierarchies are and should be shallow) and you are there which seems good enough.
(Or you can simply hit the package link which is more predictable)
I'm currently working on UX features for the documentation generated by odoc in some of my libraries and here are my thoughts about indices and search:
.odoc
files and use doc-ock
's types to generate a JSON index (later used with something like Fuse.js or Elasticlunr). Do you think this is the best way to do it? Here's an MVP that uses this idea: http://odis.io/doc/order-search/ (try searching for by
). And the generated JSON index looks like this:{ "kind": "Module", "path": ["order", "Order"], "name": "Ordered", "link": "order/Order/Ordered#", "html": "<p>Alias for interface builder for ordered monomorphic types.</p>" },
{ "kind": "Value", "path": ["order", "Order"], "name": "is", "link": "order/Order#val-is", "html": "<p><code class=\"code\">is a b</code> tests for physical equality of <code class=\"code\">a</code> and <code class=\"code\">b</code>.</p>\n<p>On mutable types such as references, arrays, byte sequences, records with\nmutable fields and objects with mutable instance variables, <code class=\"code\">is a b</code> is\ntrue if and only if physical modification of <code class=\"code\">a</code> also affects <code class=\"code\">b</code>.\nOn non-mutable types, the behavior of <code class=\"code\">is</code> is implementation-dependent;\nhowever, it is guaranteed that <code class=\"code\">is a b</code> implies <code class=\"code\">a = b</code>.</p>\n<p>To check if two values are physically distinct use <code class=\"code\">not (is a b)</code>.</p>" },
{ "kind": "Value", "path": ["order", "Order"], "name": "(==)", "link": "order/Order#val-(==)", "html": "<p>Using the <code class=\"code\">==</code> is discouraged because of its visual similarity with <code class=\"code\">=</code>\nand different semantics. The <a href=\"#val-is\"><code class=\"code\">is</code></a> operator should be used instead.</p>\n<p><b>Note:</b> This operator is included to raise a deprecation warning during\ncompilation.</p>\n<ul class=\"at-tag\"><li><span class=\"at-tag deprecated\">Deprecated</span> Please use "is" instead of "==".</li></ul>" },
{ "kind": "Value", "path": ["order", "Order"], "name": "compare", "link": "order/Order#val-compare", "html": "<p>Produces the ordering between two integers.</p>" },
...
Once I build something more complete I would like to contribute to odoc
as much as possible. For now having some initial feedback on the UI and the approach would be very appreciated!
Personally I think that a side bar (that collapses if the page is not wide enough) with only the {1 and {2 header level should be enough (and if browsers provided ui to the html outline algorithm we wouldn't even need that...).
I think this is a good idea. Perhaps even one level is enough.
Also, combined with this approach, take a look at the pages of cppreference. Specifically, notice the 'crumb bar' at the top, which shows you your path to the current page, and if you hover over it you can immediately go to all other options. The current odoc path is completely static, as seen here for example.
With these 2 things combined, I think we would have complete awareness of the user's current position.
As the topic is being discussed a bit: I generally like sidebars. I know some people think they waste space, but the truth is, on a modern laptop display, you can't actually make the text very wide before it becomes unreadable anyway. Humans do very poorly when columns of text get much wider than 70 or 90 characters, as they start having trouble tracking position in text by eye. (I have this problem myself). So, even given a quite large font, you have space available, and having the table of contents and index right there immediately at hand is very useful, because it means you can skip around quickly. Being able to skip around quickly means a document can have a lot more detail in it without slowing down experts. So it's an overall win.
The current odoc path is completely static, as seen here for example.
Note that this was designed on purpose. The module name tells you were you are you have the up
link and the package
link which are always at a reliable position. If you study the design a bit (how do I get to the package's module list ? how do I get to the package list ? How do I move up in the module hierarchy ?) these two links allow to perform most navigation functions between one to three clicks at a fixed position on every page. Bread crumbs tend to be difficult to aim (fitt's law, especially if you have short names e.g. the standard S
for signatures) and the position you need to click changes from pages to pages.
As the topic is being discussed a bit: I generally like sidebars. I know some people think they waste space, but the truth is, on a modern laptop display, you can't actually make the text very wide before it becomes unreadable anyway
Don't make too much assumptions about the width of computer screen. I work with a 13'' screen with an 80 columns editor on the left and a browser for the remaining space on the right, a lot of designs that people propose do not work at all for me (e.g. the given here docre
, odis
, the latter being particularly bad since it simply cut the overflowing text). Their design also tend to be too loose, which entails too little information per screenful. You can certainly add a side-bar for people who have large screens but do not force it.
Don't make too much assumptions about the width of computer screen. I work with a 13'' screen with an 80 columns editor on the left and a browser for the remaining space on the right, a lot of designs that people propose do not work at all for me
It is pretty simple to rig things so that the sidebar disappears when the width is too narrow. Indeed, adjusting to different types of displays is essential these days anyway because of mobile use.
Plugging this as a simple example of OCaml docs with a disappearing sidebar: http://aantron.github.io/lambda-soup/
@aantron That looks quite nice! It even reflows the text once you get narrow enough! (Though I will note that the examples get cut off at really narrow widths rather than developing horizontal scrolling, but this is a quibble.)
Plugging this as a simple example of OCaml docs with a disappearing sidebar:
You can see how the sidebar adds so much in terms of context-awareness.
The rendered Lwt draft from last year also has a disappearing sidebar: http://ocsigen.org/lwt/manual-draft/Lwt.html. It's not quite as good because I didn't spend as much time tweaking the widths and margins (it was just a quick thrown-together CSS to show the draft).
In both cases, the sidebar contains a TOC that appears after the module introductory material in the markup. When the screen is wide enough, it displays as a sidebar. Once the screen is narrow, it appears inline near the beginning of the page.
Let me chime in with what I have thought about docs navigations. This might be a Dune/Odig issue, but I'm curious to see if this could be handled at odoc level.
Currently, Dune and Odig generates the following pages based on the source (although it seems that odig currently does not support .mld manuals yet):
index.html
--> a listing of available opam packages (in the project for Dune, and in the current switch for Odig)<package>/index.html
--> a listing of findlib libraries inside the given package with their toplevel modules (or custom content based on index.mld
in the package dir)<package>/<page-name>.html
--> manual pages based on <page-name>.mld
in the package dir<package>/<Module>[/<Module>]/index.html
--> modules documentationDune's <package>/index.html
currently does not list manual pages (manuals are tied to packages). Even if it does, I'm not sure if a single page of manuals+modules listing is enough. I strongly believe that we should have a global navigation element that is available on all pages in a form of collapsible (perhaps even toggle-able) sidebar.
It is a matter of UX affordance, especially if we want to encourage people to write manuals. For packages such as Dune which have many pages on its manual it would be a nightmare to navigate on without a sidebar (I think it would be great if we could get Dune to dump readthedocs for dune+odoc).
Say I arrive at this page from a Google search of Lwt_result:
It is not immediately clear what other pages are available. It hurts discoverability of the package. The only navigational elements in the page is the "Up" link (how high?). The breadcrumb helps but only so much. That's why I don't exactly agree with this opinion:
it's quite easy to get to the module list just hit the up link one or two times (module hierarchies are and should be shallow) and you are there which seems good enough.
I think we shouldn't be satisfied with only "good enough". If we can cut one or two clicks it can improve the UX by a whole lot. I hate going to shopping malls where direction signs (e.g. to elevators, restrooms, etc.) are rare. It's not fun having to find and ask a security or to go to the mall's entrance just to find out the restroom was a few steps away from where I originally was.
Another problem with having <package>/index.html
contain the listing is, if we want to have a custom index.mld, the global page listing is totally lost. It could be solved with odoc exposing a mechanism to manually insert the listing, and I'm not sure if odoc supports the {!modules: <module...>}
element, but even so, it requires users to not forget to do it (which also could contribute to more inconsistencies between different packages' docs).
Hence, my proposal is to just put the global navigation elements into the sidebar. The <package>/index.html
can be left as is for default implementation if users don't create their own index.mld
.
Now, another question is what needs to be on the sidebar. The one I have in my mind is as follows:
As you can see, 1 and 3-5 are global to the package and 2 is local to the page. This can make the sidebar horizontally long and needs scrolling, but I don't see anything wrong with that. IMO It's better to have a reasonably comprehensive "map" available at all times.
As an aside, it would also be great if odoc has a configuration mechanism as to how the manual pages are ordered (either accepting sexp/json config file or via numbered filenames (e.g. 01-introduction.mld
, 02-getting-started.mld
, etc.).
Would love to hear people's thoughts on this.
I agree that the current state is probably not sufficient for easy navigation, but I think that putting other modules in the sidebar will just make the sidebar unusable. Most packages where the navigation is currently difficult have a lot of modules in them, and an alphabetical list of them is basically useless. All it will do is fill the sidebar with noise that makes it hard to find the useful local links.
I'm generally not a fan of side-bars, the small space makes it difficult for them to provide useful information. They are rarely used relative to the amount of screen space they occupy and they detract from the experience of reading the main content of the page. There is a reason that websites have pretty much universally abandoned them as navigation elements. They're okay for showing the structure of the current page (although they're less intrusive if they are on the right rather than the left of the page) but their not a good way to show the structure of the whole site.
The only real way to make large packages easily navigable is for the authors of those libraries to actually write a decent landing page, and to write good module title comments that include links to other related modules. I think we should focus on making it easier for them to do that rather than adding too many built-in navigation elements.
The UX reasoning behind up links/breadcrumbs and landing pages is a good one. On the modern internet clicking away to a separate landing page is quick. It allows you to use the whole landing page to display the structure of the content, and doesn't waste space on the other pages trying to display this structure. However, currently that experience is not great with odoc. It is hard to write a good landing page, as odoc doesn't offer any real assistance for things like making lists of modules. The "up" link and breadcrumbs also don't give a great indication of where you actually are at the moment -- it is not that clear in your example that you are on the API documentation of version N of the lwt library/package -- which, as you say, is painful if you arrive via an external link.
Quite in agreement with @lpw25 but:
It is hard to write a good landing page, as odoc doesn't offer any real assistance for things like making lists of modules.
I'm not sure what you mean by that, odoc
does support the {modules:
directive. What kind of other "real assistance" do you envision here ?
Most packages where the navigation is currently difficult have a lot of modules in them, and an alphabetical list of them is basically useless. All it will do is fill the sidebar with noise that makes it hard to find the useful local links.
I disagree that it would be useless, but I understand what you mean. That is why I propose the list of modules to be at the bottom of the sidebar, and the local links and manual links above it, hence it will present the most relevant information first. With enough visual cues I think it can be made intuitive. Having it there is also friendlier for CTRL+F
ing something you're not sure exist.
I'm generally not a fan of side-bars, the small space makes it difficult for them to provide useful information. They are rarely used relative to the amount of screen space they occupy and they detract from the experience of reading the main content of the page.
This should be solvable with collapsible and toggle-able sidebar. When I say that, I was referring to something along the lines of Elixir's generated docs (e.g. for the Phoenix web framework). Granted, even in the Elixir one the module listing is hidden in the MODULES
menu item on the sidebar. Elixir's docs is also more sophisticated in the link grouping aspect.
There is a reason that websites have pretty much universally abandoned them as navigation elements.
I'm not sure how much of this is true for documentation sites for libraries though, I still think that it is more common to have sidebars in doc pages (Elixir, Ruby, Python, Sphinx, Javadoc). I'd love to be proven wrong. That said, if there is an alternative other than sidebars that could include global navigation elements then I guess I'll be okay with it (dropdown menus?). I also don't mind it being on the right side, fwiw.
The only real way to make large packages easily navigable is for the authors of those libraries to actually write a decent landing page, and to write good module title comments that include links to other related modules. I think we should focus on making it easier for them to do that rather than adding too many built-in navigation elements.
Eh, humans are lazy... I think if odoc could handle creating a tidy list of links for them then authors can have one less thing to worry about and focus more on creating nice content.
What kind of other "real assistance" do you envision here ?
Well, I'd forgotten that modules
was implemented (I remember adding it to the original parser but I didn't realize it actually did anything yet). Other things I've had in mind is things like a {desc: Foo}
reference that expands to the "description" sentence for the a module, {doc: Foo.t}
that expands to the doc string of an item. Basically more tools for showing the data that odoc has, so that you have more flexibility for crafting landing pages.
I was going to suggest to either close (and accidentally did so) or clarify the scope of this issue. Now that https://github.com/ocaml/odoc/pull/261 is merged, odoc generates a TOC on all module pages. We also have a more specific issue for TOCs on mld pages (https://github.com/ocaml/odoc/issues/294).
I'm fine with closing this. Having a page with identifier indexes would be nice though I will open an issue for it.
Having a page with identifier indexes would be nice though I will open an issue for it.
We already have https://github.com/ocaml/odoc/issues/52 tracking this.
We need:
odig already generates many different kinds of index. For an example, see docs.mirage.io.
cc @yawaramin @bluddy @pmetzger