Skip to content
Draft
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
2 changes: 1 addition & 1 deletion packages/boxel-ui/addon/src/components/button/index.gts
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ const ButtonComponent: TemplateOnlyComponent<Signature> = <template>
a.boxel-button:not([href]),
a.boxel-button[href=''],
a.boxel-button.disabled-link {
--boxel-button-color: var(--boxel-border-color);
--boxel-button-color: var(--border, var(--boxel-border-color));
--boxel-button-border: 1px solid var(--boxel-button-color);
--boxel-button-text-color: var(--boxel-450);
--boxel-button-box-shadow: none;
Expand Down
4 changes: 2 additions & 2 deletions packages/boxel-ui/addon/src/components/multi-select/index.gts
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ export class BoxelMultiSelectBasic<ItemT> extends Component<Signature<ItemT>> {
padding: var(--boxel-sp-xxs) var(--boxel-sp-sm);
}
.boxel-multi-select__dropdown--rounded.ember-power-select-dropdown {
border: 1px solid var(--boxel-border-color);
border: 1px solid var(--border, var(--boxel-border-color));
border-radius: var(--boxel-border-radius-sm);
}
</style>
Expand All @@ -161,7 +161,7 @@ export class BoxelMultiSelectBasic<ItemT> extends Component<Signature<ItemT>> {
display: flex;
align-items: stretch;
overflow: hidden;
border: 1px solid var(--boxel-border-color);
border: 1px solid var(--border, var(--boxel-border-color));
border-radius: var(--boxel-border-radius-sm);
max-width: 100%;
width: 100%;
Expand Down
86 changes: 47 additions & 39 deletions packages/boxel-ui/addon/src/components/tooltip/index.gts
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,22 @@ import { Velcro } from 'ember-velcro';

import cn from '../../helpers/cn.ts';

export const TOOLTIP_VARIANTS = [
'default',
'main',
'primary',
'secondary',
'accent',
'muted',
'destructive',
] as const;
export type ThemeVariant = (typeof TOOLTIP_VARIANTS)[number];

interface Signature {
Args: {
offset?: number;
placement?: MiddlewareState['placement'];
variant?: 'primary' | 'secondary' | 'muted' | 'destructive' | 'default';
variant?: ThemeVariant;
};
Blocks: {
content: [];
Expand Down Expand Up @@ -71,11 +82,15 @@ export default class Tooltip extends Component<Signature> {
const themeVars = [
'--background',
'--foreground',
'--popover',
'--popover-foreground',
'--border',
'--primary',
'--primary-foreground',
'--secondary',
'--secondary-foreground',
'--accent',
'--accent-foreground',
'--muted',
'--muted-foreground',
'--destructive',
Expand Down Expand Up @@ -185,19 +200,10 @@ export default class Tooltip extends Component<Signature> {
}

.tooltip {
--tooltip-background-color: var(
--boxel-tooltip-background-color,
var(--background, rgb(0 0 0 / 80%))
);
--tooltip-text-color: var(
--boxel-tooltip-text-color,
var(--foreground, var(--boxel-light))
);
--tooltip-border-color: var(
--boxel-tooltip-border-color,
var(--border, var(--boxel-light-500))
var(--boxel-light-35)
);

background-color: var(--tooltip-background-color);
box-shadow: 0 0 0 1px var(--tooltip-border-color);
color: var(--tooltip-text-color);
Expand All @@ -220,75 +226,77 @@ export default class Tooltip extends Component<Signature> {
.variant-default {
--tooltip-background-color: var(
--boxel-tooltip-background-color,
var(--background, rgb(0 0 0 / 80%))
var(--boxel-dark-80)
);
--tooltip-text-color: var(
--boxel-tooltip-text-color,
var(--foreground, var(--boxel-light))
var(--boxel-light)
);
--tooltip-border-color: var(
--boxel-tooltip-border-color,
var(--border, var(--boxel-light-500))
}

.variant-main {
--tooltip-background-color: var(
--boxel-tooltip-background-color,
var(--popover, var(--background))
);
--tooltip-text-color: var(
--boxel-tooltip-text-color,
var(--popover-foreground, var(--foreground))
);
}

.variant-primary {
--tooltip-background-color: var(
--boxel-tooltip-background-color,
var(--primary, var(--boxel-600))
var(--primary)
);
--tooltip-text-color: var(
--boxel-tooltip-text-color,
var(--primary-foreground, var(--boxel-light))
);
--tooltip-border-color: var(
--boxel-tooltip-border-color,
var(--primary, var(--boxel-600))
var(--primary-foreground)
);
}

.variant-secondary {
--tooltip-background-color: var(
--boxel-tooltip-background-color,
var(--secondary, var(--boxel-400))
var(--secondary)
);
--tooltip-text-color: var(
--boxel-tooltip-text-color,
var(--secondary-foreground, var(--boxel-dark))
var(--secondary-foreground)
);
--tooltip-border-color: var(
--boxel-tooltip-border-color,
var(--secondary, var(--boxel-400))
}

.variant-accent {
--tooltip-background-color: var(
--boxel-tooltip-background-color,
var(--accent)
);
--tooltip-text-color: var(
--boxel-tooltip-text-color,
var(--accent-foreground)
);
}

.variant-muted {
--tooltip-background-color: var(
--boxel-tooltip-background-color,
var(--muted, var(--boxel-200))
var(--muted)
);
--tooltip-text-color: var(
--boxel-tooltip-text-color,
var(--muted-foreground, var(--boxel-dark))
);
--tooltip-border-color: var(
--boxel-tooltip-border-color,
var(--muted, var(--boxel-200))
var(--muted-foreground)
);
}

.variant-destructive {
--tooltip-background-color: var(
--boxel-tooltip-background-color,
var(--destructive, var(--boxel-600))
var(--destructive)
);
--tooltip-text-color: var(
--boxel-tooltip-text-color,
var(--destructive-foreground, var(--boxel-light))
);
--tooltip-border-color: var(
--boxel-tooltip-border-color,
var(--destructive, var(--boxel-600))
var(--destructive-foreground)
);
}

Expand Down
20 changes: 4 additions & 16 deletions packages/boxel-ui/addon/src/components/tooltip/usage.gts
Original file line number Diff line number Diff line change
Expand Up @@ -12,27 +12,15 @@ import {

import { cssVar } from '../../helpers.ts';
import BoxelButton from '../button/index.gts';
import BoxelTooltip from './index.gts';
import BoxelTooltip, { type ThemeVariant, TOOLTIP_VARIANTS } from './index.gts';

export default class TooltipUsage extends Component {
tooltipVariants = ['default', 'primary', 'secondary', 'muted', 'destructive'];
tooltipVariantDefault:
| undefined
| 'primary'
| 'secondary'
| 'muted'
| 'destructive'
| 'default' = undefined;
tooltipVariants = TOOLTIP_VARIANTS;
tooltipVariantDefault?: ThemeVariant;

@tracked placement: MiddlewareState['placement'] = 'bottom';
@tracked offset = 6;
@tracked variant:
| undefined
| 'primary'
| 'secondary'
| 'muted'
| 'destructive'
| 'default' = undefined;
@tracked variant?: ThemeVariant;

@cssVariable({ cssClassName: 'header-freestyle-container' })
declare tooltipBackgroundColor: CSSVariableInfo;
Expand Down
139 changes: 139 additions & 0 deletions packages/boxel-ui/addon/src/styles/theme.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
/* Boxel UI — semantic token contract + default (light) theme.

This file is the source of record for the semantic design tokens that
boxel-ui components consume (--primary, --foreground, --muted, etc.).
Shipping it from the addon means components render correctly with zero
host configuration — a consumer that imports the addon's styles gets a
complete, working theme by default.

The default values below map the semantic tokens onto the --boxel-*
palette declared in variables.css, so the palette remains the single
underlying source of truth for brand colors. A consumer overrides any
token by redeclaring it on :root (or a scoped element) after this file.

The full list of tokens declared here is the contract every theme must
satisfy. The dark-mode counterpart (a `.dark` / `[data-theme='dark']` scope)
is layered on separately, below.
*/

/* Light — the default theme, and the explicit `data-theme="light"` scope used
to force light back on inside a dark subtree. Both resolve to the same
values. */
:root,
[data-theme='light'] {
/* surfaces */
--background: var(--boxel-light);
--foreground: var(--boxel-dark);
--card: var(--boxel-light);
--card-foreground: var(--boxel-dark);
--popover: var(--boxel-light);
--popover-foreground: var(--boxel-dark);

/* roles */
--primary: var(--boxel-highlight);
--primary-foreground: var(--boxel-dark);
--secondary: var(--boxel-200);
--secondary-foreground: var(--boxel-dark);
--muted: var(--boxel-100);
--muted-foreground: var(--boxel-500);
--accent: var(--boxel-200);
--accent-foreground: var(--boxel-dark);
--destructive: var(--boxel-danger);
--destructive-foreground: var(--boxel-50);

/* form + focus */
--border: var(--boxel-border-color);
--input: var(--boxel-light);
--ring: var(--boxel-highlight);

/* charts */
--chart-1: var(--boxel-fuschia);
--chart-2: var(--boxel-purple);
--chart-3: var(--boxel-lime);
--chart-4: var(--boxel-blue);
--chart-5: var(--boxel-green);

/* sidebar */
--sidebar: var(--boxel-light);
--sidebar-foreground: var(--boxel-dark);
--sidebar-primary: var(--boxel-dark);
--sidebar-primary-foreground: var(--boxel-light);
--sidebar-accent: var(--boxel-200);
--sidebar-accent-foreground: var(--boxel-dark);
--sidebar-border: var(--boxel-border-color);
--sidebar-ring: var(--boxel-highlight);

/* typography */
--font-sans:
'IBM Plex Sans', 'Helvetica Neue', Arial, ui-sans-serif, sans-serif,
system-ui;
--font-serif: 'IBM Plex Serif', 'Georgia', Times, serif;
--font-mono:
'IBM Plex Mono', 'Menlo', 'Courier New', Courier, ui-monospace, monospace;
--tracking-normal: 0.01em;

/* geometry + spacing */
--radius: 0.625rem;
--spacing: 0.25rem;

/* shadow scale */
--shadow-x: 0;
--shadow-y: 1px;
--shadow-blur: 3px;
--shadow-spread: 0px;
--shadow-opacity: 0.1;
--shadow-color: var(--boxel-dark);
--shadow-2xs: 0 1px 3px 0px hsl(0 0% 0% / 0.05);
--shadow-xs: 0 1px 3px 0px hsl(0 0% 0% / 0.05);
--shadow-sm:
0 1px 3px 0px hsl(0 0% 0% / 0.1), 0 1px 2px -1px hsl(0 0% 0% / 0.1);
--shadow: 0 1px 3px 0px hsl(0 0% 0% / 0.1), 0 1px 2px -1px hsl(0 0% 0% / 0.1);
--shadow-md:
0 1px 3px 0px hsl(0 0% 0% / 0.1), 0 2px 4px -1px hsl(0 0% 0% / 0.1);
--shadow-lg:
0 1px 3px 0px hsl(0 0% 0% / 0.1), 0 4px 6px -1px hsl(0 0% 0% / 0.1);
--shadow-xl:
0 1px 3px 0px hsl(0 0% 0% / 0.1), 0 8px 10px -1px hsl(0 0% 0% / 0.1);
--shadow-2xl: 0 1px 3px 0px hsl(0 0% 0% / 0.25);
}

/* ── Dark mode ──────────────────────────────────────────────────────────────
Opt-in and explicit: add class `dark` or `data-theme="dark"` to <html>, or to
any subtree you want themed dark. Force light back on inside a dark subtree
with `data-theme="light"` (see the light block above).

OS-driven dark (`prefers-color-scheme` / a `data-theme="system"` mode) is
intentionally NOT wired up yet — it needs to resolve in both directions
(falling back to light when the OS is light, including inside a dark subtree),
so it is deferred until that feature is implemented.
*/
.dark,
[data-theme='dark'] {
--background: var(--boxel-700);
--foreground: var(--boxel-light);
--card: var(--boxel-650);
--card-foreground: var(--boxel-light);
--popover: #4f4b57;
--popover-foreground: var(--boxel-light);
--primary: var(--boxel-highlight);
--primary-foreground: var(--boxel-dark);
--secondary: #46434e;
--secondary-foreground: var(--boxel-light);
--muted: #34313c;
--muted-foreground: #b6b6be;
--accent: #797788;
--accent-foreground: var(--boxel-light);
--destructive: var(--boxel-danger);
--destructive-foreground: var(--boxel-light-100);
--border: var(--boxel-550);
--input: var(--boxel-dark);
--ring: var(--boxel-highlight);
--sidebar: #555366;
--sidebar-foreground: var(--boxel-light);
--sidebar-primary: var(--boxel-highlight);
--sidebar-primary-foreground: var(--boxel-dark);
--sidebar-accent: #797788;
--sidebar-accent-foreground: var(--boxel-light);
--sidebar-border: var(--boxel-550);
--sidebar-ring: var(--boxel-highlight);
}
Loading
Loading