@adnap/krysalicss 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +119 -0
- package/dist/base/global.css +141 -0
- package/dist/base/global.min.css +1 -0
- package/dist/base/reset.css +170 -0
- package/dist/base/reset.min.css +1 -0
- package/dist/element/badge.css +167 -0
- package/dist/element/badge.min.css +1 -0
- package/dist/element/button.css +250 -0
- package/dist/element/button.min.css +1 -0
- package/dist/element/checkbox.css +149 -0
- package/dist/element/checkbox.min.css +1 -0
- package/dist/element/file.css +148 -0
- package/dist/element/file.min.css +1 -0
- package/dist/element/progress.css +183 -0
- package/dist/element/progress.min.css +1 -0
- package/dist/element/radio.css +144 -0
- package/dist/element/radio.min.css +1 -0
- package/dist/element/range.css +183 -0
- package/dist/element/range.min.css +1 -0
- package/dist/element/select.css +156 -0
- package/dist/element/select.min.css +1 -0
- package/dist/element/switch.css +186 -0
- package/dist/element/switch.min.css +1 -0
- package/dist/element/text-input.css +143 -0
- package/dist/element/text-input.min.css +1 -0
- package/dist/element/textarea.css +145 -0
- package/dist/element/textarea.min.css +1 -0
- package/dist/helper/breakpoints.css +113 -0
- package/dist/helper/breakpoints.min.css +1 -0
- package/dist/helper/state.css +126 -0
- package/dist/helper/state.min.css +1 -0
- package/dist/krysalicss.css +1420 -0
- package/dist/krysalicss.css.map +1 -0
- package/dist/krysalicss.min.css +1 -0
- package/dist/layout/container.css +145 -0
- package/dist/layout/container.min.css +1 -0
- package/dist/layout/flex.css +135 -0
- package/dist/layout/flex.min.css +1 -0
- package/dist/layout/grid.css +188 -0
- package/dist/layout/grid.min.css +1 -0
- package/dist/module/alert.css +166 -0
- package/dist/module/alert.min.css +1 -0
- package/dist/module/card.css +157 -0
- package/dist/module/card.min.css +1 -0
- package/dist/module/field.css +138 -0
- package/dist/module/field.min.css +1 -0
- package/dist/module/modal.css +187 -0
- package/dist/module/modal.min.css +1 -0
- package/dist/module/navbar.css +256 -0
- package/dist/module/navbar.min.css +1 -0
- package/dist/module/tabs.css +167 -0
- package/dist/module/tabs.min.css +1 -0
- package/dist/tokens/dark.json +85 -0
- package/dist/tokens/default.json +85 -0
- package/dist/tokens/high-contrast.json +85 -0
- package/dist/typography/base.css +131 -0
- package/dist/typography/base.min.css +1 -0
- package/dist/typography/content.css +137 -0
- package/dist/typography/content.min.css +1 -0
- package/dist/typography/link.css +132 -0
- package/dist/typography/link.min.css +1 -0
- package/dist/typography/table.css +121 -0
- package/dist/typography/table.min.css +1 -0
- package/dist/typography/title.css +122 -0
- package/dist/typography/title.min.css +1 -0
- package/package.json +111 -0
- package/src/_index.scss +18 -0
- package/src/base/_index.scss +2 -0
- package/src/base/global/_index.scss +2 -0
- package/src/base/global/_plugin.scss +34 -0
- package/src/base/global/_variables.scss +11 -0
- package/src/base/reset/_index.scss +2 -0
- package/src/base/reset/_plugin.scss +70 -0
- package/src/base/reset/_variables.scss +5 -0
- package/src/element/_index.scss +11 -0
- package/src/element/badge/_index.scss +2 -0
- package/src/element/badge/_plugin.scss +44 -0
- package/src/element/badge/_variables.scss +19 -0
- package/src/element/button/_index.scss +2 -0
- package/src/element/button/_plugin.scss +173 -0
- package/src/element/button/_variables.scss +36 -0
- package/src/element/checkbox/_index.scss +2 -0
- package/src/element/checkbox/_plugin.scss +48 -0
- package/src/element/checkbox/_variables.scss +24 -0
- package/src/element/file/_index.scss +2 -0
- package/src/element/file/_plugin.scss +45 -0
- package/src/element/file/_variables.scss +27 -0
- package/src/element/progress/_index.scss +2 -0
- package/src/element/progress/_plugin.scss +96 -0
- package/src/element/progress/_variables.scss +19 -0
- package/src/element/radio/_index.scss +2 -0
- package/src/element/radio/_plugin.scss +47 -0
- package/src/element/radio/_variables.scss +16 -0
- package/src/element/range/_index.scss +2 -0
- package/src/element/range/_plugin.scss +101 -0
- package/src/element/range/_variables.scss +19 -0
- package/src/element/select/_index.scss +2 -0
- package/src/element/select/_plugin.scss +58 -0
- package/src/element/select/_variables.scss +26 -0
- package/src/element/switch/_index.scss +2 -0
- package/src/element/switch/_plugin.scss +105 -0
- package/src/element/switch/_variables.scss +28 -0
- package/src/element/text-input/_index.scss +2 -0
- package/src/element/text-input/_plugin.scss +37 -0
- package/src/element/text-input/_variables.scss +22 -0
- package/src/element/textarea/_index.scss +2 -0
- package/src/element/textarea/_plugin.scss +39 -0
- package/src/element/textarea/_variables.scss +22 -0
- package/src/helper/_breakpoints.scss +45 -0
- package/src/helper/_controls.scss +82 -0
- package/src/helper/_index.scss +3 -0
- package/src/helper/_state.scss +35 -0
- package/src/krysalicss.scss +17 -0
- package/src/layout/_index.scss +3 -0
- package/src/layout/container/_index.scss +2 -0
- package/src/layout/container/_plugin.scss +26 -0
- package/src/layout/container/_variables.scss +5 -0
- package/src/layout/flex/_index.scss +2 -0
- package/src/layout/flex/_plugin.scss +32 -0
- package/src/layout/flex/_variables.scss +9 -0
- package/src/layout/grid/_index.scss +2 -0
- package/src/layout/grid/_plugin.scss +37 -0
- package/src/layout/grid/_variables.scss +37 -0
- package/src/module/_index.scss +6 -0
- package/src/module/alert/_index.scss +2 -0
- package/src/module/alert/_plugin.scss +51 -0
- package/src/module/alert/_variables.scss +24 -0
- package/src/module/card/_index.scss +2 -0
- package/src/module/card/_plugin.scss +31 -0
- package/src/module/card/_variables.scss +13 -0
- package/src/module/field/_index.scss +2 -0
- package/src/module/field/_plugin.scss +49 -0
- package/src/module/field/_variables.scss +26 -0
- package/src/module/modal/_index.scss +2 -0
- package/src/module/modal/_plugin.scss +137 -0
- package/src/module/modal/_variables.scss +39 -0
- package/src/module/navbar/_index.scss +2 -0
- package/src/module/navbar/_plugin.scss +186 -0
- package/src/module/navbar/_variables.scss +49 -0
- package/src/module/tabs/_index.scss +2 -0
- package/src/module/tabs/_plugin.scss +106 -0
- package/src/module/tabs/_variables.scss +16 -0
- package/src/theme/_create.scss +74 -0
- package/src/theme/dark.scss +51 -0
- package/src/theme/default.scss +45 -0
- package/src/theme/high-contrast.scss +53 -0
- package/src/typography/_index.scss +5 -0
- package/src/typography/base/_index.scss +2 -0
- package/src/typography/base/_plugin.scss +21 -0
- package/src/typography/base/_variables.scss +15 -0
- package/src/typography/content/_index.scss +2 -0
- package/src/typography/content/_plugin.scss +39 -0
- package/src/typography/content/_variables.scss +1 -0
- package/src/typography/link/_index.scss +2 -0
- package/src/typography/link/_mixins.scss +29 -0
- package/src/typography/link/_plugin.scss +15 -0
- package/src/typography/link/_variables.scss +15 -0
- package/src/typography/table/_index.scss +2 -0
- package/src/typography/table/_plugin.scss +13 -0
- package/src/typography/table/_variables.scss +6 -0
- package/src/typography/title/_index.scss +2 -0
- package/src/typography/title/_plugin.scss +36 -0
- package/src/typography/title/_variables.scss +7 -0
- package/src/variables/_color.scss +66 -0
- package/src/variables/_default.scss +52 -0
- package/src/variables/_feature.scss +39 -0
- package/src/variables/_global.scss +93 -0
- package/src/variables/_index.scss +7 -0
- package/src/variables/_responsive.scss +10 -0
- package/src/variables/_selector.scss +1 -0
- package/src/variables/_size.scss +5 -0
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
@use "../variables";
|
|
2
|
+
@use "create";
|
|
3
|
+
|
|
4
|
+
$name: "dark" !default;
|
|
5
|
+
|
|
6
|
+
// Surface family: cool blue-grey at very low lightness keeps the page bg and
|
|
7
|
+
// card bg distinguishable without colour shifts. Foreground is a near-white
|
|
8
|
+
// on the same hue family for AAA contrast.
|
|
9
|
+
$_surface-bg: #121417;
|
|
10
|
+
$_surface-card: #1b1e22;
|
|
11
|
+
$_surface-fg: #e6e8eb;
|
|
12
|
+
// Brand mint #6bd1a7 — the dark-mode counterpart to default's brand green,
|
|
13
|
+
// lightened so it still reads against the near-black bg.
|
|
14
|
+
$_brand-mint: #6bd1a7;
|
|
15
|
+
|
|
16
|
+
$variables: (
|
|
17
|
+
bg: $_surface-bg,
|
|
18
|
+
fg: $_surface-fg,
|
|
19
|
+
link: $_brand-mint,
|
|
20
|
+
link-hover: #9ce3c2,
|
|
21
|
+
// Desaturated lavender keeps visited distinguishable from the mint
|
|
22
|
+
// brand link while staying readable on the near-black surface
|
|
23
|
+
// (~7.6:1 vs `$_surface-bg`). WCAG 2.4.8.
|
|
24
|
+
link-visited: #c8a8e0,
|
|
25
|
+
border-radius: variables.$global-border-radius,
|
|
26
|
+
card-bg: $_surface-card,
|
|
27
|
+
card-fg: $_surface-fg,
|
|
28
|
+
focus-ring: $_brand-mint,
|
|
29
|
+
// Light wash so the dark modal surface stands out against the dimmed page;
|
|
30
|
+
// pairs with the modal's `backdrop-filter: blur(...)`.
|
|
31
|
+
modal-backdrop: color-mix(in srgb, $_surface-fg 22%, transparent),
|
|
32
|
+
) !default;
|
|
33
|
+
|
|
34
|
+
$combinations: (
|
|
35
|
+
default: ($_surface-card, $_surface-fg),
|
|
36
|
+
primary: (#1f6e51, #f4f7fb),
|
|
37
|
+
warning: (#b8991e, #1b1b13),
|
|
38
|
+
danger: (#a2481a, #fff6f0),
|
|
39
|
+
success: (#5c6529, #f3f6e5),
|
|
40
|
+
) !default;
|
|
41
|
+
|
|
42
|
+
// Both `prefers-color-scheme: dark` (auto-switching) AND `.theme-dark`
|
|
43
|
+
// (explicit user override) are wired so consumers get either behaviour.
|
|
44
|
+
@include create.theme(
|
|
45
|
+
$name: $name,
|
|
46
|
+
$variables: $variables,
|
|
47
|
+
$combinations: $combinations,
|
|
48
|
+
$is-default: false,
|
|
49
|
+
$root-when: "prefers-color-scheme: dark",
|
|
50
|
+
$modifier-class: ".theme-dark",
|
|
51
|
+
);
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
@use "sass:map";
|
|
2
|
+
@use "../variables";
|
|
3
|
+
@use "create";
|
|
4
|
+
|
|
5
|
+
$name: "default" !default;
|
|
6
|
+
|
|
7
|
+
$_palette: variables.$color-palette;
|
|
8
|
+
|
|
9
|
+
// `sage` and `moss` from the palette are already AAA-tuned as surfaces
|
|
10
|
+
// against white (7.19:1 and 7.38:1 respectively), so they double as the
|
|
11
|
+
// brand text colours: link reaches for `sage` (the primary brand colour),
|
|
12
|
+
// hover shifts to `moss` (the success / olive accent) to match the
|
|
13
|
+
// existing brand-green / brand-olive split without needing separate
|
|
14
|
+
// brand-* tokens.
|
|
15
|
+
$variables: (
|
|
16
|
+
bg: map.get($_palette, white),
|
|
17
|
+
fg: map.get($_palette, black),
|
|
18
|
+
link: map.get($_palette, sage),
|
|
19
|
+
link-hover: map.get($_palette, moss),
|
|
20
|
+
link-visited: map.get($_palette, coral),
|
|
21
|
+
border-radius: variables.$global-border-radius,
|
|
22
|
+
card-bg: map.get($_palette, white),
|
|
23
|
+
card-fg: map.get($_palette, black),
|
|
24
|
+
focus-ring: map.get($_palette, sage),
|
|
25
|
+
) !default;
|
|
26
|
+
|
|
27
|
+
$combinations: variables.$color-combinations !default;
|
|
28
|
+
|
|
29
|
+
// `$modifier-class: ':root.theme-light'` lets an explicit "Light" choice
|
|
30
|
+
// override the dark theme's `prefers-color-scheme: dark` media query.
|
|
31
|
+
// IMPORTANT: the `:root` prefix is required, not decorative. `:root` and
|
|
32
|
+
// `.theme-light` are both single-selector specificity (0,1,0), which means
|
|
33
|
+
// a bare `.theme-light` ties with the dark theme's `@media :root` rule and
|
|
34
|
+
// loses by source order (default.scss is emitted before dark.scss). The
|
|
35
|
+
// `:root.theme-light` compound selector raises specificity to (0,2,0) and
|
|
36
|
+
// wins regardless of source order. Mirror this pattern when authoring any
|
|
37
|
+
// new theme that needs to override another theme's media-query block.
|
|
38
|
+
@include create.theme(
|
|
39
|
+
$name: $name,
|
|
40
|
+
$variables: $variables,
|
|
41
|
+
$combinations: $combinations,
|
|
42
|
+
$is-default: true,
|
|
43
|
+
$root-when: "prefers-color-scheme: light",
|
|
44
|
+
$modifier-class: ":root.theme-light",
|
|
45
|
+
);
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
@use "create";
|
|
2
|
+
|
|
3
|
+
$name: "high-contrast" !default;
|
|
4
|
+
|
|
5
|
+
// Opt-in only: high-contrast is a deliberate user choice (assistive
|
|
6
|
+
// preference, low-vision setup, very bright ambient lighting). It is NOT
|
|
7
|
+
// auto-switched via a media query: `prefers-contrast: more` would coerce
|
|
8
|
+
// users with system-level high-contrast preferences into this aggressive
|
|
9
|
+
// palette without any way to undo from the page, and most consumers want
|
|
10
|
+
// the default theme to remain in charge unless explicitly opted-in.
|
|
11
|
+
//
|
|
12
|
+
// Every (bg, fg) pair clears WCAG 2.2 AAA (7:1). Border radius is zeroed:
|
|
13
|
+
// hard edges disambiguate component boundaries at low vision better than
|
|
14
|
+
// rounded corners blending into the surrounding flat colour.
|
|
15
|
+
// #ffd500 — max-contrast yellow, ~19.6:1 against pure black bg. Reused for
|
|
16
|
+
// link / focus-ring / warning-bg as the canonical "active state" colour
|
|
17
|
+
// in this theme.
|
|
18
|
+
$_hc-yellow: #ffd500;
|
|
19
|
+
$_hc-black: #000000;
|
|
20
|
+
$_hc-white: #ffffff;
|
|
21
|
+
|
|
22
|
+
$variables: (
|
|
23
|
+
bg: $_hc-black,
|
|
24
|
+
fg: $_hc-white,
|
|
25
|
+
link: $_hc-yellow,
|
|
26
|
+
link-hover: $_hc-white,
|
|
27
|
+
link-visited: #d590ff,
|
|
28
|
+
border-radius: 0,
|
|
29
|
+
card-bg: $_hc-black,
|
|
30
|
+
card-fg: $_hc-white,
|
|
31
|
+
focus-ring: $_hc-yellow,
|
|
32
|
+
) !default;
|
|
33
|
+
|
|
34
|
+
$combinations: (
|
|
35
|
+
default: ($_hc-white, $_hc-black),
|
|
36
|
+
primary: (#00d0ff, $_hc-black),
|
|
37
|
+
warning: ($_hc-yellow, $_hc-black),
|
|
38
|
+
danger: (#ff8585, $_hc-black),
|
|
39
|
+
success: (#00ff84, $_hc-black),
|
|
40
|
+
) !default;
|
|
41
|
+
|
|
42
|
+
// `:root.theme-high-contrast`: the `:root` prefix raises specificity to
|
|
43
|
+
// (0,2,0) so this theme wins over `dark.scss`'s `@media :root` block
|
|
44
|
+
// regardless of source order. Same reasoning as `theme/default.scss`;
|
|
45
|
+
// see its comment for the full rationale.
|
|
46
|
+
@include create.theme(
|
|
47
|
+
$name: $name,
|
|
48
|
+
$variables: $variables,
|
|
49
|
+
$combinations: $combinations,
|
|
50
|
+
$is-default: false,
|
|
51
|
+
$root-when: null,
|
|
52
|
+
$modifier-class: ":root.theme-high-contrast",
|
|
53
|
+
);
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
@use "variables" as *;
|
|
2
|
+
@use "../../variables";
|
|
3
|
+
|
|
4
|
+
@if variables.$feature-typography-base {
|
|
5
|
+
html {
|
|
6
|
+
-moz-osx-font-smoothing: grayscale;
|
|
7
|
+
-webkit-font-smoothing: antialiased;
|
|
8
|
+
font-size: $body-size;
|
|
9
|
+
line-height: $body-line-height;
|
|
10
|
+
text-rendering: $render-mode;
|
|
11
|
+
@include variables.textColor(fg, $default-color);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
body,
|
|
15
|
+
button,
|
|
16
|
+
input,
|
|
17
|
+
select,
|
|
18
|
+
textarea {
|
|
19
|
+
font-family: $family-sans-serif;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
@use "sass:map";
|
|
2
|
+
@use "../../variables";
|
|
3
|
+
|
|
4
|
+
$default-color: map.get(variables.$color-palette, black) !default;
|
|
5
|
+
|
|
6
|
+
// Typography fundamentals derive from `$global-*` so consumers can configure
|
|
7
|
+
// once at the top level. Per-component override still works: the local
|
|
8
|
+
// `!default` accepts an explicit `@use 'typography/base' with (...)`.
|
|
9
|
+
$family-sans-serif: variables.$global-family-sans-serif !default;
|
|
10
|
+
$family-monospace: variables.$global-family-monospace !default;
|
|
11
|
+
$base-size: variables.$global-base-size !default;
|
|
12
|
+
$body-line-height: variables.$global-body-line-height !default;
|
|
13
|
+
|
|
14
|
+
$body-size: $base-size !default;
|
|
15
|
+
$render-mode: optimizeLegibility !default;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
@use "sass:list";
|
|
2
|
+
@use "variables" as *;
|
|
3
|
+
@use "../../variables";
|
|
4
|
+
|
|
5
|
+
@function _repeat($string, $times) {
|
|
6
|
+
$content: $string;
|
|
7
|
+
@for $_ from 1 to $times {
|
|
8
|
+
$content: $content + $string;
|
|
9
|
+
}
|
|
10
|
+
@return $content;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
@if variables.$feature-typography-content {
|
|
14
|
+
.content {
|
|
15
|
+
p,
|
|
16
|
+
dl,
|
|
17
|
+
ol,
|
|
18
|
+
ul,
|
|
19
|
+
blockquote,
|
|
20
|
+
pre,
|
|
21
|
+
table {
|
|
22
|
+
&:not(:last-child) {
|
|
23
|
+
margin-block-end: 1em;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
ol,
|
|
28
|
+
ul {
|
|
29
|
+
list-style-position: outside;
|
|
30
|
+
margin-inline-start: variables.$global-gap * 2;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
@for $i from 0 to list.length($ul-styles) {
|
|
34
|
+
#{_repeat("ul ", $i + 1)} {
|
|
35
|
+
list-style-type: list.nth($ul-styles, $i + 1);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
$ul-styles: (disc, circle, square) !default;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
@use "variables" as *;
|
|
2
|
+
@use "../../variables";
|
|
3
|
+
|
|
4
|
+
// Visual contract shared between bare `<a>` and `.button.is-link`. Both
|
|
5
|
+
// surfaces emit the same underline + pointer affordance + `--kc-link` /
|
|
6
|
+
// `--kc-link-hover` token wiring; per-surface concerns (button's transparent
|
|
7
|
+
// fill / border, hover `filter: none`) stay in their plugins. Fallbacks are
|
|
8
|
+
// parameterised so the button can pass its own combination fallback without
|
|
9
|
+
// depending on link's variable defaults.
|
|
10
|
+
@mixin linkSurface(
|
|
11
|
+
$fallback: $color,
|
|
12
|
+
$hover-fallback: $hover-color,
|
|
13
|
+
$visited-fallback: $visited-color,
|
|
14
|
+
) {
|
|
15
|
+
cursor: pointer;
|
|
16
|
+
text-decoration: underline;
|
|
17
|
+
@include variables.textColor(link, $fallback);
|
|
18
|
+
|
|
19
|
+
&:hover {
|
|
20
|
+
@include variables.textColor(link-hover, $hover-fallback);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// `:visited` keeps the underline + cursor affordance from the base
|
|
24
|
+
// selector and only swaps the colour token (UA restricts what
|
|
25
|
+
// `:visited` may change for privacy). WCAG 2.4.8.
|
|
26
|
+
&:visited {
|
|
27
|
+
@include variables.textColor(link-visited, $visited-fallback);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
@use "variables" as *;
|
|
2
|
+
@use "../../variables";
|
|
3
|
+
@use "mixins" as *;
|
|
4
|
+
|
|
5
|
+
@if variables.$feature-typography-link {
|
|
6
|
+
a {
|
|
7
|
+
@include linkSurface;
|
|
8
|
+
|
|
9
|
+
&:focus-visible {
|
|
10
|
+
outline: $focus-outline-width $focus-outline-style
|
|
11
|
+
var(--kc-focus-ring, var(--kc-fg, currentColor));
|
|
12
|
+
outline-offset: $focus-outline-offset;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
@use "sass:map";
|
|
2
|
+
@use "../../variables";
|
|
3
|
+
|
|
4
|
+
$default-color: map.get(variables.$color-palette, black) !default;
|
|
5
|
+
$color: $default-color !default;
|
|
6
|
+
$hover-color: $color !default;
|
|
7
|
+
// `:visited` defaults to the same colour as the base link so that themes
|
|
8
|
+
// which haven't opted in still render visited links visibly; consumers and
|
|
9
|
+
// themes override `--kc-link-visited` to ship a distinct visited swatch
|
|
10
|
+
// (WCAG 2.4.8).
|
|
11
|
+
$visited-color: $color !default;
|
|
12
|
+
|
|
13
|
+
$focus-outline-width: variables.$global-focus-outline-width !default;
|
|
14
|
+
$focus-outline-style: variables.$global-focus-outline-style !default;
|
|
15
|
+
$focus-outline-offset: variables.$global-focus-outline-offset !default;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
@use "sass:list";
|
|
2
|
+
@use "sass:map";
|
|
3
|
+
@use "sass:meta";
|
|
4
|
+
@use "variables" as *;
|
|
5
|
+
@use "../../variables";
|
|
6
|
+
|
|
7
|
+
@if variables.$feature-typography-title {
|
|
8
|
+
@each $label, $args in $levels {
|
|
9
|
+
#{$label} {
|
|
10
|
+
@if meta.type-of($args) == "list" {
|
|
11
|
+
$length: list.length($args);
|
|
12
|
+
@if $length >= 1 {
|
|
13
|
+
font-size: list.nth($args, 1);
|
|
14
|
+
}
|
|
15
|
+
@if $length >= 2 {
|
|
16
|
+
font-weight: list.nth($args, 2);
|
|
17
|
+
}
|
|
18
|
+
@if $length >= 3 {
|
|
19
|
+
color: list.nth($args, 3);
|
|
20
|
+
}
|
|
21
|
+
} @else if meta.type-of($args) == "map" {
|
|
22
|
+
@if map.has-key($args, size) {
|
|
23
|
+
font-size: map.get($args, size);
|
|
24
|
+
}
|
|
25
|
+
@if map.has-key($args, weight) {
|
|
26
|
+
font-weight: map.get($args, weight);
|
|
27
|
+
}
|
|
28
|
+
@if map.has-key($args, color) {
|
|
29
|
+
color: map.get($args, color);
|
|
30
|
+
}
|
|
31
|
+
} @else {
|
|
32
|
+
font-size: $args;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
@use "sass:color";
|
|
2
|
+
@use "sass:list";
|
|
3
|
+
@use "sass:map";
|
|
4
|
+
|
|
5
|
+
// Deep-accent palette, hex-encoded. The functional accents (sage / moss /
|
|
6
|
+
// amber / coral) are tuned so `colour + white text` clears WCAG 1.4.6 AAA
|
|
7
|
+
// body (≥ 7:1) and the colour-vs-white page boundary clears WCAG 1.4.11
|
|
8
|
+
// (≥ 3:1). `emerald` is the brand green from the Krysalicss logo, darkened
|
|
9
|
+
// from its logo-literal value to clear WCAG 1.4.3 AA body (~5.06:1 vs white)
|
|
10
|
+
// while staying recognisable as the brand hue. Pushing further into AAA
|
|
11
|
+
// territory (≥ 7:1) would require a forest-dark green that loses the brand
|
|
12
|
+
// identity, so `primary` is the one combination that trades AAA body for
|
|
13
|
+
// brand fidelity. The functional accents (success / warning / danger) all
|
|
14
|
+
// stay on AAA-tuned colours so the colour-as-state contract holds regardless.
|
|
15
|
+
// Hex keeps swatches stable on round-trips through design tools.
|
|
16
|
+
$palette: (
|
|
17
|
+
sage: #1a6347,
|
|
18
|
+
moss: #525a22,
|
|
19
|
+
emerald: #247d59,
|
|
20
|
+
amber: #7a4f10,
|
|
21
|
+
coral: #8c351a,
|
|
22
|
+
white: #ffffff,
|
|
23
|
+
black: #27282b,
|
|
24
|
+
) !default;
|
|
25
|
+
|
|
26
|
+
// Per-palette-name complement overrides. By default `complement($name)`
|
|
27
|
+
// returns `color.complement(map.get($palette, $name))` (a 180° hue rotation).
|
|
28
|
+
// Override individual entries here to pin a hand-picked accent — useful when
|
|
29
|
+
// the mathematical opposite lands on an unflattering hue or fails contrast.
|
|
30
|
+
//
|
|
31
|
+
// Consumer override (one or many keys, partial maps welcome):
|
|
32
|
+
// @use 'krysalicss/variables/color' with (
|
|
33
|
+
// $complement-overrides: (sage: #9d566c),
|
|
34
|
+
// );
|
|
35
|
+
$complement-overrides: () !default;
|
|
36
|
+
|
|
37
|
+
@function complement($name) {
|
|
38
|
+
@if not map.has-key($palette, $name) {
|
|
39
|
+
@error 'complement(): "#{$name}" is not in $palette. Available: #{map.keys(
|
|
40
|
+
$palette
|
|
41
|
+
)}.';
|
|
42
|
+
}
|
|
43
|
+
@if map.has-key($complement-overrides, $name) {
|
|
44
|
+
@return map.get($complement-overrides, $name);
|
|
45
|
+
}
|
|
46
|
+
@return color.complement(map.get($palette, $name));
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// (background, foreground) tuples per named combination.
|
|
50
|
+
// First entry is the default applied to components without a modifier.
|
|
51
|
+
// `primary` uses `emerald` (brand green): clears AA body against white
|
|
52
|
+
// (~5.06:1) but not AAA — see palette comment for the brand-fidelity
|
|
53
|
+
// trade-off. `success` / `warning` / `danger` stay on AAA-tuned accents.
|
|
54
|
+
$combinations: (
|
|
55
|
+
default: (map.get($palette, white), map.get($palette, black)),
|
|
56
|
+
primary: (map.get($palette, emerald), map.get($palette, white)),
|
|
57
|
+
warning: (map.get($palette, amber), map.get($palette, white)),
|
|
58
|
+
danger: (map.get($palette, coral), map.get($palette, white)),
|
|
59
|
+
success: (map.get($palette, moss), map.get($palette, white)),
|
|
60
|
+
) !default;
|
|
61
|
+
|
|
62
|
+
$combinations-list: map.keys($combinations);
|
|
63
|
+
// Alias kept for clarity: themes / validators read the canonical key
|
|
64
|
+
// roster as `$combinations-keys`; identical to `$combinations-list`.
|
|
65
|
+
$combinations-keys: $combinations-list;
|
|
66
|
+
$combination-default: map.get($combinations, list.nth($combinations-list, 1));
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
@use "sass:list";
|
|
2
|
+
@use "sass:meta";
|
|
3
|
+
@use "color";
|
|
4
|
+
@use "global";
|
|
5
|
+
@use "selector";
|
|
6
|
+
|
|
7
|
+
// Theme custom-property prefix: every token emitted as --kc-<name>.
|
|
8
|
+
// Component plugins call these mixins with the bare token short-name and the
|
|
9
|
+
// prefix is added here, so component code never embeds the literal '--kc-'.
|
|
10
|
+
$prefix: "--kc-" !default;
|
|
11
|
+
|
|
12
|
+
@mixin defaultProperty($property, $token, $fallback) {
|
|
13
|
+
#{$property}: $fallback;
|
|
14
|
+
#{$property}: var(#{$prefix}#{$token}, #{$fallback});
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
@mixin textColor($token, $fallback) {
|
|
18
|
+
@include defaultProperty("color", $token, $fallback);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
@mixin backgroundColor($token, $fallback) {
|
|
22
|
+
@include defaultProperty("background-color", $token, $fallback);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// Iterate over color combinations and emit a child selector per combination.
|
|
26
|
+
// Caller provides the per-combination body via `@content using ($label, $tuple)`,
|
|
27
|
+
// where $tuple is the (background, foreground) pair from `$color-combinations`.
|
|
28
|
+
//
|
|
29
|
+
// Usage:
|
|
30
|
+
// @include variables.combinations using ($label, $tuple) {
|
|
31
|
+
// @include variables.backgroundColor(#{$label}-bg, list.nth($tuple, 1));
|
|
32
|
+
// @include variables.textColor(#{$label}-fg, list.nth($tuple, 2));
|
|
33
|
+
// }
|
|
34
|
+
@mixin combinations($selector-prefix: selector.$prefix-is) {
|
|
35
|
+
@each $label, $tuple in color.$combinations {
|
|
36
|
+
&#{$selector-prefix}#{$label} {
|
|
37
|
+
@content ($label, $tuple);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// Per-component plugins shadow `$global-controls` with a local `$controls`
|
|
43
|
+
// (`$controls: variables.$global-controls !default;` in their `_variables.scss`)
|
|
44
|
+
// so consumers can re-tune one component's reveal mode in isolation. The
|
|
45
|
+
// `$list` arg lets the plugin pass its own resolved value; the default keeps
|
|
46
|
+
// any direct call working against the global.
|
|
47
|
+
@function has-controls($mode, $list: global.$controls) {
|
|
48
|
+
@if meta.type-of($list) == "list" {
|
|
49
|
+
@return list.index($list, $mode) != null;
|
|
50
|
+
}
|
|
51
|
+
@return $list == $mode;
|
|
52
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
@use "sass:list";
|
|
2
|
+
|
|
3
|
+
// Root feature list. `true` means "all features on" (default); a list of
|
|
4
|
+
// `<category>-<name>` tokens means "only emit these".
|
|
5
|
+
$list: true !default;
|
|
6
|
+
|
|
7
|
+
@function _defaultValue($name) {
|
|
8
|
+
@return $list == true or list.index($list, $name) != null;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
$base-reset: _defaultValue(base-reset) !default;
|
|
12
|
+
$base-global: _defaultValue(base-global) !default;
|
|
13
|
+
$layout-container: _defaultValue(layout-container) !default;
|
|
14
|
+
$layout-flex: _defaultValue(layout-flex) !default;
|
|
15
|
+
$layout-grid: _defaultValue(layout-grid) !default;
|
|
16
|
+
$typography-base: _defaultValue(typography-base) !default;
|
|
17
|
+
$typography-title: _defaultValue(typography-title) !default;
|
|
18
|
+
$typography-link: _defaultValue(typography-link) !default;
|
|
19
|
+
$typography-content: _defaultValue(typography-content) !default;
|
|
20
|
+
$typography-table: _defaultValue(typography-table) !default;
|
|
21
|
+
$module-card: _defaultValue(module-card) !default;
|
|
22
|
+
$module-alert: _defaultValue(module-alert) !default;
|
|
23
|
+
$module-field: _defaultValue(module-field) !default;
|
|
24
|
+
$module-navbar: _defaultValue(module-navbar) !default;
|
|
25
|
+
$module-modal: _defaultValue(module-modal) !default;
|
|
26
|
+
$module-tabs: _defaultValue(module-tabs) !default;
|
|
27
|
+
$element-button: _defaultValue(element-button) !default;
|
|
28
|
+
$element-badge: _defaultValue(element-badge) !default;
|
|
29
|
+
$element-progress: _defaultValue(element-progress) !default;
|
|
30
|
+
$element-text-input: _defaultValue(element-text-input) !default;
|
|
31
|
+
$element-textarea: _defaultValue(element-textarea) !default;
|
|
32
|
+
$element-select: _defaultValue(element-select) !default;
|
|
33
|
+
$element-checkbox: _defaultValue(element-checkbox) !default;
|
|
34
|
+
$element-radio: _defaultValue(element-radio) !default;
|
|
35
|
+
$element-switch: _defaultValue(element-switch) !default;
|
|
36
|
+
$element-file: _defaultValue(element-file) !default;
|
|
37
|
+
$element-range: _defaultValue(element-range) !default;
|
|
38
|
+
$helper-breakpoints: _defaultValue(helper-breakpoints) !default;
|
|
39
|
+
$helper-state: _defaultValue(helper-state) !default;
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
// Cross-cutting tokens shared by every interactive component. Per-component
|
|
2
|
+
// `_variables.scss` files derive from these via `!default`, so a consumer
|
|
3
|
+
// can either retune the whole framework here (e.g. fatten every focus ring
|
|
4
|
+
// in one place) or override per-component.
|
|
5
|
+
|
|
6
|
+
$gap: 1rem !default;
|
|
7
|
+
$border-radius: 5px !default;
|
|
8
|
+
|
|
9
|
+
// Pill / fully-rounded radius. 999px is enough to clip any rendered surface
|
|
10
|
+
// up to ~2000px tall into a stadium / circle shape. Exposed as a token so
|
|
11
|
+
// pill-shaped components (badge today, optionally button/card via consumer
|
|
12
|
+
// override) reference one source of truth instead of repeating the literal.
|
|
13
|
+
$max-border-radius: 999px !default;
|
|
14
|
+
|
|
15
|
+
// Default border width for form controls (text-input, select, checkbox, …).
|
|
16
|
+
// 1 px clears WCAG 1.4.11 (3:1 non-text contrast) when the colour is mixed
|
|
17
|
+
// at `$border-mix` against the page foreground.
|
|
18
|
+
$border-width: 1px !default;
|
|
19
|
+
|
|
20
|
+
// Focus indicator: width / offset / style. Width meets WCAG 2.4.11 (≥ 2 px),
|
|
21
|
+
// offset keeps the ring outside the border so it sits in the gap against the
|
|
22
|
+
// page bg. Colour resolves at runtime to `var(--kc-focus-ring)` so themes
|
|
23
|
+
// can ship a token explicitly tuned for AAA visibility (high-contrast yellow
|
|
24
|
+
// etc.); falls back to `--kc-fg` and finally `currentColor`. The ring needs
|
|
25
|
+
// to contrast with `--kc-bg`, NOT the per-combination button surface: the
|
|
26
|
+
// chain therefore roots at theme-level tokens, not currentColor.
|
|
27
|
+
$focus-outline-width: 2px !default;
|
|
28
|
+
$focus-outline-style: solid !default;
|
|
29
|
+
$focus-outline-offset: 2px !default;
|
|
30
|
+
|
|
31
|
+
// Disabled-state opacity. 0.6 keeps glyphs legible (~3:1 against the input
|
|
32
|
+
// bg) while clearly signalling non-interactivity. Pairs with `cursor:
|
|
33
|
+
// not-allowed`.
|
|
34
|
+
$disabled-opacity: 0.6 !default;
|
|
35
|
+
|
|
36
|
+
// Border tint for form controls relative to the page foreground. 50 % is the
|
|
37
|
+
// smallest single value that clears WCAG 1.4.11 (3:1 non-text contrast)
|
|
38
|
+
// against the page bg in both default and dark themes (~3.04:1 default,
|
|
39
|
+
// ~4.83:1 dark). Earlier 24 % missed by ~half: borders read as decoration
|
|
40
|
+
// only, not as a control boundary.
|
|
41
|
+
$border-mix: 50% !default;
|
|
42
|
+
|
|
43
|
+
// AAA touch-target minimum (WCAG 2.5.5): interactive controls must be
|
|
44
|
+
// ≥ 44 × 44 CSS pixels. Padding alone provides the height; this token
|
|
45
|
+
// enforces the floor for short labels (icon-only buttons, "OK", "No").
|
|
46
|
+
// Override to 0 for inline dense toolbars accepting the AA 24 × 24 floor.
|
|
47
|
+
$min-touch-target: 2.75rem !default;
|
|
48
|
+
|
|
49
|
+
// `filter: brightness()` factor for :hover states. Below 1 = darken. Note
|
|
50
|
+
// that brightness scales every channel uniformly, so it does NOT exactly
|
|
51
|
+
// preserve a contrast ratio: it tends to compress mid-luminance pairs.
|
|
52
|
+
// 0.95 is the largest hover-darken that keeps every shipped combination
|
|
53
|
+
// ≥ 4.5:1 (AA) at rest and ≥ 3:1 (AA-large; WCAG 2.4.11 non-text contrast)
|
|
54
|
+
// on hover. Consumers shipping their own combinations should re-verify.
|
|
55
|
+
$hover-brightness: 0.95 !default;
|
|
56
|
+
|
|
57
|
+
// Default duration for state-change transitions (switch toggle, focus
|
|
58
|
+
// fade-in, modal entrance). Short enough to feel responsive, long enough
|
|
59
|
+
// to read as motion. Consumers can override per-component or zero out
|
|
60
|
+
// here to honour `prefers-reduced-motion` globally.
|
|
61
|
+
$transition-duration: 120ms !default;
|
|
62
|
+
|
|
63
|
+
// Typography fundamentals. Live here (not just in `typography/base`) so
|
|
64
|
+
// any component can reach for the same baseline values: and so consumers
|
|
65
|
+
// configuring the framework see the typography knobs alongside the rest.
|
|
66
|
+
// `typography/base` derives from these.
|
|
67
|
+
$base-size: 16px !default;
|
|
68
|
+
$body-line-height: 1.5 !default;
|
|
69
|
+
$family-sans-serif:
|
|
70
|
+
-apple-system,
|
|
71
|
+
BlinkMacSystemFont,
|
|
72
|
+
"Segoe UI",
|
|
73
|
+
Roboto,
|
|
74
|
+
Helvetica,
|
|
75
|
+
Arial,
|
|
76
|
+
sans-serif,
|
|
77
|
+
"Apple Color Emoji",
|
|
78
|
+
"Segoe UI Emoji",
|
|
79
|
+
"Segoe UI Symbol", !default;
|
|
80
|
+
$family-monospace: monospace !default;
|
|
81
|
+
|
|
82
|
+
// Emit `:dir(rtl)` overrides for properties that don't have a logical-axis
|
|
83
|
+
// equivalent (background-position, transform). Set to `false` for an LTR-only
|
|
84
|
+
// build that strips the rtl rules at compile time.
|
|
85
|
+
$rtl: true !default;
|
|
86
|
+
|
|
87
|
+
// Reveal mechanism(s) for stateful framework components (navbar dropdown,
|
|
88
|
+
// future tabs/modal). 'css' = native pseudo-classes / :has() / <details> /
|
|
89
|
+
// <input:checked>. 'js' = attribute selectors ([aria-expanded='true'],
|
|
90
|
+
// [data-open]) for consumer JS to drive. Both in the list = both branches
|
|
91
|
+
// emitted; single value strips the other. The framework still ships zero JS;
|
|
92
|
+
// 'js' only emits the CSS hooks consumer JS sets.
|
|
93
|
+
$controls: ("css", "js") !default;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// Device-oriented min-width breakpoints. `mobile` is `null` (no media
|
|
2
|
+
// query) so it matches every viewport — keep it as the first entry; the
|
|
3
|
+
// flex grid uses it as the default-display breakpoint.
|
|
4
|
+
$breakpoints: (
|
|
5
|
+
mobile: null,
|
|
6
|
+
tablet: 768px,
|
|
7
|
+
desktop: 1024px,
|
|
8
|
+
widescreen: 1280px,
|
|
9
|
+
fullhd: 1536px,
|
|
10
|
+
) !default;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
$prefix-is: ".is-" !default;
|