Skip to content

List things related to a resource with a custom display #119

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

Open
wants to merge 22 commits into
base: main
Choose a base branch
from

Conversation

jg10-mastodon-social
Copy link
Collaborator

@jg10-mastodon-social jg10-mastodon-social commented May 24, 2025

Partly addresses #43

This PR descoped to exclude rev, given this will involve changes very similar to rel. Covering rev in a separate PR will hopefully make both PRs easier to review.

if (templateElement == null) {
this.error = "No template element found"
} else if (templateElement.content.childElementCount != 1) {
this.error = "Template element should only have one child, e.g. li"
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The reason for this is that the component will provide resources to each child based on their index. Compared to #43 (comment) this gets rid of the intermediate pos-resource. However, it will still not be possible to have li nested directly within ul, given that pos-list lies between them.

Copy link
Collaborator Author

@jg10-mastodon-social jg10-mastodon-social May 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One option would be to allow pos-list to be used as a customized built-in element, i.e. <ul is="pos-list"></ul>. I would need to look into whether/how stenciljs supports this.

Update: stenciljs does not support customized built-in elements stenciljs/core#4089 (comment)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about assigning role="list"?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The issue I had in mind is that the only permitted parents for li are ul and ol (or menu). So if a dashboard user cares about correct HTML then I suppose they could use <div role="listitem" style="display:list-item"> I hadn't thought of that.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've currently ignored correct HTML for this PR. In storybook I've used bare lis. Let me know if it's an issue.

Copy link
Contributor

@angelo-v angelo-v Jun 10, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should care for correct HTML and accessibility. Are you sure it would be invalid? As I understand this answer it would not

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wasn't aware of that, and indeed I tried the pos-list-composition storybook example in https://websiteaccessibilitychecker.com/checker/index.php and it also passes.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In my understanding pos-list should have role "list" and each child role "listitem" by default without additional effort by the dashboard author. pos-list is a list by definition and the created children are it's items

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

image
This is what I get in storybook adding role="listitem" to pos-resource and <Host role="list"> arround the elems

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I disagree that pos-list is by definition a list - when it's used to produce inline text, the contents can just be a sequence of static text - they should not necessarily be described to the user as list items.

More importantly, I would argue that a dashboard author should be encouraged to use appropriate semantic HTML elements, and if we default to setting role "list" and child role "listitem", then this will clash with any use of ul and li - we end up with nested listitems.

That said, the composition storybook example neglected to include ul, and I have now fixed that.

The current code (without aria roles) produces:
image

Code with aria roles:

const elems = this.items.map(it => (
      <pos-resource role="listitem" uri={it} lazy={!this.fetch} innerHTML={this.templateString} about={it}></pos-resource>
    ));
    return this.items.length > 0 ? <Host role="list">{elems}</Host> : null;

image

@jg10-mastodon-social jg10-mastodon-social marked this pull request as ready for review June 7, 2025 06:42
@jg10-mastodon-social
Copy link
Collaborator Author

I've marked as ready for review because I'm not sure what e2e test should be included (is the integration test enough?), and I think we can maybe descope and implement rev in a separate PR - this one is probably complex enough as it is?

Copy link
Contributor

@angelo-v angelo-v left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good work so far! I have several comments and questions, but many of them are minor, I think this goes into a good direction.

@angelo-v
Copy link
Contributor

angelo-v commented Jun 9, 2025

all dependencies are updated to the latest patch version at minimum

You don't need to bother with this in the PR, I will do this after merging before releasing a new version

@angelo-v
Copy link
Contributor

angelo-v commented Jun 9, 2025

I am having an issue using this within another stencil component. If I paste an example directly in index.html it works, but the same example fails when I e.g. use it in pos-app-browser (just replacecing the regular pos-app content with the pos-list example).

In the latter case it fails, because it does not recognize the template child (childElementCount == 0). Don't know why yet.

@angelo-v
Copy link
Contributor

angelo-v commented Jun 9, 2025

It seems to be related to what is described here: https://stackoverflow.com/a/70778523

If I pass the content to <template innerHTML={"..."} instead of the template body then it works!

@angelo-v
Copy link
Contributor

angelo-v commented Jun 9, 2025

I managed to show my bookmarks using pos-list by the way, which is really cool!

<pos-app>
      <pos-resource uri="https://angelo.veltens.org/public/bookmarks">
        <pos-list rel="http://purl.org/dc/terms/references">
          <template>
            <article>
              <h2>
                <pos-label></pos-label>
              </h2>
              <pos-value predicate="http://www.w3.org/2002/01/bookmark#recalls"></pos-value>
            </article>
          </template>
        </pos-list>
      </pos-resource>
    </pos-app>

What is unfortunately still not possible with PodOS is actually linking to the value because I cannot use pos-value in an <a href for example. Not sure if we have an issue for this yet see #123

@jg10-mastodon-social
Copy link
Collaborator Author

If I pass the content to <template innerHTML={"..."} instead of the template body then it works!

That's frustrating. Is that ok as a solution, or would you like to explore an approach that doesn't use the template tag?

I would expect that stencil components would very rarely use pos-list - given they are written in JS they can just use Thing's methods directly and create their own list.

@angelo-v
Copy link
Contributor

angelo-v commented Jun 10, 2025

That's frustrating. Is that ok as a solution, or would you like to explore an approach that doesn't use the template tag?

Nah, I think template is the right approach, is just weired with stencil, I guess we can live with that.

I would expect that stencil components would very rarely use pos-list - given they are written in JS they can just use Thing's methods directly and create their own list.

Yes indeed, though I think the issue is not only with stencil but with everything that creates template programmatically, e.g. also with React and other frameworks (would need to try out seems to be https://stackoverflow.com/a/42845196). But you could argue using those frameworks you are / have to be aware of this behavoiur, it is not unique to PodOS but html template in general.

@jg10-mastodon-social
Copy link
Collaborator Author

jg10-mastodon-social commented Jun 16, 2025

With the switch to pos-resource it turns out I need to address loading of resources (incl. #97 for lists) in this PR because pos-resource by default does fetch.

I've run into two problems: I can't get pos-resource to not fetch when testing, and even when it does fetch, os.fetch is being called twice, the first time with an undefined uri.
https://github.com/pod-os/PodOS/actions/runs/15671398762/job/44143056979?pr=119#step:7:438

Storybook seems to work fine. I'm guessing I've made a mistake in mocking, but maybe it's in how I call pos-resource in pos-list?

On my system I also get warnings:

    console.warn
      @Prop() "uri" on <pos-resource> is immutable but was modified from within the component.
      More information: https://stenciljs.com/docs/properties#prop-mutability

      at consoleDevWarn (node_modules/@stencil/core/internal/testing/index.js:162:11)
      at PosResource.set (node_modules/@stencil/core/internal/testing/index.js:2882:17)
      at PosResource.set (node_modules/@stencil/core/internal/testing/index.js:2895:26)
      at setterSetVal (node_modules/@stencil/core/internal/testing/index.js:2921:48)
      at node_modules/@stencil/core/internal/testing/index.js:2927:49

    console.warn
      @Prop() "lazy" on <pos-resource> is immutable but was modified from within the component.
      More information: https://stenciljs.com/docs/properties#prop-mutability

      at consoleDevWarn (node_modules/@stencil/core/internal/testing/index.js:162:11)
      at PosResource.set (node_modules/@stencil/core/internal/testing/index.js:2882:17)
      at PosResource.set [as lazy] (node_modules/@stencil/core/internal/testing/index.js:2895:26)
      at setterSetVal (node_modules/@stencil/core/internal/testing/index.js:2921:48)
      at node_modules/@stencil/core/internal/testing/index.js:2927:49

[repeated warnings elided]

  ● pos-list › does not fetch resources by default (if fetch attribute is not present)

    expect(received).toHaveLength(expected)

    Expected length: 0
    Received length: 4
    Received array:  [[undefined], [undefined], ["https://video.test/video-1"], ["https://video.test/video-2"]]

       96 |     });
       97 |
    >  98 |     expect(os.fetch.mock.calls).toHaveLength(0);
          |                                 ^
       99 |   });
      100 |
      101 |   it('fetch resources if fetch attribute is present', async () => {

      at Object.<anonymous> (src/components/pos-list/pos-list.integration.spec.tsx:98:33)

  ● pos-list › fetch resources if fetch attribute is present

    expect(received).toHaveLength(expected)

    Expected length: 2
    Received length: 4
    Received array:  [[undefined], [undefined], ["https://video.test/video-1"], ["https://video.test/video-2"]]

      132 |     });
      133 |
    > 134 |     expect(os.fetch.mock.calls).toHaveLength(2);
          |                                 ^
      135 |     expect(os.fetch.mock.calls).toEqual([['https://video.test/video-1'], ['https://video.test/video-2']]);
      136 |   });
      137 | });

      at Object.<anonymous> (src/components/pos-list/pos-list.integration.spec.tsx:134:33)

Edit: I've pushed an extra commit that implements the fetch attribute + unit tests - but this doesn't address the issue in this integration test

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants