diff --git a/libs/composables/class/docs/class.composable.md b/libs/composables/class/docs/class.composable.md
index d3b54fd..9e64ba2 100644
--- a/libs/composables/class/docs/class.composable.md
+++ b/libs/composables/class/docs/class.composable.md
@@ -1,171 +1,137 @@
-# `useAttribute`
+# Class Composable
-This composable is used to get and set the value of an attribute of an element.
-It will return a writable signal that can be used to change the value of the attribute.
+- [`useClass`](#useclass)
+- [`bindClass`](#bindclass)
-## Parameters
+## `useClass`
-| Name | Type | Optional? | Description |
-|------------------------|----------|-----------|---------------------------------------------------------------------------------------------------------------------------|
-| `attributeName` | `string` | no | The name of the attribute to bind to. |
-| `options` | `object` | yes | Options to customize the behavior. |
-| `options.namespace` | `string` | yes | The namespace of the attribute. |
-| `options.defaultValue` | `string` | yes | The default value of the attribute. Will be applied when no attribute value has been set in the template or on the signal |
-| `options.initialValue` | `string` | yes | The initial value of the attribute. Will force the initial value and override any value set in the template |
+This composable is used to add or remove a specific class on the host element.
+It will return a writable signal that can be used to change whether the class should be added or removed.
+### Parameters
-## Usage
+| Name | Type | Optional? | Description |
+|------------------------|-----------|-----------|---------------------------------------------|
+| `clazz` | `string` | no | The name of the class. |
+| `options` | `object` | yes | Options to customize the behavior. |
+| `options.initialValue` | `boolean` | yes | Whether the class should initially be added |
-### Default behavior
-By default, this composable will read the value of the attribute from the usage in the template
+### Usage
-```ts
-import { useAttribute } from '@bynary/angular-composables/attribute';
-
-@Component({
- selector: 'my-component'
-})
-class MyComponent {
-
- label = useAttribute('label');
-}
-```
-
-```html
-
+#### Default behavior
-{{ myComponent.label }}
-```
-
-will render as
-
-```html
-
-
-foo
-```
-
-### Default value
-
-To set a default value, you can use the `options.defaultValue` parameter:
+By default, this composable will add the class to the host element
```ts
-import { useAttribute } from '@bynary/angular-composables/attribute';
+import { useClass } from '@bynary/angular-composables/class';
@Component({
selector: 'my-component'
})
class MyComponent {
- label = useAttribute('label', { defaultValue: 'foo' });
+ isLoading = useClass('loading');
}
```
```html
-{{ myComponent.label }}
+{{ myComponent.isLoading }}
```
-and will render as
+will render as
```html
-
+
-foo
+true
```
-### Force initial value
+#### Override initial value
-You may override any template-defined value by setting `options.initialValue`:
+If you don't want to add the class initially, set `options.initialValue` to `false`:
```ts
-import { useAttribute } from '@bynary/angular-composables/attribute';
+import { useClass } from '@bynary/angular-composables/class';
@Component({
selector: 'my-component'
})
class MyComponent {
- label = useAttribute('label', { initialValue: 'bar' });
+ isLoading = useClass('label', { initialValue: false });
}
```
```html
-
+
-{{ myComponent.label }}
+{{ myComponent.isLoading }}
```
will render as
```html
-
+
-bar
+false
```
-### Custom namespace
+#### Programmatically set the value
-You may also use a custom namespace for the attribute:
+By changing the value of the signal, you can add / remove the class programmatically
```ts
-import { useAttribute } from '@bynary/angular-composables/attribute';
+import { useClass } from '@bynary/angular-composables/class';
@Component({
selector: 'my-component'
})
class MyComponent {
- label = useAttribute('label', { namespace: 'my', initialValue: 'baz' });
+ isLoading = useClass('loading', { initialValue: false });
+
+ startLoading() {
+ this.isLoading.set(true);
+ }
+
+ stopLoading() {
+ this.isLoading.set(false);
+ }
}
```
-```html
-
-{{ myComponent.label }}
-```
+## `bindClass`
-will render as
+Toggles a class on the host element based on the value of a signal. Similar to `useClass`, but accepts a boolean signal as an input instead of creating a new one.
+Will return the signal that has been passed in.
-```html
-
+### Parameters
-baz
-```
+| Name | Type | Optional? | Description |
+|---------|----------|-----------|------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| `clazz` | `string` | no | The name of the class. |
+| `value` | `Signal` | no | The signal to determine whether the class should be added or removed. When the signal's value is true, the class will be applied. Else it will be removed. |
-### Programmatically set the value
+### Usage
-You can also change the value of the attribute programmatically by using the returned signal:
+`bindClass` can be used inside a directive or component:
```ts
-import { useAttribute } from '@bynary/angular-composables/attribute';
+import { bindClass } from '@bynary/angular-composables/class';
@Component({
selector: 'my-component'
})
class MyComponent {
- label = useAttribute('label');
-
+ isLoading: Signal = signal(false);
+
constructor() {
- this.label.set('programmatically set value');
+ bindClass('loading', this.isLoading);
}
}
```
-
-```html
-
-
-{{ myComponent.label }}
-```
-
-will render as
-
-```html
-
-
-programmatically set value
-```
diff --git a/libs/composables/class/docs/classes.composable.md b/libs/composables/class/docs/classes.composable.md
new file mode 100644
index 0000000..a738c99
--- /dev/null
+++ b/libs/composables/class/docs/classes.composable.md
@@ -0,0 +1,128 @@
+# Classes Composable
+
+- [`useClasses`](#useclasses)
+- [`bindClasses`](#bindclasses)
+
+## `useClasses`
+
+This composable is used to add or remove a set of classes on the host element.
+It will return a writable signal that can be used to change whether the class should be added or removed.
+
+### Parameters
+
+| Name | Type | Optional? | Description |
+|----------------|----------------------|-----------|--------------------------------------------------------------------|
+| `initialValue` | `string \| string[]` | yes | The list of classes to apply initially. Defaults to an empty array |
+
+
+### Usage
+
+#### Default behavior
+
+By default, this composable will add the classes to the host element
+
+```ts
+import { useClasses } from '@bynary/angular-composables/class';
+
+@Component({
+ selector: 'my-component'
+})
+class MyComponent {
+
+ classes = useClasses(['my-component', 'primary', 'focusable']);
+}
+```
+
+```html
+
+```
+
+will render as
+
+```html
+
+```
+
+#### String as initial value
+
+You may also pass a string as the initial value. The string will be split by spaces and each part will be added as a class.
+Multiple spaces will be ignored.
+
+```ts
+import { useClasses } from '@bynary/angular-composables/class';
+
+@Component({
+ selector: 'my-component'
+})
+class MyComponent {
+
+ isLoading = useClasses('my-component primary focusable');
+}
+```
+
+```html
+
+```
+
+will render as
+
+```html
+
+```
+
+#### Programmatically set the value
+
+By changing the value of the signal, you can add / remove classes programmatically.
+Each previously set class will be removed and the new classes will be added.
+Classes set form somewhere else (e.g. the template) will be untouched, except for ones that are contained in new or previous list.
+
+```ts
+import { useClasses } from '@bynary/angular-composables/class';
+
+@Component({
+ selector: 'my-component',
+ host: {
+ class: 'my-component'
+ }
+})
+class MyComponent {
+
+ classes = useClasses('primary focusable'); // initially, these classes will be set on the host: `my-component`, `primary`, `focusable`
+
+ changeClasses() {
+ this.classes.set('accent'); // will remove `primary` and `focusable`, resulting in these classes set on the host: `my-component`, `accent`
+ }
+}
+```
+
+
+## `bindClasses`
+
+Binds a set of class to the host element based on the value of a signal. Similar to `useClasses`, but accepts a signal as an input instead of creating a new one.
+Will return the signal that has been passed in.
+
+### Parameters
+
+| Name | Type | Optional? | Description |
+|---------|----------|-----------|--------------------------------------------------------|
+| `value` | `Signal` | no | The signal containing the classes to bind to the host. |
+
+### Usage
+
+`bindClasses` can be used inside a directive or component:
+
+```ts
+import { bindClasses } from '@bynary/angular-composables/class';
+
+@Component({
+ selector: 'my-component'
+})
+class MyComponent {
+
+ classes = signal([ 'foo', 'bar' ]);
+
+ constructor() {
+ bindClasses(this.classes);
+ }
+}
+```