Skip to content

Commit

Permalink
Add documentation about upgrading bitstyles versions; add versions sh…
Browse files Browse the repository at this point in the history
…owcase dev tool (#119)

* Render static pages with showcases for all bitstyles versions

* Add an --only flag

* Refactoring

* Hide showcase task from library users

* Add to CI to ensure it continues working in the future

* Describe how to approach upgrading bitstyles

* Fix credo problem

* Don't include test fixtures in documentation

* Don't link from hexdoc to a dev-only doc

* Fix plural vs singular

* Split doctest into two parts in story macro

* Allow doctests for other bitstyles versions

* Extend version doc with new multi-version doctests

* credo

* Make tests async again with process dict
  • Loading branch information
angelikatyborska authored Mar 22, 2024
1 parent 8953954 commit 3e5d5e5
Show file tree
Hide file tree
Showing 32 changed files with 1,701 additions and 824 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ jobs:
- run: mix test
- run: mix credo --strict
- run: mix docs
- name: Check if versions showcase mix script finishes
run: mix run scripts/generate_version_showcase.ex
demo:
runs-on: ubuntu-latest
name: Demo
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,4 @@ erl_crash.dump
# Ignore package tarball (built via "mix hex.build").
bitstyles_phoenix-*.tar

/version_showcase
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ Basic helpers for [bitstyles](https://github.com/bitcrowd/bitstyles) for elixir

## Requirements

bitstyles must be installed separately into the asset generation. The helpers in this project just output classes for working with bitstyles.
Bitstyles must be installed separately into the asset generation. The helpers in this project just output classes for working with bitstyles.

Bitstyles versions from 4.3.0 down to 1.3.0 are supported.

## Installation

Expand Down
103 changes: 103 additions & 0 deletions docs/bitstyles_version_compatibility.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
# Bitstyles version compatibility

General rules:

- We don't drop bitstyles version support. Users of bitstyles_phoenix should be able to upgrade bitstyles_phoenix to the newest version without having to upgrade bitstyles.
- We don't skip bitstyles versions. Users of bitstyles_phoenix should be able to upgrade bitstyles to any version between the highest and lowest currently supported bitstyles version.

## Doctests ("stories")

The `story` macro is used to generate doctests, as well as the component preview in docs.

The first argument is the story's description (`"An error tag"`), the second argument is an iex code snippet, and the third argument is the expected result when the code snippet gets executed. The third argument can be a single charlist, or a keyword lists that maps bitstyles version numbers to charlists. If the third argument is a single charlist, it's assumed that is the expected result for the default bitstyles version.

⚠️ Note that the 4 space indentation in the code snippet and the expected result is important.

### Multi-version doctest example

```elixir
story(
"An error tag",
'''
iex> assigns = %{}
...> render ~H"""
...> <.ui_error error={{"Foo error", []}} />
...> """
''',
"4.3.0": '''
"""
<span class="u-fg-warning">
Foo error
</span>
"""
''',
"3.0.0": '''
"""
<span class="u-fg--warning">
Foo error
</span>
"""
'''
)
```

## Versions showcase

A showcase of components in all supported bitstyles versions can be generated by running:

```bash
mix run scripts/generate_version_showcase.ex
```

The script accepts multiple `--only` arguments if you want to limit the showcase to only a handful of versions:

```bash
mix run scripts/generate_version_showcase.ex --only 4.3.0 --only 4.2.0
```

This script will create a `version_showcase` directory with static web pages. Open the starting page with:

```bash
open version_showcase/index.html
```

## How to upgrade the default bitstyles version in bitstyles_phoenix?

1. Choose the smallest possible version jump (do not skip versions).
2. Read about the changes in version in [the bitstyles Changelog](https://github.com/bitcrowd/bitstyles/blob/main/CHANGELOG.md).
3. Update the highest supported version mentioned in the [README](../README.md).
4. Update the `@default_version` in [`BitstylesPhoenix.Bitstyles`](../lib/bitstyles_phoenix/bitstyles.ex).
5. Add the new version to the version lists in [`generate_version_showcase`](../scripts/generate_version_showcase.ex).
6. Handle classes renamed by bitstyles by adding new clauses of the `classname/2` function in [`BitstylesPhoenix.Bitstyles`](../lib/bitstyles_phoenix/bitstyles.ex).
7. If renaming classes is not enough to upgrade correctly, you can perform [a bitstyles version check in a component](#an-example-of-a-bitstyles-version-check-in-a-component).
8. Run `mix test`. Fix all doctests until `mix test` succeeds. Add new expected values for the new version, and keep the current expected value for the previous version (see [multi-version doctest example](#multi-version-doctest-example))
9. Run `mix docs` to preview components after making changes to them.
10. Use the [versions showcase](#versions-showcase) to test that you didn't break anything for older bitstyles versions.

### An example of a bitstyles version check in a component

```elixir
def ui_tricky_component(assigns) do
version = BitstylesPhoenix.Bitstyles.version()

if version >= "5.0.0" do
~H"""
<p class={classnames("u-new-class-that-does-everything")}>...</p>
"""
else
~H"""
<div class={classnames("u-old-class1 u-old-class2")}>
<div class={classnames("u-old-class3")}>
...
</div>
</div>
"""
end
end
```

## Adding new components

Ideally, if you're adding a completely new component, make sure it works with all supported bitstyles versions by using the [versions showcase](#versions-showcase) to test it.

If it's not practical to support it in other version, you can perform [a bitstyles version check in the component](#an-example-of-a-bitstyles-version-check-in-a-component).
4 changes: 4 additions & 0 deletions lib/bitstyles_phoenix/alpine3/dropdown.ex
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ defmodule BitstylesPhoenix.Alpine3.Dropdown do
...> </:menu>
...> </.ui_js_dropdown>
...> """
''',
'''
"""
<div class="u-relative" x-data="{ dropdownOpen: false }">
<button type="button" @click="dropdownOpen = true" class="a-button a-button--ui">
Expand Down Expand Up @@ -97,6 +99,8 @@ defmodule BitstylesPhoenix.Alpine3.Dropdown do
...> </:menu>
...> </.ui_js_dropdown>
...> """
''',
'''
"""
<div class="u-relative" x-data="{ myOwnDropDown: false }">
<button type="button" @click="myOwnDropDown = true" class="a-button a-button--ui">
Expand Down
2 changes: 2 additions & 0 deletions lib/bitstyles_phoenix/alpine3/sidebar.ex
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ defmodule BitstylesPhoenix.Alpine3.Sidebar do
...> </:main>
...> </.ui_js_sidebar_layout>
...> """
''',
'''
"""
<div class="u-flex u-height-100vh" x-data="{ sidebarOpen: false }">
<header role="banner" class="u-flex">
Expand Down
11 changes: 9 additions & 2 deletions lib/bitstyles_phoenix/bitstyles.ex
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ defmodule BitstylesPhoenix.Bitstyles do
@cdn_url "https://cdn.jsdelivr.net/npm/bitstyles"

def cdn_url do
"#{@cdn_url}@#{@default_version}"
"#{@cdn_url}@#{version()}"
end

@doc """
Expand Down Expand Up @@ -92,6 +92,13 @@ defmodule BitstylesPhoenix.Bitstyles do
end

def version do
Application.get_env(:bitstyles_phoenix, :bitstyles_version, @default_version)
bitstyles_version_override = Process.get(:bitstyles_phoenix_bistyles_version)

bitstyles_version_override ||
Application.get_env(:bitstyles_phoenix, :bitstyles_version, @default_version)
end

def default_version do
@default_version
end
end
122 changes: 71 additions & 51 deletions lib/bitstyles_phoenix/component/avatar.ex
Original file line number Diff line number Diff line change
Expand Up @@ -14,64 +14,84 @@ defmodule BitstylesPhoenix.Component.Avatar do
See the [bitstyles avatar docs](https://bitcrowd.github.io/bitstyles/?path=/docs/atoms-avatar--a-avatar-m) for further info.
"""

story("Default avatar", '''
iex> assigns = %{}
...> render ~H"""
...> <.ui_avatar src="https://placekitten.com/100/100" alt="Username’s avatar"/>
...> """
"""
<div class="u-flex u-items-center">
<div class="a-avatar">
<img height="32" width="32" alt="Username’s avatar" src="https://placekitten.com/100/100"/>
story(
"Default avatar",
'''
iex> assigns = %{}
...> render ~H"""
...> <.ui_avatar src="https://placekitten.com/100/100" alt="Username’s avatar"/>
...> """
''',
'''
"""
<div class="u-flex u-items-center">
<div class="a-avatar">
<img height="32" width="32" alt="Username’s avatar" src="https://placekitten.com/100/100"/>
</div>
</div>
</div>
"""
''')
"""
'''
)

story("With extra class", '''
iex> assigns = %{}
...> render ~H"""
...> <.ui_avatar src="https://placekitten.com/100/100" class="foo bar" alt="Username’s avatar"/>
...> """
"""
<div class="u-flex u-items-center">
<div class="a-avatar foo bar">
<img height="32" width="32" alt="Username’s avatar" src="https://placekitten.com/100/100"/>
story(
"With extra class",
'''
iex> assigns = %{}
...> render ~H"""
...> <.ui_avatar src="https://placekitten.com/100/100" class="foo bar" alt="Username’s avatar"/>
...> """
''',
'''
"""
<div class="u-flex u-items-center">
<div class="a-avatar foo bar">
<img height="32" width="32" alt="Username’s avatar" src="https://placekitten.com/100/100"/>
</div>
</div>
</div>
"""
''')
"""
'''
)

story("Large avatar", '''
iex> assigns = %{}
...> render ~H"""
...> <.ui_avatar size="l" src="https://placekitten.com/100/100" alt="Username’s avatar" height="46" width="46"/>
...> """
"""
<div class="u-flex u-items-center">
<div class="a-avatar a-avatar--l">
<img alt="Username’s avatar" height="46" src="https://placekitten.com/100/100" width="46"/>
story(
"Large avatar",
'''
iex> assigns = %{}
...> render ~H"""
...> <.ui_avatar size="l" src="https://placekitten.com/100/100" alt="Username’s avatar" height="46" width="46"/>
...> """
''',
'''
"""
<div class="u-flex u-items-center">
<div class="a-avatar a-avatar--l">
<img alt="Username’s avatar" height="46" src="https://placekitten.com/100/100" width="46"/>
</div>
</div>
</div>
"""
''')
"""
'''
)

story("Avatar with a text", '''
iex> assigns = %{}
...> render ~H"""
...> <.ui_avatar src="https://placekitten.com/100/100" alt="Username’s avatar"> Username </.ui_avatar>
...> """
"""
<div class="u-flex u-items-center">
<div class="a-avatar">
<img height="32" width="32" alt="Username’s avatar" src="https://placekitten.com/100/100"/>
story(
"Avatar with a text",
'''
iex> assigns = %{}
...> render ~H"""
...> <.ui_avatar src="https://placekitten.com/100/100" alt="Username’s avatar"> Username </.ui_avatar>
...> """
''',
'''
"""
<div class="u-flex u-items-center">
<div class="a-avatar">
<img height="32" width="32" alt="Username’s avatar" src="https://placekitten.com/100/100"/>
</div>
<span class="u-margin-s-left">
Username
</span>
</div>
<span class="u-margin-s-left">
Username
</span>
</div>
"""
''')
"""
'''
)

def ui_avatar(assigns) do
class =
Expand Down
Loading

0 comments on commit 3e5d5e5

Please sign in to comment.