Unverified Commit 6aed2e94 authored by Lauri Timmanee's avatar Lauri Timmanee
Browse files

Issue #3151553 by mherchel, mandclu, danflanagan8, catch, Lendude, Gábor...

Issue #3151553 by mherchel, mandclu, danflanagan8, catch, Lendude, Gábor Hojtsy:  Create new “Views Responsive Grid” format for Views Core
parent baf3e893
Loading
Loading
Loading
Loading
+17 −0
Original line number Diff line number Diff line
@@ -48,6 +48,23 @@ views.style.grid:
      type: boolean
      label: 'Default views column classes'

views.style.grid_responsive:
  type: views_style
  label: 'Grid - Responsive'
  mapping:
    columns:
      type:  integer
      label: 'Maximum number of columns'
    cell_min_width:
      type:  integer
      label: 'Minimum cell width'
    grid_gutter:
      type:  integer
      label: 'Grid gutter'
    alignment:
      type: string
      label: 'Alignment'

views.style.table:
  type: views_style
  label: 'Table'
+35 −0
Original line number Diff line number Diff line
/**
 * CSS for Views responsive grid style.
 */

.views-view-responsive-grid {
  --views-responsive-grid--layout-gap: 10px; /* Will be overridden by an inline style. */
  --views-responsive-grid--column-count: 4; /* Will be overridden by an inline style. */
  --views-responsive-grid--cell-min-width: 100px; /* Will be overridden by an inline style. */
}

.views-view-responsive-grid--horizontal {
  /**
   * Calculated values.
   */
  --views-responsive-grid--gap-count: calc(var(--views-responsive-grid--column-count) - 1);
  --views-responsive-grid--total-gap-width: calc(var(--views-responsive-grid--gap-count) * var(--views-responsive-grid--layout-gap));
  --views-responsive-grid-item--max-width: calc((100% - var(--views-responsive-grid--total-gap-width)) / var(--views-responsive-grid--column-count));

  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(max(var(--views-responsive-grid--cell-min-width), var(--views-responsive-grid-item--max-width)), 1fr));
  gap: var(--views-responsive-grid--layout-gap);
}

.views-view-responsive-grid--vertical {
  margin-bottom: calc(var(--views-responsive-grid--layout-gap) * -1); /* Offset the bottom row's padding. */
  column-width: var(--views-responsive-grid--cell-min-width);
  column-count: var(--views-responsive-grid--column-count);
  column-gap: var(--views-responsive-grid--layout-gap);
}

.views-view-responsive-grid--vertical .views-view-responsive-grid__item > * {
  padding-bottom: var(--views-responsive-grid--layout-gap);
  page-break-inside: avoid;
  break-inside: avoid;
}
+82 −0
Original line number Diff line number Diff line
<?php

namespace Drupal\views\Plugin\views\style;

use Drupal\Core\Form\FormStateInterface;

/**
 * Style plugin to render each item in a responsive grid cell.
 *
 * @ingroup views_style_plugins
 *
 * @ViewsStyle(
 *   id = "grid_responsive",
 *   title = @Translation("Responsive Grid"),
 *   help = @Translation("Displays rows in a responsive grid."),
 *   theme = "views_view_grid_responsive",
 *   display_types = {"normal"}
 * )
 */
class GridResponsive extends StylePluginBase {

  /**
   * {@inheritdoc}
   */
  protected $usesRowPlugin = TRUE;

  /**
   * {@inheritdoc}
   */
  protected function defineOptions() {
    $options = parent::defineOptions();
    $options['columns'] = ['default' => '4'];
    $options['cell_min_width'] = ['default' => '100'];
    $options['grid_gutter'] = ['default' => '10'];
    $options['alignment'] = ['default' => 'horizontal'];
    return $options;
  }

  /**
   * {@inheritdoc}
   */
  public function buildOptionsForm(&$form, FormStateInterface $form_state) {
    parent::buildOptionsForm($form, $form_state);
    $form['columns'] = [
      '#type' => 'number',
      '#title' => $this->t('Maximum number of columns'),
      '#attributes' => ['style' => 'width: 6em;'],
      '#description' => $this->t('The maximum number of columns that will be displayed within the grid.'),
      '#default_value' => $this->options['columns'],
      '#required' => TRUE,
      '#min' => 1,
    ];
    $form['cell_min_width'] = [
      '#type' => 'number',
      '#title' => $this->t('Minimum grid cell width'),
      '#field_suffix' => 'px',
      '#attributes' => ['style' => 'width: 6em;'],
      '#description' => $this->t('The minimum width of the grid cells. If the grid container becomes narrow, the grid cells will reflow onto the next row as needed.'),
      '#default_value' => $this->options['cell_min_width'],
      '#required' => TRUE,
      '#min' => 1,
    ];
    $form['grid_gutter'] = [
      '#type' => 'number',
      '#title' => $this->t('Grid gutter spacing'),
      '#field_suffix' => 'px',
      '#attributes' => ['style' => 'width: 6em;'],
      '#description' => $this->t('The spacing between the grid cells.'),
      '#default_value' => $this->options['grid_gutter'],
      '#required' => TRUE,
      '#min' => 0,
    ];
    $form['alignment'] = [
      '#type' => 'radios',
      '#title' => $this->t('Alignment'),
      '#options' => ['horizontal' => $this->t('Horizontal'), 'vertical' => $this->t('Vertical')],
      '#default_value' => $this->options['alignment'],
      '#description' => $this->t('Horizontal alignment will place items starting in the upper left and moving right. Vertical alignment will place items starting in the upper left and moving down.'),
    ];
  }

}
+55 −0
Original line number Diff line number Diff line
{#
/**
 * @file
 * Default theme implementation for views to display rows in a responsive grid.
 *
 * Available variables:
 * - attributes: HTML attributes for the wrapping element.
 * - title: The title of this group of rows.
 * - view: The view object.
 * - rows: The rows contained in this view.
 * - options: The view plugin style options.
 *   - alignment: a string set to either 'horizontal' or 'vertical'.
 *   - columns: A number representing the max number of columns.
 *   - cell_min_width: A number representing the minimum width of the grid cell.
 *   - grid_gutter: A number representing the space between the grid cells.
 * - items: A list of grid items.
 *   - attributes: HTML attributes for each row or column.
 *   - content: A list of columns or rows. Each row or column contains:
 *     - attributes: HTML attributes for each row or column.
 *     - content: The row or column contents.
 *
 * @see template_preprocess_views_view_grid_responsive()
 *
 * @ingroup themeable
 */
#}

{{ attach_library('views/views.responsive-grid') }}

{%
  set classes = [
    'views-view-responsive-grid',
    'views-view-responsive-grid--' ~ options.alignment,
  ]
%}

{% set responsive_grid_styles = [
    '--views-responsive-grid--column-count:'  ~ options.columns ~ ';',
    '--views-responsive-grid--cell-min-width:'  ~ options.cell_min_width ~ 'px;',
    '--views-responsive-grid--layout-gap:'  ~ options.grid_gutter ~ 'px;',
  ]
%}

{% if title %}
  <h3>{{ title }}</h3>
{% endif %}
<div{{ attributes.addClass(classes).setAttribute('style', responsive_grid_styles|join()) }}>
  {% for item in items %}
    <div class="views-view-responsive-grid__item">
      <div class="views-view-responsive-grid__item-inner">
        {{- item.content -}}
      </div>
    </div>
  {% endfor %}
</div>
+65 −0
Original line number Diff line number Diff line
langcode: en
status: true
dependencies: {  }
id: test_grid_responsive
label: ''
module: views
description: ''
tag: ''
base_table: views_test_data
base_field: nid
display:
  default:
    display_options:
      defaults:
        fields: false
        pager: false
        sorts: false
      fields:
        age:
          field: age
          id: age
          relationship: none
          table: views_test_data
          plugin_id: numeric
        id:
          field: id
          id: id
          relationship: none
          table: views_test_data
          plugin_id: numeric
        name:
          field: name
          id: name
          relationship: none
          table: views_test_data
          plugin_id: string
      pager:
        options:
          offset: 0
        type: none
      sorts:
        id:
          field: id
          id: id
          order: ASC
          relationship: none
          table: views_test_data
          plugin_id: numeric
      style:
        type: grid_responsive
        options:
          grouping: {  }
      row:
        type: fields
    display_plugin: default
    display_title: Default
    id: default
    position: 0
  page_1:
    display_options:
      path: test-grid
    display_plugin: page
    display_title: 'Page display'
    id: page_1
    position: 1
Loading