Skip to content

Commit

Permalink
feature #235 Implemented advanced responsive tables for smartphones (…
Browse files Browse the repository at this point in the history
…javiereguiluz)

This PR was squashed before being merged into the master branch (closes #235).

Discussion
----------

Implemented advanced responsive tables for smartphones

The other day I read this article: [Responsive Tables in Pure CSS](https://techblog.livingsocial.com/blog/2015/04/06/responsive-tables-in-pure-css/). This pull request implements that idea for tables displayed on smartphones.

Checkout the differences:

### This is a table displayed in a desktop

![table_wide](https://cloud.githubusercontent.com/assets/73419/7232097/f16b09f2-e779-11e4-9052-a752fbefdd40.png)

### This is how we display that very same table on a smartphone

![table_resposive](https://cloud.githubusercontent.com/assets/73419/7232106/ff5978be-e779-11e4-948c-56d6ebb739b1.png)

### This is how the table is displayed after applying these changes

![table_response_advanced](https://cloud.githubusercontent.com/assets/73419/7232111/0a300fbe-e77a-11e4-9c3d-5b32aed57b85.png)

-----

Personally I think that this method is a complete "game changer" for responsive tables and I see no reason for not using it.

The only minor thing that bothers me is that you cannot reorder the table. I'm planning to add soem JavaScript magic to allow table reordering when clicking on the label of each column.

Commits
-------

49126a1 Implemented advanced responsive tables for smartphones
  • Loading branch information
javiereguiluz committed Apr 20, 2015
2 parents 890d0b8 + 49126a1 commit af26df3
Show file tree
Hide file tree
Showing 2 changed files with 125 additions and 84 deletions.
181 changes: 112 additions & 69 deletions Resources/views/css/admin.css.twig
Original file line number Diff line number Diff line change
Expand Up @@ -580,82 +580,35 @@ body.list #content-header #content-search .input-group:after {
}

body.list table {
background: {{ colors.white }};
border: 1px solid {{ colors.table_border }};
margin-bottom: 10px;
}
body.list table thead th {
background: {{ colors.table_header }};
padding: 0;
}
body.list table thead th i {
color: {{ colors.gray_dark }};
padding: 0 3px;
}
body.list table thead th a,
body.list table thead th span {
color: {{ colors.text }};
display: block;
padding: 10px 6px;
white-space: nowrap;
}
body.list table thead th a:hover {
background: {{ colors.gray_lighter }};
color: {{ brand_color }};
text-decoration: none;
}
body.list table thead th a:hover i {
color: {{ brand_color }};
}

body.list table thead th.sorted,
body.list table thead th.sorted a {
background: {{ brand_color }};
color: {{ colors.white }};
text-decoration: none;
}
body.list table thead th.sorted a:hover i,
body.list table thead th.sorted i {
color: {{ colors.white }};
}
body.list table tbody td.sorted {
background: {{ colors.gray_lighter }};
border-color: {{ colors.table_row_border }};
}

body.list table thead th.boolean,
body.list table tbody td.boolean,
body.list table thead th.toggle,
body.list table tbody td.toggle {
text-align: center;
}

body.list .table thead tr th {
border-bottom: 2px solid {{ colors.gray }};
}
body.list .table thead tr th.sorted {
border-bottom: 2px outset {{ brand_color }};
background: transparent;
border: 0;
}
/* these styles are needed to fix some visual glitches when the sort field is the first column */
body.list .table thead tr th:first-child.sorted {
border-left: 1px solid {{ brand_color }};
border-top: 1px solid {{ brand_color }};
body.list table thead {
display: none;
}
body.list .table tbody {
{% if 'dark' == color_scheme %}
border-bottom: 2px solid {{ brand_color }};
{% elseif 'light' == color_scheme %}
/* this '1px double' style is correct because 'double' gives the border more priority
and allows us to override the table border bottom (otherwise this border won't
be shown) */
border-bottom: 1px double {{ colors.gray }};
{% endif %}
background: transparent;
border: 0;
}
body.list .table tbody tr:hover td {
background: {{ colors.gray_lighter }};
body.list table tbody tr {
background: {{ colors.white }};
border: 1px solid {{ colors.gray }};
display: block;
margin-bottom: 1em;
}
body.list table tbody td {
border-bottom: 1px solid {{ colors.table_row_border }};
border-top: 0;
display: block;
text-align: right;
}
body.list table tbody td:last-child {
border-bottom: 0;
}
table td:before {
content: attr(data-label);
float: left;
font-weight: bold;
}
body.list table tbody td.actions a {
margin-right: 10px;
Expand Down Expand Up @@ -887,6 +840,96 @@ body.error .error-solution pre {
float: right;
}

body.list table {
background: {{ colors.white }};
border: 1px solid {{ colors.table_border }};
}
body.list table thead {
display: table-header-group;
}
body.list table thead th {
background: {{ colors.table_header }};
padding: 0;
}
body.list table thead th i {
color: {{ colors.gray_dark }};
padding: 0 3px;
}
body.list table thead th a,
body.list table thead th span {
color: {{ colors.text }};
display: block;
padding: 10px 6px;
white-space: nowrap;
}
body.list table thead th a:hover {
background: {{ colors.gray_lighter }};
color: {{ brand_color }};
text-decoration: none;
}
body.list table thead th a:hover i {
color: {{ brand_color }};
}
body.list table thead th.sorted,
body.list table thead th.sorted a {
background: {{ brand_color }};
color: {{ colors.white }};
text-decoration: none;
}
body.list table thead th.sorted a:hover i,
body.list table thead th.sorted i {
color: {{ colors.white }};
}
body.list table thead th.boolean,
body.list table tbody td.boolean,
body.list table thead th.toggle,
body.list table tbody td.toggle {
text-align: center;
}
body.list .table thead tr th {
border-bottom: 2px solid {{ colors.gray }};
}
body.list .table thead tr th.sorted {
border-bottom: 2px outset {{ brand_color }};
}
/* these styles are needed to fix some visual glitches when the sort field is the first column */
body.list .table thead tr th:first-child.sorted {
border-left: 1px solid {{ brand_color }};
border-top: 1px solid {{ brand_color }};
}
body.list .table tbody {
{% if 'dark' == color_scheme %}
border-bottom: 2px solid {{ brand_color }};
{% elseif 'light' == color_scheme %}
/* this '1px double' style is correct because 'double' gives the border more priority
and allows us to override the table border bottom (otherwise this border won't
be shown) */
border-bottom: 1px double {{ colors.gray }};
{% endif %}
}
body.list table tbody tr {
border: 0;
display: table-row;
margin-bottom: 0;
}
body.list table tbody td {
border-bottom: 0;
border-top: 1px solid {{ colors.table_row_border }};
display: table-cell;
text-align: left;
}
table td:before {
content: none;
float: none;
}
body.list table tbody td.sorted {
background: {{ colors.gray_lighter }};
border-color: {{ colors.table_row_border }};
}
body.list .table tbody tr:hover td {
background: {{ colors.gray_lighter }};
}

body.new form .field_date select + select,
body.edit form .field_date select + select {
margin-left: .5em;
Expand Down
28 changes: 13 additions & 15 deletions Resources/views/list.html.twig
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@
<table class="table">
<thead>
<tr>
{% set _table_column_labels = [] %}
{% for field, metadata in fields %}
{% set isSortingField = metadata.property == app.request.get('sortField') %}

Expand All @@ -72,6 +73,9 @@
{% set request_attributes = request_attributes|merge({ sortField: metadata.property }) %}
{% endif %}

{% set _column_label = metadata.label ? ( metadata.label|trans(_trans_parameters) ) : ( ('id' == metadata.property) ? 'ID' : field|humanize ) %}
{% set _table_column_labels = _table_column_labels|merge([_column_label]) %}

{% if metadata.sortable %}
<a href="{{ path('admin', request_attributes|merge({ sortField: metadata.property, sortDirection: sortDirection|default('DESC') })) }}">
{% if isSortingField and sortDirection == 'DESC' %}
Expand All @@ -82,26 +86,19 @@
<i class="fa fa-sort"></i>
{% endif %}

{% if metadata.label %}
{{ metadata.label|trans(_trans_parameters) }}
{% elseif 'id' == metadata.property %}
ID
{% else %}
{{ field|humanize }}
{% endif %}
{{ _column_label }}
</a>
{% else %}
{% if metadata.label %}
<span>{{ metadata.label|trans }}</span>
{% else %}
<span>{{ field|humanize }}</span>
{% endif %}
<span>{{ _column_label }}</span>
{% endif %}
</th>
{% endfor %}

{% if _list_item_actions|length > 0 %}
{% set _column_label = 'list.row_actions'|trans(_trans_parameters) %}
{% set _table_column_labels = _table_column_labels|merge([_column_label]) %}
<th>
<span>{{ 'list.row_actions'|trans(_trans_parameters) }}</span>
<span>{{ _column_label }}</span>
</th>
{% endif %}
</tr>
Expand All @@ -114,16 +111,17 @@
{% for field, metadata in fields %}
{% set isSortingField = metadata.property == app.request.get('sortField') %}

<td class="{{ isSortingField ? 'sorted' : '' }} {{ metadata.dataType|lower }}">
<td data-label="{{ _table_column_labels[loop.index0] }}" class="{{ isSortingField ? 'sorted' : '' }} {{ metadata.dataType|lower }}">
{% if metadata.type in ['array', 'json_array', 'simple_array', 'text'] %}
{{ easyadmin_render_field_for_list_view(item, metadata)|easyadmin_truncate }}
{% else %}
{{ easyadmin_render_field_for_list_view(item, metadata) }}
{% endif %}
</td>
{% endfor %}

{% if _list_item_actions|length > 0 %}
<td class="actions">
<td data-label="{{ _table_column_labels|last }}" class="actions">
{% for _action in _list_item_actions %}
{% if 'method' == _action.type %}
{% set _action_href = path('admin', { action: _action.name, view: 'list', entity: _entity.name, id: _item_id }) %}
Expand Down

0 comments on commit af26df3

Please sign in to comment.