Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion libs/design/scss/theming/_configure-palette.scss
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
/// as the palette’s default color. The palette can then be used
/// to configure themes by setting them as primary, secondary, or tertiary colors.
///
/// The hue is recorded alongside the color as `default-hue`, so that colors can
/// be selected relative to the default with `daff-color-shift`.
///
/// @group Theming
///
/// @param {Map} $color-palette — A color palette map (e.g., `$daff-blue`, `$daff-purple`).
Expand All @@ -21,7 +24,8 @@
@return map.merge(
$color-palette,
(
'default': get-color.daff-color($color-palette, $hue)
'default': get-color.daff-color($color-palette, $hue),
'default-hue': $hue
)
);
}
3 changes: 2 additions & 1 deletion libs/design/scss/theming/_index.scss
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
@forward 'color-palettes';
@forward 'get-color';
@forward 'color-shift';
@forward 'contrast';
@forward 'configure-palette';
@forward 'create-theme/create-theme';
@forward 'create-theme';
@forward 'light-dark';
@forward 'get-palette';
@forward 'get-base-color';
Expand Down
56 changes: 56 additions & 0 deletions libs/design/scss/theming/color-shift/_color-shift.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
// stylelint-disable @stylistic/max-line-length
@use 'sass:map';
@use '../get-color';
@use '../../core/error/error-to-string';

/// @access private
/// The distance between two adjacent hues in a color palette.
$hue-step: 10;

/// Retrieves a color relative to a palette's default hue.
///
/// Positive steps move toward the darker end of the palette, negative steps
/// toward the lighter end. Use this instead of a hardcoded hue when a color is
/// meant to sit a fixed distance from a palette's default, such as the hover
/// and active states of a component.
///
/// The palette must be configured with `daff-configure-palette`, which records
/// the hue that the default was set from.
///
/// @group Theming
///
/// @param {Map} $palette — The palette to retrieve a color from.
/// @param {Number} $steps [0] — How many hue steps to shift from the default.
///
/// @return {Color} The color `$steps` away from the palette's default hue.
///
/// @throws Will throw an error if `$palette` was not configured with
/// `daff-configure-palette`, or if the shifted hue does not exist in `$palette`.
///
/// @example scss
/// // $primary configured at hue 60
/// .custom-content {
/// background-color: daff-color($primary); // hue 60
/// border-color: daff-color-shift($primary, 1); // hue 70
/// color: daff-color-shift($primary, -1); // hue 50
/// }
///
@function daff-color-shift($palette, $steps: 0) {
$default-hue: map.get($palette, 'default-hue');

@if ($default-hue == null) {
@return error-to-string.error-to-string(
'Palette has no `default-hue`. Configure it with `daff-configure-palette`.'
);
}

$hue: $default-hue + ($steps * $hue-step);

@if (not map.has-key($palette, $hue)) {
@return error-to-string.error-to-string(
'Cannot shift `#{$steps}` step(s) from hue `#{$default-hue}`. `#{$hue}` does not exist in palette.'
);
}

@return get-color.daff-color($palette, $hue);
}
107 changes: 107 additions & 0 deletions libs/design/scss/theming/color-shift/_color-shift.spec.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
@use 'true' as *;
@use 'sass:map';
@use '../color-shift' as *;
@use '../color-palettes' as palette;
@use '../configure-palette' as *;
@use '../get-color' as *;
@use '../../core/error/error-to-string';

@include describe('daff-color-shift') {
$default: daff-configure-palette(palette.$daff-blue);
$light: daff-configure-palette(palette.$daff-blue, 30);
$dark: daff-configure-palette(palette.$daff-blue, 50);
$lightest: daff-configure-palette(palette.$daff-blue, 10);
$darkest: daff-configure-palette(palette.$daff-blue, 100);

@include it('returns the default color when there is no shift') {
@include assert-equal(daff-color-shift($default), daff-color($default));
@include assert-equal(daff-color-shift($default, 0), daff-color($default, 60));
}

@include it('returns a darker color for positive steps') {
@include assert-equal(daff-color-shift($default, 1), daff-color($default, 70));
@include assert-equal(daff-color-shift($default, 2), daff-color($default, 80));
}

@include it('returns a lighter color for negative steps') {
@include assert-equal(daff-color-shift($dark, -1), daff-color($dark, 40));
@include assert-equal(daff-color-shift($dark, -2), daff-color($dark, 30));
}

@include it('shifts relative to the hue the palette was configured with') {
@include assert-equal(daff-color-shift($light, 1), daff-color($light, 40));
@include assert-equal(daff-color-shift($light, 2), daff-color($light, 50));
}

@include it('shifts across the whole palette') {
@include assert-equal(daff-color-shift($lightest, 9), daff-color($lightest, 100));
@include assert-equal(daff-color-shift($darkest, -9), daff-color($darkest, 10));
}

@include it('shifts relative to the configured hue, not a duplicate color earlier in the palette') {
$duplicate: daff-configure-palette((10: #ffffff, 20: #cccccc, 30: #cccccc, 40: #999999), 30);

@include assert-equal(daff-color-shift($duplicate, 1), #999999);
}

@include error-to-string.set-use-string(true);

@include it('errors when the shift falls past the dark end of the palette') {
@include assert-equal(
daff-color-shift($darkest, 1),
'Cannot shift `1` step(s) from hue `100`. `110` does not exist in palette.'
);
}

@include it('errors when the shift falls past the light end of the palette') {
@include assert-equal(
daff-color-shift($lightest, -1),
'Cannot shift `-1` step(s) from hue `10`. `0` does not exist in palette.'
);
}

@include it('errors when the shift lands between hues') {
@include assert-equal(
daff-color-shift($default, 0.5),
'Cannot shift `0.5` step(s) from hue `60`. `65` does not exist in palette.'
);
}

@include it('errors when the palette was not configured with daff-configure-palette') {
@include assert-equal(
daff-color-shift(palette.$daff-blue, 1),
'Palette has no `default-hue`. Configure it with `daff-configure-palette`.'
);
}

@include it('errors when the palette has a default color but no default hue') {
$manual: map.merge(palette.$daff-blue, ('default': daff-color(palette.$daff-blue, 60)));

@include assert-equal(
daff-color-shift($manual, 1),
'Palette has no `default-hue`. Configure it with `daff-configure-palette`.'
);
}

@include error-to-string.set-use-string(false);
}

@include describe('daff-configure-palette') {
@include it('records the hue the default was configured from') {
@include assert-equal(
map.get(daff-configure-palette(palette.$daff-blue), 'default-hue'),
60
);
@include assert-equal(
map.get(daff-configure-palette(palette.$daff-blue, 30), 'default-hue'),
30
);
}

@include it('replaces the recorded hue when a palette is reconfigured') {
$reconfigured: daff-configure-palette(daff-configure-palette(palette.$daff-blue, 30), 80);

@include assert-equal(map.get($reconfigured, 'default-hue'), 80);
@include assert-equal(map.get($reconfigured, 'default'), daff-color(palette.$daff-blue, 80));
}
}
1 change: 1 addition & 0 deletions libs/design/scss/theming/color-shift/_index.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
@forward 'color-shift';
Loading