Skip to content

Commit

Permalink
Add BorderBoxTable and Row components
Browse files Browse the repository at this point in the history
  • Loading branch information
oliverguenther committed Jul 30, 2024
1 parent f5573e5 commit 7286673
Show file tree
Hide file tree
Showing 12 changed files with 447 additions and 1 deletion.
1 change: 1 addition & 0 deletions app/components/_index.sass
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@
@import "filter/filters_component"
@import "projects/row_component"
@import "settings/project_custom_fields/project_custom_field_mapping/new_project_mapping_component"
@import "op_primer/border_box_table_component"
48 changes: 48 additions & 0 deletions app/components/op_primer/border_box_row_component.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<%#-- copyright
OpenProject is an open source project management software.
Copyright (C) 2012-2024 the OpenProject GmbH
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License version 3.
OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
Copyright (C) 2006-2013 Jean-Philippe Lang
Copyright (C) 2010-2013 the ChiliProject Team
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
See COPYRIGHT and LICENSE files for more details.
++#%>
<%=
render Primer::BaseComponent.new(
tag: :div,
id: row_css_id,
classes: "#{table.grid_class} #{row_css_class}",
) do %>
<% columns.each do |column| %>
<%= render(Primer::BaseComponent.new(tag: :div, classes: column_css_class(column), **column_args(column))) { column_value(column) } %>
<% end %>
<% if table.has_actions? %>
<%= flex_layout(align_items: :center, justify_content: :flex_end) do |flex| %>
<% button_links.each_with_index do |link, i| %>
<% args = i == (button_links.count - 1) ? {} : { mr: 1 } %>
<% flex.with_column(**args) { link } %>
<% end %>
<% end %>
<% end %>
<% end %>
45 changes: 45 additions & 0 deletions app/components/op_primer/border_box_row_component.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# frozen_string_literal: true

#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) 2012-2024 the OpenProject GmbH
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 3.
#
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
# Copyright (C) 2006-2013 Jean-Philippe Lang
# Copyright (C) 2010-2013 the ChiliProject Team
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# See COPYRIGHT and LICENSE files for more details.
#++

module OpPrimer
class BorderBoxRowComponent < RowComponent # rubocop:disable OpenProject/AddPreviewForViewComponent
include ComponentHelpers

def column_args(_column)
{}
end

def checkmark(condition)
if condition
render(Primer::Beta::Octicon.new(icon: :check))
end
end
end
end
53 changes: 53 additions & 0 deletions app/components/op_primer/border_box_table_component.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<%#-- copyright
OpenProject is an open source project management software.
Copyright (C) 2012-2024 the OpenProject GmbH
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License version 3.
OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
Copyright (C) 2006-2013 Jean-Philippe Lang
Copyright (C) 2010-2013 the ChiliProject Team
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
See COPYRIGHT and LICENSE files for more details.
++#%>
<%=
render(
border_box_container(
classes: container_class,
test_selector:,
)) do |component|
component.with_header(classes: grid_class, color: :muted) do
headers.each do |name, args|
caption = args.delete(:caption)
concat render(Primer::Beta::Text.new(font_weight: :semibold, **header_args(name))) { caption }
end

if has_actions?
concat render(Primer::BaseComponent.new(tag: :div))
end
end

rows.each do |row|
component.with_row(scheme: :default) do
render(row_class.new(row:, table: self))
end
end
end
%>
58 changes: 58 additions & 0 deletions app/components/op_primer/border_box_table_component.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# frozen_string_literal: true

#-- copyright
# OpenProject is an open source project management software.
# Copyright (C) 2012-2024 the OpenProject GmbH
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 3.
#
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
# Copyright (C) 2006-2013 Jean-Philippe Lang
# Copyright (C) 2010-2013 the ChiliProject Team
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# See COPYRIGHT and LICENSE files for more details.
#++

module OpPrimer
class BorderBoxTableComponent < TableComponent
include ComponentHelpers

def before_render
raise ArgumentError, "BorderBoxTableComponent cannot be #sortable?" if sortable?

super
end

def header_args(_column)
{}
end

# Default grid class with equal weights
def grid_class
"op-border-box-grid"
end

def has_actions?
false
end

def sortable?
false
end
end
end
7 changes: 7 additions & 0 deletions app/components/op_primer/border_box_table_component.sass
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
.op-border-box-grid
display: grid
justify-content: flex-start
align-items: center
// Distribute columns evenly by default
grid-auto-columns: minmax(0, 1fr)
grid-auto-flow: column
2 changes: 1 addition & 1 deletion app/components/table_component.rb
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ def row_class
rescue NameError
raise(
NameError,
"#{mod}::RowComponent required by #{mod}::TableComponent not defined. " +
"#{mod}::RowComponent required by #{name} not defined. " +
"Expected to be defined in `app/components/#{mod.underscore}/row_component.rb`."
)
end
Expand Down
50 changes: 50 additions & 0 deletions lookbook/docs/patterns/12-tables.md.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
## Overview

### Border Box Table

<%= embed OpPrimer::BorderBoxTableComponentPreview, :default %>

### Sortable table

<%= embed OpenProject::Deprecated::TablePreview, :default %>

## Usage

To use either table implementation, you need to subclass into your own namespace:

- **Regular table:** `TableComponent` and `RowComponent`
- **BorderBox table:** `OpPrimer::BorderBoxTableComponent` and `OpPrimer::BorderBoxRowComponent`

**Columns:** Define the columns of the table as class method `columns :a, :b, :c`

**Headers:** Define the headers of the component like so

```ruby
def headers
[
[:a, { caption: 'Column A' }],
[:b, { caption: 'Column B' }],
[:c, { caption: 'Column C' }]
]
end
```

**Actions:** Define the actions in the row component as `button_links`. See the example code

<%= embed OpPrimer::BorderBoxTableComponentPreview, :default, panels: %i[source] %>

## Best practices

**Do**

- Use a BorderBox table if you have a *few* entries of unsorted data, that does not require pagination
- Use up to two actions using the `:secondary` scheme of `Primer::Beta::Button` and `Primer::Beta::IconButton`.
- OR: Use an action menu with `:invisible` scheme

**Don't**

- Use the BorderBox table for a lot of items that require sorting or pagination

## Examples

For detailed examples have a look at the other [preview examples](/lookbook/inspect/OpenProject/Primer/border_box_table/default) of the component.
19 changes: 19 additions & 0 deletions lookbook/previews/op_primer/border_box_table_component_preview.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# frozen_string_literal: true

module OpPrimer
# @logical_path OpenProject/Primer
# @display min_height 300px
class BorderBoxTableComponentPreview < Lookbook::Preview
def default
render_with_template
end

def custom_column_widths
render_with_template
end

def with_action_menu
render_with_template
end
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<%=
table = Class.new(OpPrimer::BorderBoxTableComponent) do
columns :foo, :bar
def self.name
"MyTable"
end

def header_args(column)
if column == :foo
{ style: "grid-column: span 3" }
else
super
end
end

def row_class
@clazz ||= Class.new(OpPrimer::BorderBoxRowComponent) do
def self.name
"MyRow"
end

def column_args(column)
if column == :foo
{ style: "grid-column: span 3" }
else
super
end
end

def foo
"foo"
end

def bar
"bar"
end
end
end

def headers
[
[:foo, { caption: "3 columns wide" }],
[:bar, { caption: "1 column wide" }],
]
end
end

render(table.new(rows: [1, 2]))
%>
Loading

0 comments on commit 7286673

Please sign in to comment.