Skip to content

Accessibility: Removes hard-coded columns in home facet lists#4302

Open
ckaz wants to merge 8 commits intovufind-org:devfrom
finc:pullrequest_accessibility_home-facet-list_colums_NEW
Open

Accessibility: Removes hard-coded columns in home facet lists#4302
ckaz wants to merge 8 commits intovufind-org:devfrom
finc:pullrequest_accessibility_home-facet-list_colums_NEW

Conversation

@ckaz
Copy link
Contributor

@ckaz ckaz commented Mar 21, 2025

Replaces #4231.

  • introduces multiple column options for two-columned lists such as 'callnumber-first' with pure CSS breaks (W3C accessibility requirement)
  • adds various options for customization such as column-fill, different settings for XS/SM/MD devices and more
  • adds customizable visual division between home page facet blocks

@ckaz
Copy link
Contributor Author

ckaz commented Mar 21, 2025

So, finally, here's the new proposal, branched off dev:

  1. Until a better solution is found, we maintain the option that the number of entries is set in module/VuFind/src/VuFind/ContentBlock/FacetList.php (currently 10 entries, $columnSize = 10 , after which a link is inserted, which is misleadingly called "More options ..." but leads to "Advanced Search").
  2. Since all I could glean from the code is that only callnumber-first are to be displayed as two columns, I've simplified my suggestion to one column for all home facets except callnumber-first , which gets two columns. The column number is set via SCSS variables (along with a bunch of other settings which may be useful). Using variables allows every library to define their own custom settings.
    The two-column option can be overridden (again using SCSS variables) for devices from 0-420px, 420-767px, 767px-991px and above. Of course if can be defaulted to 3 or more columns, too.
    In addition, other exceptions for displaying home facets in multiple columns could be added by changing the setting in ContenBlock/FacetList.phtml (currently: $cssColumnClass = $field == 'callnumber-first' ? 'two-columns' : 'one-column'; )
  3. The multi-column setting uses CSS column breaks to satisfy W3C accessibility requirements.
  4. For safety and variability, there are additional settings defining, for example, height (defaulting to auto), which can be combined with clip which defines what will happen if entries overflow the defined height.
  5. There is a customizable visual separation now, using a vertical line (with color, width + line type) + padding. All of this is defined via SCSS variables, so it can be set to none, or to custom colors, widths etc. This separating line is only active for device width >= 768px, as the blocks containing the lists are stacked on top of each other for smaller devices

Pls. let me know what you think and whether it is feasible to continue considering this.
Cheers, Claas

Copy link
Member

@demiankatz demiankatz left a comment

Choose a reason for hiding this comment

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

Thanks, @ckaz -- I'll let @crhallberg comment on the actual styles before I dive into that part of the conversation, but I noticed a couple of minor things to clean up that are not related to the core of the logic.

@ckaz ckaz requested a review from demiankatz March 24, 2025 11:33
@ckaz ckaz force-pushed the pullrequest_accessibility_home-facet-list_colums_NEW branch from 2ed8a70 to f7b6552 Compare March 25, 2025 16:32
<ul class="home-facet-list">
<?php
// Special case: two columns for LC call numbers ...
$cssColumnClass = $field == 'callnumber-first' ? 'two-columns' : 'one-column'; // Add the CSS class logic here
Copy link
Contributor

Choose a reason for hiding this comment

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

If we're moving the column control to SCSS, we could remove this hard-coding of callnumber-first by adding the field as a class similar to how we handle page classes.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Again, great idea.

@EreMaijala EreMaijala removed their request for review June 24, 2025 10:35
Copy link
Contributor Author

@ckaz ckaz left a comment

Choose a reason for hiding this comment

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

Great ideas, many thanks

<ul class="home-facet-list">
<?php
// Special case: two columns for LC call numbers ...
$cssColumnClass = $field == 'callnumber-first' ? 'two-columns' : 'one-column'; // Add the CSS class logic here
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Again, great idea.

@ckaz ckaz force-pushed the pullrequest_accessibility_home-facet-list_colums_NEW branch from fcf3e6a to 3e81583 Compare September 5, 2025 15:39
@crhallberg
Copy link
Contributor

crhallberg commented Sep 8, 2025

My only question at this point is if using column-count is sufficient, or if we should do something more rigid like CSS grid.

@ckaz ckaz force-pushed the pullrequest_accessibility_home-facet-list_colums_NEW branch from 3e81583 to db9ec3b Compare September 9, 2025 11:44
@ckaz
Copy link
Contributor Author

ckaz commented Sep 9, 2025

My only question at this point is if using column-count is sufficient, or if we should do something more rigid like CSS grid.

Indeed, this looks tempting but wouldn't it break up the expected flow of the ul lists?
As in this example with display: grid; grid-template-columns: 1fr 1fr;
added
grid-template-columns

vs. the default version with
column-count: 2; column-gap: 1rem; column-rule: 1px dotted gray;

column-count

@crhallberg
Copy link
Contributor

I see! I misunderstood the list layout vs the layout of the facets. My mistake!

Copy link
Member

@demiankatz demiankatz left a comment

Choose a reason for hiding this comment

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

Thanks, @ckaz -- see below for some thoughts.

<div class="home-facet <?=$this->escapeHtmlAttr($field) ?><?=$isHierarchy ? ' facet-tree' : ''?>">
<h2><?=$labelHeading?></h2>
<div class="home-facet-container">
<?php /* removed the 'callnumber-first' coding here because 'callnumber-first' is set on the 'home-facet' container, so columns can be set using SCSS */ ?>
Copy link
Member

Choose a reason for hiding this comment

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

I don't think we need to keep this comment here; if we're removing the hard-coded behavior, we don't need to keep a comment about its removal forever. I think people can rely on git to figure out the history if they're curious about the change.

Suggested change
<?php /* removed the 'callnumber-first' coding here because 'callnumber-first' is set on the 'home-facet' container, so columns can be set using SCSS */ ?>

Copy link
Member

Choose a reason for hiding this comment

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

My suggestion about removing this comment was marked as resolved but not applied. I still think we can remove this comment; do you disagree?

// Special case: two columns for LC call numbers...
$maxListLength = $field == 'callnumber-first'
? $columnSize * 2 : $columnSize;
$maxListLength = $columnSize;
Copy link
Member

Choose a reason for hiding this comment

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

This change causes all the facets to revert to a single-column view. I think we still need a way to allow more values for fields where we want the double-column view. Ideally, it would be nice if the default configuration here resulted in something that looks the same as the default configuration in the current dev branch to demonstrate how to implement flexible columns.

Do you think it would make sense to support field-specific column sizes via the configuration, or am I missing/misunderstanding the point of the work so far?

And just to be clear where I'm coming from, here is how the dev branch looks:

Image

And here is how this branch looks:

Image

@ckaz
Copy link
Contributor Author

ckaz commented Oct 8, 2025

Thanks, @ckaz -- see below for some thoughts.

Hi @demiankatz , thank you.
Erm, yes and know. I understand you concern, but we should scrap the original two-column version because it simply is not accessible according to the WCAG rules: The list must not be split in the hard code html, because it is one list.

I'm on sick leave right now, so I'll look into the issue again in a couple of days. Cheers.

@demiankatz
Copy link
Member

@ckaz, I agree that we should implement the two-column appearance with more accessible markup -- which you have done here. My point is that in order to populate the new markup, we still need to retrieve more values for the facets that are supposed to display in two columns, and I think we need some kind of mechanism to accomplish that.

In any case, I hope you feel better; thanks for taking the time to comment even while not in office (and please don't feel any urgency to respond to this before you return).

@ckaz
Copy link
Contributor Author

ckaz commented Oct 13, 2025

@ckaz, I agree that we should implement the two-column appearance with more accessible markup -- which you have done here. My point is that in order to populate the new markup, we still need to retrieve more values for the facets that are supposed to display in two columns, and I think we need some kind of mechanism to accomplish that.

Hi @demiankatz , yes, I am much better ;-)

I'm afraid I don't quite understand what you mean with "we still need to retrieve more values for the facets that are supposed to display in two columns"?
Do you have any idea, what that mechanism could look like?

@demiankatz
Copy link
Member

I'm afraid I don't quite understand what you mean with "we still need to retrieve more values for the facets that are supposed to display in two columns"? Do you have any idea, what that mechanism could look like?

There is code in the template that sets a $maxListLength variable to determine how many values are displayed. In the old code, this was doubled through a hard-coded check for the call number facet in order to populate two columns. In your revisions, you remove that special case. As a result, we only display one column of call numbers because we stop outputting values before we have used enough to fill the second column. I think we still need a mechanism to configure which fields display twice as many values, or else there is no point in having the multi-column CSS since it will never be used.

@ckaz
Copy link
Contributor Author

ckaz commented Oct 28, 2025

I'm afraid I don't quite understand what you mean with "we still need to retrieve more values for the facets that are supposed to display in two columns"? Do you have any idea, what that mechanism could look like?

There is code in the template that sets a $maxListLength variable to determine how many values are displayed. In the old code, this was doubled through a hard-coded check for the call number facet in order to populate two columns. In your revisions, you remove that special case. As a result, we only display one column of call numbers because we stop outputting values before we have used enough to fill the second column. I think we still need a mechanism to configure which fields display twice as many values, or else there is no point in having the multi-column CSS since it will never be used.

Ok, I hope I get this right: In this PR we have the option to display content of one ul in two columns (conformant to WCAG). So it is possible to display call numbers as a one column or two-column ul (depending on the setting chooses in the SCSS variables column-count: $home-facet-list-column-count-default).
The call number ul gets assigned a class callnumber-first, so the value of the SCSS variable outputs it the way we have set.
What am I missing?
Is there a case where there are so few call numbers that we would not need two columns? On libraries such as that, they can pick the one-column option. Same in cases, where libraries choose to have the call numbers in one column anyway.
I'm probably still oblivious to a problem you see but I cannot for some reason.
Cheers!

@demiankatz
Copy link
Member

I'm probably still oblivious to a problem you see but I cannot for some reason. Cheers!

@ckaz, in the template code, there is a variable called $maxListLength which contrains how many values are displayed in each facet list. In order to display two columns full of values for a particular facet, this variable needs to be doubled; otherwise, even if two columns worth of values exist, they will be truncated before they are displayed. In the old code, we had hard-coded logic to double this value for the call number facet, but that logic has been removed without any replacement -- thus, even though the CSS offers the capability of displaying two columns, the data being used to generate the HTML is always cut short, and only one column will ever be displayed. We either need to restore the old hard-coded logic (maybe an acceptable short-term solution to maintain existing behavior) or else we need to make this configurable (which we could do separately as a follow-up action if it's best to do the short-term fix here).

Copy link
Contributor

Choose a reason for hiding this comment

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

This is the accessibility problem you were pointing out, right?

Copy link
Member

Choose a reason for hiding this comment

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

Good catch, @crhallberg, I think that code was removed in an earlier version of this PR; if it has returned, that's a problem.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@crhallberg exactly!

@ckaz
Copy link
Contributor Author

ckaz commented Oct 28, 2025

I'm probably still oblivious to a problem you see but I cannot for some reason. Cheers!

@ckaz, in the template code, there is a variable called $maxListLength which contrains how many values are displayed in each facet list. In order to display two columns full of values for a particular facet, this variable needs to be doubled; otherwise, even if two columns worth of values exist, they will be truncated before they are displayed. In the old code, we had hard-coded logic to double this value for the call number facet, but that logic has been removed without any replacement -- thus, even though the CSS offers the capability of displaying two columns, the data being used to generate the HTML is always cut short, and only one column will ever be displayed. We either need to restore the old hard-coded logic (maybe an acceptable short-term solution to maintain existing behavior) or else we need to make this configurable (which we could do separately as a follow-up action if it's best to do the short-term fix here).

Ok, thanks for clarifying. I think I get it now.

@ckaz
Copy link
Contributor Author

ckaz commented Oct 28, 2025

@crhallberg and @demiankatz So couldn't we simply, at least as an interim solution, re-instate the doubling of the column content:

// Special case: two columns for LC call numbers...
$maxListLength = $field == 'callnumber-first'
? $columnSize * 2 : $columnSize;

and then remove/rewrite the elseif in lines 53 to 58 so the first <ul> isn't closed and no second <ul> is opened

<?php if ($i >= $maxListLength): // list too long? show more link! ?>
<li><a href="<?=$moreUrl?>"><strong><?=$this->transEsc('more_options_ellipsis')?></strong></a></li>
<?php break; ?>
<?php elseif ($i % $columnSize === 0): // end of column? insert break! ?>
</ul><ul class="home-facet-list">
<?php endif; ?>

This would give us the desired number of items in one <ul>, which we can then style with the SCSS variables.

@demiankatz
Copy link
Member

Yes, @ckaz, that's more or less what I would suggest, and we can add configurability as a followup later.

@ckaz ckaz force-pushed the pullrequest_accessibility_home-facet-list_colums_NEW branch from 8d638d4 to 7325184 Compare October 29, 2025 11:19
@ckaz
Copy link
Contributor Author

ckaz commented Oct 29, 2025

Sorry for the confusion, @demiankatz . Here's my new suggestion: We re-instate the extra column content for callnumber-first home facet and remove the extra <ul> and break the remaining single <ul> into columns using CSS.

@ckaz ckaz requested a review from demiankatz October 29, 2025 11:26
Copy link
Member

@demiankatz demiankatz left a comment

Choose a reason for hiding this comment

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

@ckaz, I think we're on the same page about goals, but things aren't working for me yet. Here's how it looks on the dev branch:

Image

Here's how it looks here:

Image

...so something is preventing the second column formatting from being applied.

This observation may or may not be related to the problem, but I think it's worth considering in either case:

I notice that your SCSS has hard-coded rules in it related to callnumber-first, but you have variables for "non-default-column-count." I wonder if we can clean this up so the hard-coded assumptions are in fewer places. Since the template is currently the place where we make decisions based on the field name, can we apply a class (like "double-column") in the template and then use that in all the SCSS in place of hard-coded names? That will make it easier to make this configurable in the future, and should also make the SCSS a little shorter/more readable.

I also spotted a few minor formatting details which are listed below.

<div class="home-facet <?=$this->escapeHtmlAttr($field) ?><?=$isHierarchy ? ' facet-tree' : ''?>">
<h2><?=$labelHeading?></h2>
<div class="home-facet-container">
<?php /* removed the 'callnumber-first' coding here because 'callnumber-first' is set on the 'home-facet' container, so columns can be set using SCSS */ ?>
Copy link
Member

Choose a reason for hiding this comment

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

My suggestion about removing this comment was marked as resolved but not applied. I still think we can remove this comment; do you disagree?

ckaz added 6 commits October 30, 2025 07:55
* introduces multiple column options for two-columned lists such as 'callnumber-first' with pure CSS breaks (W3C accessibility requirement)
* adds various options for customization such as column-fill, different settings for XS/SM/MD devices and more
* adds customizable visual division between home page facet blocks
* adds empty line before end of file in variables.scss
@ckaz
Copy link
Contributor Author

ckaz commented Oct 30, 2025

Hi @demiankatz ! You wrote:

...so something is preventing the second column formatting from being applied.

Yes, the setting $home-facet-list-column-fill: which I will make to default to balance, so the <ul> should break.

I notice that your SCSS has hard-coded rules in it related to callnumber-first, but you have variables for "non-default-column-count." I wonder if we can clean this up so the hard-coded assumptions are in fewer places. Since the template is currently the place where we make decisions based on the field name, can we apply a class (like "double-column") in the template and then use that in all the SCSS in place of hard-coded names? That will make it easier to make this configurable in the future, and should also make the SCSS a little shorter/more readable.

You are talking about lines 146 and 152 in search.scss, I believe. The reason for this is that in FacetList.phtml in line 14 we make sure that the field name is added as a class to the home-facet class already in place:

<div class="home-facet <?=$this->escapeHtmlAttr($field) ?><?=$isHierarchy ? ' facet-tree' : ''?>">

So, we get divs with home-facet callnumber-first or home-facet language and the like. I currently fail to see how a revision of that into home-facet double-column would not be over-complicating things. Wouldn't that mean we'd have to decide at some other place, which facets get the longer <ul> split column treatment?

As it is, we are already singling out callnumber-first as the only special case in line 30 of FacetList.phtml
// Special case: two columns for LC call numbers... $maxListLength = $field == 'callnumber-first' ? $columnSize * 2 : $columnSize;

Therefore, I see no reason why we should not refer to .home-facet.callnumber-first in the SCSS. (Even though I see your concern generally that something like double-column would be better for definitions.)

I also spotted a few minor formatting details which are listed below.

I'll see to that!

Cheers!

P.S. For some reason I fail to find out how to insert quotes from the files directly here in the code, like you do.

@ckaz ckaz force-pushed the pullrequest_accessibility_home-facet-list_colums_NEW branch from afde363 to 79ceff0 Compare October 30, 2025 07:57
@ckaz ckaz requested a review from demiankatz October 30, 2025 07:57
@demiankatz
Copy link
Member

As it is, we are already singling out callnumber-first as the only special case in line 30 of FacetList.phtml // Special case: two columns for LC call numbers... $maxListLength = $field == 'callnumber-first' ? $columnSize * 2 : $columnSize;

Therefore, I see no reason why we should not refer to .home-facet.callnumber-first in the SCSS. (Even though I see your concern generally that something like double-column would be better for definitions.)

My goal, as a follow-up to this PR, is to add a config setting to facets.ini that replaces the hard-coded callnumber-first reference in FacetList.phtml, so that ANY field can be configured to show up as double-rows. A config setting can influence a template, but it cannot dynamically generate SCSS. Therefore, I'm looking for a more generic mechanism, so that if somebody wants to customize the column behavior, they only need to change one thing and not two -- that's why I'm suggesting a more semantic CSS class name, and a more general approach to the implementation of styles. I still think it is valuable to include field-name-specific classes on things to support very targeted local customizations, but I think it is better not to use such specific classes in default styles, because it makes customization more difficult.

P.S. For some reason I fail to find out how to insert quotes from the files directly here in the code, like you do.

If you go to the "Files changed" tab and click on a line number, then shift-click on another line number, it will select a set of lines. You can then click the little + button to add a comment on those lines. When you do this, there is also a "suggest changes" button in the text editor that can be used to directly propose changes to the code. A bit of a hidden feature, but very useful!

Copy link
Member

@demiankatz demiankatz left a comment

Choose a reason for hiding this comment

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

I'm putting this back into "request changes" mode until we finish our conversation about the CSS class strategy and configurability. Once we are on the same page about that, I'll do another hands-on review, but I don't want to look again until I'm certain things won't change another time. :-)

@ckaz
Copy link
Contributor Author

ckaz commented Nov 3, 2025

My goal, as a follow-up to this PR, is to add a config setting to facets.ini that replaces the hard-coded callnumber-first reference in FacetList.phtml, so that ANY field can be configured to show up as double-rows. A config setting can influence a template, but it cannot dynamically generate SCSS. Therefore, I'm looking for a more generic mechanism, so that if somebody wants to customize the column behavior, they only need to change one thing and not two -- that's why I'm suggesting a more semantic CSS class name, and a more general approach to the implementation of styles. I still think it is valuable to include field-name-specific classes on things to support very targeted local customizations, but I think it is better not to use such specific classes in default styles, because it makes customization more difficult.

Ok, that was the piece of information I was missing. Yes of course that makes perfect sense.
Unfortunately, I'm completely lost as to how to fashion code that takes settings from facets.ini via php into the template.
Do you have any idea how we could still solve this?

@demiankatz
Copy link
Member

Ok, that was the piece of information I was missing. Yes of course that makes perfect sense. Unfortunately, I'm completely lost as to how to fashion code that takes settings from facets.ini via php into the template. Do you have any idea how we could still solve this?

The getContext() method of the VuFind\ContentBlock\FacetList class provides the variables for the template. More logic could be added there to extract a list of double-column fields from the configuration.

@ckaz
Copy link
Contributor Author

ckaz commented Jan 30, 2026

Hi Demian,
here's a fresh attempt at making this more configurable as I understood your comment. Please bear with me as I am not at all well-versed as regards PHP.
My best, Claas

@ckaz ckaz requested a review from demiankatz January 30, 2026 15:29
Copy link
Member

@demiankatz demiankatz left a comment

Choose a reason for hiding this comment

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

Thanks, @ckaz, this does indeed look like what I had in mind; there are just a few details to adjust (see below).

Also, I notice there is a merge conflict here that can likely be resolved by merging the dev branch, rebuilding the CSS, and committing the resulting files to clean up the conflict. If you need any help sorting that out, let me know and I'd be happy to take care of it for you.

I haven't done hands-on testing here yet, but I will once this review has been addressed (or if you need my help with any additional parts of it).

$maxListLength = $field == 'callnumber-first'
? $columnSize * 2 : $columnSize;
// Two-column facets (configured in facets.ini: [HomePage_Settings] two_column_facets):
//$useTwoColumns = in_array($field, $twoColumnFacets ?? [], true);
Copy link
Member

Choose a reason for hiding this comment

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

Is this supposed to be commented out? I suspect not:

Suggested change
//$useTwoColumns = in_array($field, $twoColumnFacets ?? [], true);
$useTwoColumns = in_array($field, $twoColumnFacets ?? [], true);

language = Language
format = Format
;hierarchy_top_title = Collections
hierarchy_top_title = Collections
Copy link
Member

Choose a reason for hiding this comment

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

I think this was uncommented by accident:

Suggested change
hierarchy_top_title = Collections
;hierarchy_top_title = Collections

'hierarchicalFacets' => $this->getHierarchicalFacets($facetConfig),
'hierarchicalFacetSortOptions' =>
$this->getHierarchicalFacetSortSettings($facetConfig),
'twoColumnFacets' => $this->getTwoColumnFacets($facetConfig),
Copy link
Member

Choose a reason for hiding this comment

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

I believe that you can simplify this by adding:

use VuFind\Config\Feature\ExplodeSettingTrait;

at the top of the class definition, and then changing this line to:

Suggested change
'twoColumnFacets' => $this->getTwoColumnFacets($facetConfig),
'twoColumnFacets' => $this->explodeListSetting($facetConfig->HomePage_Settings->two_column_facets ?? ''),

This existing trait does much the same thing as your getTwoColumnFacets method, so we might as well use the standard logic instead of creating a new variation.

@demiankatz demiankatz added this to the 11.1 milestone Feb 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants