Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add docs for {Flex,FlexItem}Component #190

Merged
merged 17 commits into from
Feb 8, 2021
Merged
2 changes: 2 additions & 0 deletions Rakefile
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,8 @@ namespace :docs do
Primer::DetailsComponent,
Primer::DropdownMenuComponent,
Primer::FlashComponent,
Primer::FlexComponent,
Primer::FlexItemComponent,
Primer::HeadingComponent,
Primer::LabelComponent,
Primer::LayoutComponent,
Expand Down
39 changes: 38 additions & 1 deletion app/components/primer/flex_component.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
# frozen_string_literal: true

module Primer
# :nodoc
# Use FlexComponent to make an element lay out its content using the flexbox model.
# Before using these utilities, you should be familiar with CSS3 Flexible Box
# spec. If you are not, check out MDN's guide [Using CSS Flexible
# Boxes](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Flexible_Box_Layout/Basic_Concepts_of_Flexbox).
class FlexComponent < Primer::Component
JUSTIFY_CONTENT_DEFAULT = nil
JUSTIFY_CONTENT_MAPPINGS = {
Expand Down Expand Up @@ -32,6 +35,40 @@ class FlexComponent < Primer::Component
DEFAULT_DIRECTION = nil
ALLOWED_DIRECTIONS = [DEFAULT_DIRECTION, :column, :column_reverse, :row, :row_reverse].freeze

# @example 100|Default
# <%= render(Primer::FlexComponent.new(bg: :gray)) do %>
# <%= render(Primer::BoxComponent.new(p: 5, bg: :gray_light, classes: "border")) { "Item 1" } %>
# <%= render(Primer::BoxComponent.new(p: 5, bg: :gray_light, classes: "border")) { "Item 2" } %>
# <%= render(Primer::BoxComponent.new(p: 5, bg: :gray_light, classes: "border")) { "Item 3" } %>
# <% end %>
#
# @example 100|Justify center
# <%= render(Primer::FlexComponent.new(justify_content: :center, bg: :gray)) do %>
# <%= render(Primer::BoxComponent.new(p: 5, bg: :gray_light, classes: "border")) { "Item 1" } %>
# <%= render(Primer::BoxComponent.new(p: 5, bg: :gray_light, classes: "border")) { "Item 2" } %>
# <%= render(Primer::BoxComponent.new(p: 5, bg: :gray_light, classes: "border")) { "Item 3" } %>
# <% end %>
#
# @example 100|Align end
# <%= render(Primer::FlexComponent.new(align_items: :end, bg: :gray)) do %>
# <%= render(Primer::BoxComponent.new(p: 5, bg: :gray_light, classes: "border")) { "Item 1" } %>
# <%= render(Primer::BoxComponent.new(p: 5, bg: :gray_light, classes: "border")) { "Item 2" } %>
# <%= render(Primer::BoxComponent.new(p: 5, bg: :gray_light, classes: "border")) { "Item 3" } %>
# <% end %>
#
# @example 100|Direction column
# <%= render(Primer::FlexComponent.new(direction: :column, bg: :gray)) do %>
# <%= render(Primer::BoxComponent.new(p: 5, bg: :gray_light, classes: "border")) { "Item 1" } %>
# <%= render(Primer::BoxComponent.new(p: 5, bg: :gray_light, classes: "border")) { "Item 2" } %>
# <%= render(Primer::BoxComponent.new(p: 5, bg: :gray_light, classes: "border")) { "Item 3" } %>
# <% end %>
#
# @param justify_content [Symbol] Use this param to distribute space between and around flex items along the main axis of the container. <%= one_of(Primer::FlexComponent::JUSTIFY_CONTENT_OPTIONS) %>
# @param inline [Boolean] Defaults to false.
# @param flex_wrap [Boolean] Defaults to nil.
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is a boolean but also defaults to nil... what's the right thing here?

Copy link
Contributor

Choose a reason for hiding this comment

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

@srt32 that's a good question. What do we do in Primer React?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good question!

I also just noticed this on https://primer.style/components/Flex

Previously, a Flex.Item component was used for flex item specific properties; Box now contains all those properties and should be used in its place.

Maybe we should deprecate FlexItem?

I am having a hard time grokking the PRC (I'm new to the codebase) but it looks to mainly delegate to Box, which delegates to styleSystem.

The API though is directly

<Flex flexWrap="nowrap">

Copy link
Contributor

Choose a reason for hiding this comment

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

@emplums what do you think? I'd generally lean towards deprecating all of the Flex-related components and just encourage the usage of Box with the flex-related system arguments.

Copy link
Contributor

Choose a reason for hiding this comment

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

@joelhawksley the proposed game plan for PRC is that Box and Flex will have all the same properties, the only difference is Flex will have display: flex set by default. The idea is that it will be handy shortcut from having to type display: flex over and over, and will still keep the ease of grokking the code to see exactly where flex is being used

# @param align_items [Symbol] Use this param to align items on the cross axis. <%= one_of(Primer::FlexComponent::ALIGN_ITEMS_OPTIONS) %>
# @param direction [Symbol] Use this param to define the orientation of the main axis (row or column). By default, flex items will display in a row. <%= one_of(Primer::FlexComponent::ALLOWED_DIRECTIONS) %>
# @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
def initialize(
justify_content: JUSTIFY_CONTENT_DEFAULT,
inline: INLINE_DEFAULT,
Expand Down
16 changes: 15 additions & 1 deletion app/components/primer/flex_item_component.rb
Original file line number Diff line number Diff line change
@@ -1,11 +1,25 @@
# frozen_string_literal: true

module Primer
# :nodoc
# Use FlexItemComponent to specify the ability of a flex item to alter its
# dimensions to fill available space
class FlexItemComponent < Primer::Component
FLEX_AUTO_DEFAULT = false
FLEX_AUTO_ALLOWED_VALUES = [FLEX_AUTO_DEFAULT, true].freeze

# @example 100|Default
# <%= render(Primer::FlexComponent.new) do %>
# <%= render(Primer::FlexItemComponent.new) do %>
# Item 1
# <% end %>
#
# <%= render(Primer::FlexItemComponent.new(flex_auto: true)) do %>
# Item 2
# <% end %>
# <% end %>
#
# @param flex_auto [Boolean] Fills available space and auto-sizes based on the content. Defaults to <%= Primer::FlexItemComponent::FLEX_AUTO_DEFAULT %>
# @param system_arguments [Hash] <%= link_to_system_arguments_docs %>
def initialize(flex_auto: FLEX_AUTO_DEFAULT, **system_arguments)
@system_arguments = system_arguments
@system_arguments[:classes] =
Expand Down
73 changes: 73 additions & 0 deletions docs/content/components/flex.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
---
title: Flex
status: Experimental
source: https://github.com/primer/view_components/tree/main/app/components/primer/flex_component.rb
---

<!-- Warning: AUTO-GENERATED file, do not edit. Add code comments to your Ruby instead <3 -->

Use FlexComponent to make an element lay out its content using the flexbox model.
Before using these utilities, you should be familiar with CSS3 Flexible Box
spec. If you are not, check out MDN's guide [Using CSS Flexible
Boxes](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Flexible_Box_Layout/Basic_Concepts_of_Flexbox).

## Examples

### Default

<iframe style="width: 100%; border: 0px; height: 100px;" srcdoc="<html><head><link href='https://unpkg.com/@primer/css/dist/primer.css' rel='stylesheet'></head><body><div class='bg-gray d-flex'> <div class='border p-5 bg-gray-light'>Item 1</div> <div class='border p-5 bg-gray-light'>Item 2</div> <div class='border p-5 bg-gray-light'>Item 3</div></div></body></html>"></iframe>

```erb
<%= render(Primer::FlexComponent.new(bg: :gray)) do %>
<%= render(Primer::BoxComponent.new(p: 5, bg: :gray_light, classes: "border")) { "Item 1" } %>
<%= render(Primer::BoxComponent.new(p: 5, bg: :gray_light, classes: "border")) { "Item 2" } %>
<%= render(Primer::BoxComponent.new(p: 5, bg: :gray_light, classes: "border")) { "Item 3" } %>
<% end %>
```

### Justify center

<iframe style="width: 100%; border: 0px; height: 100px;" srcdoc="<html><head><link href='https://unpkg.com/@primer/css/dist/primer.css' rel='stylesheet'></head><body><div class='flex-justify-center bg-gray d-flex'> <div class='border p-5 bg-gray-light'>Item 1</div> <div class='border p-5 bg-gray-light'>Item 2</div> <div class='border p-5 bg-gray-light'>Item 3</div></div></body></html>"></iframe>

```erb
<%= render(Primer::FlexComponent.new(justify_content: :center, bg: :gray)) do %>
<%= render(Primer::BoxComponent.new(p: 5, bg: :gray_light, classes: "border")) { "Item 1" } %>
<%= render(Primer::BoxComponent.new(p: 5, bg: :gray_light, classes: "border")) { "Item 2" } %>
<%= render(Primer::BoxComponent.new(p: 5, bg: :gray_light, classes: "border")) { "Item 3" } %>
<% end %>
```

### Align end

<iframe style="width: 100%; border: 0px; height: 100px;" srcdoc="<html><head><link href='https://unpkg.com/@primer/css/dist/primer.css' rel='stylesheet'></head><body><div class='flex-items-end bg-gray d-flex'> <div class='border p-5 bg-gray-light'>Item 1</div> <div class='border p-5 bg-gray-light'>Item 2</div> <div class='border p-5 bg-gray-light'>Item 3</div></div></body></html>"></iframe>

```erb
<%= render(Primer::FlexComponent.new(align_items: :end, bg: :gray)) do %>
<%= render(Primer::BoxComponent.new(p: 5, bg: :gray_light, classes: "border")) { "Item 1" } %>
<%= render(Primer::BoxComponent.new(p: 5, bg: :gray_light, classes: "border")) { "Item 2" } %>
<%= render(Primer::BoxComponent.new(p: 5, bg: :gray_light, classes: "border")) { "Item 3" } %>
<% end %>
```

### Direction column

<iframe style="width: 100%; border: 0px; height: 100px;" srcdoc="<html><head><link href='https://unpkg.com/@primer/css/dist/primer.css' rel='stylesheet'></head><body><div class='bg-gray flex-column d-flex'> <div class='border p-5 bg-gray-light'>Item 1</div> <div class='border p-5 bg-gray-light'>Item 2</div> <div class='border p-5 bg-gray-light'>Item 3</div></div></body></html>"></iframe>

```erb
<%= render(Primer::FlexComponent.new(direction: :column, bg: :gray)) do %>
<%= render(Primer::BoxComponent.new(p: 5, bg: :gray_light, classes: "border")) { "Item 1" } %>
<%= render(Primer::BoxComponent.new(p: 5, bg: :gray_light, classes: "border")) { "Item 2" } %>
<%= render(Primer::BoxComponent.new(p: 5, bg: :gray_light, classes: "border")) { "Item 3" } %>
<% end %>
```

## Arguments

| Name | Type | Default | Description |
| :- | :- | :- | :- |
| `justify_content` | `Symbol` | `JUSTIFY_CONTENT_DEFAULT` | Use this param to distribute space between and around flex items along the main axis of the container. One of `nil`, `:flex_start`, `:flex_end`, `:center`, `:space_between`, or `:space_around`. |
| `inline` | `Boolean` | `false` | Defaults to false. |
| `flex_wrap` | `Boolean` | `FLEX_WRAP_DEFAULT` | Defaults to nil. |
| `align_items` | `Symbol` | `ALIGN_ITEMS_DEFAULT` | Use this param to align items on the cross axis. One of `nil`, `:start`, `:end`, `:center`, `:baseline`, or `:stretch`. |
| `direction` | `Symbol` | `nil` | Use this param to define the orientation of the main axis (row or column). By default, flex items will display in a row. One of `nil`, `:column`, `:column_reverse`, `:row`, or `:row_reverse`. |
| `system_arguments` | `Hash` | N/A | [System arguments](/system-arguments) |
35 changes: 35 additions & 0 deletions docs/content/components/flexitem.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
---
title: FlexItem
status: Experimental
source: https://github.com/primer/view_components/tree/main/app/components/primer/flex_item_component.rb
---

<!-- Warning: AUTO-GENERATED file, do not edit. Add code comments to your Ruby instead <3 -->

Use FlexItemComponent to specify the ability of a flex item to alter its
dimensions to fill available space

## Examples

### Default

<iframe style="width: 100%; border: 0px; height: 100px;" srcdoc="<html><head><link href='https://unpkg.com/@primer/css/dist/primer.css' rel='stylesheet'></head><body><div class='d-flex'> <div> Item 1</div> <div class='flex-auto '> Item 2</div></div></body></html>"></iframe>

```erb
<%= render(Primer::FlexComponent.new) do %>
<%= render(Primer::FlexItemComponent.new) do %>
Item 1
<% end %>

<%= render(Primer::FlexItemComponent.new(flex_auto: true)) do %>
Item 2
<% end %>
<% end %>
```

## Arguments

| Name | Type | Default | Description |
| :- | :- | :- | :- |
| `flex_auto` | `Boolean` | `false` | Fills available space and auto-sizes based on the content. Defaults to false |
| `system_arguments` | `Hash` | N/A | [System arguments](/system-arguments) |
4 changes: 4 additions & 0 deletions docs/src/@primer/gatsby-theme-doctocat/nav.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@
url: /components/dropdownmenu
- title: Flash
url: /components/flash
- title: Flex
url: /components/flex
- title: FlexItem
url: /components/flexitem
- title: Heading
url: /components/heading
- title: Label
Expand Down
23 changes: 23 additions & 0 deletions stories/primer/flex_component_stories.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# frozen_string_literal: true

class Primer::FlexComponentStories < ViewComponent::Storybook::Stories
layout "storybook_preview"

story(:default) do
controls do
select(:justify_content, Primer::FlexComponent::JUSTIFY_CONTENT_OPTIONS, :center)
select(:align_items, Primer::FlexComponent::ALIGN_ITEMS_OPTIONS, :start)
select(:direction, Primer::FlexComponent::ALLOWED_DIRECTIONS, :row)
inline false
flex_wrap false
end

content do
Copy link
Contributor

Choose a reason for hiding this comment

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

@manuelpuyol is there anything you think we could do to avoid the html_safe here?

# rubocop:disable Rails/OutputSafety
"<div class='p-5 border bg-gray-light'>Item 1</div>
<div class='p-5 border bg-gray-light'>Item 2</div>
<div class='p-5 border bg-gray-light'>Item 3</div>".html_safe
# rubocop:enable Rails/OutputSafety
end
end
end