@phila/phila-ui-button 2.0.2 → 2.1.0-beta.2

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,48 +1,152 @@
1
1
  # Phila Button Component
2
2
 
3
- The Vue component in this package is for development purposes only. See installation & usage documentation for more details.
3
+ A flexible, accessible button component built with Vue 3 and TypeScript, implementing the Philadelphia Design System.
4
4
 
5
5
  ## Features
6
6
 
7
- - 🎨 Multiple variants: primary, secondary, destructive, standard (icon-button only)
8
- - 🔄 Multiple Layouts: text, icon-text, text-icon, icon-button
9
- - 📏 Four sizes: extra-small, small, medium, large, extra-large (icon-button only)
10
- - ♿ Accessibility features: focus states, disabled state
7
+ - 🎨 Multiple variants: primary, secondary, destructive, standard
8
+ - 📐 Multiple sizes: extra-large, large, medium (default), small, extra-small
9
+ - 🎯 Icon support: left icons, right icons, and icon-only buttons
10
+ - ♿ Full accessibility: ARIA attributes, focus states, disabled state
11
+ - 🔧 Flexible API: Props or slots for content
12
+ - 💅 Design system integration: Uses Core package styles
11
13
 
12
14
  ## Installation
13
15
 
14
- Note: Button styles are included in the core package, so installation of the button vue component is optional.
15
-
16
16
  ```bash
17
- npm install @phila/core
18
- npm install @phila/phila-ui-button
17
+ npm install @phila/phila-ui-button @phila/phila-ui-core
19
18
  # or
20
- pnpm add @phila/core
21
- pnpm add @phila/phila-ui-button
19
+ pnpm add @phila/phila-ui-button @phila/phila-ui-core
22
20
  ```
23
21
 
24
- Import core styles and other components in your main entry file (e.g., `main.js|ts`):
22
+ Import core styles in your main entry file (e.g., `main.js|ts`):
25
23
 
26
24
  ```typescript
27
- import "@phila/core/styles/template-light.css";
25
+ import "@phila/phila-ui-core/styles/template-light.css";
28
26
  ```
29
27
 
30
- ## Usage
28
+ ## Vue Component Usage
31
29
 
32
- Use a button element with the appropriate classes. You can also apply those classes to links to style a link as a button.
30
+ ### Basic Usage
33
31
 
34
32
  ```vue
33
+ <script setup lang="ts">
34
+ import { PhilaButton } from "@phila/phila-ui-button";
35
+
36
+ const handleClick = () => {
37
+ console.log("Button clicked!");
38
+ };
39
+ </script>
40
+
35
41
  <template>
36
- <button class="phila-button phila-button--primary is-medium" @click="handleClick">Medium primary button</button>
42
+ <PhilaButton variant="primary" @click="handleClick"> Click Me </PhilaButton>
43
+ </template>
44
+ ```
37
45
 
38
- <a class="phila-button phila-button--primary" href="#" @click.prevent="handleClick"> Link as a button </a>
46
+ ### With Props
47
+
48
+ ```vue
49
+ <PhilaButton variant="primary" size="medium" text="Click Me" @click="handleClick" />
50
+ ```
51
+
52
+ ### With Icons
53
+
54
+ ```vue
55
+ <script setup lang="ts">
56
+ import { PhilaButton } from "@phila/phila-ui-button";
57
+ import { faPencil, faArrowRight } from "@fortawesome/pro-solid-svg-icons";
58
+ </script>
59
+
60
+ <template>
61
+ <!-- Left Icon -->
62
+ <PhilaButton variant="primary" :icon="faPencil" text="Edit" />
63
+
64
+ <!-- Right Icon -->
65
+ <PhilaButton variant="primary" :icon="faArrowRight" icon-right text="Continue" />
66
+
67
+ <!-- Icon Only -->
68
+ <PhilaButton variant="primary" icon-only :icon="faPencil" />
39
69
  </template>
70
+ ```
71
+
72
+ ### Props
73
+
74
+ | Prop | Type | Default | Description |
75
+ | ----------- | ------------------------------------------------------------------ | ----------- | ------------------------------------------------------------- |
76
+ | `variant` | `"primary" \| "secondary" \| "destructive" \| "standard"` | `"primary"` | Button style variant |
77
+ | `size` | `"extra-large" \| "large" \| "medium" \| "small" \| "extra-small"` | `"medium"` | Button size |
78
+ | `disabled` | `boolean` | `false` | Whether the button is disabled |
79
+ | `iconOnly` | `boolean` | `false` | Whether to display only an icon |
80
+ | `icon` | `IconDefinition` | `undefined` | FontAwesome icon definition |
81
+ | `iconClass` | `string` | `undefined` | FontAwesome icon class name |
82
+ | `iconRight` | `boolean` | `false` | Whether to position the icon on the right side |
83
+ | `text` | `string` | `undefined` | Button text (alternative to slot) |
84
+ | `className` | `string` | `undefined` | Additional CSS classes |
85
+ | `href` | `string` | `undefined` | URL for link buttons (renders as `<a>` instead of `<button>`) |
86
+ | `target` | `string` | `undefined` | Link target attribute (e.g., "\_blank") |
87
+ | `rel` | `string` | `undefined` | Link rel attribute (e.g., "noopener noreferrer") |
88
+
89
+ ### Variants
90
+
91
+ ```vue
92
+ <PhilaButton variant="primary">Primary</PhilaButton>
93
+ <PhilaButton variant="secondary">Secondary</PhilaButton>
94
+ <PhilaButton variant="destructive">Destructive</PhilaButton>
95
+ <PhilaButton variant="standard" icon-only :left-icon="faSearch">Standard Icon</PhilaButton>
96
+ ```
97
+
98
+ ### Sizes
99
+
100
+ ```vue
101
+ <PhilaButton size="extra-large">Extra Large</PhilaButton>
102
+ <PhilaButton size="large">Large</PhilaButton>
103
+ <PhilaButton size="medium">Medium (default)</PhilaButton>
104
+ <PhilaButton size="small">Small</PhilaButton>
105
+ <PhilaButton size="extra-small">Extra Small</PhilaButton>
106
+ ```
107
+
108
+ ### Link Buttons
109
+
110
+ Buttons can also render as links by providing an `href` prop:
40
111
 
112
+ ```vue
41
113
  <script setup lang="ts">
42
- const handleClick = () => {
43
- console.log("Button clicked!");
44
- };
114
+ import { PhilaButton } from "@phila/phila-ui-button";
115
+ import { faArrowRight } from "@fortawesome/pro-solid-svg-icons";
45
116
  </script>
117
+
118
+ <template>
119
+ <!-- Internal link -->
120
+ <PhilaButton href="/about" text="Learn More" />
121
+
122
+ <!-- External link -->
123
+ <PhilaButton
124
+ href="https://example.com"
125
+ target="_blank"
126
+ rel="noopener noreferrer"
127
+ text="Visit Site"
128
+ :icon="faArrowRight"
129
+ icon-right
130
+ />
131
+ </template>
132
+ ```
133
+
134
+ ### States
135
+
136
+ ```vue
137
+ <PhilaButton disabled>Disabled Button</PhilaButton>
138
+ ```
139
+
140
+ ## Using CSS Classes Directly
141
+
142
+ You can also use the button styles directly without the Vue component by applying CSS classes to any element:
143
+
144
+ ```vue
145
+ <template>
146
+ <button class="phila-button phila-button--primary is-medium" @click="handleClick">Medium primary button</button>
147
+
148
+ <a class="phila-button phila-button--primary" href="#" @click.prevent="handleClick"> Link as a button </a>
149
+ </template>
46
150
  ```
47
151
 
48
152
  ## Button Classes
@@ -0,0 +1,80 @@
1
+ import { BaseIconProps } from '@phila/phila-ui-core';
2
+ import { BaseProps } from '@phila/phila-ui-core';
3
+ import { ComponentSize } from '@phila/phila-ui-core';
4
+ import { DefineSetupFnComponent } from 'vue';
5
+ import { PublicProps } from 'vue';
6
+ import { RouteLocationRaw } from '@phila/phila-ui-core';
7
+
8
+ declare const __VLS_component: DefineSetupFnComponent<Record<string, any>, {}, {}, Record<string, any> & {}, PublicProps>;
9
+
10
+ declare function __VLS_template(): {
11
+ default?(_: {}): any;
12
+ };
13
+
14
+ declare type __VLS_WithTemplateSlots<T, S> = T & {
15
+ new (): {
16
+ $slots: S;
17
+ };
18
+ };
19
+
20
+ declare interface BaseButtonProps extends BaseProps, BaseIconProps {
21
+ /** Button variant type */
22
+ variant?: ButtonVariant;
23
+ /** Button size */
24
+ size?: ComponentSize;
25
+ /** Whether the button is an icon-only button */
26
+ iconOnly?: boolean;
27
+ /** Whether to position the icon on the right side */
28
+ iconRight?: boolean;
29
+ /** Button text content (alternative to using slot) */
30
+ text?: string;
31
+ }
32
+
33
+ export declare type ButtonProps = EventButtonProps | LinkButtonProps;
34
+
35
+ export declare type ButtonVariant = "primary" | "secondary" | "destructive" | "standard";
36
+
37
+ export declare interface EventButtonProps extends BaseButtonProps {
38
+ /** No href or to - renders as <button> */
39
+ href?: never;
40
+ to?: never;
41
+ /** Link target - not available for buttons */
42
+ target?: never;
43
+ /** Link rel - not available for buttons */
44
+ rel?: never;
45
+ /** Whether the button is disabled */
46
+ disabled?: boolean;
47
+ clickTarget?: string;
48
+ }
49
+
50
+ export declare interface HtmlLinkButtonProps extends BaseButtonProps {
51
+ /** URL for link buttons */
52
+ href: string;
53
+ /** No to prop for HTML buttons */
54
+ to?: never;
55
+ /** Link target attribute (e.g., "_blank") */
56
+ target?: string;
57
+ /** Link rel attribute (e.g., "noopener noreferrer") */
58
+ rel?: string;
59
+ /** Whether the button is disabled */
60
+ disabled?: boolean;
61
+ }
62
+
63
+ export declare type LinkButtonProps = HtmlLinkButtonProps | RouterLinkButtonProps;
64
+
65
+ export declare const PhilaButton: __VLS_WithTemplateSlots<typeof __VLS_component, ReturnType<typeof __VLS_template>>;
66
+
67
+ export declare interface RouterLinkButtonProps extends BaseButtonProps {
68
+ /** Vue Router route location */
69
+ to: RouteLocationRaw;
70
+ /** No href for router buttons */
71
+ href?: never;
72
+ /** No target for router buttons */
73
+ target?: never;
74
+ /** No rel for router buttons */
75
+ rel?: never;
76
+ /** Whether the button is disabled */
77
+ disabled?: boolean;
78
+ }
79
+
80
+ export { }
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("vue"),r=e.defineComponent({__name:"PhlButton",props:{disabled:{type:Boolean,default:!1}},setup(t){const o=t;return(n,l)=>(e.openBlock(),e.createElementBlock("button",e.mergeProps({class:"phila-button"},o),[e.renderSlot(n.$slots,"default")],16))}});exports.Button=r;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("vue"),o=require("@phila/phila-ui-core"),c=["disabled"],u=e.defineComponent({inheritAttrs:!1,__name:"PhlButton",props:{href:{},to:{},target:{},rel:{},disabled:{type:Boolean,default:!1},clickTarget:{},variant:{default:"primary"},size:{default:"medium"},iconOnly:{type:Boolean,default:!1},iconRight:{type:Boolean},text:{},className:{},iconDefinition:{},iconClass:{},src:{},svgRaw:{}},setup(s){const t=s,a=n=>"href"in n&&n.href!==void 0||"to"in n&&n.to!==void 0,i=e.computed(()=>o.cn("phila-button",`phila-button--${t.variant}`,t.size&&`is-${t.size}`,t.iconOnly&&"icon-button",t.iconOnly&&t.variant==="standard"&&"icon-button--standard",t.className)),l=e.computed(()=>a(t)?"to"in t&&t.to!==void 0?{to:t.to,disabled:t.disabled,className:i.value}:{href:t.href,target:t.target,rel:t.rel,disabled:t.disabled,className:i.value}:{}),r=e.computed(()=>({iconDefinition:t.iconDefinition,iconClass:t.iconClass,src:t.src,iconRight:t.iconRight,iconOnly:t.iconOnly,text:t.text,size:t.size}));return(n,d)=>a(t)?(e.openBlock(),e.createBlock(e.unref(o.BaseLink),e.mergeProps({key:0},{...l.value,...n.$attrs},{role:"button"}),{default:e.withCtx(()=>[e.createVNode(e.unref(o.ActionContent),e.normalizeProps(e.guardReactiveProps(r.value)),{default:e.withCtx(()=>[e.renderSlot(n.$slots,"default",{},()=>[e.createTextVNode(e.toDisplayString(t.text),1)])]),_:3},16)]),_:3},16)):(e.openBlock(),e.createElementBlock("button",e.mergeProps({key:1,type:"button",disabled:t.disabled,class:i.value},n.$attrs),[e.createVNode(e.unref(o.ActionContent),e.normalizeProps(e.guardReactiveProps(r.value)),{default:e.withCtx(()=>[e.renderSlot(n.$slots,"default",{},()=>[e.createTextVNode(e.toDisplayString(t.text),1)])]),_:3},16)],16,c))}});exports.PhilaButton=u;
package/dist/index.mjs CHANGED
@@ -1,16 +1,84 @@
1
- import { defineComponent as n, createElementBlock as r, openBlock as s, mergeProps as l, renderSlot as a } from "vue";
2
- const u = /* @__PURE__ */ n({
1
+ import { defineComponent as g, computed as o, createBlock as B, createElementBlock as k, openBlock as r, unref as a, mergeProps as c, withCtx as i, createVNode as d, normalizeProps as u, guardReactiveProps as f, renderSlot as m, createTextVNode as p, toDisplayString as b } from "vue";
2
+ import { cn as C, BaseLink as P, ActionContent as h } from "@phila/phila-ui-core";
3
+ const _ = ["disabled"], x = /* @__PURE__ */ g({
4
+ inheritAttrs: !1,
3
5
  __name: "PhlButton",
4
6
  props: {
5
- disabled: { type: Boolean, default: !1 }
7
+ href: {},
8
+ to: {},
9
+ target: {},
10
+ rel: {},
11
+ disabled: { type: Boolean, default: !1 },
12
+ clickTarget: {},
13
+ variant: { default: "primary" },
14
+ size: { default: "medium" },
15
+ iconOnly: { type: Boolean, default: !1 },
16
+ iconRight: { type: Boolean },
17
+ text: {},
18
+ className: {},
19
+ iconDefinition: {},
20
+ iconClass: {},
21
+ src: {},
22
+ svgRaw: {}
6
23
  },
7
- setup(e) {
8
- const t = e;
9
- return (o, p) => (s(), r("button", l({ class: "phila-button" }, t), [
10
- a(o.$slots, "default")
11
- ], 16));
24
+ setup(v) {
25
+ const t = v, s = (e) => "href" in e && e.href !== void 0 || "to" in e && e.to !== void 0, n = o(() => C(
26
+ "phila-button",
27
+ `phila-button--${t.variant}`,
28
+ t.size && `is-${t.size}`,
29
+ t.iconOnly && "icon-button",
30
+ t.iconOnly && t.variant === "standard" && "icon-button--standard",
31
+ t.className
32
+ )), y = o(() => s(t) ? "to" in t && t.to !== void 0 ? {
33
+ to: t.to,
34
+ disabled: t.disabled,
35
+ className: n.value
36
+ } : {
37
+ href: t.href,
38
+ target: t.target,
39
+ rel: t.rel,
40
+ disabled: t.disabled,
41
+ className: n.value
42
+ } : {}), l = o(
43
+ () => ({
44
+ iconDefinition: t.iconDefinition,
45
+ iconClass: t.iconClass,
46
+ src: t.src,
47
+ iconRight: t.iconRight,
48
+ iconOnly: t.iconOnly,
49
+ text: t.text,
50
+ size: t.size
51
+ })
52
+ );
53
+ return (e, z) => s(t) ? (r(), B(a(P), c({ key: 0 }, { ...y.value, ...e.$attrs }, { role: "button" }), {
54
+ default: i(() => [
55
+ d(a(h), u(f(l.value)), {
56
+ default: i(() => [
57
+ m(e.$slots, "default", {}, () => [
58
+ p(b(t.text), 1)
59
+ ])
60
+ ]),
61
+ _: 3
62
+ }, 16)
63
+ ]),
64
+ _: 3
65
+ }, 16)) : (r(), k("button", c({
66
+ key: 1,
67
+ type: "button",
68
+ disabled: t.disabled,
69
+ class: n.value
70
+ }, e.$attrs), [
71
+ d(a(h), u(f(l.value)), {
72
+ default: i(() => [
73
+ m(e.$slots, "default", {}, () => [
74
+ p(b(t.text), 1)
75
+ ])
76
+ ]),
77
+ _: 3
78
+ }, 16)
79
+ ], 16, _));
12
80
  }
13
81
  });
14
82
  export {
15
- u as Button
83
+ x as PhilaButton
16
84
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@phila/phila-ui-button",
3
- "version": "2.0.2",
3
+ "version": "2.1.0-beta.2",
4
4
  "type": "module",
5
5
  "description": "Button component for Phila UI library",
6
6
  "main": "./dist/index.js",
@@ -25,10 +25,12 @@
25
25
  "author": "",
26
26
  "license": "MIT",
27
27
  "peerDependencies": {
28
- "vue": "^3.0.0"
28
+ "vue": "^3.0.0",
29
+ "@fortawesome/fontawesome-svg-core": "^7.1.0",
30
+ "@fortawesome/vue-fontawesome": "^3.1.2"
29
31
  },
30
32
  "dependencies": {
31
- "@phila/phila-ui-core": "2.1.1"
33
+ "@phila/phila-ui-core": "2.2.0-beta.2"
32
34
  },
33
35
  "devDependencies": {
34
36
  "@types/node": "^24.0.0",