-
Notifications
You must be signed in to change notification settings - Fork 31
chore(GamutProvider): useLogicalProperties hook #3306
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
Open
dreamwasp
wants to merge
31
commits into
main
Choose a base branch
from
cass-gmt-1601
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
31 commits
Select commit
Hold shift + click to select a range
7f034fa
chore(GamutProvider): useLogicalProperties hook
dreamwasp 108f425
Merge branch 'main' into cass-gmt-1601
dreamwasp c0b93a2
add release plan
dreamwasp e9dae8d
test code
dreamwasp 1dcc89a
feat(gamut-styles): add directionIsRtl utility
dreamwasp f873f06
get directionality
dreamwasp 37924f5
console.log dir
dreamwasp 4f89003
fix syntaxerror
dreamwasp afe99d5
added release plan
dreamwasp 058aede
keep console.log
dreamwasp caf7514
version
dreamwasp 3939c6f
new docs
dreamwasp e0b009f
fix some other shit
dreamwasp 4dd96c0
fix(InfoTip): update rtl styles (#3319)
dreamwasp 2b40dea
version
dreamwasp ef51010
Update packages/styleguide/src/lib/Meta/Logical and physical CSS prop…
dreamwasp 87977e8
kenny edits
dreamwasp 264423e
Merge branch 'cass-gmt-1601' of github.com:Codecademy/gamut into cass…
dreamwasp 8975574
fix some other stuff
dreamwasp 80f56ab
fix some other stuff
dreamwasp 550e5e9
fix some other stuff
dreamwasp 29ef404
fix(InfoTip): update rtl styles (#3319)
dreamwasp 1fe7c8c
version
dreamwasp c5ad7fe
kenny edits
dreamwasp 373e16e
Update packages/styleguide/src/lib/Meta/Logical and physical CSS prop…
dreamwasp 46a2950
Merge branch 'cass-gmt-1601' of github.com:Codecademy/gamut into cass…
dreamwasp f4c3f38
Update packages/styleguide/src/lib/Meta/Logical and physical CSS prop…
dreamwasp 56011cb
fix releases
dreamwasp efe7e58
add real changelog message
dreamwasp 3c6a8ee
fix(Pagination): Previous and Next Buttons to respect RTL (#3316)
LinKCoding 6efbb0b
update changelog
dreamwasp File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| --- | ||
| gamut-styles: minor | ||
| gamut: minor | ||
| --- | ||
|
|
||
| Updates the Pagination component to have its Previous/Next buttons' icon reflect the correct dir |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| --- | ||
| gamut-styles: minor | ||
| gamut: minor | ||
| --- | ||
|
|
||
| feat: add useLogicalProperties + useElementDir hooks. fix: RTL left-center + right-center ToolTip and Pagination issues. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
25 changes: 25 additions & 0 deletions
25
packages/gamut-styles/src/utilities/__tests__/elementDir.test.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,25 @@ | ||
| import { elementDir } from '../elementDir'; | ||
|
|
||
| describe('elementDir', () => { | ||
| afterEach(() => { | ||
| document.documentElement.removeAttribute('dir'); | ||
| }); | ||
|
|
||
| it('returns rtl when the element has dir="rtl"', () => { | ||
| const el = document.createElement('div'); | ||
| el.setAttribute('dir', 'rtl'); | ||
| expect(elementDir(el)).toBe('rtl'); | ||
| }); | ||
|
|
||
| it('returns ltr when the element has dir="ltr"', () => { | ||
| const el = document.createElement('div'); | ||
| el.setAttribute('dir', 'ltr'); | ||
| expect(elementDir(el)).toBe('ltr'); | ||
| }); | ||
|
|
||
| it('falls back to documentElement dir when computed style is empty (JSDOM)', () => { | ||
| const el = document.createElement('div'); | ||
| document.documentElement.setAttribute('dir', 'rtl'); | ||
| expect(elementDir(el)).toBe('rtl'); | ||
| }); | ||
| }); |
File renamed without changes.
66 changes: 66 additions & 0 deletions
66
packages/gamut-styles/src/utilities/__tests__/useElementDir.test.tsx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,66 @@ | ||
| import * as React from 'react'; | ||
|
|
||
| import { setupRtl } from '../../__tests__/testUtils'; | ||
| import { useElementDir } from '../elementDir'; | ||
|
|
||
| const DirProbe: React.FC = () => ( | ||
| <span data-testid="dir">{useElementDir()}</span> | ||
| ); | ||
|
|
||
| const WithRef: React.FC = () => { | ||
| const ref = React.useRef<HTMLDivElement>(null); | ||
| return ( | ||
| <> | ||
| <div data-testid="dir">{useElementDir(ref)}</div> | ||
| <div dir="rtl" ref={ref}> | ||
| x | ||
| </div> | ||
| </> | ||
| ); | ||
| }; | ||
|
|
||
| const WithSpanRef: React.FC = () => { | ||
| const ref = React.useRef<HTMLSpanElement>(null); | ||
| return ( | ||
| <> | ||
| <span data-testid="dir">{useElementDir(ref)}</span> | ||
| <span dir="rtl" ref={ref}> | ||
| x | ||
| </span> | ||
| </> | ||
| ); | ||
| }; | ||
|
|
||
| const renderDirProbe = setupRtl(DirProbe, {}); | ||
| const renderWithRef = setupRtl(WithRef, {}); | ||
| const renderWithSpanRef = setupRtl(WithSpanRef, {}); | ||
|
|
||
| describe('useElementDir', () => { | ||
| afterEach(() => { | ||
| document.documentElement.removeAttribute('dir'); | ||
| }); | ||
|
|
||
| it('returns rtl when documentElement has dir=rtl and no ref', () => { | ||
| document.documentElement.setAttribute('dir', 'rtl'); | ||
|
|
||
| const { view } = renderDirProbe(); | ||
| expect(view.getByTestId('dir')).toHaveTextContent('rtl'); | ||
| }); | ||
|
|
||
| it('returns ltr when documentElement has dir=ltr and no ref', () => { | ||
| document.documentElement.setAttribute('dir', 'ltr'); | ||
|
|
||
| const { view } = renderDirProbe(); | ||
| expect(view.getByTestId('dir')).toHaveTextContent('ltr'); | ||
| }); | ||
|
|
||
| it('uses ref target when it is an Element', () => { | ||
| const { view } = renderWithRef(); | ||
| expect(view.getByTestId('dir')).toHaveTextContent('rtl'); | ||
| }); | ||
|
|
||
| it('accepts non-div element refs (e.g. span)', () => { | ||
| const { view } = renderWithSpanRef(); | ||
| expect(view.getByTestId('dir')).toHaveTextContent('rtl'); | ||
| }); | ||
| }); |
36 changes: 36 additions & 0 deletions
36
packages/gamut-styles/src/utilities/__tests__/useLogicalProperties.test.tsx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,36 @@ | ||
| import { Theme, ThemeProvider } from '@emotion/react'; | ||
| import * as React from 'react'; | ||
|
|
||
| import { setupRtl } from '../../__tests__/testUtils'; | ||
| import { coreTheme as theme } from '../../themes'; | ||
| import { useLogicalProperties } from '../useLogicalProperties'; | ||
|
|
||
| const ValueReadout: React.FC = () => <span>{`${useLogicalProperties()}`}</span>; | ||
|
|
||
| const HookProbe: React.FC<{ themeForHook?: Theme }> = ({ | ||
| themeForHook = theme, | ||
| }) => ( | ||
| <ThemeProvider theme={themeForHook}> | ||
| <ValueReadout /> | ||
| </ThemeProvider> | ||
| ); | ||
|
|
||
| const renderView = setupRtl(HookProbe, {}); | ||
|
|
||
| describe('useLogicalProperties', () => { | ||
| it('returns false when theme sets useLogicalProperties: false', () => { | ||
| const { view } = renderView({ | ||
| themeForHook: { ...theme, useLogicalProperties: false }, | ||
| }); | ||
|
|
||
| view.getByText('false'); | ||
| }); | ||
|
|
||
| it('returns true when theme sets useLogicalProperties: true', () => { | ||
| const { view } = renderView({ | ||
| themeForHook: { ...theme, useLogicalProperties: true }, | ||
| }); | ||
|
|
||
| view.getByText('true'); | ||
| }); | ||
| }); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,80 @@ | ||
| import type { RefObject } from 'react'; | ||
| import { useEffect, useLayoutEffect, useReducer } from 'react'; | ||
|
|
||
| /** | ||
| * Resolved HTML `dir` keyword: effective writing direction after `dir`, then CSS | ||
| * `direction`, then document root. | ||
| */ | ||
| export type DirValue = 'rtl' | 'ltr'; | ||
|
|
||
| /** | ||
| * Resolves the effective `dir` for an element (`rtl` or `ltr`), including JSDOM where | ||
| * `getComputedStyle(el).direction` is often empty while `dir` is set on the root. | ||
| * | ||
| * @param el - DOM node whose effective direction is resolved. | ||
| * @returns `rtl` or `ltr`. | ||
| */ | ||
| export function elementDir(el: Element): DirValue { | ||
| const ownDir = el.getAttribute('dir'); | ||
| if (ownDir === 'rtl') return 'rtl'; | ||
| if (ownDir === 'ltr') return 'ltr'; | ||
| const { direction } = getComputedStyle(el); | ||
| if (direction === 'rtl' || direction === 'ltr') { | ||
| return direction; | ||
| } | ||
| return document.documentElement.getAttribute('dir') === 'rtl' ? 'rtl' : 'ltr'; | ||
| } | ||
|
|
||
| /** | ||
| * Ref whose `current` may be any DOM {@link Element} subclass (`HTMLElement`, `SVGElement`, | ||
| * `HTMLButtonElement`, etc.). For structural/minimal types (e.g. tests), intersect with | ||
| * `Element` so `current` is still typed as an `Element` (e.g. `Pick<HTMLAnchorElement, 'id'> & Element`). | ||
| * | ||
| * @template T - DOM element type for `current`; defaults to {@link Element}. | ||
| */ | ||
| export type ElementDirRef<T extends Element = Element> = RefObject<T | null>; | ||
|
|
||
| function resolveElement<T extends Element>( | ||
| elementRef: ElementDirRef<T> | undefined | ||
| ): Element { | ||
| return elementRef?.current instanceof Element | ||
| ? elementRef.current | ||
| : document.documentElement; | ||
| } | ||
|
|
||
| /** | ||
| * Returns the effective `dir` for the resolved element (`rtl` or `ltr`), and updates when `dir` | ||
| * changes on the document subtree or after layout (so `ref.current` is current). | ||
| * Resolution uses {@link elementDir}. | ||
| * | ||
| * @template T - DOM element type for the optional ref; defaults to {@link Element}. | ||
| * @param elementRef - Optional ref; when missing or `current` is not an `Element`, uses `document.documentElement`. | ||
| * @returns Effective direction for the resolved element, or `ltr` when `document` is undefined (SSR). | ||
| */ | ||
| export function useElementDir<T extends Element = Element>( | ||
| elementRef?: ElementDirRef<T> | ||
| ): DirValue { | ||
| const [, bump] = useReducer((n: number) => n + 1, 0); | ||
|
|
||
| useLayoutEffect(() => { | ||
| bump(); | ||
| }, [elementRef]); | ||
|
|
||
| useEffect(() => { | ||
| const observer = new MutationObserver(() => { | ||
| bump(); | ||
| }); | ||
| observer.observe(document.documentElement, { | ||
| attributeFilter: ['dir'], | ||
| attributes: true, | ||
| subtree: true, | ||
| }); | ||
| return () => observer.disconnect(); | ||
| }, []); | ||
|
|
||
| if (typeof document === 'undefined') { | ||
| return 'ltr'; | ||
| } | ||
|
|
||
| return elementDir(resolveElement(elementRef)); | ||
| } |
File renamed without changes.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1 +1,3 @@ | ||
| export * from './elementDir'; | ||
| export * from './themed'; | ||
| export * from './useLogicalProperties'; |
12 changes: 12 additions & 0 deletions
12
packages/gamut-styles/src/utilities/useLogicalProperties.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| import { useTheme } from '@emotion/react'; | ||
|
|
||
| /** | ||
| * Whether Gamut system props map to logical CSS properties (`marginInlineStart`, etc.) | ||
| * vs physical (`marginLeft`, etc.). | ||
| * | ||
| * `GamutProvider` always merges an explicit boolean (default `false`). | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Just noting that this should change later when the default is also changed |
||
| */ | ||
| export function useLogicalProperties() { | ||
| const theme = useTheme(); | ||
| return theme?.useLogicalProperties; | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i was getting an error when trying to commit files with spaces, this fixes that.