zabi-components 5.0.22 → 6.0.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 (59) hide show
  1. package/README.md +41 -44
  2. package/THEME.md +473 -0
  3. package/THEMING.md +248 -0
  4. package/dist/atoms/Card.svelte +40 -67
  5. package/dist/atoms/Card.svelte.d.ts +3 -3
  6. package/dist/atoms/CardHeader.svelte +10 -1
  7. package/dist/atoms/CardHeader.svelte.d.ts +3 -0
  8. package/dist/atoms/CodeBlock.svelte +1 -1
  9. package/dist/atoms/ColorPicker.svelte +1 -1
  10. package/dist/atoms/Input.svelte +2 -2
  11. package/dist/atoms/Progress.svelte +1 -1
  12. package/dist/atoms/Select.svelte +7 -5
  13. package/dist/atoms/Textarea.svelte +2 -2
  14. package/dist/atoms/Toast.svelte +1 -1
  15. package/dist/components/index.d.ts +1 -2
  16. package/dist/components/index.d.ts.map +1 -1
  17. package/dist/components/organisms/index.d.ts +1 -2
  18. package/dist/components/organisms/index.d.ts.map +1 -1
  19. package/dist/index.d.ts +1 -2
  20. package/dist/index.js +1 -2
  21. package/dist/lib/showcase/components-catalog.d.ts +3 -0
  22. package/dist/lib/showcase/components-catalog.d.ts.map +1 -0
  23. package/dist/lib/showcase/components-showcase-constants.d.ts +63 -0
  24. package/dist/lib/showcase/components-showcase-constants.d.ts.map +1 -0
  25. package/dist/lib/showcase/docs-sidebar-helpers.d.ts +15 -0
  26. package/dist/lib/showcase/docs-sidebar-helpers.d.ts.map +1 -0
  27. package/dist/molecules/Alert.svelte +1 -1
  28. package/dist/molecules/ComponentDemo.svelte +53 -50
  29. package/dist/molecules/ContactForm.svelte +69 -64
  30. package/dist/molecules/Dropdown.svelte +2 -1
  31. package/dist/molecules/ImageUpload.svelte +1 -1
  32. package/dist/molecules/Modal.svelte +2 -2
  33. package/dist/molecules/NavigationMenuContent.svelte +1 -1
  34. package/dist/molecules/NavigationMenuLink.svelte +1 -1
  35. package/dist/molecules/NavigationMenuTrigger.svelte +1 -4
  36. package/dist/molecules/Section.svelte +12 -12
  37. package/dist/molecules/SlideUp.svelte +2 -2
  38. package/dist/molecules/Tabs.svelte +3 -3
  39. package/dist/organisms/Navbar.svelte +170 -53
  40. package/dist/organisms/Navbar.svelte.d.ts +31 -4
  41. package/dist/organisms/SidebarNavigation.svelte +209 -165
  42. package/dist/organisms/SidebarNavigation.svelte.d.ts +5 -0
  43. package/dist/organisms/{SidebarProjectPanel.svelte → SidebarPanel.svelte} +18 -17
  44. package/dist/organisms/{SidebarProjectPanel.svelte.d.ts → SidebarPanel.svelte.d.ts} +6 -6
  45. package/dist/organisms/index.d.ts +1 -2
  46. package/dist/organisms/index.js +1 -2
  47. package/dist/types/page.types.d.ts +32 -0
  48. package/dist/types/page.types.d.ts.map +1 -0
  49. package/dist/types/variants.ts +76 -0
  50. package/dist/zabi-components-colors.css +347 -324
  51. package/dist/zabi-components-theme-dark-only.css +159 -151
  52. package/dist/zabi-components-theme-dark.css +159 -151
  53. package/dist/zabi-components-theme-only.css +245 -230
  54. package/dist/zabi-components-theme.css +245 -230
  55. package/dist/zabi-components.css +437 -101
  56. package/docs/theme-imports.md +112 -0
  57. package/package.json +16 -6
  58. package/dist/organisms/Navigation.svelte +0 -119
  59. package/dist/organisms/Navigation.svelte.d.ts +0 -21
@@ -0,0 +1,63 @@
1
+ export declare const categories: {
2
+ id: string;
3
+ label: string;
4
+ description: string;
5
+ }[];
6
+ export declare const sampleCode = "function greet(name) {\n return `Hello, ${name}!`;\n}\n\nconsole.log(greet('World'));";
7
+ export declare const selectOptions: {
8
+ value: string;
9
+ label: string;
10
+ }[];
11
+ export declare const docsListItems: ({
12
+ id: string;
13
+ label: string;
14
+ description: string;
15
+ href: string;
16
+ disabled?: undefined;
17
+ } | {
18
+ id: string;
19
+ label: string;
20
+ description: string;
21
+ href?: undefined;
22
+ disabled?: undefined;
23
+ } | {
24
+ id: string;
25
+ label: string;
26
+ description: string;
27
+ href: string;
28
+ disabled: boolean;
29
+ })[];
30
+ export declare const sidebarNavItems: ({
31
+ id: string;
32
+ label: string;
33
+ href: string;
34
+ icon: import("svelte").Component<import("@lucide/svelte").IconProps, {}, "">;
35
+ badgeCount?: undefined;
36
+ group?: undefined;
37
+ } | {
38
+ id: string;
39
+ label: string;
40
+ href: string;
41
+ icon: import("svelte").Component<import("@lucide/svelte").IconProps, {}, "">;
42
+ badgeCount: number;
43
+ group?: undefined;
44
+ } | {
45
+ id: string;
46
+ label: string;
47
+ href: string;
48
+ icon: import("svelte").Component<import("@lucide/svelte").IconProps, {}, "">;
49
+ group: "secondary";
50
+ badgeCount?: undefined;
51
+ })[];
52
+ export declare const sidebarProjectItems: ({
53
+ id: string;
54
+ label: string;
55
+ description: string;
56
+ badgeText: string;
57
+ } | {
58
+ id: string;
59
+ label: string;
60
+ description: string;
61
+ badgeText?: undefined;
62
+ })[];
63
+ //# sourceMappingURL=components-showcase-constants.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"components-showcase-constants.d.ts","sourceRoot":"","sources":["../../../src/lib/showcase/components-showcase-constants.ts"],"names":[],"mappings":"AASA,eAAO,MAAM,UAAU;;;;GAiBtB,CAAC;AAEF,eAAO,MAAM,UAAU,2FAIM,CAAC;AAE9B,eAAO,MAAM,aAAa;;;GAGvB,CAAC;AAEJ,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;;IAyBzB,CAAC;AAEF,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;IAmB3B,CAAC;AAEF,eAAO,MAAM,mBAAmB;;;;;;;;;;IAuB/B,CAAC"}
@@ -0,0 +1,15 @@
1
+ import type { Component } from "svelte";
2
+ type SidebarNavIcon = Component<{
3
+ size?: number;
4
+ class?: string;
5
+ }>;
6
+ /**
7
+ * Icon for a documentation sidebar category row.
8
+ */
9
+ export declare function getDocsCategoryIcon(categoryId: string): SidebarNavIcon;
10
+ /**
11
+ * Icon for a documentation sidebar component row.
12
+ */
13
+ export declare function getDocsComponentIcon(componentName: string, componentCategory: string): SidebarNavIcon;
14
+ export {};
15
+ //# sourceMappingURL=docs-sidebar-helpers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"docs-sidebar-helpers.d.ts","sourceRoot":"","sources":["../../../src/lib/showcase/docs-sidebar-helpers.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AAExC,KAAK,cAAc,GAAG,SAAS,CAAC;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AAEnE;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,UAAU,EAAE,MAAM,GAAG,cAAc,CAKtE;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAChC,aAAa,EAAE,MAAM,EACrB,iBAAiB,EAAE,MAAM,GAC1B,cAAc,CAgBhB"}
@@ -81,7 +81,7 @@
81
81
  {#if closable}
82
82
  <button
83
83
  onclick={handleDismiss}
84
- class="absolute top-2 right-2 z-10 w-6 h-6 flex items-center justify-center rounded-full text-description hover:text-body transition-colors duration-200 motion-reduce:transition-none group focus:outline-none focus:ring-2 focus:ring-focus-ring focus:ring-offset-2"
84
+ class="group absolute right-2 top-2 z-10 flex h-6 w-6 cursor-pointer items-center justify-center rounded-full text-description transition-colors duration-200 hover:text-body motion-reduce:transition-none focus:outline-none focus:ring-2 focus:ring-focus-ring focus:ring-offset-2"
85
85
  aria-label="Dismiss alert"
86
86
  type="button"
87
87
  >
@@ -1,6 +1,8 @@
1
1
  <script lang="ts">
2
2
  import CodeBlock from "../atoms/CodeBlock.svelte";
3
3
  import Card from "../atoms/Card.svelte";
4
+ import CardHeader from "../atoms/CardHeader.svelte";
5
+ import CardContent from "../atoms/CardContent.svelte";
4
6
 
5
7
  interface Props {
6
8
  title: string;
@@ -27,61 +29,62 @@
27
29
  <Card
28
30
  size="lg"
29
31
  fullWidth={true}
30
- {title}
31
- {description}
32
32
  className="overflow-hidden {className}"
33
33
  {...restProps}
34
34
  >
35
- <button
36
- onclick={() => (showCode = !showCode)}
37
- class="absolute top-8 right-8 flex items-center gap-2 px-3 py-1.5 text-sm text-description hover:text-body hover:bg-base-50 rounded-md transition-colors duration-200 z-10"
38
- aria-label={showCode ? "Show preview" : "Show code"}
39
- >
35
+ <CardHeader {title} {description} />
36
+ <CardContent>
37
+ <button
38
+ onclick={() => (showCode = !showCode)}
39
+ class="absolute top-8 right-8 z-10 flex cursor-pointer items-center gap-2 rounded-md px-3 py-1.5 text-sm text-description transition-colors duration-200 hover:bg-base-50 hover:text-body"
40
+ aria-label={showCode ? "Show preview" : "Show code"}
41
+ >
42
+ {#if showCode}
43
+ <svg
44
+ class="w-4 h-4"
45
+ fill="none"
46
+ stroke="currentColor"
47
+ viewBox="0 0 24 24"
48
+ >
49
+ <path
50
+ stroke-linecap="round"
51
+ stroke-linejoin="round"
52
+ stroke-width="2"
53
+ d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"
54
+ />
55
+ <path
56
+ stroke-linecap="round"
57
+ stroke-linejoin="round"
58
+ stroke-width="2"
59
+ d="M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z"
60
+ />
61
+ </svg>
62
+ Preview
63
+ {:else}
64
+ <svg
65
+ class="w-4 h-4"
66
+ fill="none"
67
+ stroke="currentColor"
68
+ viewBox="0 0 24 24"
69
+ >
70
+ <path
71
+ stroke-linecap="round"
72
+ stroke-linejoin="round"
73
+ stroke-width="2"
74
+ d="M10 20l4-16m4 4l4 4-4 4M6 16l-4-4 4-4"
75
+ />
76
+ </svg>
77
+ Code
78
+ {/if}
79
+ </button>
80
+
40
81
  {#if showCode}
41
- <svg
42
- class="w-4 h-4"
43
- fill="none"
44
- stroke="currentColor"
45
- viewBox="0 0 24 24"
46
- >
47
- <path
48
- stroke-linecap="round"
49
- stroke-linejoin="round"
50
- stroke-width="2"
51
- d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"
52
- />
53
- <path
54
- stroke-linecap="round"
55
- stroke-linejoin="round"
56
- stroke-width="2"
57
- d="M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z"
58
- />
59
- </svg>
60
- Preview
82
+ <CodeBlock {code} {language} />
61
83
  {:else}
62
- <svg
63
- class="w-4 h-4"
64
- fill="none"
65
- stroke="currentColor"
66
- viewBox="0 0 24 24"
67
- >
68
- <path
69
- stroke-linecap="round"
70
- stroke-linejoin="round"
71
- stroke-width="2"
72
- d="M10 20l4-16m4 4l4 4-4 4M6 16l-4-4 4-4"
73
- />
74
- </svg>
75
- Code
84
+ <div class="min-h-[100px] flex items-center justify-center w-full">
85
+ {@render children?.()}
86
+ </div>
76
87
  {/if}
77
- </button>
78
-
79
- {#if showCode}
80
- <CodeBlock {code} {language} />
81
- {:else}
82
- <div class="min-h-[100px] flex items-center justify-center w-full">
83
- {@render children?.()}
84
- </div>
85
- {/if}
88
+ </CardContent>
86
89
  </Card>
87
90
  </div>
@@ -5,6 +5,8 @@
5
5
  import Checkbox from "../atoms/Checkbox.svelte";
6
6
  import Button from "../atoms/Button.svelte";
7
7
  import Card from "../atoms/Card.svelte";
8
+ import CardHeader from "../atoms/CardHeader.svelte";
9
+ import CardContent from "../atoms/CardContent.svelte";
8
10
  import type { ContactFormData } from "../../types/page.types";
9
11
 
10
12
  interface Props {
@@ -71,69 +73,72 @@
71
73
  </script>
72
74
 
73
75
  <div class={className}>
74
- <Card size="md" fullWidth={true} title="Get in Touch">
75
- <Form onsubmit={handleFormSubmit} className="space-y-4">
76
- {#if formErrorMessage}
77
- <div
78
- class="rounded-lg border border-error px-4 py-3 text-sm text-error"
79
- role="alert"
80
- >
81
- <p class="font-medium">Something went wrong</p>
82
- <p>{formErrorMessage}</p>
83
- <p class="mt-1">Recovery action: review your inputs and resubmit.</p>
84
- </div>
85
- {/if}
86
- <div class="space-y-4">
87
- <Input
88
- type="text"
89
- name="name"
90
- label="Name"
91
- placeholder="Enter your name"
92
- value={formData.name}
93
- oninput={(e) =>
94
- (formData.name = (e.target as HTMLInputElement).value)}
95
- variant={fieldErrors.name ? "error" : "default"}
96
- message={fieldErrors.name || ""}
97
- />
98
- <Input
99
- type="email"
100
- name="email"
101
- label="Email"
102
- placeholder="Enter your email"
103
- value={formData.email}
104
- oninput={(e) =>
105
- (formData.email = (e.target as HTMLInputElement).value)}
106
- variant={fieldErrors.email ? "error" : "default"}
107
- message={fieldErrors.email || ""}
108
- />
109
- <Textarea
110
- name="message"
111
- label="Message"
112
- placeholder="Enter your message"
113
- rows={4}
114
- value={formData.message}
115
- oninput={(e) =>
116
- (formData.message = (
117
- e.target as HTMLTextAreaElement
118
- ).value)}
119
- variant={fieldErrors.message ? "error" : "default"}
120
- message={fieldErrors.message || ""}
121
- />
122
- <Checkbox
123
- name="subscribe"
124
- label="Subscribe to updates"
125
- checked={formData.subscribe}
126
- onchange={(e) =>
127
- (formData.subscribe = (
128
- e.target as HTMLInputElement
129
- ).checked)}
130
- />
131
- </div>
132
- <div class="pt-4">
133
- <Button type="submit" variant="primary" size="md">
134
- Send Message
135
- </Button>
136
- </div>
137
- </Form>
76
+ <Card size="md" fullWidth={true}>
77
+ <CardHeader title="Get in Touch" />
78
+ <CardContent>
79
+ <Form onsubmit={handleFormSubmit} className="space-y-4">
80
+ {#if formErrorMessage}
81
+ <div
82
+ class="rounded-lg border border-error px-4 py-3 text-sm text-error"
83
+ role="alert"
84
+ >
85
+ <p class="font-medium">Something went wrong</p>
86
+ <p>{formErrorMessage}</p>
87
+ <p class="mt-1">Recovery action: review your inputs and resubmit.</p>
88
+ </div>
89
+ {/if}
90
+ <div class="space-y-4">
91
+ <Input
92
+ type="text"
93
+ name="name"
94
+ label="Name"
95
+ placeholder="Enter your name"
96
+ value={formData.name}
97
+ oninput={(e) =>
98
+ (formData.name = (e.target as HTMLInputElement).value)}
99
+ variant={fieldErrors.name ? "error" : "default"}
100
+ message={fieldErrors.name || ""}
101
+ />
102
+ <Input
103
+ type="email"
104
+ name="email"
105
+ label="Email"
106
+ placeholder="Enter your email"
107
+ value={formData.email}
108
+ oninput={(e) =>
109
+ (formData.email = (e.target as HTMLInputElement).value)}
110
+ variant={fieldErrors.email ? "error" : "default"}
111
+ message={fieldErrors.email || ""}
112
+ />
113
+ <Textarea
114
+ name="message"
115
+ label="Message"
116
+ placeholder="Enter your message"
117
+ rows={4}
118
+ value={formData.message}
119
+ oninput={(e) =>
120
+ (formData.message = (
121
+ e.target as HTMLTextAreaElement
122
+ ).value)}
123
+ variant={fieldErrors.message ? "error" : "default"}
124
+ message={fieldErrors.message || ""}
125
+ />
126
+ <Checkbox
127
+ name="subscribe"
128
+ label="Subscribe to updates"
129
+ checked={formData.subscribe}
130
+ onchange={(e) =>
131
+ (formData.subscribe = (
132
+ e.target as HTMLInputElement
133
+ ).checked)}
134
+ />
135
+ </div>
136
+ <div class="pt-4">
137
+ <Button type="submit" variant="primary" size="md">
138
+ Send Message
139
+ </Button>
140
+ </div>
141
+ </Form>
142
+ </CardContent>
138
143
  </Card>
139
144
  </div>
@@ -182,7 +182,8 @@
182
182
  bg-input
183
183
  rounded-lg
184
184
  shadow-lg
185
- border-0
185
+ border
186
+ border-input-border
186
187
  py-2
187
188
  transition-all
188
189
  duration-200
@@ -75,7 +75,7 @@
75
75
  class="w-full h-32 min-w-64 object-cover rounded-2xl border-0"
76
76
  />
77
77
  <div
78
- class="absolute inset-0 bg-input min-w-64 opacity-0 group-hover:opacity-100 transition-opacity rounded-2xl flex items-center justify-center"
78
+ class="absolute inset-0 border border-input-border bg-input min-w-64 opacity-0 group-hover:opacity-100 transition-opacity rounded-2xl flex items-center justify-center"
79
79
  >
80
80
  <div class="flex gap-2">
81
81
  <Button
@@ -86,7 +86,7 @@
86
86
 
87
87
  {#if isOpen}
88
88
  <div
89
- class="fixed inset-0 bg-overlay flex items-end md:items-center justify-center p-0 md:p-4 z-modal"
89
+ class="fixed inset-0 z-modal flex cursor-pointer items-end justify-center bg-overlay p-0 md:items-center md:p-4"
90
90
  onclick={handleBackdropClick}
91
91
  onkeydown={handleKeydown}
92
92
  role="dialog"
@@ -96,7 +96,7 @@
96
96
  >
97
97
  <div
98
98
  bind:this={modalContainer}
99
- class="bg-card rounded-t-3xl md:rounded-3xl shadow-xl min-w-[320px] {sizeClasses} max-h-[90vh] overflow-y-auto animate-[slideUp_0.3s_ease-out] md:animate-none flex flex-col p-0"
99
+ class="flex max-h-[90vh] min-w-[320px] cursor-default flex-col overflow-y-auto rounded-t-3xl bg-card p-0 shadow-xl animate-[slideUp_0.3s_ease-out] md:animate-none md:rounded-3xl {sizeClasses}"
100
100
  >
101
101
  <Card variant="default" fullWidth={false}>
102
102
  {#if title || description}
@@ -71,7 +71,7 @@
71
71
  {#if isActive}
72
72
  <div
73
73
  bind:this={contentElement}
74
- class="absolute left-0 top-full mt-2 bg-input rounded-lg shadow-lg border border-border p-4 z-dropdown min-w-[200px] transition-all duration-200 ease-in-out {className}"
74
+ class="absolute left-0 top-full mt-2 bg-input rounded-lg shadow-lg border border-input-border p-4 z-dropdown min-w-[200px] transition-all duration-200 ease-in-out {className}"
75
75
  role="menu"
76
76
  onkeydown={handleKeydown}
77
77
  data-navigation-menu-content
@@ -30,7 +30,7 @@
30
30
  }
31
31
 
32
32
  const linkClasses =
33
- "block px-4 py-2 text-sm text-headline hover:bg-base-100 rounded-md transition-colors focus:outline-none focus:ring-2 focus:ring-brand-500 focus:ring-offset-2 no-underline {className}";
33
+ "block cursor-pointer rounded-md px-4 py-2 text-sm text-nav-menu-item no-underline transition-colors duration-150 outline-none hover:bg-nav-menu-hover hover:text-nav-menu-item-hover focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-nav-menu-focus {className}";
34
34
  </script>
35
35
 
36
36
  {#if asChild}
@@ -19,8 +19,6 @@
19
19
  ...restProps
20
20
  }: Props = $props();
21
21
 
22
- let triggerElement = $state<HTMLElement | null>(null);
23
-
24
22
  const context = getContext<NavigationMenuContextValue>(
25
23
  NAVIGATION_MENU_CONTEXT_KEY,
26
24
  );
@@ -52,9 +50,8 @@
52
50
  </script>
53
51
 
54
52
  <button
55
- bind:this={triggerElement}
56
53
  type="button"
57
- class="inline-flex items-center justify-center gap-2 px-4 py-2 text-sm font-medium text-headline bg-transparent hover:bg-base-100 rounded-lg transition-colors focus:outline-none focus:ring-2 focus:ring-brand-500 focus:ring-offset-2 {className}"
54
+ class="inline-flex cursor-pointer items-center justify-center gap-2 rounded-lg bg-transparent px-4 py-2 text-sm font-medium text-nav-menu-item transition-colors duration-150 outline-none hover:bg-nav-menu-hover hover:text-nav-menu-item-hover data-[active=true]:bg-nav-menu-active data-[active=true]:text-nav-menu-item-active focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-nav-menu-focus {className}"
58
55
  aria-expanded={isActive ? 'true' : 'false'}
59
56
  aria-haspopup="true"
60
57
  onclick={handleClick}
@@ -40,7 +40,7 @@
40
40
  ...restProps
41
41
  }: Props = $props();
42
42
 
43
- const sizeClasses = $derived(() => {
43
+ const sizeClasses = $derived.by(() => {
44
44
  switch (size) {
45
45
  case "sm":
46
46
  return "text-sm";
@@ -51,7 +51,7 @@
51
51
  }
52
52
  });
53
53
 
54
- const maxWidthClasses = $derived(() => {
54
+ const maxWidthClasses = $derived.by(() => {
55
55
  switch (maxWidth) {
56
56
  case "sm":
57
57
  return "max-w-screen-sm";
@@ -72,7 +72,7 @@
72
72
  }
73
73
  });
74
74
 
75
- const backgroundClasses = $derived(() => {
75
+ const backgroundClasses = $derived.by(() => {
76
76
  switch (background) {
77
77
  case "muted":
78
78
  return "bg-base-50";
@@ -85,7 +85,7 @@
85
85
  }
86
86
  });
87
87
 
88
- const paddingClasses = $derived(() => {
88
+ const paddingClasses = $derived.by(() => {
89
89
  switch (padding) {
90
90
  case "none":
91
91
  return "";
@@ -102,14 +102,14 @@
102
102
  }
103
103
  });
104
104
 
105
- const containerClasses = $derived(() => {
105
+ const containerClasses = $derived.by(() => {
106
106
  const base = "w-full";
107
- const maxWidthClass = maxWidthClasses();
107
+ const maxWidthClass = maxWidthClasses;
108
108
  const centeredClass = centered ? "mx-auto" : "";
109
109
  return `${base} ${maxWidthClass} ${centeredClass}`.trim();
110
110
  });
111
111
 
112
- const contentClasses = $derived(() => {
112
+ const contentClasses = $derived.by(() => {
113
113
  const base = "px-4 sm:px-6 lg:px-8";
114
114
  const centeredClass = centered ? "text-center" : "";
115
115
  return `${base} ${centeredClass}`.trim();
@@ -117,18 +117,18 @@
117
117
  </script>
118
118
 
119
119
  <section
120
- class="section {backgroundClasses()} {paddingClasses()} {className}"
120
+ class="section {backgroundClasses} {paddingClasses} {className}"
121
121
  {...restProps}
122
122
  >
123
- <div class={containerClasses()}>
124
- <div class={contentClasses()}>
123
+ <div class={containerClasses}>
124
+ <div class={contentClasses}>
125
125
  {#if title}
126
126
  <div class="mb-6 {centered ? 'mx-auto' : ''}">
127
127
  <Heading level={headingLevel} text={title} />
128
128
  {#if description}
129
129
  <p
130
- class="mt-4 {sizeClasses()} text-description {centered
131
- ? 'mx-auto max-w-2xl'
130
+ class="mt-4 {sizeClasses} text-description {centered
131
+ ? 'mx-auto'
132
132
  : ''}"
133
133
  >
134
134
  {description}
@@ -68,7 +68,7 @@
68
68
 
69
69
  {#if isOpen}
70
70
  <div
71
- class="fixed inset-0 bg-overlay z-modal"
71
+ class="fixed inset-0 z-modal cursor-pointer bg-overlay"
72
72
  onclick={handleBackdropClick}
73
73
  onkeydown={handleKeydown}
74
74
  role="dialog"
@@ -78,7 +78,7 @@
78
78
  >
79
79
  <div
80
80
  bind:this={slideUpContainer}
81
- class="fixed bottom-0 left-0 right-0 bg-card rounded-t-3xl shadow-xl z-modal max-h-[90vh] overflow-y-auto animate-[slideUp_0.3s_ease-out] flex flex-col"
81
+ class="fixed bottom-0 left-0 right-0 z-modal flex max-h-[90vh] cursor-default flex-col overflow-y-auto rounded-t-3xl bg-card shadow-xl animate-[slideUp_0.3s_ease-out]"
82
82
  >
83
83
  {#if title}
84
84
  <div class="flex items-center justify-between px-6 pt-6 pb-4">
@@ -105,12 +105,12 @@
105
105
  type="button"
106
106
  role="tab"
107
107
  id={getTabId(tab.id)}
108
- class="px-4 py-2 text-sm font-medium border-b-2 transition-colors {activeTab ===
108
+ class="cursor-pointer border-b-2 px-4 py-2 text-sm font-medium transition-colors disabled:cursor-not-allowed {activeTab ===
109
109
  tab.id
110
110
  ? variant === 'pills'
111
- ? 'bg-brand-100 text-brand-700 border-brand-500'
111
+ ? 'border-brand-500 bg-brand-100 text-brand-700'
112
112
  : 'border-brand-500 text-body'
113
- : 'border-transparent text-description hover:text-body hover:border-base-300'}"
113
+ : 'border-transparent text-description hover:border-base-300 hover:text-body'}"
114
114
  onclick={() => selectTab(tab.id)}
115
115
  disabled={tab.disabled}
116
116
  aria-selected={activeTab === tab.id}