Skip to content

Commit

Permalink
refactor(grid): add experimental sass modules (#7811)
Browse files Browse the repository at this point in the history
* refactor(test-utils): update import convention and add get helper

* refactor(grid): add experimental sass modules

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
  • Loading branch information
joshblack and kodiakhq[bot] authored Feb 17, 2021
1 parent 36fcaaf commit 5dbab82
Show file tree
Hide file tree
Showing 8 changed files with 724 additions and 3 deletions.
22 changes: 22 additions & 0 deletions docs/migration/11.x-grid.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Grid

**Note: everything in this file is a work-in-progress and will be changed.**

## Changes

| Filename | v10 | v11 |
| ------------------- | ------------------------ | ---------------------------------------- |
| `scss/12.scss` | | Removed |
| `scss/_mixins.scss` | | |
| `scss/_mixins.scss` | `$carbon--aspect-ratios` | Removed, use styles package instead |
| `scss/_mixins.scss` | `@mixin carbon--grid` | |
| `scss/_prefix.scss` | | Removed, use `scss/_config.scss` instead |
| `scss/grid.scss` | | |
| `scss/index.scss` | | |

Notes

- The grid now uses 16 columns by default, there is no longer a 12 column mode
- Configure Sass Modules is now done through a `_config.scss` file (for things
like `$prefix`)
- Breakpoints are now defined in `@carbon/grid`
10 changes: 10 additions & 0 deletions packages/grid/__tests__/__snapshots__/scss-test.js.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`@carbon/grid Public API 1`] = `
Array [
"prefix",
"grid-gutter",
"grid-gutter--condensed",
"grid-breakpoints",
]
`;
34 changes: 34 additions & 0 deletions packages/grid/__tests__/scss-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/**
* Copyright IBM Corp. 2015, 2018
*
* This source code is licensed under the Apache-2.0 license found in the
* LICENSE file in the root directory of this source tree.
*
* @jest-environment node
*/

'use strict';

const { SassRenderer } = require('@carbon/test-utils/scss');

const { render } = SassRenderer.create(__dirname);

describe('@carbon/grid', () => {
test('Public API', async () => {
const { get } = await render(`
@use 'sass:meta';
@use '../index.scss' as grid;
$_: get('variables', meta.module-variables('grid'));
$_: get('mixins', (
grid: meta.mixin-exists('grid', 'grid'),
));
`);

const variables = get('variables');
expect(Object.keys(variables.value)).toMatchSnapshot();

const mixins = get('mixins');
expect(mixins.value.grid).toBe(true);
});
});
16 changes: 16 additions & 0 deletions packages/grid/index.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
//
// Copyright IBM Corp. 2018, 2018
//
// This source code is licensed under the Apache-2.0 license found in the
// LICENSE file in the root directory of this source tree.
//

@forward 'scss/modules/config' with (
$prefix: 'bx' !default,
);
@forward 'scss/modules/breakpoint';
@forward 'scss/modules/mixins';

@use 'scss/modules/mixins';

@include mixins.grid();
266 changes: 266 additions & 0 deletions packages/grid/scss/modules/_breakpoint.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,266 @@
//
// Copyright IBM Corp. 2018, 2018
//
// This source code is licensed under the Apache-2.0 license found in the
// LICENSE file in the root directory of this source tree.
//

// https://github.com/twbs/bootstrap/blob/v4-dev/scss/mixins/_breakpoints.scss
@use 'sass:list';
@use 'sass:map';
@use 'sass:meta';
@use '@carbon/layout/scss/modules/convert';

/// Map deep get
/// @author Hugo Giraudel
/// @access public
/// @param {Map} $map - Map
/// @param {Arglist} $keys - Key chain
/// @return {*} Desired value
/// @group @carbon/layout
@function map-deep-get($map, $keys...) {
@each $key in $keys {
$map: map-get($map, $key);
}
@return $map;
}

/// Provide a map and index, and get back the relevant key value
/// @access public
/// @param {Map} $map - Map
/// @param {Integer} $index - Key chain
/// @return {String} Desired value
/// @group @carbon/layout
@function key-by-index($map, $index) {
$keys: map-keys($map);
@return nth($keys, $index);
}

/// Pass in a map, and get the last one in the list back
/// @access public
/// @param {Map} $map - Map
/// @return {*} Desired value
/// @group @carbon/layout
@function last-map-item($map) {
$total-length: length($map);
@return map-get($map, key-by-index($map, $total-length));
}

/// Carbon gutter size in rem
/// @type Number
/// @access public
/// @group @carbon/layout
$grid-gutter: convert.rem(32px);

/// Carbon condensed gutter size in rem
/// @type Number
/// @access public
/// @group @carbon/layout
$grid-gutter--condensed: convert.rem(1px);

// Initial map of our breakpoints and their values
/// @type Map
/// @access public
/// @group @carbon/layout
$grid-breakpoints: (
sm: (
columns: 4,
margin: 0,
width: convert.rem(320px),
),
md: (
columns: 8,
margin: convert.rem(16px),
width: convert.rem(672px),
),
lg: (
columns: 16,
margin: convert.rem(16px),
width: convert.rem(1056px),
),
xlg: (
columns: 16,
margin: convert.rem(16px),
width: convert.rem(1312px),
),
max: (
columns: 16,
margin: convert.rem(24px),
width: convert.rem(1584px),
),
) !default;

/// Get the value of the next breakpoint, or null for the last breakpoint
/// @param {String} $name - The name of the brekapoint
/// @param {Map} $breakpoints [$grid-breakpoints] - A map of breakpoints where the key is the name of the breakpoint and the value is the values for the breakpoint
/// @param {List} $breakpoint-names [map-keys($breakpoints)] - A list of names from the `$breakpoints` map
/// @return {String}
/// @access public
/// @group @carbon/layout
@function breakpoint-next(
$name,
$breakpoints: $grid-breakpoints,
$breakpoint-names: map.keys($breakpoints)
) {
$n: list.index($breakpoint-names, $name);
@if $n != null and $n < list.length($breakpoint-names) {
@return list.nth($breakpoint-names, $n + 1);
}
@return null;
}

/// Get the value of the previous breakpoint, or null for the first breakpoint
/// @param {String} $name - The name of the brekapoint
/// @param {Map} $breakpoints [$grid-breakpoints] - A map of breakpoints where the key is the name of the breakpoint and the value is the values for the breakpoint
/// @param {List} $breakpoint-names [map-keys($breakpoints)] - A list of names from the `$breakpoints` map
/// @return {String}
/// @access public
/// @group @carbon/layout
@function breakpoint-prev(
$name,
$breakpoints: $grid-breakpoints,
$breakpoint-names: map.keys($breakpoints)
) {
$n: list.index($breakpoint-names, $name);
@if $n != null and $n > 1 {
@return list.nth($breakpoint-names, $n - 1);
}
@return null;
}

/// Check to see if the given breakpoint name
/// @param {String} $name - The name of the brekapoint
/// @param {Map} $breakpoints [$grid-breakpoints] - A map of breakpoints where the key is the name of the breakpoint and the value is the values for the breakpoint
/// @return {Bool}
/// @access public
/// @group @carbon/layout
@function is-smallest-breakpoint($name, $breakpoints: $grid-breakpoints) {
@return list.index(map.keys($breakpoints), $name) == 1;
}

/// Returns the largest breakpoint name
/// @param {Map} $breakpoints [$grid-breakpoints] - A map of breakpoints where the key is the name
/// @return {String}
/// @access public
/// @group @carbon/layout
@function largest-breakpoint-name($breakpoints: $grid-breakpoints) {
$total-breakpoints: list.length($breakpoints);
@return key-by-index($breakpoints, $total-breakpoints);
}

/// Get the infix for a given breakpoint in a list of breakpoints. Usesful for generate the size part in a selector, for example: `.prefix--col-sm-2`.
/// @param {String} $name - The name of the breakpoint
/// @return {String}
/// @access public
/// @group @carbon/layout
@function breakpoint-infix($name) {
@return '-#{$name}';
}

/// Generate a media query from the width of the given breakpoint to infinity
/// @param {String | Number} $name
/// @param {Map} $breakpoints [$grid-breakpoints] - A map of breakpoints where the key is the name
/// @content
/// @access public
/// @group @carbon/layout
@mixin breakpoint-up($name, $breakpoints: $grid-breakpoints) {
@if meta.type-of($name) == 'number' {
@media (min-width: $name) {
@content;
}
} @else if map.has-key($breakpoints, $name) {
$breakpoint: map.get($breakpoints, $name);
$width: map.get($breakpoint, width);
@if is-smallest-breakpoint($name, $breakpoints) {
@content;
} @else {
@media (min-width: $width) {
@content;
}
}
} @else {
@error 'Unable to find a breakpoint with name `#{$name}`. Expected one of: (#{map.keys($breakpoints)})';
}
}

/// Generate a media query for the maximum width of the given styles
/// @param {String | Number} $name
/// @param {Map} $breakpoints [$grid-breakpoints] - A map of breakpoints where the key is the name
/// @content
/// @access public
/// @group @carbon/layout
@mixin breakpoint-down($name, $breakpoints: $grid-breakpoints) {
@if meta.type-of($name) == 'number' {
@media (max-width: $name) {
@content;
}
} @else if map.has-key($breakpoints, $name) {
// We borrow this logic from bootstrap for specifying the value of the
// max-width. The maximum width is calculated by finding the breakpoint and
// subtracting .02 from its value. This value is used instead of .01 to
// avoid rounding issues in Safari
// https://github.com/twbs/bootstrap/blob/c5b1919deaf5393fcca9e9b9d7ce9c338160d99d/scss/mixins/_breakpoints.scss#L34-L46
$breakpoint: map.get($breakpoints, $name);
$width: map.get($breakpoint, width) - 0.02;
@media (max-width: $width) {
@content;
}
} @else {
@error 'Unable to find a breakpoint with name `#{$name}`. Expected one of: (#{map.keys($breakpoints)})';
}
}

/// Generate a media query for the range between the lower and upper breakpoints
/// @param {String | Number} $lower
/// @param {String | Number} $upper
/// @param {Map} $breakpoints [$grid-breakpoints] - A map of breakpoints where the key is the name
/// @content
/// @access public
/// @group @carbon/layout
@mixin breakpoint-between($lower, $upper, $breakpoints: $grid-breakpoints) {
$is-number-lower: meta.type-of($lower) == 'number';
$is-number-upper: meta.type-of($upper) == 'number';
$min: if($is-number-lower, $lower, map.get($breakpoints, $lower));
$max: if($is-number-upper, $upper, map.get($breakpoints, $upper));

@if $min and $max {
$min-width: if(not $is-number-lower and $min, map.get($min, width), $min);
$max-width: if(not $is-number-upper and $max, map.get($max, width), $max);
@media (min-width: $min-width) and (max-width: $max-width) {
@content;
}
} @else if $min != null and $max == null {
@include breakpoint-up($lower) {
@content;
}
} @else if $min == null and $max != null {
@include breakpoint-down($upper) {
@content;
}
} @else {
@error 'Unable to find a breakpoint to satisfy: (#{$lower},#{$upper}). Expected both to be one of (#{map.keys($breakpoints)}).';
}
}

/// Generate media query for the largest breakpoint
/// @param {Map} $breakpoints [$grid-breakpoints] - A map of breakpoints where the key is the name
/// @content
/// @access public
/// @group @carbon/layout
@mixin largest-breakpoint($breakpoints: $grid-breakpoints) {
@include breakpoint(largest-breakpoint-name()) {
@content;
}
}

/// Generate a media query for a given breakpoint
/// @param {String | Number} $name
/// @param {Map} $breakpoints [$grid-breakpoints] - A map of breakpoints where the key is the name
/// @content
/// @access public
/// @group @carbon/layout
@mixin breakpoint($name, $breakpoints: $grid-breakpoints) {
@include breakpoint-up($name, $breakpoints) {
@content;
}
}
12 changes: 12 additions & 0 deletions packages/grid/scss/modules/_config.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
//
// Copyright IBM Corp. 2018, 2018
//
// This source code is licensed under the Apache-2.0 license found in the
// LICENSE file in the root directory of this source tree.
//

/// Namespace prefix
/// @type String
/// @access public
/// @group @carbon/grid
$prefix: 'bx' !default;
Loading

0 comments on commit 5dbab82

Please sign in to comment.