nuance-ui 0.2.35 → 0.3.0

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.
Files changed (75) hide show
  1. package/dist/module.d.mts +3 -0
  2. package/dist/module.d.ts +3 -0
  3. package/dist/module.json +1 -1
  4. package/dist/module.mjs +5 -3
  5. package/dist/runtime/app-config.d.ts +4 -0
  6. package/dist/runtime/components/accordion.d.vue.ts +79 -0
  7. package/dist/runtime/components/accordion.vue +44 -0
  8. package/dist/runtime/components/accordion.vue.d.ts +79 -0
  9. package/dist/runtime/components/action-icon/action-icon.d.vue.ts +11 -1
  10. package/dist/runtime/components/action-icon/action-icon.module.css +1 -1
  11. package/dist/runtime/components/action-icon/action-icon.vue +20 -5
  12. package/dist/runtime/components/action-icon/action-icon.vue.d.ts +11 -1
  13. package/dist/runtime/components/button/button.d.vue.ts +8 -0
  14. package/dist/runtime/components/button/button.module.css +1 -1
  15. package/dist/runtime/components/button/button.vue +17 -4
  16. package/dist/runtime/components/button/button.vue.d.ts +8 -0
  17. package/dist/runtime/components/collapsible/collapsible-content.d.vue.ts +18 -0
  18. package/dist/runtime/components/collapsible/collapsible-content.vue +76 -0
  19. package/dist/runtime/components/collapsible/collapsible-content.vue.d.ts +18 -0
  20. package/dist/runtime/components/collapsible/collapsible-root.d.vue.ts +42 -0
  21. package/dist/runtime/components/collapsible/collapsible-root.vue +41 -0
  22. package/dist/runtime/components/collapsible/collapsible-root.vue.d.ts +42 -0
  23. package/dist/runtime/components/collapsible/collapsible-trigger.d.vue.ts +13 -0
  24. package/dist/runtime/components/collapsible/collapsible-trigger.vue +20 -0
  25. package/dist/runtime/components/collapsible/collapsible-trigger.vue.d.ts +13 -0
  26. package/dist/runtime/components/collapsible/index.d.ts +3 -0
  27. package/dist/runtime/components/collapsible/index.js +1 -0
  28. package/dist/runtime/components/dialog/ui/dialog-close-button.d.vue.ts +2 -2
  29. package/dist/runtime/components/dialog/ui/dialog-close-button.vue +14 -11
  30. package/dist/runtime/components/dialog/ui/dialog-close-button.vue.d.ts +2 -2
  31. package/dist/runtime/components/dialog/ui/dialog-footer.d.vue.ts +2 -2
  32. package/dist/runtime/components/dialog/ui/dialog-footer.vue +3 -5
  33. package/dist/runtime/components/dialog/ui/dialog-footer.vue.d.ts +2 -2
  34. package/dist/runtime/components/dialog/ui/dialog-header.d.vue.ts +2 -2
  35. package/dist/runtime/components/dialog/ui/dialog-header.vue +3 -5
  36. package/dist/runtime/components/dialog/ui/dialog-header.vue.d.ts +2 -2
  37. package/dist/runtime/components/dialog/ui/dialog-root.d.vue.ts +2 -2
  38. package/dist/runtime/components/dialog/ui/dialog-root.vue +23 -25
  39. package/dist/runtime/components/dialog/ui/dialog-root.vue.d.ts +2 -2
  40. package/dist/runtime/components/dialog/ui/dialog-section.d.vue.ts +2 -2
  41. package/dist/runtime/components/dialog/ui/dialog-section.vue +3 -5
  42. package/dist/runtime/components/dialog/ui/dialog-section.vue.d.ts +2 -2
  43. package/dist/runtime/components/dialog/ui/dialog-title.d.vue.ts +2 -2
  44. package/dist/runtime/components/dialog/ui/dialog-title.vue +3 -5
  45. package/dist/runtime/components/dialog/ui/dialog-title.vue.d.ts +2 -2
  46. package/dist/runtime/components/drawer/drawer-close-button.vue +5 -0
  47. package/dist/runtime/components/files/file-upload-button.vue +4 -0
  48. package/dist/runtime/components/files/file-upload-icon.vue +5 -0
  49. package/dist/runtime/components/index.d.ts +2 -0
  50. package/dist/runtime/components/index.js +1 -0
  51. package/dist/runtime/components/link/lib.d.ts +2 -2
  52. package/dist/runtime/components/link/link-button.vue +4 -0
  53. package/dist/runtime/components/modal/modal-close-button.vue +5 -0
  54. package/dist/runtime/components/nav-link/nav-icon-link.d.vue.ts +5 -11
  55. package/dist/runtime/components/nav-link/nav-icon-link.vue +12 -8
  56. package/dist/runtime/components/nav-link/nav-icon-link.vue.d.ts +5 -11
  57. package/dist/runtime/components/scroll-area.vue +2 -1
  58. package/dist/runtime/components/select.d.vue.ts +2 -2
  59. package/dist/runtime/components/select.vue.d.ts +2 -2
  60. package/dist/runtime/components/table/ui/table-sortable-header.vue +4 -0
  61. package/dist/runtime/components/table/ui/table.vue +1 -1
  62. package/dist/runtime/components/tabs/tabs-root.d.vue.ts +1 -1
  63. package/dist/runtime/components/tabs/tabs-root.vue.d.ts +1 -1
  64. package/dist/runtime/components/theme-toggle.vue +5 -0
  65. package/dist/runtime/components/transition.d.vue.ts +10 -0
  66. package/dist/runtime/components/transition.vue +14 -3
  67. package/dist/runtime/components/transition.vue.d.ts +10 -0
  68. package/dist/runtime/composables/use-config.d.ts +1 -0
  69. package/dist/runtime/composables/use-config.js +2 -1
  70. package/dist/runtime/modals/modals-provider.vue +8 -10
  71. package/dist/runtime/utils/const/active-variants.d.ts +11 -0
  72. package/dist/runtime/utils/const/active-variants.js +9 -0
  73. package/dist/runtime/utils/const/index.d.ts +1 -0
  74. package/dist/runtime/utils/const/index.js +1 -0
  75. package/package.json +4 -4
package/dist/module.d.mts CHANGED
@@ -1,5 +1,6 @@
1
1
  import * as _nuxt_schema from '@nuxt/schema';
2
2
  import { NuanceDefaultThemeColor, NuanceGradient, NuanceIcons } from '../dist/runtime/types/index.js';
3
+ import { ActiveVariantsMap } from '../dist/runtime/utils/index.js';
3
4
 
4
5
  /** Primary color: a theme palette name or an array of 10 shade values (0..9). */
5
6
  type PrimaryColor = NuanceDefaultThemeColor | string[];
@@ -30,6 +31,8 @@ interface ModuleOptions {
30
31
  gradient?: NuanceGradient;
31
32
  /** Icon registry overrides */
32
33
  icons?: Partial<NuanceIcons>;
34
+ /** Variant an ActionIcon switches to when `active`, keyed by its base variant */
35
+ activeVariants?: Partial<ActiveVariantsMap>;
33
36
  }
34
37
  declare const _default: _nuxt_schema.NuxtModule<ModuleOptions, ModuleOptions, false>;
35
38
 
package/dist/module.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import * as _nuxt_schema from '@nuxt/schema';
2
2
  import { NuanceDefaultThemeColor, NuanceGradient, NuanceIcons } from '../dist/runtime/types/index.js';
3
+ import { ActiveVariantsMap } from '../dist/runtime/utils/index.js';
3
4
 
4
5
  /** Primary color: a theme palette name or an array of 10 shade values (0..9). */
5
6
  type PrimaryColor = NuanceDefaultThemeColor | string[];
@@ -30,6 +31,8 @@ interface ModuleOptions {
30
31
  gradient?: NuanceGradient;
31
32
  /** Icon registry overrides */
32
33
  icons?: Partial<NuanceIcons>;
34
+ /** Variant an ActionIcon switches to when `active`, keyed by its base variant */
35
+ activeVariants?: Partial<ActiveVariantsMap>;
33
36
  }
34
37
  declare const _default: _nuxt_schema.NuxtModule<ModuleOptions, ModuleOptions, false>;
35
38
 
package/dist/module.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "compatibility": {
5
5
  "nuxt": "^4.0.0"
6
6
  },
7
- "version": "0.2.35",
7
+ "version": "0.3.0",
8
8
  "builder": {
9
9
  "@nuxt/module-builder": "1.0.2",
10
10
  "unbuild": "3.6.1"
package/dist/module.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  import { defineNuxtModule, createResolver, addTypeTemplate, addComponentsDir, addImportsDir, addTemplate } from '@nuxt/kit';
2
2
  import { defu } from 'defu';
3
- import { DEFAULT_ICONS, DEFAULT_GRADIENT } from '../dist/runtime/utils/index.js';
3
+ import { DEFAULT_ACTIVE_VARIANTS, DEFAULT_ICONS, DEFAULT_GRADIENT } from '../dist/runtime/utils/index.js';
4
4
 
5
5
  const SHADES = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
6
6
  function fromName(name) {
@@ -73,7 +73,8 @@ const defaultConfig = {
73
73
  prefix: "N",
74
74
  primaryColor: "blue",
75
75
  gradient: DEFAULT_GRADIENT,
76
- icons: DEFAULT_ICONS
76
+ icons: DEFAULT_ICONS,
77
+ activeVariants: DEFAULT_ACTIVE_VARIANTS
77
78
  };
78
79
  const module$1 = defineNuxtModule({
79
80
  meta: {
@@ -114,7 +115,8 @@ const module$1 = defineNuxtModule({
114
115
  }
115
116
  nuxt.options.appConfig.nui = defu(nuxt.options.appConfig.nui, {
116
117
  gradient: options.gradient,
117
- icons: options.icons
118
+ icons: options.icons,
119
+ activeVariants: options.activeVariants
118
120
  });
119
121
  addTypeTemplate({
120
122
  filename: "types/nui-app-config.d.ts",
@@ -1,4 +1,5 @@
1
1
  import type { NuanceGradient, NuanceIcons } from './types'
2
+ import type { ActiveVariantsMap } from './utils'
2
3
 
3
4
 
4
5
  declare module '@nuxt/schema' {
@@ -8,6 +9,8 @@ declare module '@nuxt/schema' {
8
9
  gradient?: NuanceGradient
9
10
  /** Icon registry overrides */
10
11
  icons?: Partial<NuanceIcons>
12
+ /** Variant an ActionIcon switches to when `active`, keyed by its base variant */
13
+ activeVariants?: Partial<ActiveVariantsMap>
11
14
  }
12
15
  }
13
16
 
@@ -15,6 +18,7 @@ declare module '@nuxt/schema' {
15
18
  nui: {
16
19
  gradient: NuanceGradient
17
20
  icons: NuanceIcons
21
+ activeVariants: ActiveVariantsMap
18
22
  }
19
23
  }
20
24
  }
@@ -0,0 +1,79 @@
1
+ import type { Classes, NuanceRadius } from '@nui/types';
2
+ import type { TitleProps } from './title.vue.js';
3
+ export interface AccordionItem {
4
+ label?: string;
5
+ slot?: string;
6
+ content?: string;
7
+ disabled?: boolean;
8
+ /** Iconify icon */
9
+ icon?: string;
10
+ /** Iconify icon */
11
+ trailingIcon?: string;
12
+ /**
13
+ * A unique value for the accordion item. Defaults to the index.
14
+ * Also used as the Vue `key` for this item, so providing a stable value prevents
15
+ * accordion content (and its local state) from remounting when items are added, removed,
16
+ * or reordered.
17
+ */
18
+ value?: string;
19
+ }
20
+ type AccordionVariant = 'default' | 'contained' | 'filled' | 'separated';
21
+ export interface AccordionProps<Multiple extends boolean = false> {
22
+ /** If set, multiple items can be opened at the same time @default false */
23
+ multiple?: Multiple;
24
+ /** If set, arrow keys loop through items (first to last and last to first) @default true */
25
+ loop?: boolean;
26
+ /** @default 'default' */
27
+ variant?: AccordionVariant;
28
+ /** Transition duration in ms @default 200 */
29
+ transitionDuration?: number;
30
+ /** If set, chevron rotation is disabled @default false */
31
+ disableChevronRotation?: boolean;
32
+ /** Position of the chevron relative to the item label @default right */
33
+ chevronPosition?: 'left' | 'right';
34
+ /** Size of the chevron icon container @default auto */
35
+ chevronSize?: number | string;
36
+ /**
37
+ * Size of the default chevron icon. Ignored when `chevron` prop is set.
38
+ * Use `chevronSize` instead when using custom chevron.
39
+ * @default 16
40
+ */
41
+ chevronIconSize?: number | string;
42
+ /**
43
+ * Sets heading level (h2-h6) for `Accordion.Control` elements.
44
+ * Wraps each control in the corresponding heading tag, recommended to meet WAI-ARIA accessibility requirements.
45
+ * Has no visual effect.
46
+ */
47
+ order?: TitleProps['order'];
48
+ /** Custom chevron icon */
49
+ chevron?: string;
50
+ /**
51
+ * Key of `theme.radius` or any valid CSS value to set border-radius.
52
+ * Numbers are converted to rem.
53
+ * @default theme.defaultRadius */
54
+ radius?: NuanceRadius;
55
+ /**
56
+ * If set to `false`, panels are unmounted when collapsed.
57
+ * By default, panels stay mounted when collapsed. @default true
58
+ */
59
+ keepMounted?: boolean;
60
+ classes?: Classes<'root' | 'content' | 'item' | 'panel' | 'icon' | 'chevron' | 'label' | 'itemTitle' | 'control'>;
61
+ }
62
+ declare const _default: typeof __VLS_export;
63
+ export default _default;
64
+ declare const __VLS_export: <Multiple extends boolean = false>(__VLS_props: NonNullable<Awaited<typeof __VLS_setup>>["props"], __VLS_ctx?: __VLS_PrettifyLocal<Pick<NonNullable<Awaited<typeof __VLS_setup>>, "attrs" | "emit" | "slots">>, __VLS_exposed?: NonNullable<Awaited<typeof __VLS_setup>>["expose"], __VLS_setup?: Promise<{
65
+ props: import("vue").PublicProps & __VLS_PrettifyLocal<AccordionProps<Multiple>> & (typeof globalThis extends {
66
+ __VLS_PROPS_FALLBACK: infer P;
67
+ } ? P : {});
68
+ expose: (exposed: {}) => void;
69
+ attrs: any;
70
+ slots: {};
71
+ emit: {};
72
+ }>) => import("vue").VNode & {
73
+ __ctx?: Awaited<typeof __VLS_setup>;
74
+ };
75
+ type __VLS_PrettifyLocal<T> = (T extends any ? {
76
+ [K in keyof T]: T[K];
77
+ } : {
78
+ [K in keyof T as K]: T[K];
79
+ }) & {};
@@ -0,0 +1,44 @@
1
+ <script>
2
+
3
+ </script>
4
+
5
+ <script setup>
6
+ import { getRadius, getSize, useVarsResolver } from "#imports";
7
+ import Box from "./box.vue";
8
+ const {
9
+ transitionDuration,
10
+ chevronSize,
11
+ radius
12
+ } = defineProps({
13
+ multiple: { type: null, required: false },
14
+ loop: { type: Boolean, required: false },
15
+ variant: { type: String, required: false },
16
+ transitionDuration: { type: Number, required: false },
17
+ disableChevronRotation: { type: Boolean, required: false },
18
+ chevronPosition: { type: String, required: false },
19
+ chevronSize: { type: [Number, String], required: false },
20
+ chevronIconSize: { type: [Number, String], required: false },
21
+ order: { type: String, required: false },
22
+ chevron: { type: String, required: false },
23
+ radius: { type: [String, Number], required: false },
24
+ keepMounted: { type: Boolean, required: false },
25
+ classes: { type: Object, required: false }
26
+ });
27
+ const style = useVarsResolver(() => ({
28
+ root: {
29
+ "--accordion-transition-duration": transitionDuration === void 0 ? void 0 : `${transitionDuration}ms`,
30
+ "--accordion-chevron-size": chevronSize === void 0 ? void 0 : getSize(chevronSize),
31
+ "--accordion-radius": radius === void 0 ? void 0 : getRadius(radius)
32
+ }
33
+ }));
34
+ </script>
35
+
36
+ <template>
37
+ <Box :style='style.root'>
38
+ accordion
39
+ </Box>
40
+ </template>
41
+
42
+ <style module>
43
+ .root{--accordion-radius:var(--radius-default)}.panel{overflow-wrap:break-word}.content{padding:var(--spacing-md);padding-top:calc(var(--spacing-xs)/2)}.itemTitle{margin:0;padding:0;width:100%}.control{align-items:center;background-color:transparent;color:var(--color-bright);cursor:pointer;display:flex;flex-direction:row-reverse;opacity:1;padding-inline:var(--spacing-md);width:100%}.control:where([data-chevron-position=left]){flex-direction:row;padding-inline-start:0}.control:where(:disabled,[data-disabled]){cursor:not-allowed;opacity:.4}.control--contained:where(:not(:disabled,[data-disabled])),.control--default:where(:not(:disabled,[data-disabled])){@mixin hover{@mixin where-light{background-color:var(--color-gray-0)}@mixin where-dark{background-color:var(--color-dark-6)}}}.label{color:inherit;flex:1;font-weight:var(--font-weight-regular);overflow:hidden;padding-bottom:var(--spacing-sm);padding-top:var(--spacing-sm);text-overflow:ellipsis}.chevron{align-items:center;display:flex;justify-content:flex-start;min-width:var(--accordion-chevron-size,rem(15px));transform:rotate(0deg);transition:transform var(--accordion-transition-duration,.2s) ease;width:var(--accordion-chevron-size,rem(15px))}.chevron:where([data-rotate]){transform:rotate(180deg)}.chevron:where([data-position=left]){margin-inline-end:var(--spacing-md);margin-inline-start:var(--spacing-md)}.icon{align-items:center;display:flex;justify-content:center;margin-inline-end:var(--spacing-sm)}.icon:where([data-chevron-position=left]){margin-inline-end:0;margin-inline-start:var(--spacing-lg)}.item{@mixin where-light{--item-border-color:var(--color-gray-3);--item-filled-color:var(--color-gray-0)}@mixin where-dark{--item-border-color:var(--color-dark-4);--item-filled-color:var(--color-dark-6)}}.item--default{border-bottom:1px solid var(--item-border-color)}.item--contained{border:1px solid var(--item-border-color);transition:background-color .15s ease}.item--contained:where([data-active]){background-color:var(--item-filled-color)}.item--contained:first-of-type,.item--contained:first-of-type>[data-accordion-control]{border-start-end-radius:var(--accordion-radius);border-start-start-radius:var(--accordion-radius)}.item--contained:last-of-type,.item--contained:last-of-type>[data-accordion-control]{border-end-end-radius:var(--accordion-radius);border-end-start-radius:var(--accordion-radius)}.item--contained+.item--contained{border-top:0}.item--filled{border-radius:var(--accordion-radius)}.item--filled:where([data-active]){background-color:var(--item-filled-color)}.item--separated{background-color:var(--item-filled-color);border:1px solid transparent;border-radius:var(--accordion-radius);transition:background-color .15s ease}.item--separated[data-active]{border-color:var(--item-border-color);@mixin where-light{background-color:var(--color-white)}@mixin where-dark{background-color:var(--color-dark-7)}}.item--separated+.item--separated{margin-top:var(--spacing-md)}
44
+ </style>
@@ -0,0 +1,79 @@
1
+ import type { Classes, NuanceRadius } from '@nui/types';
2
+ import type { TitleProps } from './title.vue.js';
3
+ export interface AccordionItem {
4
+ label?: string;
5
+ slot?: string;
6
+ content?: string;
7
+ disabled?: boolean;
8
+ /** Iconify icon */
9
+ icon?: string;
10
+ /** Iconify icon */
11
+ trailingIcon?: string;
12
+ /**
13
+ * A unique value for the accordion item. Defaults to the index.
14
+ * Also used as the Vue `key` for this item, so providing a stable value prevents
15
+ * accordion content (and its local state) from remounting when items are added, removed,
16
+ * or reordered.
17
+ */
18
+ value?: string;
19
+ }
20
+ type AccordionVariant = 'default' | 'contained' | 'filled' | 'separated';
21
+ export interface AccordionProps<Multiple extends boolean = false> {
22
+ /** If set, multiple items can be opened at the same time @default false */
23
+ multiple?: Multiple;
24
+ /** If set, arrow keys loop through items (first to last and last to first) @default true */
25
+ loop?: boolean;
26
+ /** @default 'default' */
27
+ variant?: AccordionVariant;
28
+ /** Transition duration in ms @default 200 */
29
+ transitionDuration?: number;
30
+ /** If set, chevron rotation is disabled @default false */
31
+ disableChevronRotation?: boolean;
32
+ /** Position of the chevron relative to the item label @default right */
33
+ chevronPosition?: 'left' | 'right';
34
+ /** Size of the chevron icon container @default auto */
35
+ chevronSize?: number | string;
36
+ /**
37
+ * Size of the default chevron icon. Ignored when `chevron` prop is set.
38
+ * Use `chevronSize` instead when using custom chevron.
39
+ * @default 16
40
+ */
41
+ chevronIconSize?: number | string;
42
+ /**
43
+ * Sets heading level (h2-h6) for `Accordion.Control` elements.
44
+ * Wraps each control in the corresponding heading tag, recommended to meet WAI-ARIA accessibility requirements.
45
+ * Has no visual effect.
46
+ */
47
+ order?: TitleProps['order'];
48
+ /** Custom chevron icon */
49
+ chevron?: string;
50
+ /**
51
+ * Key of `theme.radius` or any valid CSS value to set border-radius.
52
+ * Numbers are converted to rem.
53
+ * @default theme.defaultRadius */
54
+ radius?: NuanceRadius;
55
+ /**
56
+ * If set to `false`, panels are unmounted when collapsed.
57
+ * By default, panels stay mounted when collapsed. @default true
58
+ */
59
+ keepMounted?: boolean;
60
+ classes?: Classes<'root' | 'content' | 'item' | 'panel' | 'icon' | 'chevron' | 'label' | 'itemTitle' | 'control'>;
61
+ }
62
+ declare const _default: typeof __VLS_export;
63
+ export default _default;
64
+ declare const __VLS_export: <Multiple extends boolean = false>(__VLS_props: NonNullable<Awaited<typeof __VLS_setup>>["props"], __VLS_ctx?: __VLS_PrettifyLocal<Pick<NonNullable<Awaited<typeof __VLS_setup>>, "attrs" | "emit" | "slots">>, __VLS_exposed?: NonNullable<Awaited<typeof __VLS_setup>>["expose"], __VLS_setup?: Promise<{
65
+ props: import("vue").PublicProps & __VLS_PrettifyLocal<AccordionProps<Multiple>> & (typeof globalThis extends {
66
+ __VLS_PROPS_FALLBACK: infer P;
67
+ } ? P : {});
68
+ expose: (exposed: {}) => void;
69
+ attrs: any;
70
+ slots: {};
71
+ emit: {};
72
+ }>) => import("vue").VNode & {
73
+ __ctx?: Awaited<typeof __VLS_setup>;
74
+ };
75
+ type __VLS_PrettifyLocal<T> = (T extends any ? {
76
+ [K in keyof T]: T[K];
77
+ } : {
78
+ [K in keyof T as K]: T[K];
79
+ }) & {};
@@ -4,11 +4,13 @@ export type ActionIconClasses = 'root' | 'icon';
4
4
  export type ActionIconVariant = 'filled' | 'light' | 'outline' | 'subtle' | 'default' | 'gradient';
5
5
  export type ActionIconSize = NuanceSize | `input-${NuanceSize}` | AnyString;
6
6
  export interface ActionIconVars {
7
- root: '--ai-size' | '--ai-radius' | '--ai-bg' | '--ai-hover' | '--ai-color' | '--ai-bd';
7
+ root: '--ai-size' | '--ai-icon-size' | '--ai-radius' | '--ai-bg' | '--ai-hover' | '--ai-color' | '--ai-bd';
8
8
  }
9
9
  export interface ActionIconProps {
10
10
  /** Component size @default 'md' */
11
11
  size?: ActionIconSize;
12
+ /** Icon size — `%` stays relative to the button, other values resolve via size tokens @default '70%' */
13
+ iconSize?: number | string;
12
14
  /** Gradient configuration (used with `variant="gradient"`) */
13
15
  gradient?: NuanceGradient;
14
16
  /** Color from theme */
@@ -25,6 +27,14 @@ export interface ActionIconProps {
25
27
  mod?: BoxProps['mod'];
26
28
  /** Visual variant */
27
29
  variant?: ActionIconVariant;
30
+ /** Active/pressed state — adds `data-active` and the matching ARIA attribute */
31
+ active?: boolean;
32
+ /** ARIA semantic for `active` @default 'pressed' */
33
+ activeMode?: 'pressed' | 'current';
34
+ /** Variant applied when `active`. Defaults to the configured map for the current `variant` */
35
+ activeVariant?: ActionIconVariant;
36
+ /** Color applied when `active` @default 'primary' */
37
+ activeColor?: NuanceColor;
28
38
  /** Styles API */
29
39
  classes?: Classes<ActionIconClasses>;
30
40
  }
@@ -1 +1 @@
1
- .root{--ai-size-xs:rem(26px);--ai-size-sm:rem(30px);--ai-size-md:rem(36px);--ai-size-lg:rem(42px);--ai-size-xl:rem(50px);--ai-size-input-xs:rem(30px);--ai-size-input-sm:rem(36px);--ai-size-input-md:rem(42px);--ai-size-input-lg:rem(50px);--ai-size-input-xl:rem(60px);--ai-size:var(--ai-size-sm);--ai-color:var(--color-white);--ai-radius:var(--radius-default);--ai-bg:var(--color-primary-filled);--ai-hover:var(--color-primary-filled-hover);align-items:center;background:var(--ai-bg,var(--color-primary-filled));border:var(--ai-bd,rem(1px) solid transparent);border-radius:var(--ai-radius,var(--radius-default));color:var(--ai-color,var(--color-white));cursor:pointer;display:inline-flex;height:var(--ai-size);justify-content:center;line-height:1;min-height:var(--ai-size);min-width:var(--ai-size);overflow:hidden;padding:0;position:relative;-webkit-user-select:none;-moz-user-select:none;user-select:none;width:var(--ai-size)}.root[data-loading]{cursor:not-allowed}.root[data-loading] .icon{opacity:0;transform:translateY(100%)}.root:where(:disabled:not([data-loading]),[data-disabled]:not([data-loading])){border:1px solid transparent;cursor:not-allowed}.root:where(:disabled:not([data-loading]),[data-disabled]:not([data-loading])):active{transform:none}.root:where(:disabled:not([data-loading]),[data-disabled]:not([data-loading])){@mixin where-light{background-color:var(--color-gray-1);color:var(--color-gray-5)}}.root:where(:disabled:not([data-loading]),[data-disabled]:not([data-loading])){@mixin where-dark{background-color:var(--color-dark-6);color:var(--color-dark-3)}}.root:hover:where(:not([data-loading],:disabled,[data-disabled])){background-color:var(--ai-hover);color:var(--ai-color)}.loader{align-items:center;border-radius:var(--ai-radius,var(--radius-default));display:flex;justify-content:center;left:calc(50% - var(--loader-size)/2);position:absolute;top:calc(50% - var(--loader-size)/2);@mixin where-light{background-color:hsla(0,0%,100%,.15)}@mixin where-dark{background-color:rgba(0,0,0,.15)}}.icon{align-items:center;display:flex;height:100%;justify-content:center;transition:transform .15s ease,opacity .1s ease;width:100%}.icon-element{height:70%;width:70%}.group{--ai-border-width:1px;display:flex}.group :where(*):focus{position:relative;z-index:1}.group[data-orientation=horizontal]{flex-direction:row}.group[data-orientation=horizontal] .groupSection:not(:only-child):first-child,.group[data-orientation=horizontal] .root:not(:only-child):first-child{border-end-end-radius:0;border-inline-end-width:calc(var(--ai-border-width)/2);border-start-end-radius:0}.group[data-orientation=horizontal] .groupSection:not(:only-child):last-child,.group[data-orientation=horizontal] .root:not(:only-child):last-child{border-end-start-radius:0;border-inline-start-width:calc(var(--ai-border-width)/2);border-start-start-radius:0}.group[data-orientation=horizontal] .groupSection:not(:only-child):not(:first-child):not(:last-child),.group[data-orientation=horizontal] .root:not(:only-child):not(:first-child):not(:last-child){border-inline-width:calc(var(--ai-border-width)/2);border-radius:0}.group[data-orientation=vertical]{flex-direction:column}.group[data-orientation=vertical] .groupSection:not(:only-child):first-child,.group[data-orientation=vertical] .root:not(:only-child):first-child{border-bottom-width:calc(var(--ai-border-width)/2);border-end-end-radius:0;border-end-start-radius:0}.group[data-orientation=vertical] .groupSection:not(:only-child):last-child,.group[data-orientation=vertical] .root:not(:only-child):last-child{border-start-end-radius:0;border-start-start-radius:0;border-top-width:calc(var(--ai-border-width)/2)}.group[data-orientation=vertical] .groupSection:not(:only-child):not(:first-child):not(:last-child),.group[data-orientation=vertical] .root:not(:only-child):not(:first-child):not(:last-child){border-bottom-width:calc(var(--ai-border-width)/2);border-radius:0;border-top-width:calc(var(--ai-border-width)/2)}.section{--section-height-xs:var(--ai-size-xs);--section-height-sm:var(--ai-size-sm);--section-height-md:var(--ai-size-md);--section-height-lg:var(--ai-size-lg);--section-height-xl:var(--ai-size-xl);--section-height-input-xs:var(--ai-size-input-xs);--section-height-input-sm:var(--ai-size-input-sm);--section-height-input-md:var(--ai-size-input-md);--section-height-input-lg:var(--ai-size-input-lg);--section-height-input-xl:var(--ai-size-input-xl);--section-padding-x-xs:rem(6px);--section-padding-x-sm:rem(8px);--section-padding-x-md:rem(10px);--section-padding-x-lg:rem(12px);--section-padding-x-xl:rem(16px);--section-height:var(--section-height-sm);--section-padding-x:var(--section-padding-x-sm);--section-color:var(--color-white);align-items:center;background:var(--section-bg,var(--color-primary-filled));border:var(--section-bd,rem(1px) solid transparent);border-radius:var(--section-radius,var(--radius-default));color:var(--section-color,var(--color-white));display:inline-flex;font-size:var(--section-fz,var(--font-size-md));font-weight:600;height:var(--section-height,var(--section-height-sm));justify-content:center;line-height:1;padding-inline:var(--section-padding-x,var(--section-padding-x-sm));vertical-align:middle;width:auto}
1
+ .root{--ai-size-xs:rem(26px);--ai-size-sm:rem(30px);--ai-size-md:rem(36px);--ai-size-lg:rem(42px);--ai-size-xl:rem(50px);--ai-size-input-xs:rem(30px);--ai-size-input-sm:rem(36px);--ai-size-input-md:rem(42px);--ai-size-input-lg:rem(50px);--ai-size-input-xl:rem(60px);--ai-size:var(--ai-size-sm);--ai-icon-size:70%;--ai-color:var(--color-white);--ai-radius:var(--radius-default);--ai-bg:var(--color-primary-filled);--ai-hover:var(--color-primary-filled-hover);align-items:center;background:var(--ai-bg,var(--color-primary-filled));border:var(--ai-bd,rem(1px) solid transparent);border-radius:var(--ai-radius,var(--radius-default));color:var(--ai-color,var(--color-white));cursor:pointer;display:inline-flex;height:var(--ai-size);justify-content:center;line-height:1;min-height:var(--ai-size);min-width:var(--ai-size);overflow:hidden;padding:0;position:relative;-webkit-user-select:none;-moz-user-select:none;user-select:none;width:var(--ai-size)}.root[data-loading]{cursor:not-allowed}.root[data-loading] .icon{opacity:0;transform:translateY(100%)}.root:where(:disabled:not([data-loading]),[data-disabled]:not([data-loading])){border:1px solid transparent;cursor:not-allowed}.root:where(:disabled:not([data-loading]),[data-disabled]:not([data-loading])):active{transform:none}.root:where(:disabled:not([data-loading]),[data-disabled]:not([data-loading])){@mixin where-light{background-color:var(--color-gray-1);color:var(--color-gray-5)}}.root:where(:disabled:not([data-loading]),[data-disabled]:not([data-loading])){@mixin where-dark{background-color:var(--color-dark-6);color:var(--color-dark-3)}}.root:hover:where(:not([data-loading],:disabled,[data-disabled])){background-color:var(--ai-hover);color:var(--ai-color)}.loader{align-items:center;border-radius:var(--ai-radius,var(--radius-default));display:flex;justify-content:center;left:calc(50% - var(--loader-size)/2);position:absolute;top:calc(50% - var(--loader-size)/2);@mixin where-light{background-color:hsla(0,0%,100%,.15)}@mixin where-dark{background-color:rgba(0,0,0,.15)}}.icon{align-items:center;display:flex;height:100%;justify-content:center;transition:transform .15s ease,opacity .1s ease;width:100%}.icon-element{height:var(--ai-icon-size);width:var(--ai-icon-size)}.group{--ai-border-width:1px;display:flex}.group :where(*):focus{position:relative;z-index:1}.group[data-orientation=horizontal]{flex-direction:row}.group[data-orientation=horizontal] .groupSection:not(:only-child):first-child,.group[data-orientation=horizontal] .root:not(:only-child):first-child{border-end-end-radius:0;border-inline-end-width:calc(var(--ai-border-width)/2);border-start-end-radius:0}.group[data-orientation=horizontal] .groupSection:not(:only-child):last-child,.group[data-orientation=horizontal] .root:not(:only-child):last-child{border-end-start-radius:0;border-inline-start-width:calc(var(--ai-border-width)/2);border-start-start-radius:0}.group[data-orientation=horizontal] .groupSection:not(:only-child):not(:first-child):not(:last-child),.group[data-orientation=horizontal] .root:not(:only-child):not(:first-child):not(:last-child){border-inline-width:calc(var(--ai-border-width)/2);border-radius:0}.group[data-orientation=vertical]{flex-direction:column}.group[data-orientation=vertical] .groupSection:not(:only-child):first-child,.group[data-orientation=vertical] .root:not(:only-child):first-child{border-bottom-width:calc(var(--ai-border-width)/2);border-end-end-radius:0;border-end-start-radius:0}.group[data-orientation=vertical] .groupSection:not(:only-child):last-child,.group[data-orientation=vertical] .root:not(:only-child):last-child{border-start-end-radius:0;border-start-start-radius:0;border-top-width:calc(var(--ai-border-width)/2)}.group[data-orientation=vertical] .groupSection:not(:only-child):not(:first-child):not(:last-child),.group[data-orientation=vertical] .root:not(:only-child):not(:first-child):not(:last-child){border-bottom-width:calc(var(--ai-border-width)/2);border-radius:0;border-top-width:calc(var(--ai-border-width)/2)}.section{--section-height-xs:var(--ai-size-xs);--section-height-sm:var(--ai-size-sm);--section-height-md:var(--ai-size-md);--section-height-lg:var(--ai-size-lg);--section-height-xl:var(--ai-size-xl);--section-height-input-xs:var(--ai-size-input-xs);--section-height-input-sm:var(--ai-size-input-sm);--section-height-input-md:var(--ai-size-input-md);--section-height-input-lg:var(--ai-size-input-lg);--section-height-input-xl:var(--ai-size-input-xl);--section-padding-x-xs:rem(6px);--section-padding-x-sm:rem(8px);--section-padding-x-md:rem(10px);--section-padding-x-lg:rem(12px);--section-padding-x-xl:rem(16px);--section-height:var(--section-height-sm);--section-padding-x:var(--section-padding-x-sm);--section-color:var(--color-white);align-items:center;background:var(--section-bg,var(--color-primary-filled));border:var(--section-bd,rem(1px) solid transparent);border-radius:var(--section-radius,var(--radius-default));color:var(--section-color,var(--color-white));display:inline-flex;font-size:var(--section-fz,var(--font-size-md));font-weight:600;height:var(--section-height,var(--section-height-sm));justify-content:center;line-height:1;padding-inline:var(--section-padding-x,var(--section-padding-x-sm));vertical-align:middle;width:auto}
@@ -5,8 +5,9 @@ import Box from "../box.vue";
5
5
  import Loader from "../loader/loader.vue";
6
6
  import css from "./action-icon.module.css";
7
7
  const {
8
- color,
8
+ color = "gray",
9
9
  size,
10
+ iconSize,
10
11
  variant = "default",
11
12
  gradient,
12
13
  loading,
@@ -14,9 +15,14 @@ const {
14
15
  radius,
15
16
  mod,
16
17
  icon,
17
- disabled
18
+ disabled,
19
+ active,
20
+ activeMode = "pressed",
21
+ activeVariant,
22
+ activeColor = "primary"
18
23
  } = defineProps({
19
24
  size: { type: null, required: false },
25
+ iconSize: { type: [Number, String], required: false },
20
26
  gradient: { type: Object, required: false },
21
27
  color: { type: null, required: false },
22
28
  radius: { type: [String, Number, Object], required: false },
@@ -25,19 +31,26 @@ const {
25
31
  disabled: { type: Boolean, required: false },
26
32
  mod: { type: [Object, Array, null], required: false },
27
33
  variant: { type: String, required: false },
34
+ active: { type: Boolean, required: false },
35
+ activeMode: { type: String, required: false },
36
+ activeVariant: { type: String, required: false },
37
+ activeColor: { type: null, required: false },
28
38
  classes: { type: Object, required: false }
29
39
  });
30
- const { variantResolver } = useConfig();
40
+ const { variantResolver, activeVariants } = useConfig();
31
41
  const style = useVarsResolver((theme) => {
42
+ const resolvedVariant = active ? activeVariant ?? activeVariants[variant] : variant;
43
+ const resolvedColor = active ? activeColor : color;
32
44
  const {
33
45
  background,
34
46
  border,
35
47
  hover,
36
48
  text
37
- } = variantResolver({ variant, color, theme, gradient });
49
+ } = variantResolver({ variant: resolvedVariant, color: resolvedColor, theme, gradient });
38
50
  return {
39
51
  root: {
40
52
  "--ai-size": getSize(size, "ai-size"),
53
+ "--ai-icon-size": getSize(iconSize),
41
54
  "--ai-radius": getRadius(radius),
42
55
  "--ai-bg": background,
43
56
  "--ai-hover": hover,
@@ -52,10 +65,12 @@ const style = useVarsResolver((theme) => {
52
65
  <Box
53
66
  is='button'
54
67
  type='button'
55
- :mod='[{ loading }, mod]'
68
+ :mod='[{ loading, active }, mod]'
56
69
  :style='style.root'
57
70
  :class='[css.root, classes?.root]'
58
71
  :disabled='(!disabled ? loading : disabled) || void 0'
72
+ :aria-pressed='activeMode === "pressed" ? active : void 0'
73
+ :aria-current='active && activeMode === "current" ? "page" : void 0'
59
74
  >
60
75
  <Transition name='slide-down'>
61
76
  <Loader
@@ -4,11 +4,13 @@ export type ActionIconClasses = 'root' | 'icon';
4
4
  export type ActionIconVariant = 'filled' | 'light' | 'outline' | 'subtle' | 'default' | 'gradient';
5
5
  export type ActionIconSize = NuanceSize | `input-${NuanceSize}` | AnyString;
6
6
  export interface ActionIconVars {
7
- root: '--ai-size' | '--ai-radius' | '--ai-bg' | '--ai-hover' | '--ai-color' | '--ai-bd';
7
+ root: '--ai-size' | '--ai-icon-size' | '--ai-radius' | '--ai-bg' | '--ai-hover' | '--ai-color' | '--ai-bd';
8
8
  }
9
9
  export interface ActionIconProps {
10
10
  /** Component size @default 'md' */
11
11
  size?: ActionIconSize;
12
+ /** Icon size — `%` stays relative to the button, other values resolve via size tokens @default '70%' */
13
+ iconSize?: number | string;
12
14
  /** Gradient configuration (used with `variant="gradient"`) */
13
15
  gradient?: NuanceGradient;
14
16
  /** Color from theme */
@@ -25,6 +27,14 @@ export interface ActionIconProps {
25
27
  mod?: BoxProps['mod'];
26
28
  /** Visual variant */
27
29
  variant?: ActionIconVariant;
30
+ /** Active/pressed state — adds `data-active` and the matching ARIA attribute */
31
+ active?: boolean;
32
+ /** ARIA semantic for `active` @default 'pressed' */
33
+ activeMode?: 'pressed' | 'current';
34
+ /** Variant applied when `active`. Defaults to the configured map for the current `variant` */
35
+ activeVariant?: ActionIconVariant;
36
+ /** Color applied when `active` @default 'primary' */
37
+ activeColor?: NuanceColor;
28
38
  /** Styles API */
29
39
  classes?: Classes<ActionIconClasses>;
30
40
  }
@@ -30,6 +30,14 @@ export interface ButtonProps extends BoxProps {
30
30
  rightSectionProps?: HTMLAttributes;
31
31
  /** Visual variant */
32
32
  variant?: ButtonVariant;
33
+ /** Active/pressed state — adds `data-active` and the matching ARIA attribute */
34
+ active?: boolean;
35
+ /** ARIA semantic for `active` @default 'pressed' */
36
+ activeMode?: 'pressed' | 'current';
37
+ /** Variant applied when `active`. Defaults to the configured map for the current `variant` */
38
+ activeVariant?: ButtonVariant;
39
+ /** Color applied when `active` @default 'primary' */
40
+ activeColor?: NuanceColor;
33
41
  /** Styles API */
34
42
  classes?: Classes<ButtonClasses>;
35
43
  }
@@ -1 +1 @@
1
- .root{--button-height-xs:rem(26px);--button-height-sm:rem(30px);--button-height-md:rem(36px);--button-height-lg:rem(42px);--button-height-xl:rem(50px);--button-height-compact-xs:rem(22px);--button-height-compact-sm:rem(26px);--button-height-compact-md:rem(30px);--button-height-compact-lg:rem(34px);--button-height-compact-xl:rem(40px);--button-padding-x-xs:rem(14px);--button-padding-x-sm:rem(18px);--button-padding-x-md:rem(22px);--button-padding-x-lg:rem(26px);--button-padding-x-xl:rem(32px);--button-padding-x-compact-xs:rem(7px);--button-padding-x-compact-sm:rem(8px);--button-padding-x-compact-md:rem(10px);--button-padding-x-compact-lg:rem(12px);--button-padding-x-compact-xl:rem(14px);--button-height:var(--button-height-sm);--button-padding-x:var(--button-padding-x-sm);--button-color:var(--color-white);--button-fz:var(--font-size-md);--button-bg:var(--color-primary-filled);--button-radius:var(--radius-default);--button-hover:var(--color-primary-filled-hover);--button-spacing:0;--button-justify:center;--button-section-size:calc(var(--button-height) - 0.25rem);background:var(--button-bg);border:var(--button-bd,rem(1px) solid transparent);border-radius:var(--button-radius);color:var(--button-color,var(--color-white));cursor:pointer;display:inline-block;font-size:var(--button-fz);font-weight:500;height:var(--button-height,var(--button-height-sm));line-height:1;overflow:hidden;padding-inline:var(--button-padding-x,var(--button-padding-x-sm));position:relative;text-align:center;transition:background-color .2s ease-in,color .2s ease-in;-webkit-user-select:none;-moz-user-select:none;user-select:none;vertical-align:middle;width:auto}.root:where([data-with-left-section]){padding-inline-start:0}.root:where([data-with-right-section]){padding-inline-end:0}.root:where([data-variant=gradient-outline]){background-clip:padding-box,border-box;background-origin:border-box}.root:where(:disabled:not([data-loading])){background:var(--color-disabled);border:1px solid transparent;color:var(--color-disabled-text);cursor:not-allowed;transform:none}.root:before{border-radius:var(--button-radius,var(--radius-default));content:"";filter:blur(12px);inset:-1px;opacity:0;pointer-events:none;position:absolute;transform:translateY(-100%);transition:transform .15s ease,opacity .1s ease;@mixin where-light{background:var(--color-gray-1);color:var(--color-gray-5)}@mixin where-dark{background:var(--color-dark-6);color:var(--color-dark-3)}}.root:where([data-loading]){cursor:not-allowed;transform:none}.root:where([data-loading]):before{opacity:1;transform:translateY(0)}.root:where([data-loading]) .inner{opacity:0;transform:translateY(100%)}.root:hover:where(:not([data-loading],:disabled)),.root[data-active]{background:var(--button-hover);color:var(--button-color)}.root:hover:where(:not([data-loading],:disabled)):where([data-variant=gradient-outline]),.root[data-active]:where([data-variant=gradient-outline]){color:#fff}.inner{gap:var(--button-spacing);justify-content:center;overflow:visible;transition:transform .15s ease,opacity .1s ease;width:100%}.inner,.label{align-items:center;display:flex;height:100%}.label{flex:1;justify-content:var(--button-justify);opacity:1;overflow:hidden;white-space:nowrap}.label:where([data-loading]){opacity:.2}.section{--section-pointer-events:none;align-items:center;display:flex;height:100%;justify-content:center;pointer-events:var(--section-pointer-events);width:var(--button-section-size)}.loader{left:calc(50% - var(--loader-size)/2);position:absolute;top:calc(50% - var(--loader-size)/2)}.group{--group-border-width:1px;display:flex}.group>:where(*):focus{position:relative;z-index:1}.group[data-orientation=horizontal]{flex-direction:row}.group[data-orientation=horizontal]>:where(*):not(:only-child):first-child{border-end-end-radius:0;border-inline-end-width:calc(var(--group-border-width)/2);border-start-end-radius:0}.group[data-orientation=horizontal]>:where(*):not(:only-child):last-child{border-end-start-radius:0;border-inline-start-width:calc(var(--group-border-width)/2);border-start-start-radius:0}.group[data-orientation=horizontal]>:where(*):not(:only-child):not(:first-child):not(:last-child){border-inline-width:calc(var(--group-border-width)/2);border-radius:0}.group[data-orientation=vertical]{flex-direction:column}.group[data-orientation=vertical]>:where(*):not(:only-child):first-child{border-bottom-width:calc(var(--group-border-width)/2);border-end-end-radius:0;border-end-start-radius:0}.group[data-orientation=vertical]>:where(*):not(:only-child):last-child{border-start-end-radius:0;border-start-start-radius:0;border-top-width:calc(var(--group-border-width)/2)}.group[data-orientation=vertical]>:where(*):not(:only-child):not(:first-child):not(:last-child){border-bottom-width:calc(var(--group-border-width)/2);border-radius:0;border-top-width:calc(var(--group-border-width)/2)}
1
+ .root{--button-height-xs:rem(26px);--button-height-sm:rem(30px);--button-height-md:rem(36px);--button-height-lg:rem(42px);--button-height-xl:rem(50px);--button-height-compact-xs:rem(22px);--button-height-compact-sm:rem(26px);--button-height-compact-md:rem(30px);--button-height-compact-lg:rem(34px);--button-height-compact-xl:rem(40px);--button-padding-x-xs:rem(14px);--button-padding-x-sm:rem(18px);--button-padding-x-md:rem(22px);--button-padding-x-lg:rem(26px);--button-padding-x-xl:rem(32px);--button-padding-x-compact-xs:rem(7px);--button-padding-x-compact-sm:rem(8px);--button-padding-x-compact-md:rem(10px);--button-padding-x-compact-lg:rem(12px);--button-padding-x-compact-xl:rem(14px);--button-height:var(--button-height-sm);--button-padding-x:var(--button-padding-x-sm);--button-color:var(--color-white);--button-fz:var(--font-size-md);--button-bg:var(--color-primary-filled);--button-radius:var(--radius-default);--button-hover:var(--color-primary-filled-hover);--button-spacing:0;--button-justify:center;--button-section-size:calc(var(--button-height) - 0.25rem);background:var(--button-bg);border:var(--button-bd,rem(1px) solid transparent);border-radius:var(--button-radius);color:var(--button-color,var(--color-white));cursor:pointer;display:inline-block;font-size:var(--button-fz);font-weight:500;height:var(--button-height,var(--button-height-sm));line-height:1;overflow:hidden;padding-inline:var(--button-padding-x,var(--button-padding-x-sm));position:relative;text-align:center;transition:background-color .2s ease-in,color .2s ease-in;-webkit-user-select:none;-moz-user-select:none;user-select:none;vertical-align:middle;width:auto}.root:where([data-with-left-section]){padding-inline-start:0}.root:where([data-with-right-section]){padding-inline-end:0}.root:where([data-variant=gradient-outline]){background-clip:padding-box,border-box;background-origin:border-box}.root:where(:disabled:not([data-loading])){background:var(--color-disabled);border:1px solid transparent;color:var(--color-disabled-text);cursor:not-allowed;transform:none}.root:before{border-radius:var(--button-radius,var(--radius-default));content:"";filter:blur(12px);inset:-1px;opacity:0;pointer-events:none;position:absolute;transform:translateY(-100%);transition:transform .15s ease,opacity .1s ease;@mixin where-light{background:var(--color-gray-1);color:var(--color-gray-5)}@mixin where-dark{background:var(--color-dark-6);color:var(--color-dark-3)}}.root:where([data-loading]){cursor:not-allowed;transform:none}.root:where([data-loading]):before{opacity:1;transform:translateY(0)}.root:where([data-loading]) .inner{opacity:0;transform:translateY(100%)}.root:hover:where(:not([data-loading],:disabled)){background:var(--button-hover);color:var(--button-color)}.root:hover:where(:not([data-loading],:disabled)):where([data-variant=gradient-outline]){color:#fff}.inner{gap:var(--button-spacing);justify-content:center;overflow:visible;transition:transform .15s ease,opacity .1s ease;width:100%}.inner,.label{align-items:center;display:flex;height:100%}.label{flex:1;justify-content:var(--button-justify);opacity:1;overflow:hidden;white-space:nowrap}.label:where([data-loading]){opacity:.2}.section{--section-pointer-events:none;align-items:center;display:flex;height:100%;justify-content:center;pointer-events:var(--section-pointer-events);width:var(--button-section-size)}.loader{left:calc(50% - var(--loader-size)/2);position:absolute;top:calc(50% - var(--loader-size)/2)}.group{--group-border-width:1px;display:flex}.group>:where(*):focus{position:relative;z-index:1}.group[data-orientation=horizontal]{flex-direction:row}.group[data-orientation=horizontal]>:where(*):not(:only-child):first-child{border-end-end-radius:0;border-inline-end-width:calc(var(--group-border-width)/2);border-start-end-radius:0}.group[data-orientation=horizontal]>:where(*):not(:only-child):last-child{border-end-start-radius:0;border-inline-start-width:calc(var(--group-border-width)/2);border-start-start-radius:0}.group[data-orientation=horizontal]>:where(*):not(:only-child):not(:first-child):not(:last-child){border-inline-width:calc(var(--group-border-width)/2);border-radius:0}.group[data-orientation=vertical]{flex-direction:column}.group[data-orientation=vertical]>:where(*):not(:only-child):first-child{border-bottom-width:calc(var(--group-border-width)/2);border-end-end-radius:0;border-end-start-radius:0}.group[data-orientation=vertical]>:where(*):not(:only-child):last-child{border-start-end-radius:0;border-start-start-radius:0;border-top-width:calc(var(--group-border-width)/2)}.group[data-orientation=vertical]>:where(*):not(:only-child):not(:first-child):not(:last-child){border-bottom-width:calc(var(--group-border-width)/2);border-radius:0;border-top-width:calc(var(--group-border-width)/2)}
@@ -1,6 +1,7 @@
1
1
  <script setup>
2
2
  import { useConfig, useVarsResolver } from "@nui/composables";
3
3
  import { getFontSize, getRadius, getSize, getSpacing } from "@nui/utils";
4
+ import { computed } from "vue";
4
5
  import Box from "../box.vue";
5
6
  import Loader from "../loader/loader.vue";
6
7
  import css from "./button.module.css";
@@ -14,6 +15,10 @@ const {
14
15
  loading,
15
16
  classes,
16
17
  rightSectionProps,
18
+ active,
19
+ activeMode = "pressed",
20
+ activeVariant,
21
+ activeColor = "primary",
17
22
  ...props
18
23
  } = defineProps({
19
24
  color: { type: null, required: false },
@@ -29,16 +34,21 @@ const {
29
34
  leftSectionProps: { type: Object, required: false },
30
35
  rightSectionProps: { type: Object, required: false },
31
36
  variant: { type: String, required: false },
37
+ active: { type: Boolean, required: false },
38
+ activeMode: { type: String, required: false },
39
+ activeVariant: { type: String, required: false },
40
+ activeColor: { type: null, required: false },
32
41
  classes: { type: Object, required: false },
33
42
  is: { type: null, required: false },
34
43
  mod: { type: [Object, Array, null], required: false }
35
44
  });
36
- const { variantResolver } = useConfig();
45
+ const { variantResolver, activeVariants } = useConfig();
46
+ const resolvedVariant = computed(() => active ? activeVariant ?? activeVariants[variant] : variant);
37
47
  const style = useVarsResolver((theme) => {
38
48
  const { background, border, hover, text } = variantResolver({
39
49
  theme,
40
- variant,
41
- color: props.color,
50
+ variant: resolvedVariant.value,
51
+ color: active ? activeColor : props.color,
42
52
  gradient: props.gradient
43
53
  });
44
54
  return {
@@ -72,11 +82,14 @@ const style = useVarsResolver((theme) => {
72
82
  "with-left-section": !!$slots?.leftSection || !!icon,
73
83
  "with-right-section": !!$slots?.rightSection,
74
84
  loading,
75
- variant
85
+ active,
86
+ "variant": resolvedVariant
76
87
  }]'
77
88
  :style='style.root'
78
89
  :class='[css.root, classes?.root]'
79
90
  :disabled='loading'
91
+ :aria-pressed='activeMode === "pressed" ? active : void 0'
92
+ :aria-current='active && activeMode === "current" ? "page" : void 0'
80
93
  >
81
94
  <Transition name='fade-down'>
82
95
  <Loader v-show='loading' :class='css.loader' :color :size />
@@ -30,6 +30,14 @@ export interface ButtonProps extends BoxProps {
30
30
  rightSectionProps?: HTMLAttributes;
31
31
  /** Visual variant */
32
32
  variant?: ButtonVariant;
33
+ /** Active/pressed state — adds `data-active` and the matching ARIA attribute */
34
+ active?: boolean;
35
+ /** ARIA semantic for `active` @default 'pressed' */
36
+ activeMode?: 'pressed' | 'current';
37
+ /** Variant applied when `active`. Defaults to the configured map for the current `variant` */
38
+ activeVariant?: ButtonVariant;
39
+ /** Color applied when `active` @default 'primary' */
40
+ activeColor?: NuanceColor;
33
41
  /** Styles API */
34
42
  classes?: Classes<ButtonClasses>;
35
43
  }
@@ -0,0 +1,18 @@
1
+ import type { BoxProps } from '../box.vue.js';
2
+ export interface CollapsibleContentProps extends BoxProps {
3
+ /**
4
+ * Used to force mounting when more control is needed. Useful when
5
+ * controlling animation with Vue animation libraries.
6
+ */
7
+ forceMount?: boolean;
8
+ }
9
+ declare const _default: typeof __VLS_export;
10
+ export default _default;
11
+ declare const __VLS_export: __VLS_WithSlots<import("vue").DefineComponent<CollapsibleContentProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<CollapsibleContentProps> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>, {
12
+ default?: (props: {}) => any;
13
+ }>;
14
+ type __VLS_WithSlots<T, S> = T & {
15
+ new (): {
16
+ $slots: S;
17
+ };
18
+ };