@phila/phila-ui-core
v3.0.1
Published
Core utilities and styles for Phila UI library
Readme
@phila/phila-ui-core
Component Status
| Component | Status |
| ------------- | ----------------------------------------------------------- |
| ExpandChevron | |
| Icon |
|
| Typography |
|
Core utilities and styles for the Phila UI library. This package provides shared TypeScript utilities and design tokens used in the Phila UI components.
Features
- Design Tokens: Essential colors, spacing, typography, and border radius
- TypeScript Utilities: Class name utilities and type definitions
- Type Safety: Full TypeScript support with comprehensive type definitions
- Vanilla CSS: Pure CSS approach without external dependencies
Installation
pnpm add @phila/phila-ui-core
# or
npm install @phila/phila-ui-coreUsage
Icons
The Phila UI design system uses bundled SVG icons sourced from Font Awesome Free (CC BY 4.0). All icons are embedded directly in the package — no external icon font or auth token required.
Using icons in components
Import named icon components from @phila/phila-ui-core/icons and pass them to the Icon component via the icon prop:
<script setup lang="ts">
import { Icon } from "@phila/phila-ui-core";
import { IconMagnifyingGlass, IconArrowRight } from "@phila/phila-ui-core/icons";
</script>
<template>
<Icon :icon="IconMagnifyingGlass" aria-label="Search" />
<Icon :icon="IconArrowRight" decorative />
</template>When building a component that uses icons, add @phila/phila-ui-core/icons to your vite.config.ts externals:
rollupOptions: {
external: ["vue", "@phila/phila-ui-core", "@phila/phila-ui-core/icons"],
}Adding new icons
- Copy the SVG into
packages/core/src/icons/svg/<name>.svg(follow Font Awesome's filename conventions, e.g.arrow-right.svg). - Run
pnpm --filter @phila/phila-ui-core build— the icon index and CSS sidecar regenerate automatically. - Import the new export:
import { Icon<PascalCase> } from "@phila/phila-ui-core/icons".
Phila UI Core Styles (Light mode):
In your main.ts file, import the core styles:
import "@phila/phila-ui-core/styles/template-light.css";Class Name Utilities
import { cn } from "@phila/phila-ui-core";
// Combine class names efficiently
const buttonClass = cn("base-button", "active", className);BaseProps
Every component's props interface extends BaseProps, which just adds a className?: string prop
for passing through extra classes:
import type { BaseProps } from "@phila/phila-ui-core";
export interface MyComponentProps extends BaseProps {
variant?: "primary" | "secondary";
}Design Tokens
Design tokens are CSS custom properties generated from Figma and shipped in
packages/core/src/styles/generated/. Importing the core styles (see Usage above) gives you
access to all of them.
Colors
Semantic color tokens: --Schemes-* (e.g. --Schemes-Primary, --Schemes-On-Surface,
--Schemes-Error, --Schemes-Border, --Schemes-Background). See schemes.css for the full
set — palettes.css and extended-colors.css hold the underlying palette values the semantic
tokens are built from.
Spacing
--spacing-*: 3xs, 2xs, xs, s, m, l, xl, 2xl, 3xl, 4xl, 5xl, 6xl, 7xl,
and none.
Border Radius
--border-radius-*: xxs, xs, s, m, l, xl, 2xl, full, and none.
Border Width
--border-width-*: xs, s, m, l, xl, 2xl.
Typography
Typography tokens follow the pattern --<Style>-font-<style>-<property> (e.g.
--Body-Default-font-body-default-size, -weight, -lineheight, -family) for each named text
style — see typography.css for the full list. Most components apply typography via the
content class rather than referencing these tokens directly.
Utility Classes
Beyond tokens, packages/core/src/styles/utilities/ ships ready-made classes for common layout,
spacing, text, and color needs. They're available globally as soon as you import the core
stylesheet — no separate import, and no JS to wire up. A few examples:
- Layout (
containers.css):is-flex,is-flex-column,is-justify-*,is-align-*,is-gap-1throughis-gap-6(mapped to the spacing scale),is-12/is-6/etc. (flex-basis columns). - Spacing (
spacing.css):p-0–p-7,m-0–m-7, and directional/axis variants (pt-*/px-*/mt-*/mx-*/etc.) — all mapped to the--spacing-*scale. - Text (
text.css):has-text-bold,has-text-italic,has-text-underline,has-text-center,has-text-label-*sizes,sr-onlyfor visually-hidden content. - Color (
color.css):has-background-*,has-links-on-primary,resets-link-colorsfor overriding link-color tokens inside colored containers.
These are the same classes the components use internally in their own templates, so check the
relevant file under packages/core/src/styles/utilities/ for the full, current list before
hand-writing a declaration one of these might already cover.
Core Components
FocusTrap
A component that traps focus within its children, ensuring accessibility for modals and dropdowns. It handles keyboard navigation. Optionally, allows escaping to fire custom events when focus leaves.
Basic Usage
<script lang="ts" setup>
import { FocusTrap } from "@phila/phila-ui-core";
</script>
<template>
<FocusTrap>
<div>
<p>This content is focus-trapped. Press Tab to navigate within this area.</p>
<button>Button 1</button>
<button>Button 2</button>
</div>
</FocusTrap>
</template>- When the
FocusTrapcomponent is mounted, it automatically focuses the first focusable element within its children. If no focusable elements are found, it focuses itself. - The component listens for
keydownevents to manage focus. Pressing the Tab key will cycle through the focusable elements within the trap. If the user tries to tab out of the trap, it will loop back to the beginning or end of the focusable elements, depending on the direction of the tabbing.Shift + Tabwill move focus backward, whileTabalone will move focus forward.PageUpmoves focus to the first focusable element, andPageDownmoves focus to the last focusable element.
| Prop | Type | Description |
| --------------------- | --------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| initialFocusElement | string | An ID of the element to focus initially when the trap is activated. If the element is not focusable (like a div, heading, span, etc.), the element will be given a temporary tabindex of 0 to make initially focusable. |
| arrowNavigation | boolean | If true, the component will also listen for ArrowUp and ArrowDown keys to navigate through focusable elements. |
| allowEscape | boolean | If true, tabbing outside of the focus trap and focusing on an external element will be allowed. An escape event will be emitted that can be listened to by the parent component. Useful for closing navbar menus when using keyboard navigation. |
| as | string | The HTML element to render as the wrapper for the focus trap. Defaults to span. |
Composables
useVisibility
A composable for managing visibility state of components, such as dropdowns and modals. It provides methods to toggle visibility and handles hover interactions.
Basic Usage
<script lang="ts" setup>
// Manage visibility state of a single element
import { useVisibility } from "@phila/phila-ui-core";
const { isVisible, toggleProps } = useVisibility({
id: "my-component",
group: "my-group", //optional, defaults to "global"
outsideClickHide: true, //optional, defaults to false.
});
</script>
<template>
<button v-bind="toggleProps">Toggle Visibility</button>
<div v-if="isVisible">This content is visible when the button is toggled.</div>
</template>- Including an Id prop when calling useVisibility will initilize the visibility state using that ID.
- Whenever useVisibility is called with the same ID/group, any settings that are defined will be applied to its visibility state.
- Toggle props includes the required
data-toggleattribute with the appropriate ID (visbility-${id}) and an optional click handler, though you can importsetVisiblityfrom the composable and create your own.
// Accessing visility state across components
<script lang="ts" setup>
import { useVisibility } from "@phila/phila-ui-core";
const { isVisible, setVisibility } = useVisibility({
group: "my-group",
});
const visible = computed(() => isVisible("my-component"));
const toggleVisibilityExternally = () => {
setVisibility(!visible.value, "my-component");
};
</script>
<template>
<button @click="toggleVisibilityExternally">{{ visible ? "Close" : "Open" }} Component</button>
</template>useVisibility options
| Option | Type | Default | Description |
| ------------------ | ------- | ----------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| id | string | undefined | Unique identifier for the visibility state of a component. |
| group | string | global | Grouping mechanism for visibility states. Components with the same group will share visibility state. |
| blurHide | boolean | false | If true, visbility will be set to false when the component (including focusable children) and its toggle loses focus. |
| showSingle | boolean | false | If true, only one component in the same group can be visible at a time. When a component's visibility is set to true, all other components in the same group will have their visibility set to false. |
| mouseOverToggle | boolean | false | If true, the exported onMouseEnter and onMouseLeave event handlers will set visibility to true and false, respectively. These event handlers can be applied to a wrapper element to listen for @onmouseenter or @onmouseleave events. |
| outsideClickHide | boolean | false | If true, clicking outside of the component will set its visibility to false. |
| escapeKeyHide | boolean | false | If true, pressing the Escape key will set visibility to false. |
| visibleOnMount | boolean | false | If true, the component will be visible when it mounts. |
useVisiblity methods
| Method | Type | Description |
| ----------------- | ----------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| isVisible | (id?: string) => boolean | A function that takes an optional ID and returns the visibility state (boolean) of the component. If an ID is provided, it returns the visibility state of the component with that ID. If no ID is provided, it returns the visibility state of the component that called the useVisibility hook. If no ID was provided when useVisiblity was called, and no ID is provided to isVisiblle, the default ID and group will be used: id: default-item, group: global. |
| setVisibility | (visible: boolean, id?: string) => void | A function that takes a boolean value and an optional ID to set the initial visibility state and sets up click and mouse event listeners for that component. If an ID is provided, it sets the visibility state of the component with that ID. If no ID is provided, it sets the visibility state of the component that called the useVisibility hook. If no ID was provided when useVisiblity was called, and no ID is provided to setVisiblity, the default ID and group will be used: id: default-item, group: global. |
| create | (id: string) => void | A function that takes an ID and initializes a new visibility state for the component with that ID. This is called automatically when ID is provided to useVisibility. |
| setState | (id: string, visible: boolean) => void | A function that takes an ID and a visible value to manually set the visibility state for a component. showSingle rules are preserved, but no event handlers are added/removed. |
| onMouseEnter | () => void | An event handler that sets visibility to true when the mouse enters the component. This is only added if the mouseOverToggle option is set to true. |
| onMouseLeave | () => void | An event handler that sets visibility to false when the mouse leaves the component. This is only added if the mouseOverToggle option is set to true. |
| visibilityState | VisibilityState | An object that contains the visibility state for all components, organized by group and ID. This is useful for debugging or advanced use cases where you need to access the visibility state of multiple components. |
TypeScript Support
The package includes TypeScript definitions for all utilities and design tokens.
License
MIT
