Skip to content

Commit

Permalink
feat(scale): dynamically apply minimumSize as second argument
Browse files Browse the repository at this point in the history
Add logo and turn on provenance. release-npm

BREAKING CHANGE: If the second argument is likely a size it will be used as the minimum size instead of the scale factor. Should have no effect in most cases.
  • Loading branch information
tobua committed Feb 13, 2024
1 parent db82763 commit d40a34e
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 16 deletions.
27 changes: 21 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
<p align="center">
<img src="https:/tobua/optica/raw/main/logo.png" alt="avait" width="50%">
</p>

# optica

Responsively scaling CSS properties for JavaScript, successor to [wasser](https:/tobua/wasser). Linearly scales a value between a minimum and a maximum breakpoint. Requires only the CSS [`clamp`](https://developer.mozilla.org/en-US/docs/Web/CSS/clamp) function, no breakpoints.
Expand All @@ -13,10 +17,12 @@ createRoot(document.body).render(
<div style={{ margin: scale(10), background: 'gray', borderRadius: scale(5) }}>
<h1 style={{ fontSize: scale(24) }}>Title</h1>
<p style={{ fontSize: scale(24) }}>Description</p>
</div>
</div>,
)
```

The plugin will convert `scale(15)` into `clamp(10px, calc(8.65px + 0.42vw), 15px)` which will ensure any sized CSS property will linearly scale between `10px` for the `minimumViewport` (320px) and `15px` for the `maximumViewport` (1500px).

## Configuration

By default values will scale between the `320px` and the `1500px` breakpoint with a scaling factor of `1.5`. The `scale` method can additionally receive a custom scaling factor as the second argument.
Expand All @@ -25,10 +31,19 @@ By default values will scale between the `320px` and the `1500px` breakpoint wit
import { configure, scale } from 'optica'

configure({
minimumViewport: 400,
maximumViewport: 1200,
scalingFactor: 2
minimumViewport: 400, // Default 320
maximumViewport: 1200, // Default 1500
scalingFactor: 2, // Default: 1.5
})

const MyText = () => <span style={{ fontSize: scale(16, 3) }}>
```
const MyCustomText = () => <span style={{ fontSize: scale(18) }} /> // 9px - 18px instead of 12px - 18px
```

`scale(maximumSize: number, scalingFactorOrMinimumSize: number)` also takes a second argument. Depending on the size it's either a `scalingFactor` or an explicit `minimumSize`.

```ts
scale(18, 3) // scaleFactor of 3: 6px - 18px
scale(18, 1.2) // scaleFactor of 1.2: 15px - 18px
scale(18, 12) // minimumSize of 12: 12px - 18px
scale(18, 16) // minimumSize of 16: 16px - 18px
```
19 changes: 15 additions & 4 deletions index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,20 @@ export function configure(values: Partial<typeof configuration>) {
Object.assign(configuration, values)
}

export function scale(size: number, scalingFactor = configuration.scalingFactor) {
const minimumSize = size / scalingFactor
function getMinimumSize(maximumSize: number, input: number) {
if (input < maximumSize / 5) return maximumSize / input
if (input > 5) return input
if (input < maximumSize / 3 && input < 3) return maximumSize / input
return input
}

export function scale(
maximumSize: number,
scalingFactorOrMinimumSize = configuration.scalingFactor,
) {
const minimumSize = getMinimumSize(maximumSize, scalingFactorOrMinimumSize)
const multiplier =
(size - minimumSize) / (configuration.maximumViewport - (configuration.minimumViewport - 1))
return `clamp(${round(minimumSize)}px, calc(${round(minimumSize - multiplier * configuration.minimumViewport)}px + ${round(multiplier * 100)}vw), ${size}px)`
(maximumSize - minimumSize) /
(configuration.maximumViewport - (configuration.minimumViewport - 1))
return `clamp(${round(minimumSize)}px, calc(${round(minimumSize - multiplier * configuration.minimumViewport)}px + ${round(multiplier * 100)}vw), ${maximumSize}px)`
}
Binary file added logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
"extends": "./node_modules/padua/configuration/eslint.cjs"
},
"publishConfig": {
"provenance": false
"provenance": true
},
"engines": {
"node": ">= 18"
Expand Down
24 changes: 19 additions & 5 deletions test/scale.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,32 @@ import { scale, configure } from '../index'

test('Returns correct clamp function values.', () => {
expect(scale(10)).toEqual('clamp(6.67px, calc(5.76px + 0.28vw), 10px)')
expect(scale(15)).toEqual('clamp(10px, calc(8.65px + 0.42vw), 15px)')
expect(scale(20)).toEqual('clamp(13.33px, calc(11.53px + 0.56vw), 20px)')
})

test('scale: second argument can either be the scalingFactor or the minimum target size.', () => {
// Choice between factor and minimum is an approximation and not perfect.
expect(scale(10, 2)).toEqual('clamp(5px, calc(3.65px + 0.42vw), 10px)')
expect(scale(10, 8)).toEqual('clamp(8px, calc(7.46px + 0.17vw), 10px)')
expect(scale(30, 10)).toEqual('clamp(10px, calc(4.58px + 1.69vw), 30px)')
expect(scale(45, 3)).toEqual('clamp(15px, calc(6.87px + 2.54vw), 45px)')
expect(scale(2, 1)).toEqual('clamp(1px, calc(0.73px + 0.08vw), 2px)')
expect(scale(5, 3)).toEqual('clamp(3px, calc(2.46px + 0.17vw), 5px)')
expect(scale(16, 3)).toEqual('clamp(5.33px, calc(2.44px + 0.9vw), 16px)')
expect(scale(16, 2)).toEqual('clamp(8px, calc(5.83px + 0.68vw), 16px)')
expect(scale(16, 4)).toEqual('clamp(4px, calc(0.75px + 1.02vw), 16px)')
expect(scale(16, 5)).toEqual('clamp(5px, calc(2.02px + 0.93vw), 16px)')
})

test('configure: default parameters can be configured.', () => {
expect(scale(10)).toEqual('clamp(6.67px, calc(5.76px + 0.28vw), 10px)')
configure({ scalingFactor: 2 })

expect(scale(10)).toEqual('clamp(5px, calc(3.65px + 0.42vw), 10px)')

configure({ minimumViewport: 500, maximumViewport: 1000 })

expect(scale(10)).toEqual('clamp(5px, calc(0.01px + 1vw), 10px)')

configure({ scalingFactor: 1 })

expect(scale(10)).toEqual('clamp(10px, calc(10px + 0vw), 10px)')
// Second argument to scale has precedence over configuration override.
expect(scale(10, 2)).toEqual('clamp(5px, calc(0.01px + 1vw), 10px)')
})

0 comments on commit d40a34e

Please sign in to comment.