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

[meter] Create Meter component #743

Open
wants to merge 6 commits into
base: master
Choose a base branch
from

Conversation

mj12albert
Copy link
Member

@mj12albert mj12albert commented Oct 17, 2024

Closes: #662

Docs: https://deploy-preview-743--base-ui.netlify.app/components/react-meter/

Demo: https://deploy-preview-743--base-ui.netlify.app/experiments/meter

Summary

  • Does not use the meter element due to cross-browser inconsistencies, attributes like optimum actually make the VO experience worse 1, styling is also annoying 2
  • Uses the same anatomy as Progress since they are closely related
  • Implements the "high/medium/low segmenting" feature from the HTML spec - the high/low props can be used to set the boundaries between the 3 segments, and sets a data-segment attribute indicating which segment the current value falls in. Due to inconsistent and incorrect browser implementations of this feature, we assume the prop value is inclusive 3
  • The value of the optimum prop, in combination with segmenting, indicates which segment of the range is "preferred". If the current value is in the preferred segment, a [data-optimum] attribute is set
  • Handles RTL per [core] Use a DirectionProvider to configure text direction (RTL/LTR) #831. Built-in styles on the Indicator use inset-inline-start instead of left/right that automatically account f or this

Footnotes

  1. https://www.htmhell.dev/adventcalendar/2022/5/

  2. https://scottaohara.github.io/a11y_styled_form_controls/src/meter/

  3. https://www.ctrl.blog/entry/html-meter-segment-boundaries.html

@mui-bot
Copy link

mui-bot commented Oct 17, 2024

Netlify deploy preview

https://deploy-preview-743--base-ui.netlify.app/

Generated by 🚫 dangerJS against 3e8ad95

@mj12albert mj12albert force-pushed the feat/meter branch 3 times, most recently from d8734f9 to e927c2d Compare October 18, 2024 07:17
@mj12albert mj12albert added the new feature New feature or request label Oct 19, 2024
@mj12albert mj12albert force-pushed the feat/meter branch 2 times, most recently from e7386f8 to 395484a Compare October 24, 2024 13:48
@mj12albert mj12albert force-pushed the feat/meter branch 4 times, most recently from c63f06d to 5bbda04 Compare October 28, 2024 09:16
@mj12albert
Copy link
Member Author

@colmtuite I've added a demo here with some controls to tweak the value, min, max, low, high and optimum props that define the range represented by the component, and pretty much demos all the features.

The combination of min, max, low, high divides the Meter's range into 3 segments, low (red), medium (yellow), high (green):
Screenshot 2024-10-28 at 5 23 12 PM

A [data-segment='low|medium|high'] attribute is set depending on where the value falls in the range.

The optimum prop defines whether the low, medium, or high segment of the range is "preferable", e.g. for "battery health" higher is better, but for "CPU temperature" lower is better. A [data-optimum] attribute is set when the value is in the "preferable" segment.

NOTE: The corresponding optimum HTML attribute does nothing if the "optimum value" is in the medium segment, while the implementation here does allow the "medium" segment to be "preferable"

@mj12albert mj12albert marked this pull request as ready for review October 28, 2024 09:32
@mj12albert mj12albert force-pushed the feat/meter branch 4 times, most recently from 307db4c to cd70734 Compare November 1, 2024 13:06
@mj12albert mj12albert force-pushed the feat/meter branch 3 times, most recently from 6c377dc to 34bb2bd Compare November 11, 2024 03:43
@mj12albert mj12albert force-pushed the feat/meter branch 3 times, most recently from 78622dc to 016893e Compare November 20, 2024 15:53
@github-actions github-actions bot added the PR: out-of-date The pull request has merge conflicts and can't be merged label Nov 21, 2024
@github-actions github-actions bot removed the PR: out-of-date The pull request has merge conflicts and can't be merged label Nov 21, 2024
@github-actions github-actions bot added the PR: out-of-date The pull request has merge conflicts and can't be merged label Nov 26, 2024
@github-actions github-actions bot removed the PR: out-of-date The pull request has merge conflicts and can't be merged label Nov 27, 2024
@mj12albert
Copy link
Member Author

mj12albert commented Nov 27, 2024

Updated RTL handling per #831

Added a demo to: https://deploy-preview-743--base-ui.netlify.app/experiments/meter

Instead of using left/right to position the Indicator in the built-in styles, inset-inline-start is used which accounts for text direction and matches our browser support

min?: number;
/**
* Indicates the optimal point in the numeric range represented by the component.
* If unspecified, it will fall back to the midpoint between `min` and `max`.
Copy link
Member

Choose a reason for hiding this comment

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

This API feels a bit weird to me, but I understand it reflects the native <meter> element.
I think I wouldn't set the default value for optimum if not provided and not set the data-optimum attribute in this case.

Copy link
Member Author

Choose a reason for hiding this comment

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

Sounds good, it does seem a bit arbitrary anyway

}

namespace useMeterRoot {
export type Segment = 'low' | 'medium' | 'high';
Copy link
Member

Choose a reason for hiding this comment

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

Have we considered going beyond the native meter capabilities and allow custom ranges? I can think of a gauge that has a preferable range in the middle. A bit lower and a bit higher would be less preferable (yellow) and the extremes on both sides could be red. The built-in range doesn't support such a scenario (but on the other hand is simpler to use in more common cases)

Copy link
Member Author

@mj12albert mj12albert Dec 3, 2024

Choose a reason for hiding this comment

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

I can think of a gauge that has a preferable range in the middle. A bit lower and a bit higher would be less preferable (yellow) and the extremes on both sides could be red. The built-in range doesn't support such a scenario

@michaldudak This still sounds like a normal numeric range just with different styling?

The "preferable range" is still the middle segment of among 3 segments, sandwiched by 2 non-preferable ranges on each end

And it could be styled with a gradient that goes red (0%) > yellow > green (~middle) > yellow > red (100%)

.indicator {
  background: linear-gradient(to-right, red 0%, yellow 25%, green 50%, yellow 75%, red 100%);
}

@github-actions github-actions bot added the PR: out-of-date The pull request has merge conflicts and can't be merged label Nov 30, 2024
@github-actions github-actions bot removed the PR: out-of-date The pull request has merge conflicts and can't be merged label Dec 3, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
component: meter new feature New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Meter] Implement Meter
3 participants