WARNING: When using manual builds of Kahi UI, you'll need to rebuild the distributables every time you upgrade Kahi UI.
If you want a more compreshensive customization of Kahi UI's look and feel, you can use the Framework's Custom Builds system to produce your own distributables.
Prerequisites
Make sure to familiarize yourself with Framework's Custom Builds system before starting. It's also recommended to learn SASS as-well.
Global Theme
After having Kahi UI's source code downloaded and installed, edit the src/themes/default/_theme.scss
stylesheet. This file contains all the non-Component specific definitions that apply every where in the Framework. Which is broken up into the headers as seen below.
Palettes
IMPORTANT: You must ALWAYS include
accent
,dark
,light
,neutral
, andoff
color palettes when modifying the theme.
These definitions relate to the Framework's overall color design. By default, we use the Framework's palette generation system, which mixes the base color into the dark
and light
colors to produce the various shades that Kahi UI uses in its color design.
USAGE: When using the generative color system, the
dark
andlight
palettes ALWAYS needs to come first.
USAGE: When using the generative color system, the foreground color will be automatically selected from the
dark
andlight
palettes based on contrast.
@include constants.define(
generators.darklight(
$dark: (
// Base color used to generate shades, can be in any color space
"base": <COLOR>,
// How much of the `light` palette should be mixed into the base color per shade
"stepping": <PERCENTAGE>,
),
$light: (
// Base color used to generate shades, can be in any color space
"base": <COLOR>,
// How much of the `dark` palette should be mixed into the base color per shade
"stepping": <PERCENTAGE>,
)
)
);
@include constants.define(
(
"palettes": (
"<PALETTE>": generators.palette(
$dark: (
// Base darkmode color used to generate shades, can be in any color
"base": <COLOR>,
// How much of the `dark` palette should be mixed into the base color per shade
"stepping": <PERCENTAGE>,
),
$light: (
// Base lightmode color used to generate shades, can be in any color
"base": <COLOR>,
// How much of the `light` palette should be mixed into the base color per shade
"stepping": <PERCENTAGE>,
)
),
),
)
);
Alternatively, you can opt-out of the generative color system and manually specify each palette individually.
USAGE: Keep in mind that the shading scale used in Kahi UI is
lightest
blends in the most with the background color andboldest
is the least.
@include constants.define(
(
"palettes": (
"<PALETTE>": (
"dark": (
"base": <COLOR>,
// Which palette color is used to contrast with this definition, e.g. for
"foreground": "<PALETTE>",
"lightest": <COLOR>,
"lighter": <COLOR>,
"light": <COLOR>,
"normal": <COLOR>,
"bold": <COLOR>,
"bolder": <COLOR>,
"boldest": <COLOR>,
),
"light": (
"base": <COLOR>,
// Which palette color is used to contrast with this definition, e.g. for
"foreground": "<PALETTE>",
"lightest": <COLOR>,
"lighter": <COLOR>,
"light": <COLOR>,
"normal": <COLOR>,
"bold": <COLOR>,
"bolder": <COLOR>,
"boldest": <COLOR>,
),
),
),
)
);
As an example accent
palette based on the default
theme that ships with Kahi UI.
@include constants.define(
(
"palettes": (
"accent": (
"dark": (
"base": hsl(200deg, 25%, 47.5%),
"foreground": "light",
"lightest": hsl(201deg, 24%, 40%),
"lighter": hsl(200deg, 24%, 42%),
"light": hsl(200deg, 24%, 43%),
"normal": hsl(200deg, 24%, 44%),
"bold": hsl(200deg, 24%, 46%),
"bolder": hsl(200deg, 25%, 47.5%),
"boldest": hsl(199deg, 23%, 49%),
),
"light": (
"base": hsl(200deg, 30%, 47.5%),
"foreground": "light",
"lightest": hsl(199deg, 26%, 57%),
"lighter": hsl(200deg, 26%, 55%),
"light": hsl(200deg, 26%, 53%),
"normal": hsl(199deg, 27%, 51%),
"bold": hsl(200deg, 27%, 49%),
"bolder": hsl(200deg, 30%, 47.5%),
"boldest": hsl(200deg, 29%, 46%),
),
),
),
)
);
Viewports
IMPORTANT: Viewports are NOT to be modified AT ALL. Due to Custom Media Queries not being supported at the moment by Browsers.
These definitions relate to the Framework's Viewport breakpoints.
Font Families
IMPORTANT: You must ALWAYS include
block
,inline
, andmonospace
font families when modifying the theme.
These definitions relate to the font family stacks used across the Framework.
@include variables.define(
(
"fonts.families": (
"<FAMILY>": <FONT-STACK>,
),
)
);
Font Line Heights
IMPORTANT: These definitions must remain unitless! Components typically define their own unit depending on context.
These definitions relate to the spacing between each line of text. By default we use Modular Scale to generate spacings.
@include variables.define(
(
"fonts": (
"line-heights": generators.modular(
$base: <BASE-MULTIPLIER>,
$ratio: <RATIO>
),
),
)
);
Alternatively, you can opt-out of the generative spacing system and manually specify each spacing individually.
USAGE: Keep in mind that the spacing scale used in Kahi UI is
nano
is the smallest spacing andmassive
is the biggest.
@include variables.define(
(
"fonts": (
"line-heights": (
"nano": <MULTIPLIER>,
"tiny": <MULTIPLIER>,
"small": <MULTIPLIER>,
"medium": <MULTIPLIER>,
"large": <MULTIPLIER>,
"huge": <MULTIPLIER>,
"massive": <MULTIPLIER>,
),
),
)
);
As an example based on the default
theme that ships with Kahi UI.
@include variables.define(
(
"fonts": (
"line-heights": (
"nano": 1,
"tiny": 1.075,
"small": 1.155,
"medium": 1.242,
"large": 1.335,
"huge": 1.435,
"massive": 1.543,
),
),
)
);
Font Sizings
IMPORTANT: These definitions must remain unitless! Components typically define their own unit depending on context.
IMPORTANT: You must ALWAYS include
block
andinline
font sizings when modifying the theme.
These definitions relate to the , typically used in . By default we use Modular Scale to generate sizings.
@include variables.define(
(
"fonts": (
"sizes": (
"<TIER>": generators.modular(
$base: <BASE-MULTIPLIER>,
$ratio: <RATIO>
),
),
),
)
);
Alternatively, you can opt-out of the generative sizing system and manually specify each sizing individually.
USAGE: Keep in mind that the sizing scale used in Kahi UI is
nano
is the smallest andmassive
is the biggest.
@include variables.define(
(
"fonts": (
"sizes": (
"<TIER>": (
"nano": <MULTIPLIER>,
"tiny": <MULTIPLIER>,
"small": <MULTIPLIER>,
"medium": <MULTIPLIER>,
"large": <MULTIPLIER>,
"huge": <MULTIPLIER>,
"massive": <MULTIPLIER>,
),
),
),
)
);
As an example based on the inline
tier that the default
theme that ships with Kahi UI.
@include variables.define(
(
"fonts": (
"sizes": (
"inline": (
"nano": 0.75,
"tiny": 0.866,
"small": 1,
"medium": 1.155,
"large": 1.334,
"huge": 1.541,
"massive": 1.78,
),
),
),
)
);
Spacing Tiers
IMPORTANT: These definitions must remain unitless! Components typically define their own unit depending on context.
IMPORTANT: You must ALWAYS include
block
andinline
spacings when modifying the theme.
These definitions relate to spacing modifiers, typically used in Layout Components, letter spacings, or global intrinsics properties like margin
. By default we use Modular Scale to generate spacings.
@include variables.define(
(
"spacings": (
"<TIER>": generators.modular(
$base: <BASE-MULTIPLIER>,
$ratio: <RATIO>
),
),
)
);
Alternatively, you can opt-out of the generative spacing system and manually specify each spacing individually.
USAGE: Keep in mind that the spacing scale used in Kahi UI
massive
is the biggest andnano
is the smallest.
@include variables.define(
(
"spacings": (
"<TIER>": (
"nano": <MULTIPLIER>,
"tiny": <MULTIPLIER>,
"small": <MULTIPLIER>,
"medium": <MULTIPLIER>,
"large": <MULTIPLIER>,
"huge": <MULTIPLIER>,
"massive": <MULTIPLIER>,
),
),
)
);
As an example based on the block
tier that the default
theme that ships with Kahi UI.
@include variables.define(
(
"spacings": (
"block": (
"nano": 0.125,
"tiny": 0.25,
"small": 0.5,
"medium": 1,
"large": 2,
"huge": 4,
"massive": 8,
),
),
)
);
Spacing Constants
These definitions relate to spacing modifiers, used for global intrinsics properties like margin
.
@include constants.define(
(
"spacings": (
"<CONSTANT>": <SPACING>,
),
)
);
Size Tiers
IMPORTANT: These definitions must remain unitless! Components typically define their own unit depending on context.
IMPORTANT: You must ALWAYS include
block
sizings when modifying the theme.
These definitions relate to size modifiers, used for global intrinsics properties like width
. By default we use Modular Scale to generate sizes.
@include variables.define(
(
"sizes": (
"<TIER>": generators.modular(
$base: <BASE-MULTIPLIER>,
$ratio: <RATIO>
),
),
)
);
Alternatively, you can opt-out of the generative size system and manually specify each size individually.
USAGE: Keep in mind that the size scale used in Kahi UI is
nano
is the smallest andmassive
is the biggest.
@include variables.define(
(
"sizes": (
"<TIER>": (
"nano": <MULTIPLIER>,
"tiny": <MULTIPLIER>,
"small": <MULTIPLIER>,
"medium": <MULTIPLIER>,
"large": <MULTIPLIER>,
"huge": <MULTIPLIER>,
"massive": <MULTIPLIER>,
),
),
)
);
As an example based on the block
tier that the default
theme that ships with Kahi UI.
@include variables.define(
(
"sizes": (
"block": (
"nano": 9.5,
"tiny": 11.4,
"small": 13.68,
"medium": 16.416,
"large": 19.699,
"huge": 23.639,
"massive": 28.366,
),
),
)
);
Size Constants
These definitions relate to size modifiers, used for global intrinsics properties like width
.
@include constants.define(
(
"sizes": (
"<CONSTANT>": <SPACING>,
),
)
);
Radius Sizes
IMPORTANT: These definitions must remain unitless! Components typically define their own unit depending on context.
These definitions relate to sizing modifiers, typically used for Component radii and global radius properties. By default we use Modular Scale to generate sizes.
@include variables.define(
(
"radius": generators.modular(
$base: <BASE-MULTIPLIER>,
$ratio: <RATIO>
)
),
)
);
Alternatively, you can opt-out of the generative size system and manually specify each individually.
USAGE: Keep in mind that the size scale used in Kahi UI is
nano
is the smallest andmassive
is the biggest.
@include variables.define(
(
"radius": (
"nano": <MULTIPLIER>,
"tiny": <MULTIPLIER>,
"small": <MULTIPLIER>,
"medium": <MULTIPLIER>,
"large": <MULTIPLIER>,
"huge": <MULTIPLIER>,
"massive": <MULTIPLIER>,
),
)
);
As an example based on the default
theme that ships with Kahi UI.
@include variables.define(
(
"radius": (
"nano": 0.125,
"tiny": 0.25,
"small": 0.5,
"medium": 1,
"large": 2,
"huge": 4,
"massive": 8,
),
)
);
Radius Constants
These definitions relate to border radius modifiers, used for global intrinsics properties like shape
.
@include constants.define(
(
"radius": (
"<CONSTANT>": <SPACING>,
),
)
);
Easings
TODO: documentation
...
Animations
TODO: documentation
...
Z-Index
TODO: documentation
...
Elevations
TODO: documentation
...
Component Theme
Components are usually have this or similar directory structure depending on format (multi-pattern or singular).
src/lib/components/:category/:component
│
└───:component.scss // Stylesheet for Component
└───:component.default.scss // `default` Theme Variables for Component
└───:Component.svelte // Component Implementation
└───:Component.stories.svelte // Storybook Tests
└───index.ts // Exports Entry Point
You can edit each Component's :component.default.css
stylesheet to modify its default
theme, just like with the global theme. Using the Badge
Component as an example, the stylesheets typically look similar to this.
@use "../../../../framework/abstracts/variables";
// NOTE: By using this if statement, `--disable-components-display-badge` turns off this file in custom builds
@if not env("DISABLE_COMPONENTS_DISPLAY_BADGE") {
// NOTE: Every identifier + dot path is treated is treated as a namespaced CSS Custom Property,
// e.g. `badge.background.opacity` will be built as `--badge-background-opacity`
@include variables.define(
(
"badge": (
// NOTE: Whenever a namespace only has one (1) member instead of multiple, we can
// just shortcut to using a period instead of creating a new map like the `font` namespace
"background.opacity": 1,
"border.radius": none,
"color.opacity": 1,
"font": (
// NOTE: `variables.use` is used to look up variables registered to the global
// themeing variables. This allows the build process to validate our variables exist
"size": variables.use("fonts.sizes.inline.nano"),
"weight": bold,
),
"gap": (
"x": variables.use("spacings.block.small"),
"y": variables.use("spacings.block.small"),
),
"padding": (
"x": variables.use("spacings.block.small"),
"y": variables.use("spacings.block.nano"),
),
),
)
);
}
For detailed documentation on what each Component's variables are, visit their documentation page and scroll down to the API Reference.