Coder Social home page Coder Social logo

Comments (27)

josevalim avatar josevalim commented on August 16, 2024 1

Tabsets look good to me. @DavidOliver, would you be interested in sending a PR for this?

from ex_doc.

josevalim avatar josevalim commented on August 16, 2024 1

Beautiful! Just please make sure that if you generate the docs with --language erlang, the detail over the tab is in red and not purple (which will be the case if you are using the css vars anyway!).

from ex_doc.

wojtekmach avatar wojtekmach commented on August 16, 2024

Funny that you mention it, I was thinking about it a lot recently but taking it even further, automatically generating Elixir code snippet out of Erlang and vice-versa. :) Showing things in tabs is orthogonal problem to that so let's definitely focus on that first.

I have found that rmarkdown has tabsets. Could you do some more research and see if there's any other prior art?

from ex_doc.

DavidOliver avatar DavidOliver commented on August 16, 2024

@josevalim Yes, I'll take a look. Thanks!

from ex_doc.

DavidOliver avatar DavidOliver commented on August 16, 2024

@wojtekmach, I expect you may have realised this (I didn't): the tabsets mentioned are specific to R Markdown, and I believe they are not available via EarmarkParser, which supports Gruber + some of GitHub Flavored Markdown.

So are we agreed that we would be adding an ExDoc-specific custom feature? If so, I'll take a look through ExDoc's code and see if I can see where to start working on the parsing, which will be new to me. Are we definitely happy with the R Markdown syntax?

Just to share the only other thing I found on tabsets in Markdown-esque documents, Docusaurus also supports tabsets, via MDX (JSX).

from ex_doc.

wojtekmach avatar wojtekmach commented on August 16, 2024

yeah tabs aren't standardised. I think supporting the syntax like the one in rMarkdown would make them super ergonomic to use but I think we can start with no syntax changes, e.g.:

<div class="tabset">
## Tab 1

Content 1
</div>

<div class="tabset">
## Tab 2

Content 2
</div>

in other words, we just make the necessary CSS changes. And then whether we add syntax for it is a separate discussion. WDYT?

from ex_doc.

DavidOliver avatar DavidOliver commented on August 16, 2024

Okay, great - I'll go with that. Thanks.

from ex_doc.

DavidOliver avatar DavidOliver commented on August 16, 2024

I was wondering about starting to use Alpine for the tabs, and perhaps progressively replacing other custom JS + Handlebars templates over time. Is that something you'd like me to explore, or would you prefer I stick with the approach currently in use?

from ex_doc.

josevalim avatar josevalim commented on August 16, 2024

Let's stick with the current approach for now!

from ex_doc.

DavidOliver avatar DavidOliver commented on August 16, 2024

I've made a start but have run up against the issue whereby content in HTML elements is not parsed as Markdown, meaning, I think, all code blocks, lists, etc. would have to be marked up as HTML by the author if we went with the HTML structure mentioned previously. Some Markdown parsers support Markdown in HTML, but I don't think ours does; see 'HTML blocks' here.

Perhaps we can use the existing class-adding mechanism to add a 'tab' class to H4s?

#### Tab 1 {: .tab}

Tab 1 content.

#### Tab 2 {: .tab}

Tab 2 content.

We should then be able to convert the HTML output into tabs-suitable HTML.

We'd have to decide how to denote the end of the (last) tab content. I.e. until another heading, or maybe via a designated end word? 🤔

from ex_doc.

josevalim avatar josevalim commented on August 16, 2024

@DavidOliver going with the classes would be the preferred approach for sure. Although I assume we would need to annotate the "parent" of the tabs instead? Because that will annotate only the header but we need to wrap the contents somehow. And maybe that's not doable with only Markdown?

from ex_doc.

DavidOliver avatar DavidOliver commented on August 16, 2024

I was planning to handle that via selecting elements/output as necessary via JS. I think this would be necessary either way, but maybe annotating a parent heading would be better overall.

#### Tabs content {: .tabs}

##### Tab 1

Tab 1 content.

##### Tab 2

Tab 2 content.

If we go with something like that, do you have any thoughts on how to terminate the tabs content, at the end of the last tab? I've seen another doc tool that requires a new header, but it seems a shame to not allow for non-heading content after a tabset.

I was wondering if a new paragraph with the text 'tabs end' as content would be acceptable, if a little clunky. Maybe there's some other Markdown/HTML comment approach we could use?

I have to leave the keyboard for a few hours now, but will try to find something useful later.

from ex_doc.

DavidOliver avatar DavidOliver commented on August 16, 2024

Maybe:

#### Tabs content {: .tabs}

##### Tab 1

Tab 1 content.

##### Tab 2

Tab 2 content.

#### This heading will be deleted via JS {:. .tabs-end}

Non-tab paragraph text!

(Yuck?)

from ex_doc.

josevalim avatar josevalim commented on August 16, 2024

We need to write it in a way that it renders "ok" outside of ExDoc where those classes are not considered. Perhaps using rulers would be fine:

--- {: .tabs-open}

### Tab 1

Tab 1 content.

### Tab 2

Tab 2 content.

--- {: .tabs-close}

?

from ex_doc.

DavidOliver avatar DavidOliver commented on August 16, 2024

Nice. The class attribute isn't added to hr unless the {: ...} is on the following line, but I think that's fine?

So the Telemetry documentation referenced in this issue's original description could be:

## Usage

In a nutshell, you register a custom module and function to be invoked for certain events,
which are executed whenever there is such an event. The event name is a list of atoms. Each event is
composed of a numeric value and can have metadata attached to it. Let's look at an example.

Imagine that you have a web application and you'd like to log latency and response status for each
incoming request. With Telemetry, you can build a module which does exactly that whenever a response
is sent. The first step is to execute a measurement.

---
{: .tabs-open}

### Elixir

```elixir
:telemetry.execute(
  [:web, :request, :done],
  %{latency: latency},
  %{request_path: path, status_code: status}
)
```

### Erlang

```erlang
telemetry:execute(
  [web, request, done],
  #{latency => Latency},
  #{request_path => Path, status_code => Status}
)
```

---
{: .tabs-close}

Then you can create a module to be invoked whenever the event happens.

And the hrs will be deleted after the Handlebars template has been applied, and the headings within the tabs section will denote each tab content panel and be used for the tab labels. We could reserve H3 headings for this, and leave H4/5/6 headings to render as headings within tab content panels? (Tabs may be used for more than code of multiple languages.)

If that looks good to you, I'll have a bash at the JS and Handlebars template. Thanks.

from ex_doc.

josevalim avatar josevalim commented on August 16, 2024

@DavidOliver is there any chance we can do this with CSS only? We can also hide the .hr with CSS but I am not sure about the rest.

from ex_doc.

DavidOliver avatar DavidOliver commented on August 16, 2024

Not as far as I can see, as we need to generate the row of tabs/buttons and split up the content into panels to be shown/hidden.

from ex_doc.

josevalim avatar josevalim commented on August 16, 2024

@wojtekmach are we ok with including markup that requires JS to work? I am not sure if I want to cross this line. :)

from ex_doc.

DavidOliver avatar DavidOliver commented on August 16, 2024

It would at least be progressive enhancement rather than being completely reliant on JS to be readable. Without JS, the content would, of course, display serially with its headings. :)

from ex_doc.

josevalim avatar josevalim commented on August 16, 2024

Good point @DavidOliver. I think it is still worth giving it a try then.

from ex_doc.

DavidOliver avatar DavidOliver commented on August 16, 2024

Quick update: I've got the content from the HTML (based on using rules, as above) in a form suitable for templating, and have the start of a Handlebars tabset template hooked up.

image

image

To do:

  1. Fix tab button text (I need to remove the screen reader-only text)
  2. Add frontend behaviour and style

Regarding 1, is there a particular reason that the headings have a slug-friendly version of the text in a sr-only <p>? Could we remove this, leaving just the actual heading text for screen readers to read? If so, this would avoid having to massage in JS the innerText of the heading into a form usable for the tab label.

<h2 id="features" class="section-heading">
  <a href="#features" class="hover-link"><i class="ri-link-m" aria-hidden="true"></i>
  <p class="sr-only">features</p> <!-- can we remove this paragraph? -->
  </a>
  Features
</h2>

Edit: oh, it's so the anchor has readable text. I'm not sure there's a good way we can preserve that without the actual inner text being present, so I'll probably go ahead with the massaging in JS.

from ex_doc.

josevalim avatar josevalim commented on August 16, 2024

Looks good to me.
Maybe the anchor does not need to have readable text? Also, isnt a p inside a link invalid?

from ex_doc.

DavidOliver avatar DavidOliver commented on August 16, 2024

Okay, great. Thanks.

Block elements are okay to go in anchors in HTML 5.

Yeah, I don't know about the anchor and readable text. Perhaps I can go ahead with getting things working and come back to it later.

from ex_doc.

DavidOliver avatar DavidOliver commented on August 16, 2024

After reading through this article, I'm leaning toward having the anchor wrap the actual heading text, which is how the mdn web docs do it. In our case:

<h2 id="features" class="section-heading">
  <a href="#features" class="hover-link">
    <i class="ri-link-m" aria-hidden="true"></i>
    Features
  </a>
</h2>

(Edit: that may need to be tweaked to keep the icon-on-hover display.)

I gather that this avoids the heading being read out twice (as we have at present, with once being a slug version - not ideal) whilst maintaining a good page structure summary.

Would you mind if I include this in the PR if I find it works out?

from ex_doc.

josevalim avatar josevalim commented on August 16, 2024

As you prefer :)

from ex_doc.

DavidOliver avatar DavidOliver commented on August 16, 2024

Okay - thanks!

The tabsets JS behaviour is now in place, including keyboard navigation and ARIA accessibility properties. Styling to do next.

from ex_doc.

DavidOliver avatar DavidOliver commented on August 16, 2024

Some tidying/testing on mobile to do, but here's where I'm currently at.

image

image

As I was considering colours as part of this, I've darkened the code background colour in the night/dark theme, lowering the contrast between it and the page background to better match that of the day/light theme.

from ex_doc.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.