figma-plugin-utilities 0.1.0 → 0.2.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.
package/README.md CHANGED
@@ -1,11 +1,11 @@
1
- # figma-plugin-utils
1
+ # figma-plugin-utilities
2
2
 
3
3
  Shared Svelte components and utilities for Figma plugins.
4
4
 
5
5
  ## Installation
6
6
 
7
7
  ```bash
8
- npm install figma-plugin-utils
8
+ npm install figma-plugin-ulities
9
9
  ```
10
10
 
11
11
  ## Usage
@@ -23,6 +23,7 @@ import {
23
23
  ListItem,
24
24
  LoadingState,
25
25
  FieldGroup,
26
+ CheckboxCard,
26
27
  // Utilities
27
28
  sendToPlugin,
28
29
  createMessageHandler,
@@ -56,6 +57,7 @@ import { sendToPlugin, createMessageHandler } from "figma-plugin-utils/lib";
56
57
  | `ListItem` | Selectable list items with metadata slot and action menu |
57
58
  | `LoadingState` | Centered loading indicator with custom message |
58
59
  | `FieldGroup` | Label + input wrapper for form fields |
60
+ | `CheckboxCard` | Large checkbox with card styling and better touch targets |
59
61
 
60
62
  ### Header
61
63
 
@@ -140,6 +142,37 @@ Types: `info`, `success`, `error`, `warning`. Auto-dismisses after 4s for `info`
140
142
  </ListItem>
141
143
  ```
142
144
 
145
+ ### CheckboxCard
146
+
147
+ Large checkbox with card-style background and better touch targets.
148
+
149
+ ```svelte
150
+ <!-- Basic usage -->
151
+ <CheckboxCard
152
+ checked={isSelected}
153
+ on:change={handleToggle}
154
+ >
155
+ Small
156
+ </CheckboxCard>
157
+
158
+ <!-- With secondary text -->
159
+ <CheckboxCard
160
+ checked={isSelected}
161
+ on:change={handleToggle}
162
+ >
163
+ Small
164
+ <svelte:fragment slot="secondary">400px</svelte:fragment>
165
+ </CheckboxCard>
166
+
167
+ <!-- Disabled state -->
168
+ <CheckboxCard
169
+ checked={true}
170
+ disabled={true}
171
+ >
172
+ Large
173
+ </CheckboxCard>
174
+ ```
175
+
143
176
  ## Utilities
144
177
 
145
178
  ### Messages (`lib/messages.js`)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "figma-plugin-utilities",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "Shared Svelte components and utilities for Figma plugins",
5
5
  "type": "module",
6
6
  "svelte": "./src/index.js",
@@ -21,6 +21,9 @@
21
21
  "import": "./src/lib/index.js",
22
22
  "default": "./src/lib/index.js"
23
23
  },
24
+ "./lib/*": {
25
+ "import": "./src/lib/*.js"
26
+ },
24
27
  "./lib/figma-helpers": {
25
28
  "types": "./src/lib/figma-helpers.ts",
26
29
  "import": "./src/lib/figma-helpers.ts",
@@ -47,7 +50,7 @@
47
50
  "author": "Marius Roosendaal",
48
51
  "license": "MIT",
49
52
  "dependencies": {
50
- "figma-ui3-kit-svelte": "^0.4.0",
53
+ "figma-ui3-kit-svelte": "file:../figma-ui3-kit-svelte",
51
54
  "svelte": "^4.2.20"
52
55
  }
53
56
  }
@@ -0,0 +1,109 @@
1
+ <script>
2
+ import { createEventDispatcher } from "svelte";
3
+ import { Checkbox } from "figma-ui3-kit-svelte";
4
+
5
+ /**
6
+ * Large checkbox card component with better touch targets
7
+ * Wraps the standard checkbox in a card-like layout
8
+ *
9
+ * @example
10
+ * <CheckboxCard
11
+ * checked={isSelected}
12
+ * on:change={handleToggle}
13
+ * >
14
+ * Small
15
+ * </CheckboxCard>
16
+ *
17
+ * @example with secondary text
18
+ * <CheckboxCard
19
+ * checked={isSelected}
20
+ * on:change={handleToggle}
21
+ * >
22
+ * Small
23
+ * <svelte:fragment slot="secondary">400px</svelte:fragment>
24
+ * </CheckboxCard>
25
+ */
26
+
27
+ const dispatch = createEventDispatcher();
28
+
29
+ /** Whether checkbox is checked */
30
+ export let checked = false;
31
+
32
+ /** Whether checkbox is disabled */
33
+ export let disabled = false;
34
+
35
+ function handleCardClick(e) {
36
+ if (disabled) return;
37
+
38
+ // Don't toggle if clicking directly on the checkbox or label
39
+ // (let the checkbox handle it natively)
40
+ const target = e.target;
41
+ const isCheckboxOrLabel =
42
+ target.tagName === "INPUT" ||
43
+ target.tagName === "LABEL" ||
44
+ target.closest("label");
45
+
46
+ if (isCheckboxOrLabel) return;
47
+
48
+ // Toggle and dispatch change event
49
+ checked = !checked;
50
+ dispatch("change", { checked });
51
+ }
52
+ </script>
53
+
54
+ <div
55
+ class="checkbox-card"
56
+ class:disabled
57
+ on:click={handleCardClick}
58
+ on:keydown={(e) => e.key === "Enter" && handleCardClick(e)}
59
+ role="button"
60
+ tabindex={disabled ? -1 : 0}
61
+ >
62
+ <Checkbox {checked} {disabled} on:change>
63
+ <slot />
64
+ </Checkbox>
65
+ {#if $$slots.secondary}
66
+ <div class="checkbox-card__secondary">
67
+ <slot name="secondary" />
68
+ </div>
69
+ {/if}
70
+ </div>
71
+
72
+ <style>
73
+ .checkbox-card {
74
+ display: flex;
75
+ align-items: center;
76
+ justify-content: space-between;
77
+ padding: 0 var(--size-xxxsmall);
78
+ background: var(--figma-color-bg-secondary);
79
+ border: 1px solid transparent;
80
+ border-radius: var(--border-radius-medium);
81
+ cursor: pointer;
82
+ min-height: 24px;
83
+ }
84
+
85
+ .checkbox-card:hover {
86
+ border-color: var(--figma-color-border);
87
+ background: var(--figma-color-bg-secondary);
88
+ }
89
+
90
+ .checkbox-card.disabled {
91
+ opacity: 0.4;
92
+ cursor: not-allowed;
93
+ }
94
+
95
+ /* Custom checkbox styling for card variant */
96
+ .checkbox-card :global(.checkbox-box) {
97
+ background-color: var(--figma-color-bg);
98
+ }
99
+
100
+ .checkbox-card__secondary {
101
+ font-size: var(--body-small-font-size);
102
+ font-weight: var(--body-small-font-weight);
103
+ letter-spacing: var(--body-small-letter-spacing);
104
+ line-height: var(--body-small-line-height);
105
+ color: var(--figma-color-text-secondary);
106
+ margin-left: auto;
107
+ padding-left: var(--size-xsmall);
108
+ }
109
+ </style>
@@ -30,12 +30,14 @@
30
30
  /** Whether to center vertically */
31
31
  export let centered = true;
32
32
 
33
+ let className = '';
34
+ export { className as class };
33
35
  // Normalize actions
34
36
  $: normalizedActions = actions ? actions : action ? [action] : null;
35
37
  </script>
36
38
 
37
39
  <div
38
- class="empty-state"
40
+ class="empty-state {className}"
39
41
  class:centered
40
42
  class:small={size === "small"}
41
43
  class:large={size === "large"}
@@ -16,11 +16,14 @@
16
16
 
17
17
  /** For attribute for the label (optional) */
18
18
  export let labelFor = "";
19
+
20
+ /** Size of the label (optional) */
21
+ export let size = undefined;
19
22
  </script>
20
23
 
21
- <div class="field-group">
24
+ <div class="field-group" class:small={size === "small"}>
22
25
  {#if label}
23
- <Label for={labelFor}>{label}</Label>
26
+ <Label for={labelFor} {size}>{label}</Label>
24
27
  {/if}
25
28
  <slot />
26
29
  </div>
@@ -31,4 +34,8 @@
31
34
  flex-direction: column;
32
35
  gap: var(--size-xxsmall);
33
36
  }
37
+
38
+ .field-group.small {
39
+ gap: var(--size-xxxsmall);
40
+ }
34
41
  </style>
@@ -1,4 +1,5 @@
1
1
  // Svelte components
2
+ export { default as CheckboxCard } from "./CheckboxCard.svelte";
2
3
  export { default as EmptyState } from "./EmptyState.svelte";
3
4
  export { default as FieldGroup } from "./FieldGroup.svelte";
4
5
  export { default as Footer } from "./Footer.svelte";
package/src/index.js CHANGED
@@ -1,5 +1,6 @@
1
1
  // Re-export all components
2
2
  export {
3
+ CheckboxCard,
3
4
  EmptyState,
4
5
  FieldGroup,
5
6
  Footer,