UNPKG

20.8 kBSCSSView Raw
1@use "sass:map";
2@use "sass:color";
3@use "./helpers/utils";
4@use "helpers/color_inference";
5
6/// Deep merged two maps and gives you the value of a key in the merged map.
7/// @param {Map} $map - The base map, whose keys will be overridden by the keys in $map2.
8/// @param {Map} $map2 - The map whose keys will override the keys in $map.
9/// @param {String} $key - The key whose value you want to get from the merged map.
10@function get-merged($map, $map2, $key) {
11 @return map.get(map.deep-merge($map, $map2), $key);
12}
13
14/// Set this to the background color of your page. It's needed for example for some things that fade into the background color (that are over another element).
15$page-background-color: white !default;
16
17/// The colors to be used across the UI
18/// We're trying to avoid getting colours from this map directly in style declarations, instead there's a layer of abstraction on top of this map.
19/// That is because different things in the UI need to have different colours from the palette, depending on the palette.
20/// See the maps below for text and icon colours, border colors and background colors.
21$base-colors: () !default;
22$base-colors-defaults: (
23 1000: #000,
24 800: #0f0f0f,
25 600: #333335,
26 500: #868689,
27 400: #cbcbcc,
28 300: #e4e4e5,
29 200: #f3f3f5,
30 100: #fafafc,
31 0: #fff,
32);
33
34$text-icon-colors: () !default;
35$text-icon-colors-defaults: (
36 "base": (
37 "default": get-merged($base-colors-defaults, $base-colors, 800),
38 "hover": get-merged($base-colors-defaults, $base-colors, 600),
39 "pressed": get-merged($base-colors-defaults, $base-colors, 1000),
40 "disabled": get-merged($base-colors-defaults, $base-colors, 400),
41 ),
42 "neutral": (
43 "default": get-merged($base-colors-defaults, $base-colors, 600),
44 "hover": get-merged($base-colors-defaults, $base-colors, 800),
45 "pressed": get-merged($base-colors-defaults, $base-colors, 1000),
46 "disabled": get-merged($base-colors-defaults, $base-colors, 400),
47 ),
48 "subtle": (
49 "default": get-merged($base-colors-defaults, $base-colors, 500),
50 "hover": get-merged($base-colors-defaults, $base-colors, 600),
51 "pressed": get-merged($base-colors-defaults, $base-colors, 800),
52 "disabled": get-merged($base-colors-defaults, $base-colors, 400),
53 ),
54 "inverse": (
55 "default": get-merged($base-colors-defaults, $base-colors, 0),
56 "hover": get-merged($base-colors-defaults, $base-colors, 200),
57 "pressed": get-merged($base-colors-defaults, $base-colors, 300),
58 "disabled": get-merged($base-colors-defaults, $base-colors, 500),
59 ),
60);
61
62/// Makes it easy to get the text color
63/// @param {"base" | "neutral" | "subtle" | "inverse"} $type - What type of color
64/// @param {"default" | "hover" | "pressed" | "disabled"} $state ["base"] - The state
65@function get-text-icon-color($type, $state) {
66 @return color_inference.get-possible-inferred-or-merged-something(
67 $text-icon-colors-defaults,
68 $text-icon-colors,
69 $type,
70 $state
71 );
72}
73
74$border-colors: () !default;
75$border-colors-defaults: (
76 "base": (
77 "default": get-merged($base-colors-defaults, $base-colors, 800),
78 "hover": get-merged($base-colors-defaults, $base-colors, 600),
79 "pressed": get-merged($base-colors-defaults, $base-colors, 1000),
80 "disabled": get-merged($base-colors-defaults, $base-colors, 400),
81 ),
82 "neutral": (
83 "default": get-merged($base-colors-defaults, $base-colors, 400),
84 "hover": get-merged($base-colors-defaults, $base-colors, 500),
85 "pressed": get-merged($base-colors-defaults, $base-colors, 700),
86 "disabled": get-merged($base-colors-defaults, $base-colors, 300),
87 ),
88 "subtle": (
89 "default": get-merged($base-colors-defaults, $base-colors, 300),
90 "hover": get-merged($base-colors-defaults, $base-colors, 400),
91 "pressed": get-merged($base-colors-defaults, $base-colors, 500),
92 "disabled": get-merged($base-colors-defaults, $base-colors, 200),
93 ),
94 "inverse": (
95 "default": get-merged($base-colors-defaults, $base-colors, 0),
96 "hover": get-merged($base-colors-defaults, $base-colors, 400),
97 "pressed": get-merged($base-colors-defaults, $base-colors, 300),
98 "disabled": get-merged($base-colors-defaults, $base-colors, 500),
99 ),
100);
101
102/// Makes it easy to get the border color
103/// @param {"base" | "neutral" | "subtle" | "inverse"} $type - What type of color
104/// @param {"default" | "hover" | "pressed" | "disabled"} $state ["base"] - The state
105@function get-border-color($type, $state) {
106 @return color_inference.get-possible-inferred-or-merged-something(
107 $border-colors-defaults,
108 $border-colors,
109 $type,
110 $state
111 );
112}
113
114$background-colors: () !default;
115$background-colors-defaults: (
116 "base": (
117 "default": get-merged($base-colors-defaults, $base-colors, 0),
118 "hover": get-merged($base-colors-defaults, $base-colors, 200),
119 "pressed": get-merged($base-colors-defaults, $base-colors, 300),
120 "disabled": get-merged($base-colors-defaults, $base-colors, 100),
121 ),
122 "neutral": (
123 "default": get-merged($base-colors-defaults, $base-colors, 300),
124 "hover": get-merged($base-colors-defaults, $base-colors, 400),
125 "pressed": get-merged($base-colors-defaults, $base-colors, 200),
126 "disabled": get-merged($base-colors-defaults, $base-colors, 100),
127 ),
128 "subtle": (
129 "default": get-merged($base-colors-defaults, $base-colors, 200),
130 "hover": get-merged($base-colors-defaults, $base-colors, 300),
131 "pressed": get-merged($base-colors-defaults, $base-colors, 400),
132 "disabled": get-merged($base-colors-defaults, $base-colors, 100),
133 ),
134 "inverse": (
135 "default": get-merged($base-colors-defaults, $base-colors, 800),
136 "hover": get-merged($base-colors-defaults, $base-colors, 600),
137 "pressed": get-merged($base-colors-defaults, $base-colors, 1000),
138 "disabled": get-merged($base-colors-defaults, $base-colors, 400),
139 ),
140);
141
142/// Makes it easy to get the background color
143/// @param {"base" | "neutral" | "subtle" | "inverse"} $type - What type of color
144/// @param {"default" | "hover" | "pressed" | "disabled"} $state ["base"] - The state
145@function get-background-color($type, $state) {
146 @return color_inference.get-possible-inferred-or-merged-something(
147 $background-colors-defaults,
148 $background-colors,
149 $type,
150 $state
151 );
152}
153
154/// What font weights to use for the different font weights. The main reason to allow customisation for this is to allow for custom fonts that don't have the same font weights as the default font. So for example if your font doesn't have a "light" (300) font weight then you can set it to 400 and it will use the "regular" (400) font weight instead.
155/// @prop {Number} font-weights.300 [300] - The font weight to use for "light" (300) text
156/// @prop {Number} font-weights.400 [400] - The font weight to use for "regular" (400) text
157/// @prop {Number} font-weights.500 [500] - The font weight to use for "medium" (500) text
158/// @prop {Number} font-weights.600 [600] - The font weight to use for "semibold" (600) text
159/// @prop {Number} font-weights.700 [700] - The font weight to use for "bold" (700) text
160$font-weights: () !default;
161$font-weights-defaults: (
162 300: 300,
163 400: 400,
164 500: 500,
165 600: 600,
166 700: 700,
167);
168
169/// Makes it easy to get font weight
170/// @param {300 | 400 | 500 | 600} $type - What type of font weight to get (light, regular, medium or bold)
171@function get-font-weight($type) {
172 @return get-merged($font-weights-defaults, $font-weights, $type);
173}
174
175/// The base z-index of the modal
176$base-z-index: 5000 !default;
177/// The z-index of the search page
178$search-page-base-z-index: 1 !default;
179/// The border radius to use. This is used in many places and not often exactly this value. Sometimes a multiple is used and if it's 0 then everything will be square
180$border-radius: 4px !default;
181/// The search modal layout to use. Set it to "v2" for the new layout. The v2 layout uses modern css features such as :has(), container queries and grid.
182$search-modal-layout: "v2" !default;
183
184// The color of the progress bar below the toast that shows when it will auto-close
185$toast-progress-bar-color: get-text-icon-color("base", "default") !default;
186
187/// Sometimes text is all uppercase in the UI. This is the default text transform used to do that that. For example, if you don't want uppercase text, you can set this to `none`
188$uppercase-text-transform: uppercase !default;
189
190/// Configuration for the filters on the right
191/// @prop {Number with size unit} filters-configuration.spacing-between-input-rows [10px] - How much space should be between the input rows. Input row being a checkbox/radio button and its label.
192/// @prop {Number with size unit} filters-configuration.input-row-height-goal [20px] - How high an "input row" should try to be. Input row being a checkbox/radio button and its label. If this is smaller than the text size, it will be ignored. If this is an odd number, the filled-in part of checked radio buttons look off-center in google chrome on macOS on 1440p screens.
193/// @prop {Border} filters-configuration.radio-checkbox-border [1px solid variables.get-border-color("base", "default")] - The border on radio buttons and checkboxes. The reason for this being a variable is that its width is extracted and used in calculations to make the input element fit into to "input-row-height-goal".
194/// @prop {Border} filters-configuration.hovered-radio-checkbox-border [2px solid variables.get-border-color("base", "default")] - The border on radio buttons and checkboxes, when hovered. You might want to change this to be 1px wide if you want the hover effect to be less pronounced (and only change the background).
195/// @prop {Border} filters-configuration.disabled-radio-checkbox-border [2px solid variables.get-border-color("base", "disabled")] - The border on radio buttons and checkboxes, when disabled.
196/// @prop {Color} filters-configuration.mobile-modal-background-color [variables.get-background-color("base", "default")] - The background color of the SortAndFilterModal, a modal containing the sorting and filters on smaller displays. We need this as a variable to calculate a border color that blends with a shadow (apart from setting the background color).
197$filters-configuration: () !default;
198$filters-configuration-defaults: (
199 "spacing-between-input-rows": 10px,
200 "input-row-height-goal": 20px,
201 "radio-checkbox-border": 1px solid get-border-color("base", "default"),
202 "disabled-radio-checkbox-border": 1px solid get-border-color("base", "disabled"),
203 "hovered-radio-checkbox-border": 2px solid get-border-color("base", "default"),
204 "mobile-modal-background-color": get-background-color("base", "default"),
205);
206
207/// Configuration for the search modal.
208/// @prop {Number with size unit} search-modal.max-width [800px/1400px] - The max width of the modal. When using the classic layout this is also used for the max width of SearchField on the search page.
209/// @prop {Boolean} search-modal.top-snapping [true] - If the modal should snap to the top at certain screen sizes, only recommended to disable if you take care of this via JS
210/// @prop {Number with size unit} search-modal.stacked-side-padding [16px] - The padding on the sides of the modal when stacked (mobile layout), only applicable when $search-modal-layout is set to v2
211$search-modal: () !default;
212$search-modal-defaults: (
213 "max-width": if($search-modal-layout == "v2", 1500px, 800px),
214 "top-snapping": true,
215 "stacked-side-padding": 16px,
216);
217
218/// Configuration for the buttons that show up when scrolling up after not being too close to the top on mobile
219/// @prop {Number with size unit} floating-buttons.bottom-distance [12px] - The distance from the bottom of the buttons to the bottom of the screen.
220/// @prop {Number with size unit} floating-buttons.side-distance [12px] - The distance from the `$position`-side of the buttons to the `$position`-side of the screen.
221/// @prop {"left" | "right"} floating-buttons.position ["left"] - The side of the screen the buttons should be aligned to. Can be "left" or "right".
222$floating-buttons: () !default;
223$floating-buttons-defaults: (
224 "bottom-distance": 12px,
225 "side-distance": 12px,
226 "position": "left",
227);
228
229/// Configuration for the search field, that is inside the search modal or on the search page.
230/// @prop {Color} search-field.background [map.get(get-merged($background-colors-defaults, $background-colors, "base"), "default")] - The background color of the input field, clear button and back button
231/// @prop {Number with size unit} search-modal.max-width [600px] - The max width of the input field, only used when v2 search modal is used
232/// @prop {Number with size unit} search-field.border-radius [variables.$border-radius * 2.5] - Border radius of the outer edges of the whole SearchField
233$search-field: () !default;
234$search-field-defaults: (
235 "background":
236 if($search-modal-layout == "v2", get-background-color("subtle", "default"), get-background-color("base", "default")),
237 "border-radius": if($search-modal-layout == "v2", calc(#{$border-radius} * 20), calc(#{$border-radius} * 2.5)),
238 "max-width": 600px,
239);
240
241/// Not all gaps can currently be customised using this but some of them do. If this is useful for you and you think we should make it more consistent, please let us know.
242/// @prop {Number with size unit} gaps.between-instant-results [5px] - The gap between the individual instant results in the modal, unused when $search-modal-layout is set to v2
243/// @prop {Number with size unit} gaps.autocomplete.between-items-in-row-mode [5px] - The vertical gap between the "list-style items", the individual suggestions that have the full width.
244/// @prop {Number with size unit} gaps.autocomplete.between-category-and-other [20px] - The vertical gap between the category and query suggestion sections
245/// @prop {Number with size unit} gaps.autocomplete.between-compact-suggestions [5px] - The horizontal gap between the individual query suggestions that show up in "compact" mode (multiple in the same row) when no query has been entered
246/// @prop {Map} gaps.listing-page - The product listing page (PLP) overall. Note that for the gaps here not the exact values will always be used but often multiples for different places where it's appropriate.
247/// @prop {Number with size unit} gaps.listing-page.spacing-to-filters [12px] - The spacing between the filters and content.
248/// @prop {Number with size unit} gaps.listing-page.desktop-item-gap [20px] - The vertical gap between the different items on desktop.
249/// @prop {Number with size unit} gaps.listing-page.mobile-item-gap [16px] - The vertical gap between the different items on mobile.
250/// @prop {Number with size unit} gaps.listing-page.above-and-below-selected-filters.mobile [10px] - The spacing above and below the selected filters on mobile.
251/// @prop {Number with size unit} gaps.listing-page.above-and-below-selected-filters.desktop [0] - The spacing above and below the selected filters on desktop.
252/// @prop {Boolean} gaps.listing-page.search.spacing-above-search-field [true] - Whether to add equal spacing above the search field as below.
253/// @prop {Number with size unit} gaps.listing-page.search.gaps-to-refactor [3] - the factor to multiply the gaps with to get the spacing above the recommendations.
254$gaps: () !default;
255$gaps-defaults: (
256 "between-instant-results": 5px,
257 "autocomplete": (
258 "between-items-in-row-mode": 5px,
259 "between-category-and-other": 20px,
260 "between-compact-suggestions": 5px,
261 ),
262 "listing-page": (
263 "spacing-to-filters": 12px,
264 "desktop-item-gap": 20px,
265 "mobile-item-gap": 16px,
266 "above-and-below-selected-filters": (
267 "mobile": 10px,
268 "desktop": 0,
269 ),
270 "search": (
271 "spacing-above-search-field": true,
272 "gap-to-recs-factor": 3,
273 ),
274 ),
275);
276
277/// Makes it easy to get a gap value from the $gaps map
278/// @param {String} $name - The name of the property to get
279@function get-gap($name) {
280 @return get-merged($gaps-defaults, $gaps, $name);
281}
282
283/// Styling overrides for the InstantCard component - the component which shows 4 search results in the SearchModal.
284/// @prop {Color} instant-card.sales-price-color [#ff2e3e] - The color of the sales price, only applicable to the modal if $search-modal-layout is set to "classic". Also applies to the Looks component.
285/// @prop {Boolean} instant-card.show-price [true] - Whether to show the price
286/// @prop {Boolean} instant-card.show-tagline [true] - Whether to show the "tagline" (different for different customers, some show for example the material of the product)
287$instant-card: () !default;
288$instant-card-defaults: (
289 "sales-price-color": #ff2e3e,
290 "show-price": true,
291 "show-tagline": true,
292);
293
294/// See [documentation of Autocomplete mixin](https://scss-docs.depict.ai/#mixin-Autocomplete) for explanation of this map.
295/// It allows customizing the highlighting in the query suggestions
296$autocomplete-entries-without-highlight: () !default;
297/// See [documentation of Autocomplete mixin](https://scss-docs.depict.ai/#mixin-Autocomplete) for explanation of this map.
298/// It allows customizing the highlighting in the query suggestions
299$autocomplete-entries-with-highlight: () !default;
300
301/// Styling overrides for our primary buttons (`button.major`, styled by the PrimaryButton mixin)
302/// @prop {Color} primary-button.background [variables.get-background-color("inverse", "default")] - The background color of the primary button
303/// @prop {Color} primary-button.hover-background [variables.get-background-color("inverse", "hover")] - The hovered background color of the primary button
304/// @prop {Color} primary-button.active-background [variables.get-background-color("inverse", "pressed")] - The active background color of the primary button
305/// @prop {Color} primary-button.color [variables.get-text-icon-color("inverse", "default")] - The text color of the primary button
306/// @prop {Border} primary-button.border [1px solid transparent] - The border of the primary button
307/// @prop {Number with size unit} primary-button.border-radius [variables.$border-radius] - The border radius of the primary button
308/// @prop {Filter} primary-button.hover-filter [drop-shadow(-2px -2px 4px rgba(255, 255, 255, 0.25)) drop-shadow(2px 2px 4px rgba(0, 0, 0, 0.15))] - The filter to apply to the primary button when hovered
309/// @prop {Filter} primary-button.active-filter [drop-shadow(2px 2px 4px rgba(255, 255, 255, 0.25)) drop-shadow(-2px -2px 4px rgba(0, 0, 0, 0.15))] - The filter to apply to the primary button when active
310/// @prop {Filter} primary-button.focus-visible-filter [drop-shadow(2px 2px 4px rgba(65, 143, 195, 0.8))
311/// drop-shadow(-2px -2px 4px rgba(65, 143, 195, 0.8))] - The filter to apply to the primary button when focused with keyboard navigation.
312/// @prop {Color} primary-button.disabled-background [variables.get-background-color("inverse", "disabled")] - The background color of the primary button when disabled
313$primary-button: () !default;
314/// Styling overrides for our secondary buttons (`button.minor`, styled by the SecondaryButton mixin)
315/// @prop {Color} secondary-button.background [variables.get-background-color("base", "default")] - The background color of the secondary button
316/// @prop {Color} secondary-button.hover-background [variables.get-background-color("base", "hover")] - The hovered background color of the secondary button
317/// @prop {Color} secondary-button.active-background [variables.get-background-color("base", "pressed")] - The active background color of the secondary button
318/// @prop {Color} secondary-button.color [variables.get-text-icon-color("base", "default")] - The text color of the secondary button
319/// @prop {Border} secondary-button.border [variables.get-border("base", "default") 1px solid] - The border of the secondary button
320/// @prop {Number with size unit} secondary-button.border-radius [variables.$border-radius] - The border radius of the secondary button
321/// @prop {Filter} secondary-button.hover-filter [drop-shadow(-2px -2px 4px rgba(255, 255, 255, 0.25)) drop-shadow(2px 2px 4px rgba(0, 0, 0, 0.15))] - The filter to apply to the secondary button when hovered
322/// @prop {Filter} secondary-button.active-filter [drop-shadow(2px 2px 4px rgba(255, 255, 255, 0.25)) drop-shadow(-2px -2px 4px rgba(0, 0, 0, 0.15))] - The filter to apply to the secondary button when active
323/// @prop {Filter} secondary-button.focus-visible-filter [drop-shadow(-2px -2px 4px rgba(65, 143, 195, 0.8))
324/// drop-shadow(2px 2px 4px rgba(65, 143, 195, 0.8))] - The filter to apply to the secondary button when focused with keyboard navigation.
325/// @prop {Color} secondary-button.disabled-background [variables.get-background-color("base", "disabled")] - The background color of the secondary button when disabled
326$secondary-button: () !default;
327
328$subtle-secondary-button: () !default;