Skip to content

Commit

Permalink
Update RTL handling
Browse files Browse the repository at this point in the history
  • Loading branch information
mj12albert committed Nov 27, 2024
1 parent 29b2e9d commit 28e7e8b
Show file tree
Hide file tree
Showing 20 changed files with 212 additions and 83 deletions.
4 changes: 0 additions & 4 deletions docs/data/api/meter-indicator.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,7 @@
"themeDefaultProps": true,
"muiName": "MeterIndicator",
"forwardsRefTo": "HTMLSpanElement",
<<<<<<< HEAD
"filename": "/packages/react/src/meter/indicator/MeterIndicator.tsx",
=======
"filename": "/packages/react/src/Meter/Indicator/MeterIndicator.tsx",
>>>>>>> 8ac5427ed7 (Fix proptypes and docs)
"inheritance": null,
"demos": "<ul><li><a href=\"/components/react-meter/\">Meter</a></li></ul>",
"cssComponent": false
Expand Down
8 changes: 0 additions & 8 deletions docs/data/api/meter-root.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,6 @@
"aria-labelledby": { "type": { "name": "string" } },
"aria-valuetext": { "type": { "name": "string" } },
"className": { "type": { "name": "union", "description": "func<br>&#124;&nbsp;string" } },
"direction": {
"type": { "name": "enum", "description": "'ltr'<br>&#124;&nbsp;'rtl'" },
"default": "'ltr'"
},
"getAriaLabel": {
"type": { "name": "func" },
"signature": { "type": "function(value: number) => string", "describedArgs": ["value"] }
Expand All @@ -33,11 +29,7 @@
"themeDefaultProps": true,
"muiName": "MeterRoot",
"forwardsRefTo": "HTMLDivElement",
<<<<<<< HEAD
"filename": "/packages/react/src/meter/root/MeterRoot.tsx",
=======
"filename": "/packages/react/src/Meter/Root/MeterRoot.tsx",
>>>>>>> 8ac5427ed7 (Fix proptypes and docs)
"inheritance": null,
"demos": "<ul><li><a href=\"/components/react-meter/\">Meter</a></li></ul>",
"cssComponent": false
Expand Down
4 changes: 0 additions & 4 deletions docs/data/api/meter-track.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,7 @@
"themeDefaultProps": true,
"muiName": "MeterTrack",
"forwardsRefTo": "HTMLSpanElement",
<<<<<<< HEAD
"filename": "/packages/react/src/meter/track/MeterTrack.tsx",
=======
"filename": "/packages/react/src/Meter/Track/MeterTrack.tsx",
>>>>>>> 8ac5427ed7 (Fix proptypes and docs)
"inheritance": null,
"demos": "<ul><li><a href=\"/components/react-meter/\">Meter</a></li></ul>",
"cssComponent": false
Expand Down
8 changes: 6 additions & 2 deletions docs/data/components/meter/meter.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -86,10 +86,14 @@ The optimum prop defines whether the low, medium, or high segment of the range i

## RTL

Set the `direction` prop to `'rtl'` to change the direction that the `Indicator` fills towards for right-to-left languages:
Place the component inside any HTML element or component with the HTML dir attribute to change the direction that the `Indicator` fills towards for right-to-left languages:

```jsx
<Meter.Root direction="rtl">{/* Subcomponents */}</Meter.Root>
<html dir="rtl">
<body>
<Meter.Root>{/* Subcomponents */}</Meter.Root>
</body>
</html>
```

## Overriding default components
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"componentDescription": "",
"propDescriptions": {
"className": {
"description": "Class names applied to the element or a function that returns them based on the component&#39;s state."
},
"render": { "description": "A function to customize rendering of the component." }
},
"classDescriptions": {}
}
37 changes: 37 additions & 0 deletions docs/data/translations/api-docs/meter-root/meter-root.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
{
"componentDescription": "",
"propDescriptions": {
"aria-label": { "description": "The label for the Indicator component." },
"aria-labelledby": {
"description": "An id or space-separated list of ids of elements that label the Indicator component."
},
"aria-valuetext": {
"description": "A string value that provides a human-readable text alternative for the current value of the meter indicator."
},
"className": {
"description": "Class names applied to the element or a function that returns them based on the component&#39;s state."
},
"getAriaLabel": {
"description": "Accepts a function which returns a string value that provides an accessible name for the Indicator component",
"typeDescriptions": { "value": "The component&#39;s value" }
},
"getAriaValueText": {
"description": "Accepts a function which returns a string value that provides a human-readable text alternative for the current value of the meter indicator.",
"typeDescriptions": { "value": "The component&#39;s value to format" }
},
"high": {
"description": "Sets the lower boundary of the high end of the numeric range represented by the component. If unspecified, or greater than <code>max</code>, it will fall back to <code>max</code>."
},
"low": {
"description": "Sets the upper boundary of the low end of the numeric range represented by the component. If unspecified, or less than <code>min</code>, it will fall back to <code>min</code>."
},
"max": { "description": "The maximum value" },
"min": { "description": "The minimum value" },
"optimum": {
"description": "Indicates the optimal point in the numeric range represented by the component. If unspecified, it will fall back to the midpoint between <code>min</code> and <code>max</code>."
},
"render": { "description": "A function to customize rendering of the component." },
"value": { "description": "The current value." }
},
"classDescriptions": {}
}
10 changes: 10 additions & 0 deletions docs/data/translations/api-docs/meter-track/meter-track.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"componentDescription": "",
"propDescriptions": {
"className": {
"description": "Class names applied to the element or a function that returns them based on the component&#39;s state."
},
"render": { "description": "A function to customize rendering of the component." }
},
"classDescriptions": {}
}
14 changes: 14 additions & 0 deletions docs/reference/generated/meter-indicator.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"name": "MeterIndicator",
"description": "",
"props": {
"className": {
"type": "string | (state) => string",
"description": "Class names applied to the element or a function that returns them based on the component's state."
},
"render": {
"type": "React.ReactElement | (props, state) => React.ReactElement",
"description": "A function to customize rendering of the component."
}
}
}
64 changes: 64 additions & 0 deletions docs/reference/generated/meter-root.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
{
"name": "MeterRoot",
"description": "",
"props": {
"value": {
"type": "number",
"required": true,
"description": "The current value."
},
"aria-label": {
"type": "string",
"description": "The label for the Indicator component."
},
"aria-labelledby": {
"type": "string",
"description": "An id or space-separated list of ids of elements that label the Indicator component."
},
"aria-valuetext": {
"type": "string",
"description": "A string value that provides a human-readable text alternative for the current value of the meter indicator."
},
"className": {
"type": "string | (state) => string",
"description": "Class names applied to the element or a function that returns them based on the component's state."
},
"getAriaLabel": {
"type": "function(value: number) => string",
"description": "Accepts a function which returns a string value that provides an accessible name for the Indicator component"
},
"getAriaValueText": {
"type": "function(value: number) => string",
"description": "Accepts a function which returns a string value that provides a human-readable text alternative for the current value of the meter indicator."
},
"high": {
"type": "number",
"default": "100",
"description": "Sets the lower boundary of the high end of the numeric range represented by the component.\nIf unspecified, or greater than `max`, it will fall back to `max`."
},
"low": {
"type": "number",
"default": "0",
"description": "Sets the upper boundary of the low end of the numeric range represented by the component.\nIf unspecified, or less than `min`, it will fall back to `min`."
},
"max": {
"type": "number",
"default": "100",
"description": "The maximum value"
},
"min": {
"type": "number",
"default": "0",
"description": "The minimum value"
},
"optimum": {
"type": "number",
"default": "50",
"description": "Indicates the optimal point in the numeric range represented by the component.\nIf unspecified, it will fall back to the midpoint between `min` and `max`."
},
"render": {
"type": "React.ReactElement | (props, state) => React.ReactElement",
"description": "A function to customize rendering of the component."
}
}
}
14 changes: 14 additions & 0 deletions docs/reference/generated/meter-track.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"name": "MeterTrack",
"description": "",
"props": {
"className": {
"type": "string | (state) => string",
"description": "Class names applied to the element or a function that returns them based on the component's state."
},
"render": {
"type": "React.ReactElement | (props, state) => React.ReactElement",
"description": "A function to customize rendering of the component."
}
}
}
11 changes: 9 additions & 2 deletions docs/src/app/experiments/meter.module.css
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
.grid {
background-color: var(--gray-container-1);
.wrapper {
font-family: system-ui, sans-serif;
background-color: var(--gray-container-1);
display: flex;
flex-flow: column nowrap;
gap: 3rem;
padding: 3rem;
}

.grid {
display: grid;
grid-template-columns: 40rem 40rem;
width: 100%;
Expand Down
53 changes: 38 additions & 15 deletions docs/src/app/experiments/meter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,44 @@ export default function MeterIntroduction() {
}

return (
<div className={classes.grid}>
<div className={classes.demo}>
<div className={classes.wrapper}>
<div className={classes.grid}>
<div className={classes.demo}>
<Meter.Root
className={classes.meter}
aria-label="Battery Life"
value={range.value}
min={range.min}
max={range.max}
high={range.high}
low={range.low}
optimum={range.optimum}
>
<Meter.Track className={classes.track}>
<Meter.Indicator className={classes.indicator} />
</Meter.Track>
</Meter.Root>
</div>
<div className={classes.controls}>
{['value', 'min', 'max', 'high', 'low', 'optimum'].map((v) => {
return (
<Input
key={v}
name={v}
label={v}
value={range[v as keyof Range]}
setValue={setValue}
/>
);
})}
</div>
</div>

<div dir="rtl">
<pre>
This is the same meter as above but wrapped in a div with the `dir="rtl"`
attribute so it fills from right-to-left
</pre>
<Meter.Root
className={classes.meter}
aria-label="Battery Life"
Expand All @@ -51,19 +87,6 @@ export default function MeterIntroduction() {
</Meter.Track>
</Meter.Root>
</div>
<div className={classes.controls}>
{['value', 'min', 'max', 'high', 'low', 'optimum'].map((v) => {
return (
<Input
key={v}
name={v}
label={v}
value={range[v as keyof Range]}
setValue={setValue}
/>
);
})}
</div>
</div>
);
}
Expand Down
2 changes: 0 additions & 2 deletions packages/react/src/meter/index.parts.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
export { MeterRoot as Root } from './root/MeterRoot';
export { MeterTrack as Track } from './track/MeterTrack';
export { MeterIndicator as Indicator } from './indicator/MeterIndicator';

export type { MeterDirection as Direction } from './root/useMeterRoot';
6 changes: 3 additions & 3 deletions packages/react/src/meter/indicator/MeterIndicator.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,16 @@ import { Meter } from '@base-ui-components/react/meter';
import { createRenderer, describeConformance } from '#test-utils';
import { MeterRootContext } from '../root/MeterRootContext';

const isJSDOM = /jsdom/.test(window.navigator.userAgent);

const contextValue: MeterRootContext = {
direction: 'ltr',
max: 100,
min: 0,
value: 30,
percentageValue: 30,
segment: 'low',
isOptimal: false,
state: {
direction: 'ltr',
max: 100,
min: 0,
segment: 'low',
Expand All @@ -35,7 +35,7 @@ describe('<Meter.Indicator />', () => {

describe('internal styles', () => {
it('sets positioning styles', async function test(t = {}) {
if (/jsdom/.test(window.navigator.userAgent)) {
if (isJSDOM) {
// @ts-expect-error to support mocha and vitest
// eslint-disable-next-line @typescript-eslint/no-unused-expressions
this?.skip?.() || t?.skip();
Expand Down
3 changes: 1 addition & 2 deletions packages/react/src/meter/indicator/MeterIndicator.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,9 @@ const MeterIndicator = React.forwardRef(function MeterIndicator(
) {
const { render, className, ...otherProps } = props;

const { direction, percentageValue, state } = useMeterRootContext();
const { percentageValue, state } = useMeterRootContext();

const { getRootProps } = useMeterIndicator({
direction,
percentageValue,
});

Expand Down
14 changes: 3 additions & 11 deletions packages/react/src/meter/indicator/useMeterIndicator.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,18 @@
'use client';
import * as React from 'react';
import { mergeReactProps } from '../../utils/mergeReactProps';
import { MeterDirection } from '../root/useMeterRoot';

function useMeterIndicator(
parameters: useMeterIndicator.Parameters,
): useMeterIndicator.ReturnValue {
const { direction, percentageValue } = parameters;

const isRtl = direction === 'rtl';
const { percentageValue } = parameters;

const getStyles = React.useCallback(() => {
return {
[isRtl ? 'right' : 'left']: 0,
insetInlineStart: 0,
width: `${percentageValue}%`,
};
}, [isRtl, percentageValue]);
}, [percentageValue]);

const getRootProps: useMeterIndicator.ReturnValue['getRootProps'] = React.useCallback(
(externalProps = {}) =>
Expand All @@ -32,11 +29,6 @@ function useMeterIndicator(

namespace useMeterIndicator {
export interface Parameters {
/**
* The direction that the meter fills towards
* @default 'ltr'
*/
direction?: MeterDirection;
/**
* The current value.
*/
Expand Down
Loading

0 comments on commit 28e7e8b

Please sign in to comment.