public inbox for yew-devel@lists.proxmox.com
 help / color / mirror / Atom feed
From: "Shannon Sterz" <s.sterz@proxmox.com>
To: "Dominik Csapak" <d.csapak@proxmox.com>
Cc: yew-devel@lists.proxmox.com
Subject: Re: [PATCH yew-comp 1/3] task (viewer): add task download button
Date: Tue, 31 Mar 2026 09:39:46 +0200	[thread overview]
Message-ID: <DHGSMHN0N6TA.292F4RLLAQUU3@proxmox.com> (raw)
In-Reply-To: <6e6fa075-2b27-4635-8fcf-ebdcdfdad3d8@proxmox.com>

On Mon Mar 30, 2026 at 4:44 PM CEST, Dominik Csapak wrote:
>
>
> On 3/30/26 4:39 PM, Shannon Sterz wrote:
>> On Mon Mar 30, 2026 at 4:23 PM CEST, Dominik Csapak wrote:
>>>
>>>
>>> On 3/30/26 4:17 PM, Shannon Sterz wrote:
>>>> On Mon Mar 30, 2026 at 3:48 PM CEST, Dominik Csapak wrote:
>>>>>
>>>>>
>>>>> On 3/30/26 3:35 PM, Shannon Sterz wrote:
>>>>>> On Mon Mar 30, 2026 at 2:53 PM CEST, Dominik Csapak wrote:
>>>>> [snip]
>>>>>>> @@ -273,18 +297,94 @@ impl PwtTaskViewer {
>>>>>>>             let active = self.active;
>>>>>>>             let link = ctx.link();
>>>>>>>
>>>>>>> -        let toolbar = Toolbar::new().class("pwt-border-bottom").with_child(
>>>>>>> -            Button::new(tr!("Stop"))
>>>>>>> -                .disabled(!active)
>>>>>>> -                .onclick(link.callback(|_| Msg::StopTask)),
>>>>>>> -        );
>>>>>>> -
>>>>>>>             let url = format!(
>>>>>>>                 "{}/{}/log",
>>>>>>>                 props.base_url,
>>>>>>>                 percent_encode_component(&task_id),
>>>>>>>             );
>>>>>>>
>>>>>>> +        let filename = match props.task_id.parse::<ProxmoxUpid>() {
>>>>>>> +            Ok(upid) => {
>>>>>>> +                format!(
>>>>>>> +                    "task-{}-{}-{}.log",
>>>>>>> +                    upid.node,
>>>>>>> +                    upid.worker_type,
>>>>>>> +                    epoch_to_rfc3339_utc(upid.starttime).unwrap_or(upid.starttime.to_string())
>>>>>>> +                )
>>>>>>> +            }
>>>>>>> +            Err(_) => format!("task-{}.log", props.task_id),
>>>>>>> +        };
>>>>>>> +
>>>>>>> +        let download_btn: Html = if props.download_api {
>>>>>>> +            Container::from_tag("a")
>>>>>>> +                .attribute("disabled", active.then_some(""))
>>>>>>> +                .attribute("target", "_blank")
>>>>>>> +                .attribute("href", format!("/api2/extjs{url}?download=1"))
>>>>>>> +                .attribute("filename", filename)
>>>>>>> +                .with_child(
>>>>>>> +                    Button::new(tr!("Download"))
>>>>>>> +                        .disabled(active)
>>>>>>> +                        .icon_class("fa fa-download"),
>>>>>>> +                )
>>>>>>> +                .into()
>>>>>>
>>>>>> is there a reason you construct a new `<a>` element as a container here
>>>>>> instead of using the `download_as_file` helper in an `on_activate`
>>>>>> callback for the button?
>>>>>>
>>>>>
>>>>> if we have a static link, there is no need to create an 'a' element
>>>>> on the fly and clicking it programmatically. Since browsers use
>>>>> heuristics to detect 'user-initiated' actions to determine if things
>>>>> are allowed (e.g. auto-clicking on links) such helpers should be used
>>>>> sparingly.
>>>>>
>>>>> a static link is better expressed with native browser methods such as
>>>>> an a element that the user clicks. (the button inside is just for
>>>>> cosmetics in this case)
>>>>>
>>>>> e.g. if one would send a message in on_activate and call the helper in
>>>>> the update method, this might not work as intended since the browser
>>>>> can't detect that it was user-initiated.
>>>>
>>>> you could just call the helper directly instead of going through a
>>>> message though, no? however, im not sure if that is picked up as
>>>> user-initiated in all browsers either.
>>>>
>>>>> so my intent was to only use it when absolutely necessary.
>>>>>
>>>>> it's also what we do in PDM to download the report (though there we
>>>>> use a data url)
>>>>>
>>>>> the idea here was also that once all task log endpoints support the
>>>>> download api parameter, we can remove the button below again,
>>>>> and the helper too.
>>>>>
>>>>> do you see any advantage with using the helper in the first case too?
>>>>
>>>> my thinking was mostly about being able to re-use certain code paths
>>>> here.
>>>>
>>>> more importantly, though, from what i can tell the html 5 spec does not
>>>> allow interactive elements, like <button>, as descendants of <a>
>>>> elements:
>>>>
>>>>> Transparent, but there must be no interactive content descendant, a
>>>>> element descendant, or descendant with the tabindex attribute
>>>>> specified.
>>>>> - https://html.spec.whatwg.org/#the-a-element
>>>>
>>>> after looking into it some more, coding download buttons for static
>>>> resources as <a> elements is the right way to go accessibility-wise. so
>>>> maybe replacing the inner `Button` component with purely aesthetic
>>>> button.
>>>>
>>>> -->8 snip 8<--
>>>
>>> Sound good in general, I'll look into that, but since none of the part
>>> of the button is really interactive, i think it can be fine for now?
>>>
>>> (it's sadly not as simple as adding some class currently, since the e.g.
>>> ripple effect has to be done manually)
>>
>> i know it's a little trickier. sadly, this is definitively forbidden
>> regardless of "real interactivity". as per spec `<button>` is always
>> "interactive content":
>>
>>> § 3.2.5.2.7 Interactive content
>>>
>>> *Interactive content* is content that is specifically intended for
>>> user interaction.
>>>      => `a` (if the `href` attribute is present), `audio` (if the controls
>>>      attribute is present), `button`, `details`, `embed`, `iframe`,
>>>      `img` (if the usemap attribute is present), `input` (if the type
>>>      attribute is not in the Hidden state), `label`, `select`,
>>>      `textarea`, `video` (if the controls attribute is present)
>>> - https://html.spec.whatwg.org/#interactive-content-2
>>
>> we also set a tabindex attribute on buttons unconditionally [1], this is
>> also explicitly forbidden for descendants of the `<a>` element.
>>
>> [1]: https://git.proxmox.com/?p=ui/proxmox-yew-widget-toolkit.git;a=blob;f=src/widget/button.rs;h=584f923c;hb=HEAD#l289
>
>
> yes it might be "forbidden", but still works for these purposes for now
> until we have a better way? Not sure if we want to block features
> just to be spec compliant when it clearly works in all relevant
> browsers, especially when I already said I'll fix it.

sorry if i misunderstood you here, i'm not saying this should be a
general blocker. i was just concerned that invalid markup might mess
with certain screen readers and other accessibility aids.

(added the list back as i accidentally dropped it along the way, sorry
for that)




  parent reply	other threads:[~2026-03-31  7:39 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-03-30 12:53 [PATCH yew-comp 0/3] improve task/log viewer Dominik Csapak
2026-03-30 12:53 ` [PATCH yew-comp 1/3] task (viewer): add task download button Dominik Csapak
2026-03-30 13:36   ` Shannon Sterz
2026-03-30 13:48     ` Dominik Csapak
     [not found]       ` <DHG6K6Z0MPF2.1RFDEDL4NQM3M@proxmox.com>
     [not found]         ` <059e96c0-1b42-4c94-979a-6dfcf6ff5860@proxmox.com>
     [not found]           ` <DHG71AI5H1Z9.1E3IKBB4GT12K@proxmox.com>
     [not found]             ` <6e6fa075-2b27-4635-8fcf-ebdcdfdad3d8@proxmox.com>
2026-03-31  7:39               ` Shannon Sterz [this message]
2026-03-31 11:14   ` Maximiliano Sandoval
2026-03-31 12:05     ` Dominik Csapak
2026-03-31 12:14       ` Dominik Csapak
2026-03-31 12:55         ` Shannon Sterz
2026-03-30 12:53 ` [PATCH yew-comp 2/3] log-view: reorganize imports Dominik Csapak
2026-03-30 12:53 ` [RFC PATCH yew-comp 3/3] log-view: improve display of lines with '\r' Dominik Csapak

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=DHGSMHN0N6TA.292F4RLLAQUU3@proxmox.com \
    --to=s.sterz@proxmox.com \
    --cc=d.csapak@proxmox.com \
    --cc=yew-devel@lists.proxmox.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
Service provided by Proxmox Server Solutions GmbH | Privacy | Legal