Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
d40df11
Add Phoenix Playground demo file
nkyllonen Jul 3, 2025
49f6ff1
Handle scale value conversions with Axes + Separate out Dimensions
doughsay Aug 26, 2024
5248c28
Update DateTimeScale + Add basic tests
doughsay Aug 27, 2024
7018fd0
Change points_plot to circles + Update icon SVG
nkyllonen Oct 17, 2024
5a85816
Implement Access and Enumberable protocols for Datasets
doughsay Oct 18, 2024
e765b3b
Fetch padding from dimensions options instead of margin (#14)
krainboltgreene Jan 29, 2025
5733d69
Update demo with new example graph
nkyllonen Jul 3, 2025
8dd415e
Add logo example graph + Add animated example graph
nkyllonen Jul 7, 2025
b56fc77
Update README and add migration_guide
nkyllonen Jul 8, 2025
26b9a9a
Rename line_points to polyline and pass list of tuples for points
nkyllonen Jul 8, 2025
a35760b
Update demo files with new polyline component
nkyllonen Jul 8, 2025
211078b
Simplify the way we generate multiple values from datasets (#18)
doughsay Jul 9, 2025
076be76
Add docs to points and values + Update demo_live
nkyllonen Jul 9, 2025
a2fc0ef
Refactor Axis protocol and add Axis using macro so that axes can be a…
doughsay Jul 9, 2025
19ca435
Update step_polyline to follow polyline component
nkyllonen Jul 10, 2025
4c0bdd5
Remove unneeded marker components + Update docs and animated demo
nkyllonen Jul 10, 2025
7772660
Organize demos and migration guide into subfolders
nkyllonen Jul 10, 2025
28902b5
Update tests and docs (#20)
nkyllonen Jul 17, 2025
eb5a79f
Bump Erlang and Elixir versions for CI
nkyllonen Jul 18, 2025
fa122b3
Update docs to present better in HexDocs
nkyllonen Jul 18, 2025
c75dd9f
Run CI against more elixir/OTP versions (#22)
doughsay Jul 23, 2025
bc62321
Update CI to only push to main
nkyllonen Jul 23, 2025
010a6d5
Small cleanups + Fix incorrect migration guide example
nkyllonen Jan 15, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
129 changes: 41 additions & 88 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,125 +2,78 @@ name: CI

on:
push:
branches: [main]
branches:
- main
pull_request:
branches: [main]

env:
MIX_ENV: test
OTP_VERSION_SPEC: "26.x"
ELIXIR_VERSION_SPEC: "1.16.x"

jobs:
compile:
name: Compile
runs-on: ubuntu-latest

steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up Elixir
uses: erlef/setup-beam@v1
with:
otp-version: ${{ env.OTP_VERSION_SPEC }}
elixir-version: ${{ env.ELIXIR_VERSION_SPEC }}
- name: Install dependencies
run: mix deps.get
- name: Compile dependencies
run: mix deps.compile
- name: Compile
run: mix compile --warnings-as-errors

jobs:
test:
name: Test
runs-on: ubuntu-latest

# Test on the 3 latest Elixir versions with the latest OTP version that each supports
strategy:
matrix:
include:
- elixir: 1.16.x
otp: 26.x

- elixir: 1.17.x
otp: 27.x

- elixir: 1.18.x
otp: 28.x
lint: true

steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up Elixir
uses: erlef/setup-beam@v1
with:
otp-version: ${{ env.OTP_VERSION_SPEC }}
elixir-version: ${{ env.ELIXIR_VERSION_SPEC }}
otp-version: ${{ matrix.otp }}
elixir-version: ${{ matrix.elixir }}

- name: Install dependencies
run: mix deps.get
- name: Compile dependencies
run: mix deps.compile

# We only check for warnings on latest Elixir version
- name: Compile & lint
run: mix compile --warnings-as-errors
if: ${{ matrix.lint }}

- name: Run tests
run: mix test

check-formatted:
name: Check Formatted
runs-on: ubuntu-latest

# Check formatting on the latest Elixir version only
strategy:
matrix:
include:
- elixir: 1.18.x
otp: 28.x

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Set up Elixir
uses: erlef/setup-beam@v1
with:
otp-version: ${{ env.OTP_VERSION_SPEC }}
elixir-version: ${{ env.ELIXIR_VERSION_SPEC }}
otp-version: ${{ matrix.otp }}
elixir-version: ${{ matrix.elixir }}

- name: Install dependencies
run: mix deps.get
- name: Compile dependencies
run: mix deps.compile
- name: Check formatted
run: mix format --check-formatted

# credo:
# name: Credo
# runs-on: ubuntu-latest

# steps:
# - name: Checkout
# uses: actions/checkout@v4
# - name: Set up Elixir
# uses: erlef/setup-beam@v1
# with:
# otp-version: ${{ env.OTP_VERSION_SPEC }}
# elixir-version: ${{ env.ELIXIR_VERSION_SPEC }}
# - name: Install dependencies
# run: mix deps.get
# - name: Compile dependencies
# run: mix deps.compile
# - name: Run credo
# run: mix credo --strict

# dialyzer:
# name: Dialyzer
# runs-on: ubuntu-latest

# env:
# MIX_ENV: dev
- name: Compile
run: mix compile

# steps:
# - name: Checkout
# uses: actions/checkout@v4
# - name: Set mix file hash
# id: set_vars
# run: |
# mix_hash="${{ hashFiles(format('{0}{1}', github.workspace, '/mix.lock')) }}"
# echo "::set-output name=mix_hash::$mix_hash"
# - name: Cache PLT files
# id: cache-plt
# uses: actions/cache@v4
# with:
# path: |
# _build/dev/*.plt
# _build/dev/*.plt.hash
# key: plt-cache-${{ steps.set_vars.outputs.mix_hash }}
# restore-keys: |
# plt-cache-
# - name: Set up Elixir
# uses: erlef/setup-beam@v1
# with:
# otp-version: ${{ env.OTP_VERSION_SPEC }}
# elixir-version: ${{ env.ELIXIR_VERSION_SPEC }}
# - name: Install dependencies
# run: mix deps.get
# - name: Compile dependencies
# run: mix deps.compile
# - name: Run dialyzer
# run: mix dialyzer
- name: Check formatted
run: mix format --check-formatted
53 changes: 24 additions & 29 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ installed by adding `plox` to your list of dependencies in `mix.exs`:
```elixir
def deps do
[
{:plox, "~> 0.1.0"}
{:plox, "~> 0.2.0"}
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

We'll change this later to 1.0.0 ✨ when this rewrite is ready! 🤩 (not ready yet)

]
end
```
Expand All @@ -27,7 +27,7 @@ Documentation is published on [HexDocs](https://hexdocs.pm) and can be found at

<img width="740" src="images/readme-example-plot@2x.png" alt="Example screenshot">

Start by setting up your data, scales, and dataset:
Start by setting up your data, dimensions, axes, and dataset:

```elixir
data = [
Expand All @@ -38,44 +38,39 @@ data = [
%{date: ~D[2023-08-05], value: 50.0}
]

date_scale = date_scale(Date.range(~D[2023-08-01], ~D[2023-08-05]))
number_scale = number_scale(0.0, 80.0)
dimensions = Plox.Dimensions.new(800, 250)

dataset =
dataset(data,
x: {date_scale, & &1.date},
y: {number_scale, & &1.value}
)
```
x_axis = Plox.XAxis.new(
Plox.DateScale.new(Date.range(~D[2023-08-01], ~D[2023-08-05])),
dimensions
)

Once you have those, you can build a `Plox.Graph` struct:
y_axis = Plox.YAxis.new(Plox.NumberScale.new(0.0, 80.0), dimensions)

```elixir
example_graph =
to_graph(
scales: [date_scale: date_scale, number_scale: number_scale],
datasets: [dataset: dataset]
dataset =
Plox.Dataset.new(data,
x: {x_axis, & &1.date},
y: {y_axis, & &1.value}
)
```

Finally, render the `Plox.Graph` directly within your HEEx template:
Once you have those, you can render a `graph` component within your HEEx template:

```html
<.graph :let={graph} id="example_graph" for={@example_graph} width="800" height="250">
<:legend>
<.legend_item color="#EC7E16" label="Data" />
</:legend>
<.graph id="example_graph" dimensions={@dimensions}>
<.x_axis_labels :let={date} axis={@x_axis}>
{Calendar.strftime(date, "%-m/%-d")}
</.x_axis_labels>

<.x_axis :let={date} scale={graph[:date_scale]}>
<%= Calendar.strftime(date, "%-m/%-d") %>
</.x_axis>
<.y_axis_labels :let={value} axis={@y_axis} ticks={5}>
{value}
</.y_axis_labels>

<.y_axis :let={value} scale={graph[:number_scale]} ticks={5}>
<%= value %>
</.y_axis>
<.x_axis_grid_lines axis={@x_axis} stroke="#D3D3D3" />
<.y_axis_grid_lines axis={@y_axis} ticks={5} stroke="#D3D3D3" />

<.line_plot dataset={graph[:dataset]} color="#EC7E16" />
<.polyline points={points(@dataset[:x], @dataset[:y])} stroke="#EC7E16" stroke-width={2} />

<.points_plot dataset={graph[:dataset]} color="#EC7E16" />
<.circle cx={@dataset[:x]} cy={@dataset[:y]} r={3} fill="#EC7E16" />
</.graph>
```
112 changes: 112 additions & 0 deletions docs/migration_guide.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
# Plox Migration Guide (0.2.0 to X.X.X)
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Leaving this generic for now, but this should be 1.0.0 when we're ready.


Plox has gone through a major philosophical rewrite since its initial publication. This
guide will help users convert their current Plox graphs over to the new approach.

## Example of 0.2.0 usage

1. Set up data, scales, and dataset:

```elixir
data = [
%{date: ~D[2023-08-01], value: 35.0},
%{date: ~D[2023-08-02], value: 60.0},
%{date: ~D[2023-08-03], value: 65.0},
%{date: ~D[2023-08-04], value: 10.0},
%{date: ~D[2023-08-05], value: 50.0}
]

date_scale = date_scale(Date.range(~D[2023-08-01], ~D[2023-08-05]))
number_scale = number_scale(0.0, 80.0)

dataset =
dataset(data,
x: {date_scale, & &1.date},
y: {number_scale, & &1.value}
)
```

2. Build a `Plox.Graph` struct:

```elixir
example_graph =
to_graph(
scales: [date_scale: date_scale, number_scale: number_scale],
datasets: [dataset: dataset]
)
```

3. Render the `Plox.Graph` within your HEEx template:

```html
<.graph :let={graph} id="example_graph" for={@example_graph} width="800" height="250">
<.x_axis :let={date} scale={graph[:date_scale]}>
{Calendar.strftime(date, "%-m/%-d")}
</.x_axis>

<.y_axis :let={value} scale={graph[:number_scale]} ticks={5}>
{value}
</.y_axis>

<.line_plot dataset={graph[:dataset]} color="#EC7E16" />

<.points_plot dataset={graph[:dataset]} color="#EC7E16" />
</.graph>
```

## Example of X.X.X usage

1. Set up data, dimensions, axes, and dataset:

```elixir
data = [
%{date: ~D[2023-08-01], value: 35.0},
%{date: ~D[2023-08-02], value: 60.0},
%{date: ~D[2023-08-03], value: 65.0},
%{date: ~D[2023-08-04], value: 10.0},
%{date: ~D[2023-08-05], value: 50.0}
]

# Instead of passing the height and width via the `graph` component,
# create Dimensions and pass them to each Axis
dimensions = Plox.Dimensions.new(800, 250)

# Instead of creating separate Scales, we need them when creating our Axes
x_axis = Plox.XAxis.new(
Plox.DateScale.new(Date.range(~D[2023-08-01], ~D[2023-08-05])),
dimensions
)

y_axis = Plox.YAxis.new(Plox.NumberScale.new(0.0, 80.0), dimensions)

# Create a Dataset with our Axes
dataset =
Plox.Dataset.new(data,
x: {x_axis, & &1.date},
y: {y_axis, & &1.value}
)
```

2. Render the `graph` component within your HEEx template:

```html
<.graph id="example_graph" dimensions={@dimensions}>
<!-- Render axis labels and lines individually -->
<.x_axis_labels :let={date} axis={@x_axis}>
{Calendar.strftime(date, "%-m/%-d")}
</.x_axis_labels>

<.y_axis_labels :let={value} axis={@y_axis} ticks={5}>
{value}
</.y_axis_labels>

<.x_axis_grid_lines axis={@x_axis} stroke="#D3D3D3" />
<.y_axis_grid_lines axis={@y_axis} ticks={5} stroke="#D3D3D3" />

<!-- Use the `points/2` helper to generate a list of {x, y} tuples from our Dataset -->
<.polyline points={points(@dataset[:x], @dataset[:y])} stroke="#EC7E16" stroke-width={2} />

<!-- Pass all the `x` values and the `y` values to render circles at each datapoint -->
<.circle cx={@dataset[:x]} cy={@dataset[:y]} r={3} fill="#EC7E16" />
</.graph>
```
Loading